Changeset 44801 in vbox for trunk/src/VBox/Devices/PC/DevPIC.cpp
- Timestamp:
- Feb 22, 2013 1:57:19 PM (12 years ago)
- svn:sync-xref-src-repo-rev:
- 83919
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/PC/DevPIC.cpp
r44528 r44801 14 14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the 15 15 * 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 * 65 20 * QEMU 8259 interrupt controller emulation 66 21 * … … 84 39 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 85 40 * 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 87 73 88 74 /* debug PIC */ … … 91 77 /*#define DEBUG_IRQ_COUNT*/ 92 78 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 */ 82 typedef 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 */ 99 89 uint8_t irq_base; 100 90 uint8_t read_reg_select; … … 105 95 uint8_t rotate_on_auto_eoi; 106 96 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*/ 109 99 uint8_t elcr_mask; 110 100 /** Pointer to the device instance, R3 Ptr. */ … … 114 104 /** Pointer to the device instance, RC Ptr. */ 115 105 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. */ 117 109 /** The IRQ tags and source IDs for each (tracing purposes). */ 118 110 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. */ 113 typedef PICSTATE *PPICSTATE; 114 115 116 /** 117 * The whole PIC device instance data. 124 118 */ 125 119 typedef struct DEVPIC 126 120 { 127 121 /** The two interrupt controllers. */ 128 P icStateaPics[2];122 PICSTATE aPics[2]; 129 123 /** Pointer to the device instance - R3 Ptr. */ 130 124 PPDMDEVINSR3 pDevInsR3; … … 149 143 STAMCOUNTER StatClearedActiveSlaveIRQ; 150 144 #endif 151 } DEVPIC, *PDEVPIC; 145 } DEVPIC; 146 /** Pointer to the whole PIC instance data. */ 147 typedef DEVPIC *PDEVPIC; 152 148 153 149 154 150 #ifndef VBOX_DEVICE_STRUCT_TESTCASE 155 151 #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);152 DECLINLINE(void) DumpPICState(PPICSTATE pPic, const char *pszFn) 153 { 154 PDEVPIC pThis = PDMINS_2_DATA(pPic->CTX_SUFF(pDevIns), PDEVPIC); 159 155 160 156 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)); 163 159 } 164 160 #else … … 167 163 168 164 /* 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; 165 DECLINLINE(void) pic_set_irq1(PPICSTATE pPic, int irq, int level, uint32_t uTagSrc) 166 { 172 167 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 { 175 171 /* 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 { 186 187 /* edge triggered */ 187 if (level) { 188 if ((s->last_irr & mask) == 0) 188 if (level) 189 { 190 if ((pPic->last_irr & mask) == 0) 189 191 { 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; 192 194 } 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; 197 201 } 198 202 } … … 201 205 if (level) 202 206 { 203 if (! s->auTags[irq])204 s->auTags[irq] = uTagSrc;207 if (!pPic->auTags[irq]) 208 pPic->auTags[irq] = uTagSrc; 205 209 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"); 210 214 } 211 215 212 216 /* return the highest priority found in mask (highest = smallest 213 217 number). Return 8 if no irq */ 214 static inline int get_priority(PicState *s, int mask)218 DECLINLINE(int) get_priority(PPICSTATE pPic, int mask) 215 219 { 216 220 int priority; … … 218 222 return 8; 219 223 priority = 0; 220 while ((mask & (1 << ((priority + s->priority_add) & 7))) == 0)224 while ((mask & (1 << ((priority + pPic->priority_add) & 7))) == 0) 221 225 priority++; 222 226 return priority; … … 224 228 225 229 /* 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]; 230 static int pic_get_irq(PPICSTATE pPic) 231 { 229 232 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); 235 238 Log(("pic_get_irq: priority=%x\n", priority)); 236 239 if (priority == 8) … … 239 242 master, the IRQ coming from the slave is not taken into account 240 243 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) 243 246 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 { 247 252 /* 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; 252 256 } 253 257 … … 256 260 static int pic_update_irq(PDEVPIC pThis) 257 261 { 258 PicState *pics = &pThis->aPics[0];259 262 int irq2, irq; 260 263 261 264 /* first look at slave pic */ 262 irq2 = pic_get_irq(&p ics[1]);265 irq2 = pic_get_irq(&pThis->aPics[1]); 263 266 Log(("pic_update_irq irq2=%d\n", irq2)); 264 if (irq2 >= 0) { 267 if (irq2 >= 0) 268 { 265 269 /* 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 { 268 274 /* If not, clear the IR on the master PIC. */ 269 pic_set_irq1(&p ics[0], 2, 0, 0 /*uTagSrc*/);275 pic_set_irq1(&pThis->aPics[0], 2, 0, 0 /*uTagSrc*/); 270 276 } 271 277 /* look at requested irq */ 272 irq = pic_get_irq(&p ics[0]);278 irq = pic_get_irq(&pThis->aPics[0]); 273 279 if (irq >= 0) 274 280 { … … 279 285 { 280 286 #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)); 287 289 Log(("pic: cpu_interrupt\n")); 288 290 #endif … … 298 300 pThis->CTX_SUFF(pPicHlp)->pfnClearInterruptFF(pThis->CTX_SUFF(pDevIns)); 299 301 300 /** @ noteIs this correct? */301 p ics[0].irr &= ~(1 << 2);302 /** @todo Is this correct? */ 303 pThis->aPics[0].irr &= ~(1 << 2); 302 304 303 305 /* Call ourselves again just in case other interrupts are pending */ … … 316 318 317 319 /** @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, P icState *s, uint8_t val)320 static void pic_update_imr(PDEVPIC pThis, PPICSTATE pPic, uint8_t val) 319 321 { 320 322 int irq, intno; 321 P icState *pActivePIC;323 PPICSTATE pActivePIC; 322 324 323 325 /* Query the current pending irq, if any. */ … … 332 334 333 335 /* Update IMR */ 334 s->imr = val;336 pPic->imr = val; 335 337 336 338 /* If an interrupt is pending and now masked, then clear the FF flag. */ … … 394 396 395 397 /* 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 } 398 DECLINLINE(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 404 408 /* 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); 409 413 } 410 414 } … … 436 440 { 437 441 irq2 = pic_get_irq(&pThis->aPics[1]); 438 if (irq2 >= 0) {442 if (irq2 >= 0) 439 443 pic_intack(&pThis->aPics[1], irq2); 440 }441 444 else 442 445 { … … 474 477 } 475 478 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); 479 static 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 497 static int pic_ioport_write(PDEVPIC pThis, PPICSTATE pPic, uint32_t addr, uint32_t val) 498 { 498 499 int rc = VINF_SUCCESS; 499 int priority, cmd,irq;500 int irq; 500 501 501 502 Log(("pic_write: addr=0x%02x val=0x%02x\n", addr, val)); 502 503 addr &= 1; 503 if (addr == 0) { 504 if (val & 0x10) { 504 if (addr == 0) 505 { 506 if (val & 0x10) 507 { 505 508 /* init */ 506 pic_reset( s);509 pic_reset(pPic); 507 510 /* deassert a pending interrupt */ 508 511 pThis->CTX_SUFF(pPicHlp)->pfnClearInterruptFF(pThis->CTX_SUFF(pDevIns)); 509 512 510 s->init_state = 1;511 s->init4 = val & 1;513 pPic->init_state = 1; 514 pPic->init4 = val & 1; 512 515 if (val & 0x02) 513 516 AssertReleaseMsgFailed(("single mode not supported")); … … 515 518 if (pThis->cRelLogEntries++ < 64) 516 519 LogRel(("pic_write: Level sensitive IRQ setting ignored.\n")); 517 } else if (val & 0x08) { 520 } 521 else if (val & 0x08) 522 { 518 523 if (val & 0x04) 519 s->poll = 1;524 pPic->poll = 1; 520 525 if (val & 0x02) 521 s->read_reg_select = val & 1;526 pPic->read_reg_select = val & 1; 522 527 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) 533 534 { 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); 541 560 rc = pic_update_irq(pThis); 542 561 Assert(rc == VINF_SUCCESS); 543 DumpPICState(s, "eoi"); 562 DumpPICState(pPic, "eoi2"); 563 break; 544 564 } 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; 546 587 } 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 561 598 rc = pic_update_irq(pThis); 562 599 Assert(rc == VINF_SUCCESS); 563 600 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)); 574 605 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; 578 611 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; 610 618 } 611 619 } … … 614 622 615 623 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){624 static 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 { 625 633 Log2(("pic_poll_read: clear slave irq (isr)\n")); 626 p ics[0].isr &= ~(1 << 2);627 p ics[0].irr &= ~(1 << 2);634 pThis->aPics[0].isr &= ~(1 << 2); 635 pThis->aPics[0].irr &= ~(1 << 2); 628 636 } 629 637 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); 632 640 if (addr1 >> 7 || ret != 2) 633 641 pic_update_irq(pThis); 634 } else { 642 } 643 else 644 { 635 645 ret = 0; 636 646 pic_update_irq(pThis); … … 641 651 642 652 643 static uint32_t pic_ioport_read(void *opaque, uint32_t addr1, int *pRC) 644 { 645 PicState *s = (PicState*)opaque; 653 static uint32_t pic_ioport_read(PPICSTATE pPic, uint32_t addr1, int *pRC) 654 { 646 655 unsigned int addr; 647 656 int ret; … … 651 660 addr = addr1; 652 661 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; 660 673 else 661 ret = s->irr;662 } else {663 ret = s->imr;664 }674 ret = pPic->irr; 675 } 676 else 677 ret = pPic->imr; 665 678 } 666 679 Log(("pic_read: addr=0x%02x val=0x%02x\n", addr1, ret)); … … 670 683 671 684 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} 684 689 */ 685 690 PDMBOTHCBDECL(int) picIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb) … … 700 705 } 701 706 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} 712 710 */ 713 711 PDMBOTHCBDECL(int) picIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) … … 722 720 int rc; 723 721 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); 725 723 PIC_UNLOCK(pThis); 726 724 return rc; … … 731 729 732 730 /** 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} 742 732 */ 743 733 PDMBOTHCBDECL(int) picIOPortElcrRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb) … … 745 735 if (cb == 1) 746 736 { 747 P icState *s = (PicState*)pvUser;737 PPICSTATE pPic = (PPICSTATE)pvUser; 748 738 PIC_LOCK(PDMINS_2_DATA(pDevIns, PDEVPIC), VINF_IOM_R3_IOPORT_READ); 749 *pu32 = s->elcr;739 *pu32 = pPic->elcr; 750 740 PIC_UNLOCK(PDMINS_2_DATA(pDevIns, PDEVPIC)); 751 741 return VINF_SUCCESS; … … 755 745 } 756 746 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} 767 750 */ 768 751 PDMBOTHCBDECL(int) picIOPortElcrWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) … … 770 753 if (cb == 1) 771 754 { 772 P icState *s = (PicState*)pvUser;755 PPICSTATE pPic = (PPICSTATE)pvUser; 773 756 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; 775 758 PIC_UNLOCK(PDMINS_2_DATA(pDevIns, PDEVPIC)); 776 759 } … … 783 766 784 767 /** 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} 790 769 */ 791 770 static DECLCALLBACK(void) picInfo(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs) … … 799 778 for (int i = 0; i < 2; i++) 800 779 { 801 P icState *pPic = &pThis->aPics[i];780 PPICSTATE pPic = &pThis->aPics[i]; 802 781 803 782 pHlp->pfnPrintf(pHlp, "PIC%d:\n", i); … … 815 794 } 816 795 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 */ 802 static DECLCALLBACK(int) picSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) 825 803 { 826 804 PDEVPIC pThis = PDMINS_2_DATA(pDevIns, PDEVPIC); 827 805 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aPics); i++) 828 806 { 829 SSMR3PutU8(pSSM Handle, pThis->aPics[i].last_irr);830 SSMR3PutU8(pSSM Handle, pThis->aPics[i].irr);831 SSMR3PutU8(pSSM Handle, pThis->aPics[i].imr);832 SSMR3PutU8(pSSM Handle, pThis->aPics[i].isr);833 SSMR3PutU8(pSSM Handle, pThis->aPics[i].priority_add);834 SSMR3PutU8(pSSM Handle, pThis->aPics[i].irq_base);835 SSMR3PutU8(pSSM Handle, pThis->aPics[i].read_reg_select);836 SSMR3PutU8(pSSM Handle, pThis->aPics[i].poll);837 SSMR3PutU8(pSSM Handle, pThis->aPics[i].special_mask);838 SSMR3PutU8(pSSM Handle, pThis->aPics[i].init_state);839 SSMR3PutU8(pSSM Handle, pThis->aPics[i].auto_eoi);840 SSMR3PutU8(pSSM Handle, pThis->aPics[i].rotate_on_auto_eoi);841 SSMR3PutU8(pSSM Handle, pThis->aPics[i].special_fully_nested_mode);842 SSMR3PutU8(pSSM Handle, pThis->aPics[i].init4);843 SSMR3PutU8(pSSM Handle, 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); 844 822 } 845 823 return VINF_SUCCESS; … … 848 826 849 827 /** 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 */ 830 static DECLCALLBACK(int) picLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass) 859 831 { 860 832 PDEVPIC pThis = PDMINS_2_DATA(pDevIns, PDEVPIC); … … 866 838 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aPics); i++) 867 839 { 868 SSMR3GetU8(pSSM Handle, &pThis->aPics[i].last_irr);869 SSMR3GetU8(pSSM Handle, &pThis->aPics[i].irr);870 SSMR3GetU8(pSSM Handle, &pThis->aPics[i].imr);871 SSMR3GetU8(pSSM Handle, &pThis->aPics[i].isr);872 SSMR3GetU8(pSSM Handle, &pThis->aPics[i].priority_add);873 SSMR3GetU8(pSSM Handle, &pThis->aPics[i].irq_base);874 SSMR3GetU8(pSSM Handle, &pThis->aPics[i].read_reg_select);875 SSMR3GetU8(pSSM Handle, &pThis->aPics[i].poll);876 SSMR3GetU8(pSSM Handle, &pThis->aPics[i].special_mask);877 SSMR3GetU8(pSSM Handle, &pThis->aPics[i].init_state);878 SSMR3GetU8(pSSM Handle, &pThis->aPics[i].auto_eoi);879 SSMR3GetU8(pSSM Handle, &pThis->aPics[i].rotate_on_auto_eoi);880 SSMR3GetU8(pSSM Handle, &pThis->aPics[i].special_fully_nested_mode);881 SSMR3GetU8(pSSM Handle, &pThis->aPics[i].init4);882 SSMR3GetU8(pSSM Handle, &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); 883 855 } 884 856 return VINF_SUCCESS; … … 886 858 887 859 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} 895 864 */ 896 865 static DECLCALLBACK(void) picReset(PPDMDEVINS pDevIns) … … 909 878 910 879 /** 911 * @ copydoc FNPDMDEVRELOCATE880 * @interface_method_impl{PDMDEVREG,pfnRelocate} 912 881 */ 913 882 static DECLCALLBACK(void) picRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta) … … 924 893 925 894 /** 926 * @ copydoc FNPDMDEVCONSTRUCT895 * @interface_method_impl{PDMDEVREG,pfnConstruct} 927 896 */ 928 897 static DECLCALLBACK(int) picConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg) … … 967 936 pThis->aPics[0].pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); 968 937 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; 970 941 971 942 /*
Note:
See TracChangeset
for help on using the changeset viewer.