summaryrefslogtreecommitdiff
path: root/src/VBox/Devices/PC/DevPIC.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Devices/PC/DevPIC.cpp')
-rw-r--r--src/VBox/Devices/PC/DevPIC.cpp686
1 files changed, 329 insertions, 357 deletions
diff --git a/src/VBox/Devices/PC/DevPIC.cpp b/src/VBox/Devices/PC/DevPIC.cpp
index a95f0bad..10fe2a0c 100644
--- a/src/VBox/Devices/PC/DevPIC.cpp
+++ b/src/VBox/Devices/PC/DevPIC.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -13,8 +13,35 @@
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ * -------------------------------------------------------------------
+ *
+ * This code is based on:
+ *
+ * QEMU 8259 interrupt controller emulation
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
*/
+
/*******************************************************************************
* Header Files *
*******************************************************************************/
@@ -44,58 +71,21 @@
(pThis)->CTX_SUFF(pPicHlp)->pfnUnlock((pThis)->CTX_SUFF(pDevIns))
-#ifndef VBOX_DEVICE_STRUCT_TESTCASE
-/*******************************************************************************
-* Internal Functions *
-*******************************************************************************/
-RT_C_DECLS_BEGIN
-
-PDMBOTHCBDECL(void) picSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc);
-PDMBOTHCBDECL(int) picGetInterrupt(PPDMDEVINS pDevIns, uint32_t *puTagSrc);
-PDMBOTHCBDECL(int) picIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
-PDMBOTHCBDECL(int) picIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
-PDMBOTHCBDECL(int) picIOPortElcrRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
-PDMBOTHCBDECL(int) picIOPortElcrWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
-
-RT_C_DECLS_END
-#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
-
-
-/*
- * QEMU 8259 interrupt controller emulation
- *
- * Copyright (c) 2003-2004 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
/* debug PIC */
#define DEBUG_PIC
/*#define DEBUG_IRQ_COUNT*/
-typedef struct PicState {
- uint8_t last_irr; /* edge detection */
- uint8_t irr; /* interrupt request register */
- uint8_t imr; /* interrupt mask register */
- uint8_t isr; /* interrupt service register */
- uint8_t priority_add; /* highest irq priority */
+/**
+ * The instance data of one (1) PIC.
+ */
+typedef struct PICSTATE
+{
+ uint8_t last_irr; /**< edge detection */
+ uint8_t irr; /**< interrupt request register */
+ uint8_t imr; /**< interrupt mask register */
+ uint8_t isr; /**< interrupt service register */
+ uint8_t priority_add; /**< highest irq priority */
uint8_t irq_base;
uint8_t read_reg_select;
uint8_t poll;
@@ -104,8 +94,8 @@ typedef struct PicState {
uint8_t auto_eoi;
uint8_t rotate_on_auto_eoi;
uint8_t special_fully_nested_mode;
- uint8_t init4; /* true if 4 byte init */
- uint8_t elcr; /* PIIX edge/trigger selection*/
+ uint8_t init4; /**< true if 4 byte init */
+ uint8_t elcr; /**< PIIX edge/trigger selection*/
uint8_t elcr_mask;
/** Pointer to the device instance, R3 Ptr. */
PPDMDEVINSR3 pDevInsR3;
@@ -113,19 +103,23 @@ typedef struct PicState {
PPDMDEVINSR0 pDevInsR0;
/** Pointer to the device instance, RC Ptr. */
PPDMDEVINSRC pDevInsRC;
- RTRCPTR Alignment0; /**< Structure size alignment. */
+ /** The PIC index (0 or 1). */
+ uint8_t idxPic;
+ uint8_t abAlignment0[3]; /**< Alignment padding. */
/** The IRQ tags and source IDs for each (tracing purposes). */
uint32_t auTags[8];
+} PICSTATE;
+/** Pointer to the state of one PIC. */
+typedef PICSTATE *PPICSTATE;
-} PicState;
/**
- * A PIC device instance data.
+ * The whole PIC device instance data.
*/
typedef struct DEVPIC
{
/** The two interrupt controllers. */
- PicState aPics[2];
+ PICSTATE aPics[2];
/** Pointer to the device instance - R3 Ptr. */
PPDMDEVINSR3 pDevInsR3;
/** Pointer to the PIC R3 helpers. */
@@ -148,128 +142,140 @@ typedef struct DEVPIC
STAMCOUNTER StatClearedActiveMasterIRQ;
STAMCOUNTER StatClearedActiveSlaveIRQ;
#endif
-} DEVPIC, *PDEVPIC;
+} DEVPIC;
+/** Pointer to the whole PIC instance data. */
+typedef DEVPIC *PDEVPIC;
#ifndef VBOX_DEVICE_STRUCT_TESTCASE
#ifdef LOG_ENABLED
-static inline void DumpPICState(PicState *s, const char *szFn)
+DECLINLINE(void) DumpPICState(PPICSTATE pPic, const char *pszFn)
{
- PDEVPIC pThis = PDMINS_2_DATA(s->CTX_SUFF(pDevIns), PDEVPIC);
+ PDEVPIC pThis = PDMINS_2_DATA(pPic->CTX_SUFF(pDevIns), PDEVPIC);
Log2(("%s: pic%d: elcr=%x last_irr=%x irr=%x imr=%x isr=%x irq_base=%x\n",
- szFn, (&pThis->aPics[0] == s) ? 0 : 1,
- s->elcr, s->last_irr, s->irr, s->imr, s->isr, s->irq_base));
+ pszFn, (&pThis->aPics[0] == pPic) ? 0 : 1,
+ pPic->elcr, pPic->last_irr, pPic->irr, pPic->imr, pPic->isr, pPic->irq_base));
}
#else
# define DumpPICState(pThis, szFn) do { } while (0)
#endif
/* set irq level. If an edge is detected, then the IRR is set to 1 */
-static inline void pic_set_irq1(PicState *s, int irq, int level, uint32_t uTagSrc)
+DECLINLINE(void) pic_set_irq1(PPICSTATE pPic, int irq, int level, uint32_t uTagSrc)
{
- int mask;
Log(("pic_set_irq1: irq=%d level=%d\n", irq, level));
- mask = 1 << irq;
- if (s->elcr & mask) {
+ int mask = 1 << irq;
+ if (pPic->elcr & mask)
+ {
/* level triggered */
- if (level) {
- Log2(("pic_set_irq1(ls) irr=%d irrnew=%d\n", s->irr, s->irr | mask));
- s->irr |= mask;
- s->last_irr |= mask;
- } else {
- Log2(("pic_set_irq1(lc) irr=%d irrnew=%d\n", s->irr, s->irr & ~mask));
- s->irr &= ~mask;
- s->last_irr &= ~mask;
+ if (level)
+ {
+ Log2(("pic_set_irq1(ls) irr=%d irrnew=%d\n", pPic->irr, pPic->irr | mask));
+ pPic->irr |= mask;
+ pPic->last_irr |= mask;
+ }
+ else
+ {
+ Log2(("pic_set_irq1(lc) irr=%d irrnew=%d\n", pPic->irr, pPic->irr & ~mask));
+ pPic->irr &= ~mask;
+ pPic->last_irr &= ~mask;
}
- } else {
+ }
+ else
+ {
/* edge triggered */
- if (level) {
- if ((s->last_irr & mask) == 0)
+ if (level)
+ {
+ if ((pPic->last_irr & mask) == 0)
{
- Log2(("pic_set_irq1 irr=%x last_irr=%x\n", s->irr | mask, s->last_irr));
- s->irr |= mask;
+ Log2(("pic_set_irq1 irr=%x last_irr=%x\n", pPic->irr | mask, pPic->last_irr));
+ pPic->irr |= mask;
}
- s->last_irr |= mask;
- } else {
- s->irr &= ~mask;
- s->last_irr &= ~mask;
+ pPic->last_irr |= mask;
+ }
+ else
+ {
+ pPic->irr &= ~mask;
+ pPic->last_irr &= ~mask;
}
}
/* Save the tag. */
if (level)
{
- if (!s->auTags[irq])
- s->auTags[irq] = uTagSrc;
+ if (!pPic->auTags[irq])
+ pPic->auTags[irq] = uTagSrc;
else
- s->auTags[irq] |= RT_BIT_32(31);
+ pPic->auTags[irq] |= RT_BIT_32(31);
}
- DumpPICState(s, "pic_set_irq1");
+ DumpPICState(pPic, "pic_set_irq1");
}
/* return the highest priority found in mask (highest = smallest
number). Return 8 if no irq */
-static inline int get_priority(PicState *s, int mask)
+DECLINLINE(int) get_priority(PPICSTATE pPic, int mask)
{
int priority;
if (mask == 0)
return 8;
priority = 0;
- while ((mask & (1 << ((priority + s->priority_add) & 7))) == 0)
+ while ((mask & (1 << ((priority + pPic->priority_add) & 7))) == 0)
priority++;
return priority;
}
/* return the pic wanted interrupt. return -1 if none */
-static int pic_get_irq(PicState *s)
+static int pic_get_irq(PPICSTATE pPic)
{
- PicState *pics = &(PDMINS_2_DATA(s->CTX_SUFF(pDevIns), PDEVPIC))->aPics[0];
int mask, cur_priority, priority;
- Log(("pic_get_irq%d: mask=%x\n", (s == pics) ? 0 : 1, s->irr & ~s->imr));
- DumpPICState(s, "pic_get_irq");
+ Log(("pic_get_irq%d: mask=%x\n", pPic->idxPic, pPic->irr & ~pPic->imr));
+ DumpPICState(pPic, "pic_get_irq");
- mask = s->irr & ~s->imr;
- priority = get_priority(s, mask);
+ mask = pPic->irr & ~pPic->imr;
+ priority = get_priority(pPic, mask);
Log(("pic_get_irq: priority=%x\n", priority));
if (priority == 8)
return -1;
/* compute current priority. If special fully nested mode on the
master, the IRQ coming from the slave is not taken into account
for the priority computation. */
- mask = s->isr;
- if (s->special_fully_nested_mode && s == &pics[0])
+ mask = pPic->isr;
+ if (pPic->special_fully_nested_mode && pPic->idxPic == 0)
mask &= ~(1 << 2);
- cur_priority = get_priority(s, mask);
- Log(("pic_get_irq%d: cur_priority=%x pending=%d\n", (s == pics) ? 0 : 1, cur_priority, (priority == 8) ? -1 : (priority + s->priority_add) & 7));
- if (priority < cur_priority) {
+ cur_priority = get_priority(pPic, mask);
+ Log(("pic_get_irq%d: cur_priority=%x pending=%d\n", pPic->idxPic,
+ cur_priority, (priority == 8) ? -1 : (priority + pPic->priority_add) & 7));
+ if (priority < cur_priority)
+ {
/* higher priority found: an irq should be generated */
- return (priority + s->priority_add) & 7;
- } else {
- return -1;
+ return (priority + pPic->priority_add) & 7;
}
+ return -1;
}
/* raise irq to CPU if necessary. must be called every time the active
irq may change */
static int pic_update_irq(PDEVPIC pThis)
{
- PicState *pics = &pThis->aPics[0];
int irq2, irq;
/* first look at slave pic */
- irq2 = pic_get_irq(&pics[1]);
+ irq2 = pic_get_irq(&pThis->aPics[1]);
Log(("pic_update_irq irq2=%d\n", irq2));
- if (irq2 >= 0) {
+ if (irq2 >= 0)
+ {
/* if irq request by slave pic, signal master PIC */
- pic_set_irq1(&pics[0], 2, 1, pics[1].auTags[irq2]);
- } else {
+ pic_set_irq1(&pThis->aPics[0], 2, 1, pThis->aPics[1].auTags[irq2]);
+ }
+ else
+ {
/* If not, clear the IR on the master PIC. */
- pic_set_irq1(&pics[0], 2, 0, 0 /*uTagSrc*/);
+ pic_set_irq1(&pThis->aPics[0], 2, 0, 0 /*uTagSrc*/);
}
/* look at requested irq */
- irq = pic_get_irq(&pics[0]);
+ irq = pic_get_irq(&pThis->aPics[0]);
if (irq >= 0)
{
/* If irq 2 is pending on the master pic, then there must be one pending on the slave pic too! Otherwise we'll get
@@ -278,12 +284,8 @@ static int pic_update_irq(PDEVPIC pThis)
if (irq != 2 || irq2 != -1)
{
#if defined(DEBUG_PIC)
- int i;
- for(i = 0; i < 2; i++) {
- Log(("pic%d: imr=%x irr=%x padd=%d\n",
- i, pics[i].imr, pics[i].irr,
- pics[i].priority_add));
- }
+ for (int i = 0; i < 2; i++)
+ Log(("pic%d: imr=%x irr=%x padd=%d\n", i, pThis->aPics[i].imr, pThis->aPics[i].irr, pThis->aPics[i].priority_add));
Log(("pic: cpu_interrupt\n"));
#endif
pThis->CTX_SUFF(pPicHlp)->pfnSetInterruptFF(pThis->CTX_SUFF(pDevIns));
@@ -297,8 +299,8 @@ static int pic_update_irq(PDEVPIC pThis)
/* if this was the only pending irq, then we must clear the interrupt ff flag */
pThis->CTX_SUFF(pPicHlp)->pfnClearInterruptFF(pThis->CTX_SUFF(pDevIns));
- /** @note Is this correct? */
- pics[0].irr &= ~(1 << 2);
+ /** @todo Is this correct? */
+ pThis->aPics[0].irr &= ~(1 << 2);
/* Call ourselves again just in case other interrupts are pending */
return pic_update_irq(pThis);
@@ -315,10 +317,10 @@ static int pic_update_irq(PDEVPIC pThis)
}
/** @note if an interrupt line state changes from unmasked to masked, then it must be deactivated when currently pending! */
-static void pic_update_imr(PDEVPIC pThis, PicState *s, uint8_t val)
+static void pic_update_imr(PDEVPIC pThis, PPICSTATE pPic, uint8_t val)
{
int irq, intno;
- PicState *pActivePIC;
+ PPICSTATE pActivePIC;
/* Query the current pending irq, if any. */
pActivePIC = &pThis->aPics[0];
@@ -331,7 +333,8 @@ static void pic_update_imr(PDEVPIC pThis, PicState *s, uint8_t val)
}
/* Update IMR */
- s->imr = val;
+ Log(("pic_update_imr: pic%u %#x -> %#x\n", pPic->idxPic, pPic->imr, val));
+ pPic->imr = val;
/* If an interrupt is pending and now masked, then clear the FF flag. */
if ( irq >= 0
@@ -393,19 +396,21 @@ PDMBOTHCBDECL(void) picSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t
/* acknowledge interrupt 'irq' */
-static inline void pic_intack(PicState *s, int irq)
+DECLINLINE(void) pic_intack(PPICSTATE pPic, int irq)
{
- if (s->auto_eoi) {
- if (s->rotate_on_auto_eoi)
- s->priority_add = (irq + 1) & 7;
- } else {
- s->isr |= (1 << irq);
+ if (pPic->auto_eoi)
+ {
+ if (pPic->rotate_on_auto_eoi)
+ pPic->priority_add = (irq + 1) & 7;
}
+ else
+ pPic->isr |= (1 << irq);
+
/* We don't clear a level sensitive interrupt here */
- if (!(s->elcr & (1 << irq)))
+ if (!(pPic->elcr & (1 << irq)))
{
- Log2(("pic_intack: irr=%x irrnew=%x\n", s->irr, s->irr & ~(1 << irq)));
- s->irr &= ~(1 << irq);
+ Log2(("pic_intack: irr=%x irrnew=%x\n", pPic->irr, pPic->irr & ~(1 << irq)));
+ pPic->irr &= ~(1 << irq);
}
}
@@ -435,9 +440,8 @@ PDMBOTHCBDECL(int) picGetInterrupt(PPDMDEVINS pDevIns, uint32_t *puTagSrc)
if (irq == 2)
{
irq2 = pic_get_irq(&pThis->aPics[1]);
- if (irq2 >= 0) {
+ if (irq2 >= 0)
pic_intack(&pThis->aPics[1], irq2);
- }
else
{
/* Interrupt went away or is now masked. */
@@ -473,165 +477,172 @@ PDMBOTHCBDECL(int) picGetInterrupt(PPDMDEVINS pDevIns, uint32_t *puTagSrc)
return intno;
}
-static void pic_reset(PicState *s)
+static void pic_reset(PPICSTATE pPic)
{
- PPDMDEVINSR3 pDevInsR3 = s->pDevInsR3;
- PPDMDEVINSR0 pDevInsR0 = s->pDevInsR0;
- PPDMDEVINSRC pDevInsRC = s->pDevInsRC;
- int elcr_mask = s->elcr_mask;
- int elcr = s->elcr;
-
- memset(s, 0, sizeof(PicState));
-
- s->elcr = elcr;
- s->elcr_mask = elcr_mask;
- s->pDevInsRC = pDevInsRC;
- s->pDevInsR0 = pDevInsR0;
- s->pDevInsR3 = pDevInsR3;
+ PPDMDEVINSR3 pDevInsR3 = pPic->pDevInsR3;
+ PPDMDEVINSR0 pDevInsR0 = pPic->pDevInsR0;
+ PPDMDEVINSRC pDevInsRC = pPic->pDevInsRC;
+ int elcr_mask = pPic->elcr_mask;
+ int elcr = pPic->elcr;
+
+ memset(pPic, 0, sizeof(*pPic));
+
+ pPic->elcr = elcr;
+ pPic->elcr_mask = elcr_mask;
+ pPic->pDevInsRC = pDevInsRC;
+ pPic->pDevInsR0 = pDevInsR0;
+ pPic->pDevInsR3 = pDevInsR3;
}
-static int pic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+static int pic_ioport_write(PDEVPIC pThis, PPICSTATE pPic, uint32_t addr, uint32_t val)
{
- PicState *s = (PicState*)opaque;
- PDEVPIC pThis = PDMINS_2_DATA(s->CTX_SUFF(pDevIns), PDEVPIC);
int rc = VINF_SUCCESS;
- int priority, cmd, irq;
+ int irq;
Log(("pic_write: addr=0x%02x val=0x%02x\n", addr, val));
addr &= 1;
- if (addr == 0) {
- if (val & 0x10) {
+ if (addr == 0)
+ {
+ if (val & 0x10)
+ {
/* init */
- pic_reset(s);
+ pic_reset(pPic);
/* deassert a pending interrupt */
pThis->CTX_SUFF(pPicHlp)->pfnClearInterruptFF(pThis->CTX_SUFF(pDevIns));
- s->init_state = 1;
- s->init4 = val & 1;
+ pPic->init_state = 1;
+ pPic->init4 = val & 1;
if (val & 0x02)
AssertReleaseMsgFailed(("single mode not supported"));
if (val & 0x08)
if (pThis->cRelLogEntries++ < 64)
LogRel(("pic_write: Level sensitive IRQ setting ignored.\n"));
- } else if (val & 0x08) {
+ }
+ else if (val & 0x08)
+ {
if (val & 0x04)
- s->poll = 1;
+ pPic->poll = 1;
if (val & 0x02)
- s->read_reg_select = val & 1;
+ pPic->read_reg_select = val & 1;
if (val & 0x40)
- s->special_mask = (val >> 5) & 1;
- } else {
- cmd = val >> 5;
- switch(cmd) {
- case 0:
- case 4:
- s->rotate_on_auto_eoi = cmd >> 2;
- break;
- case 1: /* end of interrupt */
- case 5:
+ pPic->special_mask = (val >> 5) & 1;
+ }
+ else
+ {
+ int cmd = val >> 5;
+ switch (cmd)
{
- priority = get_priority(s, s->isr);
- if (priority != 8) {
- irq = (priority + s->priority_add) & 7;
- Log(("pic_write: EOI prio=%d irq=%d\n", priority, irq));
- s->isr &= ~(1 << irq);
- if (cmd == 5)
- s->priority_add = (irq + 1) & 7;
+ case 0:
+ case 4:
+ pPic->rotate_on_auto_eoi = cmd >> 2;
+ break;
+ case 1: /* end of interrupt */
+ case 5:
+ {
+ int priority = get_priority(pPic, pPic->isr);
+ if (priority != 8) {
+ irq = (priority + pPic->priority_add) & 7;
+ Log(("pic_write: EOI prio=%d irq=%d\n", priority, irq));
+ pPic->isr &= ~(1 << irq);
+ if (cmd == 5)
+ pPic->priority_add = (irq + 1) & 7;
+ rc = pic_update_irq(pThis);
+ Assert(rc == VINF_SUCCESS);
+ DumpPICState(pPic, "eoi");
+ }
+ break;
+ }
+ case 3:
+ {
+ irq = val & 7;
+ Log(("pic_write: EOI2 for irq %d\n", irq));
+ pPic->isr &= ~(1 << irq);
rc = pic_update_irq(pThis);
Assert(rc == VINF_SUCCESS);
- DumpPICState(s, "eoi");
+ DumpPICState(pPic, "eoi2");
+ break;
}
- break;
+ case 6:
+ {
+ pPic->priority_add = (val + 1) & 7;
+ Log(("pic_write: lowest priority %d (highest %d)\n", val & 7, pPic->priority_add));
+ rc = pic_update_irq(pThis);
+ Assert(rc == VINF_SUCCESS);
+ break;
+ }
+ case 7:
+ {
+ irq = val & 7;
+ Log(("pic_write: EOI3 for irq %d\n", irq));
+ pPic->isr &= ~(1 << irq);
+ pPic->priority_add = (irq + 1) & 7;
+ rc = pic_update_irq(pThis);
+ Assert(rc == VINF_SUCCESS);
+ DumpPICState(pPic, "eoi3");
+ break;
+ }
+ default:
+ /* no operation */
+ break;
}
- case 3:
- {
- irq = val & 7;
- Log(("pic_write: EOI2 for irq %d\n", irq));
- s->isr &= ~(1 << irq);
+ }
+ }
+ else
+ {
+ switch (pPic->init_state)
+ {
+ case 0:
+ /* normal mode */
+ pic_update_imr(pThis, pPic, val);
+
rc = pic_update_irq(pThis);
Assert(rc == VINF_SUCCESS);
- DumpPICState(s, "eoi2");
break;
- }
- case 6:
- {
- s->priority_add = (val + 1) & 7;
- Log(("pic_write: lowest priority %d (highest %d)\n", val & 7, s->priority_add));
- rc = pic_update_irq(pThis);
- Assert(rc == VINF_SUCCESS);
+ case 1:
+ pPic->irq_base = val & 0xf8;
+ pPic->init_state = 2;
+ Log(("pic_write: set irq base to %x\n", pPic->irq_base));
break;
- }
- case 7:
- {
- irq = val & 7;
- Log(("pic_write: EOI3 for irq %d\n", irq));
- s->isr &= ~(1 << irq);
- s->priority_add = (irq + 1) & 7;
- rc = pic_update_irq(pThis);
- Assert(rc == VINF_SUCCESS);
- DumpPICState(s, "eoi3");
+ case 2:
+ if (pPic->init4)
+ pPic->init_state = 3;
+ else
+ pPic->init_state = 0;
break;
- }
- default:
- /* no operation */
+ case 3:
+ pPic->special_fully_nested_mode = (val >> 4) & 1;
+ pPic->auto_eoi = (val >> 1) & 1;
+ pPic->init_state = 0;
+ Log(("pic_write: special_fully_nested_mode=%d auto_eoi=%d\n", pPic->special_fully_nested_mode, pPic->auto_eoi));
break;
- }
- }
- } else {
- switch(s->init_state) {
- case 0:
- {
- /* normal mode */
- pic_update_imr(pThis, s, val);
-
- rc = pic_update_irq(pThis);
- Assert(rc == VINF_SUCCESS);
- break;
- }
- case 1:
- s->irq_base = val & 0xf8;
- s->init_state = 2;
- Log(("pic_write: set irq base to %x\n", s->irq_base));
- break;
- case 2:
- if (s->init4) {
- s->init_state = 3;
- } else {
- s->init_state = 0;
- }
- break;
- case 3:
- s->special_fully_nested_mode = (val >> 4) & 1;
- s->auto_eoi = (val >> 1) & 1;
- s->init_state = 0;
- Log(("pic_write: special_fully_nested_mode=%d auto_eoi=%d\n", s->special_fully_nested_mode, s->auto_eoi));
- break;
}
}
return rc;
}
-static uint32_t pic_poll_read (PicState *s, uint32_t addr1)
+static uint32_t pic_poll_read(PPICSTATE pPic, uint32_t addr1)
{
- PDEVPIC pThis = PDMINS_2_DATA(s->CTX_SUFF(pDevIns), PDEVPIC);
- PicState *pics = &pThis->aPics[0];
- int ret;
+ PDEVPIC pThis = RT_FROM_MEMBER(pPic, DEVPIC, aPics[pPic->idxPic]);
- ret = pic_get_irq(s);
- if (ret >= 0) {
- if (addr1 >> 7) {
+ int ret = pic_get_irq(pPic);
+ if (ret >= 0)
+ {
+ if (addr1 >> 7)
+ {
Log2(("pic_poll_read: clear slave irq (isr)\n"));
- pics[0].isr &= ~(1 << 2);
- pics[0].irr &= ~(1 << 2);
+ pThis->aPics[0].isr &= ~(1 << 2);
+ pThis->aPics[0].irr &= ~(1 << 2);
}
Log2(("pic_poll_read: clear irq %d (isr)\n", ret));
- s->irr &= ~(1 << ret);
- s->isr &= ~(1 << ret);
+ pPic->irr &= ~(1 << ret);
+ pPic->isr &= ~(1 << ret);
if (addr1 >> 7 || ret != 2)
pic_update_irq(pThis);
- } else {
+ }
+ else
+ {
ret = 0;
pic_update_irq(pThis);
}
@@ -640,9 +651,8 @@ static uint32_t pic_poll_read (PicState *s, uint32_t addr1)
}
-static uint32_t pic_ioport_read(void *opaque, uint32_t addr1, int *pRC)
+static uint32_t pic_ioport_read(PPICSTATE pPic, uint32_t addr1, int *pRC)
{
- PicState *s = (PicState*)opaque;
unsigned int addr;
int ret;
@@ -650,18 +660,22 @@ static uint32_t pic_ioport_read(void *opaque, uint32_t addr1, int *pRC)
addr = addr1;
addr &= 1;
- if (s->poll) {
- ret = pic_poll_read(s, addr1);
- s->poll = 0;
- } else {
- if (addr == 0) {
- if (s->read_reg_select)
- ret = s->isr;
+ if (pPic->poll)
+ {
+ ret = pic_poll_read(pPic, addr1);
+ pPic->poll = 0;
+ }
+ else
+ {
+ if (addr == 0)
+ {
+ if (pPic->read_reg_select)
+ ret = pPic->isr;
else
- ret = s->irr;
- } else {
- ret = s->imr;
+ ret = pPic->irr;
}
+ else
+ ret = pPic->imr;
}
Log(("pic_read: addr=0x%02x val=0x%02x\n", addr1, ret));
return ret;
@@ -669,18 +683,10 @@ static uint32_t pic_ioport_read(void *opaque, uint32_t addr1, int *pRC)
-/* -=-=-=-=-=- wrappers / stuff -=-=-=-=-=- */
+/* -=-=-=-=-=- I/O ports -=-=-=-=-=- */
/**
- * Port I/O Handler for IN operations.
- *
- * @returns VBox status code.
- *
- * @param pDevIns The device instance.
- * @param pvUser User argument - pointer to the PIC in question.
- * @param uPort Port number used for the IN operation.
- * @param pu32 Where to store the result.
- * @param cb Number of bytes read.
+ * @callback_method_impl{FNIOMIOPORTIN}
*/
PDMBOTHCBDECL(int) picIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
{
@@ -699,16 +705,9 @@ PDMBOTHCBDECL(int) picIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port
return VERR_IOM_IOPORT_UNUSED;
}
+
/**
- * Port I/O Handler for OUT operations.
- *
- * @returns VBox status code.
- *
- * @param pDevIns The device instance.
- * @param pvUser User argument - pointer to the PIC in question.
- * @param uPort Port number used for the IN operation.
- * @param u32 The value to output.
- * @param cb The value size in bytes.
+ * @callback_method_impl{FNIOMIOPORTOUT}
*/
PDMBOTHCBDECL(int) picIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
{
@@ -721,7 +720,7 @@ PDMBOTHCBDECL(int) picIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Por
{
int rc;
PIC_LOCK(pThis, VINF_IOM_R3_IOPORT_WRITE);
- rc = pic_ioport_write(&pThis->aPics[iPic], Port, u32);
+ rc = pic_ioport_write(pThis, &pThis->aPics[iPic], Port, u32);
PIC_UNLOCK(pThis);
return rc;
}
@@ -730,23 +729,15 @@ PDMBOTHCBDECL(int) picIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Por
/**
- * Port I/O Handler for IN operations.
- *
- * @returns VBox status code.
- *
- * @param pDevIns The device instance.
- * @param pvUser User argument - pointer to the PIC in question.
- * @param uPort Port number used for the IN operation.
- * @param pu32 Where to store the result.
- * @param cb Number of bytes read.
+ * @callback_method_impl{FNIOMIOPORTIN, ELCR}
*/
PDMBOTHCBDECL(int) picIOPortElcrRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
{
if (cb == 1)
{
- PicState *s = (PicState*)pvUser;
+ PPICSTATE pPic = (PPICSTATE)pvUser;
PIC_LOCK(PDMINS_2_DATA(pDevIns, PDEVPIC), VINF_IOM_R3_IOPORT_READ);
- *pu32 = s->elcr;
+ *pu32 = pPic->elcr;
PIC_UNLOCK(PDMINS_2_DATA(pDevIns, PDEVPIC));
return VINF_SUCCESS;
}
@@ -754,24 +745,17 @@ PDMBOTHCBDECL(int) picIOPortElcrRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT
return VERR_IOM_IOPORT_UNUSED;
}
+
/**
- * Port I/O Handler for OUT operations.
- *
- * @returns VBox status code.
- *
- * @param pDevIns The device instance.
- * @param pvUser User argument - pointer to the PIC in question.
- * @param uPort Port number used for the IN operation.
- * @param u32 The value to output.
- * @param cb The value size in bytes.
+ * @callback_method_impl{FNIOMIOPORTOUT, ELCR}
*/
PDMBOTHCBDECL(int) picIOPortElcrWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
{
if (cb == 1)
{
- PicState *s = (PicState*)pvUser;
+ PPICSTATE pPic = (PPICSTATE)pvUser;
PIC_LOCK(PDMINS_2_DATA(pDevIns, PDEVPIC), VINF_IOM_R3_IOPORT_WRITE);
- s->elcr = u32 & s->elcr_mask;
+ pPic->elcr = u32 & pPic->elcr_mask;
PIC_UNLOCK(PDMINS_2_DATA(pDevIns, PDEVPIC));
}
NOREF(Port);
@@ -782,11 +766,7 @@ PDMBOTHCBDECL(int) picIOPortElcrWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT
#ifdef IN_RING3
/**
- * PIC status info callback.
- *
- * @param pDevIns The device instance.
- * @param pHlp The output helpers.
- * @param pszArgs The arguments.
+ * @callback_method_impl{FNDBGFINFOHANDLERDEV}
*/
static DECLCALLBACK(void) picInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
{
@@ -798,7 +778,7 @@ static DECLCALLBACK(void) picInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const
*/
for (int i = 0; i < 2; i++)
{
- PicState *pPic = &pThis->aPics[i];
+ PPICSTATE pPic = &pThis->aPics[i];
pHlp->pfnPrintf(pHlp, "PIC%d:\n", i);
pHlp->pfnPrintf(pHlp, " IMR :%02x ISR :%02x IRR :%02x LIRR:%02x\n",
@@ -814,48 +794,41 @@ static DECLCALLBACK(void) picInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const
}
}
+
+/* -=-=-=-=-=- Saved State -=-=-=-=-=- */
+
/**
- * Saves a state of the programmable interrupt controller device.
- *
- * @returns VBox status code.
- * @param pDevIns The device instance.
- * @param pSSMHandle The handle to save the state to.
+ * @callback_method_impl{FNSSMDEVSAVEEXEC}
*/
-static DECLCALLBACK(int) picSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
+static DECLCALLBACK(int) picSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
{
PDEVPIC pThis = PDMINS_2_DATA(pDevIns, PDEVPIC);
for (unsigned i = 0; i < RT_ELEMENTS(pThis->aPics); i++)
{
- SSMR3PutU8(pSSMHandle, pThis->aPics[i].last_irr);
- SSMR3PutU8(pSSMHandle, pThis->aPics[i].irr);
- SSMR3PutU8(pSSMHandle, pThis->aPics[i].imr);
- SSMR3PutU8(pSSMHandle, pThis->aPics[i].isr);
- SSMR3PutU8(pSSMHandle, pThis->aPics[i].priority_add);
- SSMR3PutU8(pSSMHandle, pThis->aPics[i].irq_base);
- SSMR3PutU8(pSSMHandle, pThis->aPics[i].read_reg_select);
- SSMR3PutU8(pSSMHandle, pThis->aPics[i].poll);
- SSMR3PutU8(pSSMHandle, pThis->aPics[i].special_mask);
- SSMR3PutU8(pSSMHandle, pThis->aPics[i].init_state);
- SSMR3PutU8(pSSMHandle, pThis->aPics[i].auto_eoi);
- SSMR3PutU8(pSSMHandle, pThis->aPics[i].rotate_on_auto_eoi);
- SSMR3PutU8(pSSMHandle, pThis->aPics[i].special_fully_nested_mode);
- SSMR3PutU8(pSSMHandle, pThis->aPics[i].init4);
- SSMR3PutU8(pSSMHandle, pThis->aPics[i].elcr);
+ SSMR3PutU8(pSSM, pThis->aPics[i].last_irr);
+ SSMR3PutU8(pSSM, pThis->aPics[i].irr);
+ SSMR3PutU8(pSSM, pThis->aPics[i].imr);
+ SSMR3PutU8(pSSM, pThis->aPics[i].isr);
+ SSMR3PutU8(pSSM, pThis->aPics[i].priority_add);
+ SSMR3PutU8(pSSM, pThis->aPics[i].irq_base);
+ SSMR3PutU8(pSSM, pThis->aPics[i].read_reg_select);
+ SSMR3PutU8(pSSM, pThis->aPics[i].poll);
+ SSMR3PutU8(pSSM, pThis->aPics[i].special_mask);
+ SSMR3PutU8(pSSM, pThis->aPics[i].init_state);
+ SSMR3PutU8(pSSM, pThis->aPics[i].auto_eoi);
+ SSMR3PutU8(pSSM, pThis->aPics[i].rotate_on_auto_eoi);
+ SSMR3PutU8(pSSM, pThis->aPics[i].special_fully_nested_mode);
+ SSMR3PutU8(pSSM, pThis->aPics[i].init4);
+ SSMR3PutU8(pSSM, pThis->aPics[i].elcr);
}
return VINF_SUCCESS;
}
/**
- * Loads a saved programmable interrupt controller device state.
- *
- * @returns VBox status code.
- * @param pDevIns The device instance.
- * @param pSSMHandle The handle to the saved state.
- * @param uVersion The data unit version number.
- * @param uPass The data pass.
+ * @callback_method_impl{FNSSMDEVLOADEXEC}
*/
-static DECLCALLBACK(int) picLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle, uint32_t uVersion, uint32_t uPass)
+static DECLCALLBACK(int) picLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
{
PDEVPIC pThis = PDMINS_2_DATA(pDevIns, PDEVPIC);
@@ -865,33 +838,30 @@ static DECLCALLBACK(int) picLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle,
for (unsigned i = 0; i < RT_ELEMENTS(pThis->aPics); i++)
{
- SSMR3GetU8(pSSMHandle, &pThis->aPics[i].last_irr);
- SSMR3GetU8(pSSMHandle, &pThis->aPics[i].irr);
- SSMR3GetU8(pSSMHandle, &pThis->aPics[i].imr);
- SSMR3GetU8(pSSMHandle, &pThis->aPics[i].isr);
- SSMR3GetU8(pSSMHandle, &pThis->aPics[i].priority_add);
- SSMR3GetU8(pSSMHandle, &pThis->aPics[i].irq_base);
- SSMR3GetU8(pSSMHandle, &pThis->aPics[i].read_reg_select);
- SSMR3GetU8(pSSMHandle, &pThis->aPics[i].poll);
- SSMR3GetU8(pSSMHandle, &pThis->aPics[i].special_mask);
- SSMR3GetU8(pSSMHandle, &pThis->aPics[i].init_state);
- SSMR3GetU8(pSSMHandle, &pThis->aPics[i].auto_eoi);
- SSMR3GetU8(pSSMHandle, &pThis->aPics[i].rotate_on_auto_eoi);
- SSMR3GetU8(pSSMHandle, &pThis->aPics[i].special_fully_nested_mode);
- SSMR3GetU8(pSSMHandle, &pThis->aPics[i].init4);
- SSMR3GetU8(pSSMHandle, &pThis->aPics[i].elcr);
+ SSMR3GetU8(pSSM, &pThis->aPics[i].last_irr);
+ SSMR3GetU8(pSSM, &pThis->aPics[i].irr);
+ SSMR3GetU8(pSSM, &pThis->aPics[i].imr);
+ SSMR3GetU8(pSSM, &pThis->aPics[i].isr);
+ SSMR3GetU8(pSSM, &pThis->aPics[i].priority_add);
+ SSMR3GetU8(pSSM, &pThis->aPics[i].irq_base);
+ SSMR3GetU8(pSSM, &pThis->aPics[i].read_reg_select);
+ SSMR3GetU8(pSSM, &pThis->aPics[i].poll);
+ SSMR3GetU8(pSSM, &pThis->aPics[i].special_mask);
+ SSMR3GetU8(pSSM, &pThis->aPics[i].init_state);
+ SSMR3GetU8(pSSM, &pThis->aPics[i].auto_eoi);
+ SSMR3GetU8(pSSM, &pThis->aPics[i].rotate_on_auto_eoi);
+ SSMR3GetU8(pSSM, &pThis->aPics[i].special_fully_nested_mode);
+ SSMR3GetU8(pSSM, &pThis->aPics[i].init4);
+ SSMR3GetU8(pSSM, &pThis->aPics[i].elcr);
}
return VINF_SUCCESS;
}
-/* -=-=-=-=-=- real code -=-=-=-=-=- */
+/* -=-=-=-=-=- PDMDEVREG -=-=-=-=-=- */
/**
- * Reset notification.
- *
- * @returns VBox status.
- * @param pDevIns The device instance data.
+ * @interface_method_impl{PDMDEVREG,pfnReset}
*/
static DECLCALLBACK(void) picReset(PPDMDEVINS pDevIns)
{
@@ -908,7 +878,7 @@ static DECLCALLBACK(void) picReset(PPDMDEVINS pDevIns)
/**
- * @copydoc FNPDMDEVRELOCATE
+ * @interface_method_impl{PDMDEVREG,pfnRelocate}
*/
static DECLCALLBACK(void) picRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
{
@@ -923,12 +893,11 @@ static DECLCALLBACK(void) picRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
/**
- * @copydoc FNPDMDEVCONSTRUCT
+ * @interface_method_impl{PDMDEVREG,pfnConstruct}
*/
static DECLCALLBACK(int) picConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
{
PDEVPIC pThis = PDMINS_2_DATA(pDevIns, PDEVPIC);
- PDMPICREG PicReg;
int rc;
bool fGCEnabled;
bool fR0Enabled;
@@ -967,11 +936,14 @@ static DECLCALLBACK(int) picConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMN
pThis->aPics[1].pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
pThis->aPics[0].pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
pThis->aPics[1].pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
- pThis->cRelLogEntries = 0;
+ pThis->aPics[0].idxPic = 0;
+ pThis->aPics[1].idxPic = 1;
+ pThis->cRelLogEntries = 0;
/*
* Register us as the PIC with PDM.
*/
+ PDMPICREG PicReg;
PicReg.u32Version = PDM_PICREG_VERSION;
PicReg.pfnSetIrqR3 = picSetIrq;
PicReg.pfnGetInterruptR3 = picGetInterrupt;
@@ -1133,7 +1105,7 @@ const PDMDEVREG g_DeviceI8259 =
NULL,
/* pfnRelocate */
picRelocate,
- /* pfnIOCtl */
+ /* pfnMemSetup */
NULL,
/* pfnPowerOn */
NULL,