Changeset 37515 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Jun 16, 2011 7:18:56 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/PC/DevPit-i8254.cpp
r37475 r37515 90 90 /** The effective counter mode - if bit 1 is set, bit 2 is ignored. */ 91 91 #define EFFECTIVE_MODE(x) ((x) & ~(((x) & 2) << 1)) 92 93 94 /** 95 * Acquires the PIT lock or returns. 96 */ 97 #define DEVPIT_LOCK_RETURN(a_pThis, a_rcBusy) \ 98 do { \ 99 int rcLock = PDMCritSectEnter(&(a_pThis)->CritSect, (a_rcBusy)); \ 100 if (rcLock != VINF_SUCCESS) \ 101 return rcLock; \ 102 } while (0) 103 104 /** 105 * Releases the PIT lock. 106 */ 107 #define DEVPIT_UNLOCK(a_pThis) \ 108 do { PDMCritSectLeave(&(a_pThis)->CritSect); } while (0) 109 110 111 /** 112 * Acquires the TM lock and PIT lock, returns on failure. 113 */ 114 #define DEVPIT_LOCK_BOTH_RETURN(a_pThis, a_rcBusy) \ 115 do { \ 116 int rcLock = TMTimerLock((a_pThis)->channels[0].CTX_SUFF(pTimer), (a_rcBusy)); \ 117 if (rcLock != VINF_SUCCESS) \ 118 return rcLock; \ 119 rcLock = PDMCritSectEnter(&(a_pThis)->CritSect, (a_rcBusy)); \ 120 if (rcLock != VINF_SUCCESS) \ 121 { \ 122 TMTimerUnlock((a_pThis)->channels[0].CTX_SUFF(pTimer)); \ 123 return rcLock; \ 124 } \ 125 } while (0) 126 127 #if IN_RING3 128 /** 129 * Acquires the TM lock and PIT lock, ignores failures. 130 */ 131 # define DEVPIT_R3_LOCK_BOTH(a_pThis) \ 132 do { \ 133 TMTimerLock((a_pThis)->channels[0].CTX_SUFF(pTimer), VERR_IGNORED); \ 134 PDMCritSectEnter(&(a_pThis)->CritSect, VERR_IGNORED); \ 135 } while (0) 136 #endif /* IN_RING3 */ 137 138 /** 139 * Releases the PIT lock and TM lock. 140 */ 141 #define DEVPIT_UNLOCK_BOTH(a_pThis) \ 142 do { \ 143 PDMCritSectLeave(&(a_pThis)->CritSect); \ 144 TMTimerUnlock((a_pThis)->channels[0].CTX_SUFF(pTimer)); \ 145 } while (0) 146 147 92 148 93 149 /******************************************************************************* … … 141 197 typedef struct PITState 142 198 { 199 /** Channel state. Must come first? */ 143 200 PITChannelState channels[3]; 144 201 /** Speaker data. */ … … 164 221 /** Profiling the timer callback handler. */ 165 222 STAMPROFILEADV StatPITHandler; 223 /** Critical section protecting the state. */ 224 PDMCRITSECT CritSect; 166 225 } PITState; 167 226 … … 171 230 * Internal Functions * 172 231 *******************************************************************************/ 173 RT_C_DECLS_BEGIN174 PDMBOTHCBDECL(int) pitIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);175 PDMBOTHCBDECL(int) pitIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);176 PDMBOTHCBDECL(int) pitIOPortSpeakerRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);177 232 #ifdef IN_RING3 178 PDMBOTHCBDECL(int) pitIOPortSpeakerWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);179 233 static void pit_irq_timer_update(PITChannelState *s, uint64_t current_time, uint64_t now, bool in_timer); 180 234 #endif 181 RT_C_DECLS_END182 183 235 184 236 … … 189 241 int counter; 190 242 PTMTIMER pTimer = s->CTX_SUFF(pPit)->channels[0].CTX_SUFF(pTimer); 243 Assert(TMTimerIsLockOwner(pTimer)); 191 244 192 245 if (EFFECTIVE_MODE(s->mode) == 2) … … 294 347 PTMTIMER pTimer = s->CTX_SUFF(pPit)->channels[0].CTX_SUFF(pTimer); 295 348 Assert((val & 1) == val); 349 Assert(TMTimerIsLockOwner(pTimer)); 296 350 297 351 switch(EFFECTIVE_MODE(s->mode)) { … … 324 378 } 325 379 326 DECLINLINE(void)pit_load_count(PITChannelState *s, int val)380 static void pit_load_count(PITChannelState *s, int val) 327 381 { 328 382 PTMTIMER pTimer = s->CTX_SUFF(pPit)->channels[0].CTX_SUFF(pTimer); 383 Assert(TMTimerIsLockOwner(pTimer)); 384 329 385 if (val == 0) 330 386 val = 0x10000; … … 435 491 PPDMDEVINS pDevIns; 436 492 PTMTIMER pTimer = s->CTX_SUFF(pPit)->channels[0].CTX_SUFF(pTimer); 493 Assert(TMTimerIsLockOwner(pTimer)); 437 494 438 495 if (!s->CTX_SUFF(pTimer)) … … 519 576 int ret; 520 577 PITChannelState *s = &pit->channels[Port]; 578 579 DEVPIT_LOCK_RETURN(pit, VINF_IOM_HC_IOPORT_READ); 521 580 if (s->status_latched) 522 581 { 523 582 s->status_latched = 0; 524 583 ret = s->status; 584 DEVPIT_UNLOCK(pit); 525 585 } 526 586 else if (s->count_latched) … … 542 602 break; 543 603 } 604 DEVPIT_UNLOCK(pit); 544 605 } 545 606 else 546 607 { 608 DEVPIT_UNLOCK(pit); 609 DEVPIT_LOCK_BOTH_RETURN(pit, VINF_IOM_HC_IOPORT_READ); 547 610 int count; 548 611 switch (s->read_state) … … 568 631 break; 569 632 } 633 DEVPIT_UNLOCK_BOTH(pit); 570 634 } 571 635 … … 621 685 { 622 686 /* read-back command */ 687 DEVPIT_LOCK_BOTH_RETURN(pit, VINF_IOM_HC_IOPORT_WRITE); 623 688 for (channel = 0; channel < RT_ELEMENTS(pit->channels); channel++) 624 689 { … … 640 705 } 641 706 } 707 DEVPIT_UNLOCK_BOTH(pit); 642 708 } 643 709 else … … 646 712 unsigned access = (u32 >> 4) & 3; 647 713 if (access == 0) 714 { 715 DEVPIT_LOCK_BOTH_RETURN(pit, VINF_IOM_HC_IOPORT_WRITE); 648 716 pit_latch_count(s); 717 DEVPIT_UNLOCK_BOTH(pit); 718 } 649 719 else 650 720 { 721 DEVPIT_LOCK_RETURN(pit, VINF_IOM_HC_IOPORT_WRITE); 651 722 s->rw_mode = access; 652 723 s->read_state = access; … … 656 727 s->bcd = u32 & 1; 657 728 /* XXX: update irq timer ? */ 729 DEVPIT_UNLOCK(pit); 658 730 } 659 731 } … … 662 734 { 663 735 #ifndef IN_RING3 736 /** @todo There is no reason not to do this in all contexts these 737 * days... */ 664 738 return VINF_IOM_HC_IOPORT_WRITE; 665 739 #else /* IN_RING3 */ … … 668 742 */ 669 743 PITChannelState *s = &pit->channels[Port]; 670 switch(s->write_state) 744 uint8_t const write_state = s->write_state; 745 DEVPIT_LOCK_BOTH_RETURN(pit, VINF_IOM_HC_IOPORT_WRITE); 746 switch (s->write_state) 671 747 { 672 748 default: … … 686 762 break; 687 763 } 764 DEVPIT_UNLOCK_BOTH(pit); 688 765 #endif /* !IN_RING3 */ 689 766 } … … 709 786 { 710 787 PITState *pThis = PDMINS_2_DATA(pDevIns, PITState *); 788 DEVPIT_LOCK_BOTH_RETURN(pThis, VINF_IOM_HC_IOPORT_READ); 789 711 790 const uint64_t u64Now = TMTimerGet(pThis->channels[0].CTX_SUFF(pTimer)); 712 791 Assert(TMTimerGetFreq(pThis->channels[0].CTX_SUFF(pTimer)) == 1000000000); /* lazy bird. */ … … 729 808 const int fTimer2GateStatus = pit_get_gate(pThis, 2); 730 809 810 DEVPIT_UNLOCK_BOTH(pThis); 811 731 812 *pu32 = fTimer2GateStatus 732 813 | (fSpeakerStatus << 1) … … 759 840 { 760 841 PITState *pThis = PDMINS_2_DATA(pDevIns, PITState *); 842 DEVPIT_LOCK_BOTH_RETURN(pThis, VERR_IGNORED); 843 761 844 pThis->speaker_data_on = (u32 >> 1) & 1; 762 845 pit_set_gate(pThis, 2, u32 & 1); 846 847 DEVPIT_UNLOCK_BOTH(pThis); 763 848 } 764 849 Log(("pitIOPortSpeakerWrite: Port=%#x cb=%x u32=%#x\n", Port, cb, u32)); … … 786 871 { 787 872 PITState *pThis = PDMINS_2_DATA(pDevIns, PITState *); 788 unsigned i;873 PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED); 789 874 790 875 /* The config. */ … … 792 877 793 878 /* The state. */ 794 for ( i = 0; i < RT_ELEMENTS(pThis->channels); i++)879 for (unsigned i = 0; i < RT_ELEMENTS(pThis->channels); i++) 795 880 { 796 881 PITChannelState *s = &pThis->channels[i]; … … 822 907 #endif 823 908 824 return SSMR3PutBool(pSSM, pThis->fDisabledByHpet); 909 SSMR3PutBool(pSSM, pThis->fDisabledByHpet); 910 911 PDMCritSectLeave(&pThis->CritSect); 912 return VINF_SUCCESS; 825 913 } 826 914 … … 919 1007 PITChannelState *s = (PITChannelState *)pvUser; 920 1008 STAM_PROFILE_ADV_START(&s->CTX_SUFF(pPit)->StatPITHandler, a); 1009 921 1010 Log(("pitTimer\n")); 1011 Assert(PDMCritSectIsOwner(&PDMINS_2_DATA(pDevIns, PITState *)->CritSect)); 1012 Assert(TMTimerIsLockOwner(pTimer)); 1013 922 1014 pit_irq_timer_update(s, s->next_transition_time, TMTimerGet(pTimer), true); 1015 923 1016 STAM_PROFILE_ADV_STOP(&s->CTX_SUFF(pPit)->StatPITHandler, a); 924 1017 } … … 987 1080 { 988 1081 PITState *pThis = RT_FROM_MEMBER(pInterface, PITState, IHpetLegacyNotify); 1082 PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED); 1083 989 1084 pThis->fDisabledByHpet = fActivated; 1085 1086 PDMCritSectLeave(&pThis->CritSect); 990 1087 } 991 1088 … … 1001 1098 { 1002 1099 PITState *pThis = PDMINS_2_DATA(pDevIns, PITState *); 1003 unsigned i;1004 1100 LogFlow(("pitRelocate: \n")); 1005 1101 1006 for ( i = 0; i < RT_ELEMENTS(pThis->channels); i++)1102 for (unsigned i = 0; i < RT_ELEMENTS(pThis->channels); i++) 1007 1103 { 1008 1104 PITChannelState *pCh = &pThis->channels[i]; … … 1023 1119 { 1024 1120 PITState *pThis = PDMINS_2_DATA(pDevIns, PITState *); 1025 unsigned i;1026 1121 LogFlow(("pitReset: \n")); 1027 1122 1123 DEVPIT_R3_LOCK_BOTH(pThis); 1124 1028 1125 pThis->fDisabledByHpet = false; 1029 1126 1030 for ( i = 0; i < RT_ELEMENTS(pThis->channels); i++)1127 for (unsigned i = 0; i < RT_ELEMENTS(pThis->channels); i++) 1031 1128 { 1032 1129 PITChannelState *s = &pThis->channels[i]; … … 1049 1146 pit_load_count(s, 0); 1050 1147 } 1148 1149 DEVPIT_UNLOCK_BOTH(pThis); 1051 1150 } 1052 1151 … … 1121 1220 1122 1221 /* 1123 * Create timer, register I/O Ports and save state. 1222 * We do our own locking. This must be done before creating timers. 1223 */ 1224 rc = PDMDevHlpCritSectInit(pDevIns, &pThis->CritSect, RT_SRC_POS, "pit"); 1225 AssertRCReturn(rc, rc); 1226 1227 rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns)); 1228 AssertRCReturn(rc, rc); 1229 1230 /* 1231 * Create the timer, make it take our critsect. 1124 1232 */ 1125 1233 rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, pitTimer, &pThis->channels[0], 1126 TMTIMER_FLAGS_ DEFAULT_CRIT_SECT, "i8254 Programmable Interval Timer",1234 TMTIMER_FLAGS_NO_CRIT_SECT, "i8254 Programmable Interval Timer", 1127 1235 &pThis->channels[0].pTimerR3); 1128 1236 if (RT_FAILURE(rc)) … … 1130 1238 pThis->channels[0].pTimerRC = TMTimerRCPtr(pThis->channels[0].pTimerR3); 1131 1239 pThis->channels[0].pTimerR0 = TMTimerR0Ptr(pThis->channels[0].pTimerR3); 1132 1240 rc = TMR3TimerSetCritSect(pThis->channels[0].pTimerR3, &pThis->CritSect); 1241 AssertRCReturn(rc, rc); 1242 1243 /* 1244 * Register I/O ports. 1245 */ 1133 1246 rc = PDMDevHlpIOPortRegister(pDevIns, u16Base, 4, NULL, pitIOPortWrite, pitIOPortRead, NULL, NULL, "i8254 Programmable Interval Timer"); 1134 1247 if (RT_FAILURE(rc)) … … 1160 1273 } 1161 1274 1275 /* 1276 * Saved state. 1277 */ 1162 1278 rc = PDMDevHlpSSMRegister3(pDevIns, PIT_SAVED_STATE_VERSION, sizeof(*pThis), pitLiveExec, pitSaveExec, pitLoadExec); 1163 1279 if (RT_FAILURE(rc))
Note:
See TracChangeset
for help on using the changeset viewer.