VirtualBox

Ignore:
Timestamp:
Feb 22, 2013 1:57:19 PM (12 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
83919
Message:

DevPIC.cpp: Cleanups.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/PC/DevPIC.cpp

    r44528 r44801  
    1414 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
    1515 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
    16  */
    17 
    18 /*******************************************************************************
    19 *   Header Files                                                               *
    20 *******************************************************************************/
    21 #define LOG_GROUP LOG_GROUP_DEV_PIC
    22 #include <VBox/vmm/pdmdev.h>
    23 #include <VBox/log.h>
    24 #include <iprt/assert.h>
    25 #include <iprt/string.h>
    26 
    27 #include "VBoxDD.h"
    28 
    29 
    30 /*******************************************************************************
    31 *   Defined Constants And Macros                                               *
    32 *******************************************************************************/
    33 /** @def PIC_LOCK
    34  * Acquires the PDM lock. This is a NOP if locking is disabled. */
    35 /** @def PIC_UNLOCK
    36  * Releases the PDM lock. This is a NOP if locking is disabled. */
    37 #define PIC_LOCK(pThis, rc) \
    38     do { \
    39         int rc2 = (pThis)->CTX_SUFF(pPicHlp)->pfnLock((pThis)->CTX_SUFF(pDevIns), rc); \
    40         if (rc2 != VINF_SUCCESS) \
    41             return rc2; \
    42     } while (0)
    43 #define PIC_UNLOCK(pThis) \
    44     (pThis)->CTX_SUFF(pPicHlp)->pfnUnlock((pThis)->CTX_SUFF(pDevIns))
    45 
    46 
    47 #ifndef VBOX_DEVICE_STRUCT_TESTCASE
    48 /*******************************************************************************
    49 *   Internal Functions                                                         *
    50 *******************************************************************************/
    51 RT_C_DECLS_BEGIN
    52 
    53 PDMBOTHCBDECL(void) picSetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc);
    54 PDMBOTHCBDECL(int) picGetInterrupt(PPDMDEVINS pDevIns, uint32_t *puTagSrc);
    55 PDMBOTHCBDECL(int) picIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
    56 PDMBOTHCBDECL(int) picIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
    57 PDMBOTHCBDECL(int) picIOPortElcrRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
    58 PDMBOTHCBDECL(int) picIOPortElcrWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
    59 
    60 RT_C_DECLS_END
    61 #endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
    62 
    63 
    64 /*
     16 * -------------------------------------------------------------------
     17 *
     18 * This code is based on:
     19 *
    6520 * QEMU 8259 interrupt controller emulation
    6621 *
     
    8439 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    8540 * THE SOFTWARE.
    86  */
     41 *
     42 */
     43
     44
     45/*******************************************************************************
     46*   Header Files                                                               *
     47*******************************************************************************/
     48#define LOG_GROUP LOG_GROUP_DEV_PIC
     49#include <VBox/vmm/pdmdev.h>
     50#include <VBox/log.h>
     51#include <iprt/assert.h>
     52#include <iprt/string.h>
     53
     54#include "VBoxDD.h"
     55
     56
     57/*******************************************************************************
     58*   Defined Constants And Macros                                               *
     59*******************************************************************************/
     60/** @def PIC_LOCK
     61 * Acquires the PDM lock. This is a NOP if locking is disabled. */
     62/** @def PIC_UNLOCK
     63 * Releases the PDM lock. This is a NOP if locking is disabled. */
     64#define PIC_LOCK(pThis, rc) \
     65    do { \
     66        int rc2 = (pThis)->CTX_SUFF(pPicHlp)->pfnLock((pThis)->CTX_SUFF(pDevIns), rc); \
     67        if (rc2 != VINF_SUCCESS) \
     68            return rc2; \
     69    } while (0)
     70#define PIC_UNLOCK(pThis) \
     71    (pThis)->CTX_SUFF(pPicHlp)->pfnUnlock((pThis)->CTX_SUFF(pDevIns))
     72
    8773
    8874/* debug PIC */
     
    9177/*#define DEBUG_IRQ_COUNT*/
    9278
    93 typedef struct PicState {
    94     uint8_t last_irr; /* edge detection */
    95     uint8_t irr; /* interrupt request register */
    96     uint8_t imr; /* interrupt mask register */
    97     uint8_t isr; /* interrupt service register */
    98     uint8_t priority_add; /* highest irq priority */
     79/**
     80 * The instance data of one (1) PIC.
     81 */
     82typedef struct PICSTATE
     83{
     84    uint8_t last_irr;       /**< edge detection */
     85    uint8_t irr;            /**< interrupt request register */
     86    uint8_t imr;            /**< interrupt mask register */
     87    uint8_t isr;            /**< interrupt service register */
     88    uint8_t priority_add;   /**< highest irq priority */
    9989    uint8_t irq_base;
    10090    uint8_t read_reg_select;
     
    10595    uint8_t rotate_on_auto_eoi;
    10696    uint8_t special_fully_nested_mode;
    107     uint8_t init4; /* true if 4 byte init */
    108     uint8_t elcr; /* PIIX edge/trigger selection*/
     97    uint8_t init4;          /**< true if 4 byte init */
     98    uint8_t elcr;           /**< PIIX edge/trigger selection*/
    10999    uint8_t elcr_mask;
    110100    /** Pointer to the device instance, R3 Ptr. */
     
    114104    /** Pointer to the device instance, RC Ptr. */
    115105    PPDMDEVINSRC    pDevInsRC;
    116     RTRCPTR         Alignment0; /**< Structure size alignment. */
     106    /** The PIC index (0 or 1). */
     107    uint8_t         idxPic;
     108    uint8_t         abAlignment0[3]; /**< Alignment padding. */
    117109    /** The IRQ tags and source IDs for each (tracing purposes). */
    118110    uint32_t        auTags[8];
    119 
    120 } PicState;
    121 
    122 /**
    123  * A PIC device instance data.
     111} PICSTATE;
     112/** Pointer to the state of one PIC. */
     113typedef PICSTATE *PPICSTATE;
     114
     115
     116/**
     117 * The whole PIC device instance data.
    124118 */
    125119typedef struct DEVPIC
    126120{
    127121    /** The two interrupt controllers. */
    128     PicState                aPics[2];
     122    PICSTATE                aPics[2];
    129123    /** Pointer to the device instance - R3 Ptr. */
    130124    PPDMDEVINSR3            pDevInsR3;
     
    149143    STAMCOUNTER             StatClearedActiveSlaveIRQ;
    150144#endif
    151 } DEVPIC, *PDEVPIC;
     145} DEVPIC;
     146/** Pointer to the whole PIC instance data. */
     147typedef DEVPIC *PDEVPIC;
    152148
    153149
    154150#ifndef VBOX_DEVICE_STRUCT_TESTCASE
    155151#ifdef LOG_ENABLED
    156 static inline void DumpPICState(PicState *s, const char *szFn)
    157 {
    158     PDEVPIC pThis = PDMINS_2_DATA(s->CTX_SUFF(pDevIns), PDEVPIC);
     152DECLINLINE(void) DumpPICState(PPICSTATE pPic, const char *pszFn)
     153{
     154    PDEVPIC pThis = PDMINS_2_DATA(pPic->CTX_SUFF(pDevIns), PDEVPIC);
    159155
    160156    Log2(("%s: pic%d: elcr=%x last_irr=%x irr=%x imr=%x isr=%x irq_base=%x\n",
    161         szFn, (&pThis->aPics[0] == s) ? 0 : 1,
    162           s->elcr, s->last_irr, s->irr, s->imr, s->isr, s->irq_base));
     157          pszFn, (&pThis->aPics[0] == pPic) ? 0 : 1,
     158          pPic->elcr, pPic->last_irr, pPic->irr, pPic->imr, pPic->isr, pPic->irq_base));
    163159}
    164160#else
     
    167163
    168164/* set irq level. If an edge is detected, then the IRR is set to 1 */
    169 static inline void pic_set_irq1(PicState *s, int irq, int level, uint32_t uTagSrc)
    170 {
    171     int mask;
     165DECLINLINE(void) pic_set_irq1(PPICSTATE pPic, int irq, int level, uint32_t uTagSrc)
     166{
    172167    Log(("pic_set_irq1: irq=%d level=%d\n", irq, level));
    173     mask = 1 << irq;
    174     if (s->elcr & mask) {
     168    int mask = 1 << irq;
     169    if (pPic->elcr & mask)
     170    {
    175171        /* level triggered */
    176         if (level) {
    177             Log2(("pic_set_irq1(ls) irr=%d irrnew=%d\n", s->irr, s->irr | mask));
    178             s->irr |= mask;
    179             s->last_irr |= mask;
    180         } else {
    181             Log2(("pic_set_irq1(lc) irr=%d irrnew=%d\n", s->irr, s->irr & ~mask));
    182             s->irr &= ~mask;
    183             s->last_irr &= ~mask;
    184         }
    185     } else {
     172        if (level)
     173        {
     174            Log2(("pic_set_irq1(ls) irr=%d irrnew=%d\n", pPic->irr, pPic->irr | mask));
     175            pPic->irr |= mask;
     176            pPic->last_irr |= mask;
     177        }
     178        else
     179        {
     180            Log2(("pic_set_irq1(lc) irr=%d irrnew=%d\n", pPic->irr, pPic->irr & ~mask));
     181            pPic->irr &= ~mask;
     182            pPic->last_irr &= ~mask;
     183        }
     184    }
     185    else
     186    {
    186187        /* edge triggered */
    187         if (level) {
    188             if ((s->last_irr & mask) == 0)
     188        if (level)
     189        {
     190            if ((pPic->last_irr & mask) == 0)
    189191            {
    190                 Log2(("pic_set_irq1 irr=%x last_irr=%x\n", s->irr | mask, s->last_irr));
    191                 s->irr |= mask;
     192                Log2(("pic_set_irq1 irr=%x last_irr=%x\n", pPic->irr | mask, pPic->last_irr));
     193                pPic->irr |= mask;
    192194            }
    193             s->last_irr |= mask;
    194         } else {
    195             s->irr &= ~mask;
    196             s->last_irr &= ~mask;
     195            pPic->last_irr |= mask;
     196        }
     197        else
     198        {
     199            pPic->irr &= ~mask;
     200            pPic->last_irr &= ~mask;
    197201        }
    198202    }
     
    201205    if (level)
    202206    {
    203         if (!s->auTags[irq])
    204             s->auTags[irq] = uTagSrc;
     207        if (!pPic->auTags[irq])
     208            pPic->auTags[irq] = uTagSrc;
    205209        else
    206             s->auTags[irq] |= RT_BIT_32(31);
    207     }
    208 
    209     DumpPICState(s, "pic_set_irq1");
     210            pPic->auTags[irq] |= RT_BIT_32(31);
     211    }
     212
     213    DumpPICState(pPic, "pic_set_irq1");
    210214}
    211215
    212216/* return the highest priority found in mask (highest = smallest
    213217   number). Return 8 if no irq */
    214 static inline int get_priority(PicState *s, int mask)
     218DECLINLINE(int) get_priority(PPICSTATE pPic, int mask)
    215219{
    216220    int priority;
     
    218222        return 8;
    219223    priority = 0;
    220     while ((mask & (1 << ((priority + s->priority_add) & 7))) == 0)
     224    while ((mask & (1 << ((priority + pPic->priority_add) & 7))) == 0)
    221225        priority++;
    222226    return priority;
     
    224228
    225229/* return the pic wanted interrupt. return -1 if none */
    226 static int pic_get_irq(PicState *s)
    227 {
    228     PicState *pics = &(PDMINS_2_DATA(s->CTX_SUFF(pDevIns), PDEVPIC))->aPics[0];
     230static int pic_get_irq(PPICSTATE pPic)
     231{
    229232    int mask, cur_priority, priority;
    230     Log(("pic_get_irq%d: mask=%x\n", (s == pics) ? 0 : 1, s->irr & ~s->imr));
    231     DumpPICState(s, "pic_get_irq");
    232 
    233     mask = s->irr & ~s->imr;
    234     priority = get_priority(s, mask);
     233    Log(("pic_get_irq%d: mask=%x\n", pPic->idxPic, pPic->irr & ~pPic->imr));
     234    DumpPICState(pPic, "pic_get_irq");
     235
     236    mask = pPic->irr & ~pPic->imr;
     237    priority = get_priority(pPic, mask);
    235238    Log(("pic_get_irq: priority=%x\n", priority));
    236239    if (priority == 8)
     
    239242       master, the IRQ coming from the slave is not taken into account
    240243       for the priority computation. */
    241     mask = s->isr;
    242     if (s->special_fully_nested_mode && s == &pics[0])
     244    mask = pPic->isr;
     245    if (pPic->special_fully_nested_mode && pPic->idxPic == 0)
    243246        mask &= ~(1 << 2);
    244     cur_priority = get_priority(s, mask);
    245     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));
    246     if (priority < cur_priority) {
     247    cur_priority = get_priority(pPic, mask);
     248    Log(("pic_get_irq%d: cur_priority=%x pending=%d\n", pPic->idxPic,
     249         cur_priority, (priority == 8) ? -1 : (priority + pPic->priority_add) & 7));
     250    if (priority < cur_priority)
     251    {
    247252        /* higher priority found: an irq should be generated */
    248         return (priority + s->priority_add) & 7;
    249     } else {
    250         return -1;
    251     }
     253        return (priority + pPic->priority_add) & 7;
     254    }
     255    return -1;
    252256}
    253257
     
    256260static int pic_update_irq(PDEVPIC pThis)
    257261{
    258     PicState *pics = &pThis->aPics[0];
    259262    int irq2, irq;
    260263
    261264    /* first look at slave pic */
    262     irq2 = pic_get_irq(&pics[1]);
     265    irq2 = pic_get_irq(&pThis->aPics[1]);
    263266    Log(("pic_update_irq irq2=%d\n", irq2));
    264     if (irq2 >= 0) {
     267    if (irq2 >= 0)
     268    {
    265269        /* if irq request by slave pic, signal master PIC */
    266         pic_set_irq1(&pics[0], 2, 1, pics[1].auTags[irq2]);
    267     } else {
     270        pic_set_irq1(&pThis->aPics[0], 2, 1, pThis->aPics[1].auTags[irq2]);
     271    }
     272    else
     273    {
    268274        /* If not, clear the IR on the master PIC. */
    269         pic_set_irq1(&pics[0], 2, 0, 0 /*uTagSrc*/);
     275        pic_set_irq1(&pThis->aPics[0], 2, 0, 0 /*uTagSrc*/);
    270276    }
    271277    /* look at requested irq */
    272     irq = pic_get_irq(&pics[0]);
     278    irq = pic_get_irq(&pThis->aPics[0]);
    273279    if (irq >= 0)
    274280    {
     
    279285        {
    280286#if defined(DEBUG_PIC)
    281             int i;
    282             for(i = 0; i < 2; i++) {
    283                 Log(("pic%d: imr=%x irr=%x padd=%d\n",
    284                     i, pics[i].imr, pics[i].irr,
    285                     pics[i].priority_add));
    286             }
     287            for (int i = 0; i < 2; i++)
     288                Log(("pic%d: imr=%x irr=%x padd=%d\n", i, pThis->aPics[i].imr, pThis->aPics[i].irr, pThis->aPics[i].priority_add));
    287289            Log(("pic: cpu_interrupt\n"));
    288290#endif
     
    298300            pThis->CTX_SUFF(pPicHlp)->pfnClearInterruptFF(pThis->CTX_SUFF(pDevIns));
    299301
    300             /** @note Is this correct? */
    301             pics[0].irr &= ~(1 << 2);
     302            /** @todo Is this correct? */
     303            pThis->aPics[0].irr &= ~(1 << 2);
    302304
    303305            /* Call ourselves again just in case other interrupts are pending */
     
    316318
    317319/** @note if an interrupt line state changes from unmasked to masked, then it must be deactivated when currently pending! */
    318 static void pic_update_imr(PDEVPIC pThis, PicState *s, uint8_t val)
     320static void pic_update_imr(PDEVPIC pThis, PPICSTATE pPic, uint8_t val)
    319321{
    320322    int       irq, intno;
    321     PicState *pActivePIC;
     323    PPICSTATE pActivePIC;
    322324
    323325    /* Query the current pending irq, if any. */
     
    332334
    333335    /* Update IMR */
    334     s->imr = val;
     336    pPic->imr = val;
    335337
    336338    /* If an interrupt is pending and now masked, then clear the FF flag. */
     
    394396
    395397/* acknowledge interrupt 'irq' */
    396 static inline void pic_intack(PicState *s, int irq)
    397 {
    398     if (s->auto_eoi) {
    399         if (s->rotate_on_auto_eoi)
    400             s->priority_add = (irq + 1) & 7;
    401     } else {
    402         s->isr |= (1 << irq);
    403     }
     398DECLINLINE(void) pic_intack(PPICSTATE pPic, int irq)
     399{
     400    if (pPic->auto_eoi)
     401    {
     402        if (pPic->rotate_on_auto_eoi)
     403            pPic->priority_add = (irq + 1) & 7;
     404    }
     405    else
     406        pPic->isr |= (1 << irq);
     407
    404408    /* We don't clear a level sensitive interrupt here */
    405     if (!(s->elcr & (1 << irq)))
    406     {
    407         Log2(("pic_intack: irr=%x irrnew=%x\n", s->irr, s->irr & ~(1 << irq)));
    408         s->irr &= ~(1 << irq);
     409    if (!(pPic->elcr & (1 << irq)))
     410    {
     411        Log2(("pic_intack: irr=%x irrnew=%x\n", pPic->irr, pPic->irr & ~(1 << irq)));
     412        pPic->irr &= ~(1 << irq);
    409413    }
    410414}
     
    436440        {
    437441            irq2 = pic_get_irq(&pThis->aPics[1]);
    438             if (irq2 >= 0) {
     442            if (irq2 >= 0)
    439443                pic_intack(&pThis->aPics[1], irq2);
    440             }
    441444            else
    442445            {
     
    474477}
    475478
    476 static void pic_reset(PicState *s)
    477 {
    478     PPDMDEVINSR3 pDevInsR3 = s->pDevInsR3;
    479     PPDMDEVINSR0 pDevInsR0 = s->pDevInsR0;
    480     PPDMDEVINSRC pDevInsRC = s->pDevInsRC;
    481     int elcr_mask = s->elcr_mask;
    482     int elcr = s->elcr;
    483 
    484     memset(s, 0, sizeof(PicState));
    485 
    486     s->elcr = elcr;
    487     s->elcr_mask = elcr_mask;
    488     s->pDevInsRC = pDevInsRC;
    489     s->pDevInsR0 = pDevInsR0;
    490     s->pDevInsR3 = pDevInsR3;
    491 }
    492 
    493 
    494 static int pic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
    495 {
    496     PicState *s = (PicState*)opaque;
    497     PDEVPIC     pThis = PDMINS_2_DATA(s->CTX_SUFF(pDevIns), PDEVPIC);
     479static void pic_reset(PPICSTATE pPic)
     480{
     481    PPDMDEVINSR3 pDevInsR3 = pPic->pDevInsR3;
     482    PPDMDEVINSR0 pDevInsR0 = pPic->pDevInsR0;
     483    PPDMDEVINSRC pDevInsRC = pPic->pDevInsRC;
     484    int elcr_mask = pPic->elcr_mask;
     485    int elcr = pPic->elcr;
     486
     487    memset(pPic, 0, sizeof(*pPic));
     488
     489    pPic->elcr = elcr;
     490    pPic->elcr_mask = elcr_mask;
     491    pPic->pDevInsRC = pDevInsRC;
     492    pPic->pDevInsR0 = pDevInsR0;
     493    pPic->pDevInsR3 = pDevInsR3;
     494}
     495
     496
     497static int pic_ioport_write(PDEVPIC pThis, PPICSTATE pPic, uint32_t addr, uint32_t val)
     498{
    498499    int         rc = VINF_SUCCESS;
    499     int priority, cmd, irq;
     500    int         irq;
    500501
    501502    Log(("pic_write: addr=0x%02x val=0x%02x\n", addr, val));
    502503    addr &= 1;
    503     if (addr == 0) {
    504         if (val & 0x10) {
     504    if (addr == 0)
     505    {
     506        if (val & 0x10)
     507        {
    505508            /* init */
    506             pic_reset(s);
     509            pic_reset(pPic);
    507510            /* deassert a pending interrupt */
    508511            pThis->CTX_SUFF(pPicHlp)->pfnClearInterruptFF(pThis->CTX_SUFF(pDevIns));
    509512
    510             s->init_state = 1;
    511             s->init4 = val & 1;
     513            pPic->init_state = 1;
     514            pPic->init4 = val & 1;
    512515            if (val & 0x02)
    513516                AssertReleaseMsgFailed(("single mode not supported"));
     
    515518                if (pThis->cRelLogEntries++ < 64)
    516519                    LogRel(("pic_write: Level sensitive IRQ setting ignored.\n"));
    517         } else if (val & 0x08) {
     520        }
     521        else if (val & 0x08)
     522        {
    518523            if (val & 0x04)
    519                 s->poll = 1;
     524                pPic->poll = 1;
    520525            if (val & 0x02)
    521                 s->read_reg_select = val & 1;
     526                pPic->read_reg_select = val & 1;
    522527            if (val & 0x40)
    523                 s->special_mask = (val >> 5) & 1;
    524         } else {
    525             cmd = val >> 5;
    526             switch(cmd) {
    527             case 0:
    528             case 4:
    529                 s->rotate_on_auto_eoi = cmd >> 2;
    530                 break;
    531             case 1: /* end of interrupt */
    532             case 5:
     528                pPic->special_mask = (val >> 5) & 1;
     529        }
     530        else
     531        {
     532            int cmd = val >> 5;
     533            switch (cmd)
    533534            {
    534                 priority = get_priority(s, s->isr);
    535                 if (priority != 8) {
    536                     irq = (priority + s->priority_add) & 7;
    537                     Log(("pic_write: EOI prio=%d irq=%d\n", priority, irq));
    538                     s->isr &= ~(1 << irq);
    539                     if (cmd == 5)
    540                         s->priority_add = (irq + 1) & 7;
     535                case 0:
     536                case 4:
     537                    pPic->rotate_on_auto_eoi = cmd >> 2;
     538                    break;
     539                case 1: /* end of interrupt */
     540                case 5:
     541                {
     542                    int priority = get_priority(pPic, pPic->isr);
     543                    if (priority != 8) {
     544                        irq = (priority + pPic->priority_add) & 7;
     545                        Log(("pic_write: EOI prio=%d irq=%d\n", priority, irq));
     546                        pPic->isr &= ~(1 << irq);
     547                        if (cmd == 5)
     548                            pPic->priority_add = (irq + 1) & 7;
     549                        rc = pic_update_irq(pThis);
     550                        Assert(rc == VINF_SUCCESS);
     551                        DumpPICState(pPic, "eoi");
     552                    }
     553                    break;
     554                }
     555                case 3:
     556                {
     557                    irq = val & 7;
     558                    Log(("pic_write: EOI2 for irq %d\n", irq));
     559                    pPic->isr &= ~(1 << irq);
    541560                    rc = pic_update_irq(pThis);
    542561                    Assert(rc == VINF_SUCCESS);
    543                     DumpPICState(s, "eoi");
     562                    DumpPICState(pPic, "eoi2");
     563                    break;
    544564                }
    545                 break;
     565                case 6:
     566                {
     567                    pPic->priority_add = (val + 1) & 7;
     568                    Log(("pic_write: lowest priority %d (highest %d)\n", val & 7, pPic->priority_add));
     569                    rc = pic_update_irq(pThis);
     570                    Assert(rc == VINF_SUCCESS);
     571                    break;
     572                }
     573                case 7:
     574                {
     575                    irq = val & 7;
     576                    Log(("pic_write: EOI3 for irq %d\n", irq));
     577                    pPic->isr &= ~(1 << irq);
     578                    pPic->priority_add = (irq + 1) & 7;
     579                    rc = pic_update_irq(pThis);
     580                    Assert(rc == VINF_SUCCESS);
     581                    DumpPICState(pPic, "eoi3");
     582                    break;
     583                }
     584                default:
     585                    /* no operation */
     586                    break;
    546587            }
    547             case 3:
    548             {
    549                 irq = val & 7;
    550                 Log(("pic_write: EOI2 for irq %d\n", irq));
    551                 s->isr &= ~(1 << irq);
    552                 rc = pic_update_irq(pThis);
    553                 Assert(rc == VINF_SUCCESS);
    554                 DumpPICState(s, "eoi2");
    555                 break;
    556             }
    557             case 6:
    558             {
    559                 s->priority_add = (val + 1) & 7;
    560                 Log(("pic_write: lowest priority %d (highest %d)\n", val & 7, s->priority_add));
     588        }
     589    }
     590    else
     591    {
     592        switch (pPic->init_state)
     593        {
     594            case 0:
     595                /* normal mode */
     596                pic_update_imr(pThis, pPic, val);
     597
    561598                rc = pic_update_irq(pThis);
    562599                Assert(rc == VINF_SUCCESS);
    563600                break;
    564             }
    565             case 7:
    566             {
    567                 irq = val & 7;
    568                 Log(("pic_write: EOI3 for irq %d\n", irq));
    569                 s->isr &= ~(1 << irq);
    570                 s->priority_add = (irq + 1) & 7;
    571                 rc = pic_update_irq(pThis);
    572                 Assert(rc == VINF_SUCCESS);
    573                 DumpPICState(s, "eoi3");
     601            case 1:
     602                pPic->irq_base = val & 0xf8;
     603                pPic->init_state = 2;
     604                Log(("pic_write: set irq base to %x\n", pPic->irq_base));
    574605                break;
    575             }
    576             default:
    577                 /* no operation */
     606            case 2:
     607                if (pPic->init4)
     608                    pPic->init_state = 3;
     609                else
     610                    pPic->init_state = 0;
    578611                break;
    579             }
    580         }
    581     } else {
    582         switch(s->init_state) {
    583         case 0:
    584         {
    585             /* normal mode */
    586             pic_update_imr(pThis, s, val);
    587 
    588             rc = pic_update_irq(pThis);
    589             Assert(rc == VINF_SUCCESS);
    590             break;
    591         }
    592         case 1:
    593             s->irq_base = val & 0xf8;
    594             s->init_state = 2;
    595             Log(("pic_write: set irq base to %x\n", s->irq_base));
    596             break;
    597         case 2:
    598             if (s->init4) {
    599                 s->init_state = 3;
    600             } else {
    601                 s->init_state = 0;
    602             }
    603             break;
    604         case 3:
    605             s->special_fully_nested_mode = (val >> 4) & 1;
    606             s->auto_eoi = (val >> 1) & 1;
    607             s->init_state = 0;
    608             Log(("pic_write: special_fully_nested_mode=%d auto_eoi=%d\n", s->special_fully_nested_mode, s->auto_eoi));
    609             break;
     612            case 3:
     613                pPic->special_fully_nested_mode = (val >> 4) & 1;
     614                pPic->auto_eoi = (val >> 1) & 1;
     615                pPic->init_state = 0;
     616                Log(("pic_write: special_fully_nested_mode=%d auto_eoi=%d\n", pPic->special_fully_nested_mode, pPic->auto_eoi));
     617                break;
    610618        }
    611619    }
     
    614622
    615623
    616 static uint32_t pic_poll_read (PicState *s, uint32_t addr1)
    617 {
    618     PDEVPIC     pThis = PDMINS_2_DATA(s->CTX_SUFF(pDevIns), PDEVPIC);
    619     PicState   *pics = &pThis->aPics[0];
    620     int ret;
    621 
    622     ret = pic_get_irq(s);
    623     if (ret >= 0) {
    624         if (addr1 >> 7) {
     624static uint32_t pic_poll_read(PPICSTATE pPic, uint32_t addr1)
     625{
     626    PDEVPIC pThis = RT_FROM_MEMBER(pPic, DEVPIC, aPics[pPic->idxPic]);
     627
     628    int ret = pic_get_irq(pPic);
     629    if (ret >= 0)
     630    {
     631        if (addr1 >> 7)
     632        {
    625633            Log2(("pic_poll_read: clear slave irq (isr)\n"));
    626             pics[0].isr &= ~(1 << 2);
    627             pics[0].irr &= ~(1 << 2);
     634            pThis->aPics[0].isr &= ~(1 << 2);
     635            pThis->aPics[0].irr &= ~(1 << 2);
    628636        }
    629637        Log2(("pic_poll_read: clear irq %d (isr)\n", ret));
    630         s->irr &= ~(1 << ret);
    631         s->isr &= ~(1 << ret);
     638        pPic->irr &= ~(1 << ret);
     639        pPic->isr &= ~(1 << ret);
    632640        if (addr1 >> 7 || ret != 2)
    633641            pic_update_irq(pThis);
    634     } else {
     642    }
     643    else
     644    {
    635645        ret = 0;
    636646        pic_update_irq(pThis);
     
    641651
    642652
    643 static uint32_t pic_ioport_read(void *opaque, uint32_t addr1, int *pRC)
    644 {
    645     PicState *s = (PicState*)opaque;
     653static uint32_t pic_ioport_read(PPICSTATE pPic, uint32_t addr1, int *pRC)
     654{
    646655    unsigned int addr;
    647656    int ret;
     
    651660    addr = addr1;
    652661    addr &= 1;
    653     if (s->poll) {
    654         ret = pic_poll_read(s, addr1);
    655         s->poll = 0;
    656     } else {
    657         if (addr == 0) {
    658             if (s->read_reg_select)
    659                 ret = s->isr;
     662    if (pPic->poll)
     663    {
     664        ret = pic_poll_read(pPic, addr1);
     665        pPic->poll = 0;
     666    }
     667    else
     668    {
     669        if (addr == 0)
     670        {
     671            if (pPic->read_reg_select)
     672                ret = pPic->isr;
    660673            else
    661                 ret = s->irr;
    662         } else {
    663             ret = s->imr;
    664         }
     674                ret = pPic->irr;
     675        }
     676        else
     677            ret = pPic->imr;
    665678    }
    666679    Log(("pic_read: addr=0x%02x val=0x%02x\n", addr1, ret));
     
    670683
    671684
    672 /* -=-=-=-=-=- wrappers / stuff -=-=-=-=-=- */
    673 
    674 /**
    675  * Port I/O Handler for IN operations.
    676  *
    677  * @returns VBox status code.
    678  *
    679  * @param   pDevIns     The device instance.
    680  * @param   pvUser      User argument - pointer to the PIC in question.
    681  * @param   uPort       Port number used for the IN operation.
    682  * @param   pu32        Where to store the result.
    683  * @param   cb          Number of bytes read.
     685/* -=-=-=-=-=- I/O ports -=-=-=-=-=- */
     686
     687/**
     688 * @callback_method_impl{FNIOMIOPORTIN}
    684689 */
    685690PDMBOTHCBDECL(int) picIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
     
    700705}
    701706
    702 /**
    703  * Port I/O Handler for OUT operations.
    704  *
    705  * @returns VBox status code.
    706  *
    707  * @param   pDevIns     The device instance.
    708  * @param   pvUser      User argument - pointer to the PIC in question.
    709  * @param   uPort       Port number used for the IN operation.
    710  * @param   u32         The value to output.
    711  * @param   cb          The value size in bytes.
     707
     708/**
     709 * @callback_method_impl{FNIOMIOPORTOUT}
    712710 */
    713711PDMBOTHCBDECL(int) picIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
     
    722720        int rc;
    723721        PIC_LOCK(pThis, VINF_IOM_R3_IOPORT_WRITE);
    724         rc = pic_ioport_write(&pThis->aPics[iPic], Port, u32);
     722        rc = pic_ioport_write(pThis, &pThis->aPics[iPic], Port, u32);
    725723        PIC_UNLOCK(pThis);
    726724        return rc;
     
    731729
    732730/**
    733  * Port I/O Handler for IN operations.
    734  *
    735  * @returns VBox status code.
    736  *
    737  * @param   pDevIns     The device instance.
    738  * @param   pvUser      User argument - pointer to the PIC in question.
    739  * @param   uPort       Port number used for the IN operation.
    740  * @param   pu32        Where to store the result.
    741  * @param   cb          Number of bytes read.
     731 * @callback_method_impl{FNIOMIOPORTIN, ELCR}
    742732 */
    743733PDMBOTHCBDECL(int) picIOPortElcrRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
     
    745735    if (cb == 1)
    746736    {
    747         PicState *s = (PicState*)pvUser;
     737        PPICSTATE pPic = (PPICSTATE)pvUser;
    748738        PIC_LOCK(PDMINS_2_DATA(pDevIns, PDEVPIC), VINF_IOM_R3_IOPORT_READ);
    749         *pu32 = s->elcr;
     739        *pu32 = pPic->elcr;
    750740        PIC_UNLOCK(PDMINS_2_DATA(pDevIns, PDEVPIC));
    751741        return VINF_SUCCESS;
     
    755745}
    756746
    757 /**
    758  * Port I/O Handler for OUT operations.
    759  *
    760  * @returns VBox status code.
    761  *
    762  * @param   pDevIns     The device instance.
    763  * @param   pvUser      User argument - pointer to the PIC in question.
    764  * @param   uPort       Port number used for the IN operation.
    765  * @param   u32         The value to output.
    766  * @param   cb          The value size in bytes.
     747
     748/**
     749 * @callback_method_impl{FNIOMIOPORTOUT, ELCR}
    767750 */
    768751PDMBOTHCBDECL(int) picIOPortElcrWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
     
    770753    if (cb == 1)
    771754    {
    772         PicState *s = (PicState*)pvUser;
     755        PPICSTATE pPic = (PPICSTATE)pvUser;
    773756        PIC_LOCK(PDMINS_2_DATA(pDevIns, PDEVPIC), VINF_IOM_R3_IOPORT_WRITE);
    774         s->elcr = u32 & s->elcr_mask;
     757        pPic->elcr = u32 & pPic->elcr_mask;
    775758        PIC_UNLOCK(PDMINS_2_DATA(pDevIns, PDEVPIC));
    776759    }
     
    783766
    784767/**
    785  * PIC status info callback.
    786  *
    787  * @param   pDevIns     The device instance.
    788  * @param   pHlp        The output helpers.
    789  * @param   pszArgs     The arguments.
     768 * @callback_method_impl{FNDBGFINFOHANDLERDEV}
    790769 */
    791770static DECLCALLBACK(void) picInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
     
    799778    for (int i = 0; i < 2; i++)
    800779    {
    801         PicState   *pPic = &pThis->aPics[i];
     780        PPICSTATE pPic = &pThis->aPics[i];
    802781
    803782        pHlp->pfnPrintf(pHlp, "PIC%d:\n", i);
     
    815794}
    816795
    817 /**
    818  * Saves a state of the programmable interrupt controller device.
    819  *
    820  * @returns VBox status code.
    821  * @param   pDevIns     The device instance.
    822  * @param   pSSMHandle  The handle to save the state to.
    823  */
    824 static DECLCALLBACK(int) picSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
     796
     797/* -=-=-=-=-=- Saved State -=-=-=-=-=- */
     798
     799/**
     800 * @callback_method_impl{FNSSMDEVSAVEEXEC}
     801 */
     802static DECLCALLBACK(int) picSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
    825803{
    826804    PDEVPIC     pThis = PDMINS_2_DATA(pDevIns, PDEVPIC);
    827805    for (unsigned i = 0; i < RT_ELEMENTS(pThis->aPics); i++)
    828806    {
    829         SSMR3PutU8(pSSMHandle, pThis->aPics[i].last_irr);
    830         SSMR3PutU8(pSSMHandle, pThis->aPics[i].irr);
    831         SSMR3PutU8(pSSMHandle, pThis->aPics[i].imr);
    832         SSMR3PutU8(pSSMHandle, pThis->aPics[i].isr);
    833         SSMR3PutU8(pSSMHandle, pThis->aPics[i].priority_add);
    834         SSMR3PutU8(pSSMHandle, pThis->aPics[i].irq_base);
    835         SSMR3PutU8(pSSMHandle, pThis->aPics[i].read_reg_select);
    836         SSMR3PutU8(pSSMHandle, pThis->aPics[i].poll);
    837         SSMR3PutU8(pSSMHandle, pThis->aPics[i].special_mask);
    838         SSMR3PutU8(pSSMHandle, pThis->aPics[i].init_state);
    839         SSMR3PutU8(pSSMHandle, pThis->aPics[i].auto_eoi);
    840         SSMR3PutU8(pSSMHandle, pThis->aPics[i].rotate_on_auto_eoi);
    841         SSMR3PutU8(pSSMHandle, pThis->aPics[i].special_fully_nested_mode);
    842         SSMR3PutU8(pSSMHandle, pThis->aPics[i].init4);
    843         SSMR3PutU8(pSSMHandle, pThis->aPics[i].elcr);
     807        SSMR3PutU8(pSSM, pThis->aPics[i].last_irr);
     808        SSMR3PutU8(pSSM, pThis->aPics[i].irr);
     809        SSMR3PutU8(pSSM, pThis->aPics[i].imr);
     810        SSMR3PutU8(pSSM, pThis->aPics[i].isr);
     811        SSMR3PutU8(pSSM, pThis->aPics[i].priority_add);
     812        SSMR3PutU8(pSSM, pThis->aPics[i].irq_base);
     813        SSMR3PutU8(pSSM, pThis->aPics[i].read_reg_select);
     814        SSMR3PutU8(pSSM, pThis->aPics[i].poll);
     815        SSMR3PutU8(pSSM, pThis->aPics[i].special_mask);
     816        SSMR3PutU8(pSSM, pThis->aPics[i].init_state);
     817        SSMR3PutU8(pSSM, pThis->aPics[i].auto_eoi);
     818        SSMR3PutU8(pSSM, pThis->aPics[i].rotate_on_auto_eoi);
     819        SSMR3PutU8(pSSM, pThis->aPics[i].special_fully_nested_mode);
     820        SSMR3PutU8(pSSM, pThis->aPics[i].init4);
     821        SSMR3PutU8(pSSM, pThis->aPics[i].elcr);
    844822    }
    845823    return VINF_SUCCESS;
     
    848826
    849827/**
    850  * Loads a saved programmable interrupt controller device state.
    851  *
    852  * @returns VBox status code.
    853  * @param   pDevIns     The device instance.
    854  * @param   pSSMHandle  The handle to the saved state.
    855  * @param   uVersion    The data unit version number.
    856  * @param   uPass       The data pass.
    857  */
    858 static DECLCALLBACK(int) picLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle, uint32_t uVersion, uint32_t uPass)
     828 * @callback_method_impl{FNSSMDEVLOADEXEC}
     829 */
     830static DECLCALLBACK(int) picLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
    859831{
    860832    PDEVPIC pThis = PDMINS_2_DATA(pDevIns, PDEVPIC);
     
    866838    for (unsigned i = 0; i < RT_ELEMENTS(pThis->aPics); i++)
    867839    {
    868         SSMR3GetU8(pSSMHandle, &pThis->aPics[i].last_irr);
    869         SSMR3GetU8(pSSMHandle, &pThis->aPics[i].irr);
    870         SSMR3GetU8(pSSMHandle, &pThis->aPics[i].imr);
    871         SSMR3GetU8(pSSMHandle, &pThis->aPics[i].isr);
    872         SSMR3GetU8(pSSMHandle, &pThis->aPics[i].priority_add);
    873         SSMR3GetU8(pSSMHandle, &pThis->aPics[i].irq_base);
    874         SSMR3GetU8(pSSMHandle, &pThis->aPics[i].read_reg_select);
    875         SSMR3GetU8(pSSMHandle, &pThis->aPics[i].poll);
    876         SSMR3GetU8(pSSMHandle, &pThis->aPics[i].special_mask);
    877         SSMR3GetU8(pSSMHandle, &pThis->aPics[i].init_state);
    878         SSMR3GetU8(pSSMHandle, &pThis->aPics[i].auto_eoi);
    879         SSMR3GetU8(pSSMHandle, &pThis->aPics[i].rotate_on_auto_eoi);
    880         SSMR3GetU8(pSSMHandle, &pThis->aPics[i].special_fully_nested_mode);
    881         SSMR3GetU8(pSSMHandle, &pThis->aPics[i].init4);
    882         SSMR3GetU8(pSSMHandle, &pThis->aPics[i].elcr);
     840        SSMR3GetU8(pSSM, &pThis->aPics[i].last_irr);
     841        SSMR3GetU8(pSSM, &pThis->aPics[i].irr);
     842        SSMR3GetU8(pSSM, &pThis->aPics[i].imr);
     843        SSMR3GetU8(pSSM, &pThis->aPics[i].isr);
     844        SSMR3GetU8(pSSM, &pThis->aPics[i].priority_add);
     845        SSMR3GetU8(pSSM, &pThis->aPics[i].irq_base);
     846        SSMR3GetU8(pSSM, &pThis->aPics[i].read_reg_select);
     847        SSMR3GetU8(pSSM, &pThis->aPics[i].poll);
     848        SSMR3GetU8(pSSM, &pThis->aPics[i].special_mask);
     849        SSMR3GetU8(pSSM, &pThis->aPics[i].init_state);
     850        SSMR3GetU8(pSSM, &pThis->aPics[i].auto_eoi);
     851        SSMR3GetU8(pSSM, &pThis->aPics[i].rotate_on_auto_eoi);
     852        SSMR3GetU8(pSSM, &pThis->aPics[i].special_fully_nested_mode);
     853        SSMR3GetU8(pSSM, &pThis->aPics[i].init4);
     854        SSMR3GetU8(pSSM, &pThis->aPics[i].elcr);
    883855    }
    884856    return VINF_SUCCESS;
     
    886858
    887859
    888 /* -=-=-=-=-=- real code -=-=-=-=-=- */
    889 
    890 /**
    891  * Reset notification.
    892  *
    893  * @returns VBox status.
    894  * @param   pDevIns     The device instance data.
     860/* -=-=-=-=-=- PDMDEVREG -=-=-=-=-=- */
     861
     862/**
     863 * @interface_method_impl{PDMDEVREG,pfnReset}
    895864 */
    896865static DECLCALLBACK(void)  picReset(PPDMDEVINS pDevIns)
     
    909878
    910879/**
    911  * @copydoc FNPDMDEVRELOCATE
     880 * @interface_method_impl{PDMDEVREG,pfnRelocate}
    912881 */
    913882static DECLCALLBACK(void) picRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
     
    924893
    925894/**
    926  * @copydoc FNPDMDEVCONSTRUCT
     895 * @interface_method_impl{PDMDEVREG,pfnConstruct}
    927896 */
    928897static DECLCALLBACK(int)  picConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
     
    967936    pThis->aPics[0].pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
    968937    pThis->aPics[1].pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
    969     pThis->cRelLogEntries = 0;
     938    pThis->aPics[0].idxPic    = 0;
     939    pThis->aPics[1].idxPic    = 1;
     940    pThis->cRelLogEntries     = 0;
    970941
    971942    /*
Note: See TracChangeset for help on using the changeset viewer.

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