VirtualBox

Changeset 37511 in vbox for trunk


Ignore:
Timestamp:
Jun 16, 2011 5:56:26 PM (13 years ago)
Author:
vboxsync
Message:

DevRTC: Moving the code around, adjusting it thowards our style.

File:
1 edited

Legend:

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

    r35353 r37511  
    204204
    205205#ifndef VBOX_DEVICE_STRUCT_TESTCASE
    206 static void rtc_set_time(RTCState *s);
    207 static void rtc_copy_date(RTCState *s);
    208 
    209 static void rtc_timer_update(RTCState *s, int64_t current_time)
     206
     207static void rtc_timer_update(RTCState *pThis, int64_t current_time)
    210208{
    211209    int period_code, period;
     
    213211    uint32_t freq;
    214212
    215     period_code = s->cmos_data[RTC_REG_A] & 0x0f;
    216     if (period_code != 0 &&
    217         (s->cmos_data[RTC_REG_B] & REG_B_PIE)) {
     213    period_code = pThis->cmos_data[RTC_REG_A] & 0x0f;
     214    if (   period_code != 0
     215        && (pThis->cmos_data[RTC_REG_B] & REG_B_PIE))
     216    {
    218217        if (period_code <= 2)
    219218            period_code += 7;
     
    221220        period = 1 << (period_code - 1);
    222221        /* compute 32 kHz clock */
    223         freq = TMTimerGetFreq(s->CTX_SUFF(pPeriodicTimer));
     222        freq = TMTimerGetFreq(pThis->CTX_SUFF(pPeriodicTimer));
    224223
    225224        cur_clock = ASMMultU64ByU32DivByU32(current_time, 32768, freq);
    226225        next_irq_clock = (cur_clock & ~(uint64_t)(period - 1)) + period;
    227         s->next_periodic_time = ASMMultU64ByU32DivByU32(next_irq_clock, freq, 32768) + 1;
    228         TMTimerSet(s->CTX_SUFF(pPeriodicTimer), s->next_periodic_time);
     226        pThis->next_periodic_time = ASMMultU64ByU32DivByU32(next_irq_clock, freq, 32768) + 1;
     227        TMTimerSet(pThis->CTX_SUFF(pPeriodicTimer), pThis->next_periodic_time);
    229228
    230229#ifdef IN_RING3
    231         if (RT_UNLIKELY(period != s->CurLogPeriod))
     230        if (RT_UNLIKELY(period != pThis->CurLogPeriod))
    232231#else
    233         if (RT_UNLIKELY(period != s->CurHintPeriod))
     232        if (RT_UNLIKELY(period != pThis->CurHintPeriod))
    234233#endif
    235234        {
    236235#ifdef IN_RING3
    237             if (s->cRelLogEntries++ < 64)
     236            if (pThis->cRelLogEntries++ < 64)
    238237                LogRel(("RTC: period=%#x (%d) %u Hz\n", period, period, _32K / period));
    239             s->CurLogPeriod  = period;
     238            pThis->CurLogPeriod  = period;
    240239#endif
    241             s->CurHintPeriod = period;
    242             TMTimerSetFrequencyHint(s->CTX_SUFF(pPeriodicTimer), _32K / period);
     240            pThis->CurHintPeriod = period;
     241            TMTimerSetFrequencyHint(pThis->CTX_SUFF(pPeriodicTimer), _32K / period);
    243242        }
    244     } else {
    245         if (TMTimerIsActive(s->CTX_SUFF(pPeriodicTimer)) && s->cRelLogEntries++ < 64)
     243    }
     244    else
     245    {
     246        if (TMTimerIsActive(pThis->CTX_SUFF(pPeriodicTimer)) && pThis->cRelLogEntries++ < 64)
    246247            LogRel(("RTC: stopped the periodic timer\n"));
    247         TMTimerStop(s->CTX_SUFF(pPeriodicTimer));
     248        TMTimerStop(pThis->CTX_SUFF(pPeriodicTimer));
    248249    }
    249250}
     
    255256}
    256257
    257 static void rtc_periodic_timer(void *opaque)
    258 {
    259     RTCState *s = (RTCState*)opaque;
    260 
    261     rtc_timer_update(s, s->next_periodic_time);
    262     s->cmos_data[RTC_REG_C] |= 0xc0;
    263 
    264     rtc_raise_irq(s, 1);
    265 }
    266 
    267 static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
    268 {
    269     RTCState *s = (RTCState*)opaque;
    270     uint32_t bank;
    271 
    272     bank = (addr >> 1) & 1;
    273     if ((addr & 1) == 0) {
    274         s->cmos_index[bank] = (data & 0x7f) + (bank * 128);
    275     } else {
    276         Log(("CMOS: Write bank %d idx %#04x: %#04x (old %#04x)\n", bank,
    277              s->cmos_index[bank], data, s->cmos_data[s->cmos_index[bank]]));
    278         switch(s->cmos_index[bank]) {
    279         case RTC_SECONDS_ALARM:
    280         case RTC_MINUTES_ALARM:
    281         case RTC_HOURS_ALARM:
    282             s->cmos_data[s->cmos_index[0]] = data;
    283             break;
    284         case RTC_SECONDS:
    285         case RTC_MINUTES:
    286         case RTC_HOURS:
    287         case RTC_DAY_OF_WEEK:
    288         case RTC_DAY_OF_MONTH:
    289         case RTC_MONTH:
    290         case RTC_YEAR:
    291             s->cmos_data[s->cmos_index[0]] = data;
    292             /* if in set mode, do not update the time */
    293             if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
    294                 rtc_set_time(s);
    295             }
    296             break;
    297         case RTC_REG_A:
    298             /* UIP bit is read only */
    299             s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
    300                 (s->cmos_data[RTC_REG_A] & REG_A_UIP);
    301             rtc_timer_update(s, TMTimerGet(s->CTX_SUFF(pPeriodicTimer)));
    302             break;
    303         case RTC_REG_B:
    304             if (data & REG_B_SET) {
    305                 /* set mode: reset UIP mode */
    306                 s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
    307 #if 0 /* This is probably wrong as it breaks changing the time/date in OS/2. */
    308                 data &= ~REG_B_UIE;
    309 #endif
    310             } else {
    311                 /* if disabling set mode, update the time */
    312                 if (s->cmos_data[RTC_REG_B] & REG_B_SET) {
    313                     rtc_set_time(s);
    314                 }
    315             }
    316             s->cmos_data[RTC_REG_B] = data;
    317             rtc_timer_update(s, TMTimerGet(s->CTX_SUFF(pPeriodicTimer)));
    318             break;
    319         case RTC_REG_C:
    320         case RTC_REG_D:
    321             /* cannot write to them */
    322             break;
    323         default:
    324             s->cmos_data[s->cmos_index[bank]] = data;
    325             break;
    326         }
    327     }
    328 }
    329 
    330 static inline int to_bcd(RTCState *s, int a)
    331 {
    332     if (s->cmos_data[RTC_REG_B] & 0x04) {
     258
     259DECLINLINE(int) to_bcd(RTCState *pThis, int a)
     260{
     261    if (pThis->cmos_data[RTC_REG_B] & 0x04) {
    333262        return a;
    334263    } else {
     
    337266}
    338267
    339 static inline int from_bcd(RTCState *s, int a)
    340 {
    341     if (s->cmos_data[RTC_REG_B] & 0x04) {
     268DECLINLINE(int) from_bcd(RTCState *pThis, int a)
     269{
     270    if (pThis->cmos_data[RTC_REG_B] & 0x04) {
    342271        return a;
    343272    } else {
     
    346275}
    347276
    348 static void rtc_set_time(RTCState *s)
    349 {
    350     struct my_tm *tm = &s->current_tm;
    351 
    352     tm->tm_sec = from_bcd(s, s->cmos_data[RTC_SECONDS]);
    353     tm->tm_min = from_bcd(s, s->cmos_data[RTC_MINUTES]);
    354     tm->tm_hour = from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
    355     if (!(s->cmos_data[RTC_REG_B] & 0x02) &&
    356         (s->cmos_data[RTC_HOURS] & 0x80)) {
     277static void rtc_set_time(RTCState *pThis)
     278{
     279    struct my_tm *tm = &pThis->current_tm;
     280
     281    tm->tm_sec  = from_bcd(pThis, pThis->cmos_data[RTC_SECONDS]);
     282    tm->tm_min  = from_bcd(pThis, pThis->cmos_data[RTC_MINUTES]);
     283    tm->tm_hour = from_bcd(pThis, pThis->cmos_data[RTC_HOURS] & 0x7f);
     284    if (   !(pThis->cmos_data[RTC_REG_B] & 0x02)
     285        && (pThis->cmos_data[RTC_HOURS] & 0x80))
    357286        tm->tm_hour += 12;
    358     }
    359     tm->tm_wday = from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]);
    360     tm->tm_mday = from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]);
    361     tm->tm_mon = from_bcd(s, s->cmos_data[RTC_MONTH]) - 1;
    362     tm->tm_year = from_bcd(s, s->cmos_data[RTC_YEAR]) + 100;
    363 }
    364 
    365 static void rtc_copy_date(RTCState *s)
    366 {
    367     const struct my_tm *tm = &s->current_tm;
    368 
    369     s->cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec);
    370     s->cmos_data[RTC_MINUTES] = to_bcd(s, tm->tm_min);
    371     if (s->cmos_data[RTC_REG_B] & 0x02) {
    372         /* 24 hour format */
    373         s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour);
    374     } else {
    375         /* 12 hour format */
    376         s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour % 12);
    377         if (tm->tm_hour >= 12)
    378             s->cmos_data[RTC_HOURS] |= 0x80;
    379     }
    380     s->cmos_data[RTC_DAY_OF_WEEK] = to_bcd(s, tm->tm_wday);
    381     s->cmos_data[RTC_DAY_OF_MONTH] = to_bcd(s, tm->tm_mday);
    382     s->cmos_data[RTC_MONTH] = to_bcd(s, tm->tm_mon + 1);
    383     s->cmos_data[RTC_YEAR] = to_bcd(s, tm->tm_year % 100);
    384 }
     287    tm->tm_wday = from_bcd(pThis, pThis->cmos_data[RTC_DAY_OF_WEEK]);
     288    tm->tm_mday = from_bcd(pThis, pThis->cmos_data[RTC_DAY_OF_MONTH]);
     289    tm->tm_mon  = from_bcd(pThis, pThis->cmos_data[RTC_MONTH]) - 1;
     290    tm->tm_year = from_bcd(pThis, pThis->cmos_data[RTC_YEAR]) + 100;
     291}
     292
     293
     294/* -=-=-=-=-=- I/O Port -=-=-=-=-=- */
     295
     296/**
     297 * Port I/O Handler for IN operations.
     298 *
     299 * @returns VBox status code.
     300 *
     301 * @param   pDevIns     The device instance.
     302 * @param   pvUser      User argument - ignored.
     303 * @param   uPort       Port number used for the IN operation.
     304 * @param   pu32        Where to store the result.
     305 * @param   cb          Number of bytes read.
     306 */
     307PDMBOTHCBDECL(int) rtcIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
     308{
     309    NOREF(pvUser);
     310    if (cb != 1)
     311        return VERR_IOM_IOPORT_UNUSED;
     312
     313    RTCState *pThis = PDMINS_2_DATA(pDevIns, RTCState *);
     314    if ((Port & 1) == 0)
     315        *pu32 = 0xff;
     316    else
     317    {
     318        unsigned bank = (Port >> 1) & 1;
     319        switch (pThis->cmos_index[bank])
     320        {
     321            case RTC_SECONDS:
     322            case RTC_MINUTES:
     323            case RTC_HOURS:
     324            case RTC_DAY_OF_WEEK:
     325            case RTC_DAY_OF_MONTH:
     326            case RTC_MONTH:
     327            case RTC_YEAR:
     328                *pu32 = pThis->cmos_data[pThis->cmos_index[0]];
     329                break;
     330
     331            case RTC_REG_A:
     332                *pu32 = pThis->cmos_data[pThis->cmos_index[0]];
     333                break;
     334
     335            case RTC_REG_C:
     336                *pu32 = pThis->cmos_data[pThis->cmos_index[0]];
     337                rtc_raise_irq(pThis, 0);
     338                pThis->cmos_data[RTC_REG_C] = 0x00;
     339                break;
     340
     341            default:
     342                *pu32 = pThis->cmos_data[pThis->cmos_index[bank]];
     343                break;
     344        }
     345
     346        Log(("CMOS: Read bank %d idx %#04x: %#04x\n", bank, pThis->cmos_index[bank], *pu32));
     347    }
     348
     349    return VINF_SUCCESS;
     350}
     351
     352
     353/**
     354 * Port I/O Handler for OUT operations.
     355 *
     356 * @returns VBox status code.
     357 *
     358 * @param   pDevIns     The device instance.
     359 * @param   pvUser      User argument - ignored.
     360 * @param   uPort       Port number used for the IN operation.
     361 * @param   u32         The value to output.
     362 * @param   cb          The value size in bytes.
     363 */
     364PDMBOTHCBDECL(int) rtcIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
     365{
     366    NOREF(pvUser);
     367    if (cb != 1)
     368        return VINF_SUCCESS;
     369
     370    RTCState *pThis = PDMINS_2_DATA(pDevIns, RTCState *);
     371    uint32_t bank = (Port >> 1) & 1;
     372    if ((Port & 1) == 0)
     373    {
     374        pThis->cmos_index[bank] = (u32 & 0x7f) + (bank * 128);
     375    }
     376    else
     377    {
     378        Log(("CMOS: Write bank %d idx %#04x: %#04x (old %#04x)\n", bank,
     379             pThis->cmos_index[bank], u32, pThis->cmos_data[pThis->cmos_index[bank]]));
     380
     381        switch (pThis->cmos_index[bank])
     382        {
     383            case RTC_SECONDS_ALARM:
     384            case RTC_MINUTES_ALARM:
     385            case RTC_HOURS_ALARM:
     386                pThis->cmos_data[pThis->cmos_index[0]] = u32;
     387                break;
     388
     389            case RTC_SECONDS:
     390            case RTC_MINUTES:
     391            case RTC_HOURS:
     392            case RTC_DAY_OF_WEEK:
     393            case RTC_DAY_OF_MONTH:
     394            case RTC_MONTH:
     395            case RTC_YEAR:
     396                pThis->cmos_data[pThis->cmos_index[0]] = u32;
     397                /* if in set mode, do not update the time */
     398                if (!(pThis->cmos_data[RTC_REG_B] & REG_B_SET))
     399                    rtc_set_time(pThis);
     400                break;
     401
     402            case RTC_REG_A:
     403                /* UIP bit is read only */
     404                pThis->cmos_data[RTC_REG_A] = (u32                        & ~REG_A_UIP)
     405                                            | (pThis->cmos_data[RTC_REG_A] & REG_A_UIP);
     406                rtc_timer_update(pThis, TMTimerGet(pThis->CTX_SUFF(pPeriodicTimer)));
     407                break;
     408
     409            case RTC_REG_B:
     410                if (u32 & REG_B_SET)
     411                {
     412                    /* set mode: reset UIP mode */
     413                    pThis->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
     414#if 0 /* This is probably wrong as it breaks changing the time/date in OS/2. */
     415                    u32 &= ~REG_B_UIE;
     416#endif
     417                }
     418                else
     419                {
     420                    /* if disabling set mode, update the time */
     421                    if (pThis->cmos_data[RTC_REG_B] & REG_B_SET)
     422                        rtc_set_time(pThis);
     423                }
     424                pThis->cmos_data[RTC_REG_B] = u32;
     425                rtc_timer_update(pThis, TMTimerGet(pThis->CTX_SUFF(pPeriodicTimer)));
     426                break;
     427
     428            case RTC_REG_C:
     429            case RTC_REG_D:
     430                /* cannot write to them */
     431                break;
     432
     433            default:
     434                pThis->cmos_data[pThis->cmos_index[bank]] = u32;
     435                break;
     436        }
     437    }
     438
     439    return VINF_SUCCESS;
     440}
     441
     442#ifdef IN_RING3
     443
     444/* -=-=-=-=-=- Timers and their support code  -=-=-=-=-=- */
     445
     446
     447/**
     448 * Device timer callback function, periodic.
     449 *
     450 * @param   pDevIns         Device instance of the device which registered the timer.
     451 * @param   pTimer          The timer handle.
     452 * @param   pvUser          Pointer to the RTC state.
     453 */
     454static DECLCALLBACK(void) rtcTimerPeriodic(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
     455{
     456    RTCState *pThis = PDMINS_2_DATA(pDevIns, RTCState *);
     457
     458    rtc_timer_update(pThis, pThis->next_periodic_time);
     459    pThis->cmos_data[RTC_REG_C] |= 0xc0;
     460
     461    rtc_raise_irq(pThis, 1);
     462}
     463
    385464
    386465/* month is between 0 and 11. */
    387466static int get_days_in_month(int month, int year)
    388467{
    389     static const int days_tab[12] = {
     468    static const int days_tab[12] =
     469    {
    390470        31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
    391471    };
    392472    int d;
     473
    393474    if ((unsigned )month >= 12)
    394475        return 31;
     476
    395477    d = days_tab[month];
    396     if (month == 1) {
     478    if (month == 1)
     479    {
    397480        if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0))
    398481            d++;
     
    401484}
    402485
     486
    403487/* update 'tm' to the next second */
    404488static void rtc_next_second(struct my_tm *tm)
     
    407491
    408492    tm->tm_sec++;
    409     if ((unsigned)tm->tm_sec >= 60) {
     493    if ((unsigned)tm->tm_sec >= 60)
     494    {
    410495        tm->tm_sec = 0;
    411496        tm->tm_min++;
    412         if ((unsigned)tm->tm_min >= 60) {
     497        if ((unsigned)tm->tm_min >= 60)
     498        {
    413499            tm->tm_min = 0;
    414500            tm->tm_hour++;
    415             if ((unsigned)tm->tm_hour >= 24) {
     501            if ((unsigned)tm->tm_hour >= 24)
     502            {
    416503                tm->tm_hour = 0;
    417504                /* next day */
     
    422509                                                  tm->tm_year + 1900);
    423510                tm->tm_mday++;
    424                 if (tm->tm_mday < 1) {
     511                if (tm->tm_mday < 1)
    425512                    tm->tm_mday = 1;
    426                 } else if (tm->tm_mday > days_in_month) {
     513                else if (tm->tm_mday > days_in_month)
     514                {
    427515                    tm->tm_mday = 1;
    428516                    tm->tm_mon++;
    429                     if (tm->tm_mon >= 12) {
     517                    if (tm->tm_mon >= 12)
     518                    {
    430519                        tm->tm_mon = 0;
    431520                        tm->tm_year++;
     
    438527
    439528
    440 static void rtc_update_second(void *opaque)
    441 {
    442     RTCState *s = (RTCState*)opaque;
    443 
    444     /* if the oscillator is not in normal operation, we do not update */
    445     if ((s->cmos_data[RTC_REG_A] & 0x70) != 0x20) {
    446         s->next_second_time += TMTimerGetFreq(s->CTX_SUFF(pSecondTimer));
    447         TMTimerSet(s->CTX_SUFF(pSecondTimer), s->next_second_time);
    448     } else {
    449         rtc_next_second(&s->current_tm);
    450 
    451         if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
    452             /* update in progress bit */
    453             Log2(("RTC: UIP %x -> 1\n", !!(s->cmos_data[RTC_REG_A] & REG_A_UIP)));
    454             s->cmos_data[RTC_REG_A] |= REG_A_UIP;
    455         }
    456 
    457         /* 244140 ns = 8 / 32768 seconds */
    458         uint64_t delay = TMTimerFromNano(s->CTX_SUFF(pSecondTimer2), 244140);
    459         TMTimerSet(s->CTX_SUFF(pSecondTimer2), s->next_second_time + delay);
    460     }
    461 }
    462 
    463 static void rtc_update_second2(void *opaque)
    464 {
    465     RTCState *s = (RTCState*)opaque;
    466 
    467     if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
    468         rtc_copy_date(s);
    469     }
    470 
    471     /* check alarm */
    472     if (s->cmos_data[RTC_REG_B] & REG_B_AIE) {
    473         if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 ||
    474              from_bcd(s, s->cmos_data[RTC_SECONDS_ALARM]) == s->current_tm.tm_sec) &&
    475             ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 ||
    476              from_bcd(s, s->cmos_data[RTC_MINUTES_ALARM]) == s->current_tm.tm_min) &&
    477             ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 ||
    478              from_bcd(s, s->cmos_data[RTC_HOURS_ALARM]) == s->current_tm.tm_hour)) {
    479 
    480             s->cmos_data[RTC_REG_C] |= 0xa0;
    481             rtc_raise_irq(s, 1);
    482         }
    483     }
    484 
    485     /* update ended interrupt */
    486     if (s->cmos_data[RTC_REG_B] & REG_B_UIE) {
    487         s->cmos_data[RTC_REG_C] |= 0x90;
    488         rtc_raise_irq(s, 1);
    489     }
    490 
    491     /* clear update in progress bit */
    492     Log2(("RTC: UIP %x -> 0\n", !!(s->cmos_data[RTC_REG_A] & REG_A_UIP)));
    493     s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
    494 
    495     s->next_second_time += TMTimerGetFreq(s->CTX_SUFF(pSecondTimer));
    496     TMTimerSet(s->CTX_SUFF(pSecondTimer), s->next_second_time);
    497 }
    498 
    499 static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
    500 {
    501     RTCState *s = (RTCState*)opaque;
    502     int ret;
    503     unsigned bank;
    504 
    505     bank = (addr >> 1) & 1;
    506     if ((addr & 1) == 0) {
    507         return 0xff;
    508     } else {
    509         switch(s->cmos_index[bank]) {
    510         case RTC_SECONDS:
    511         case RTC_MINUTES:
    512         case RTC_HOURS:
    513         case RTC_DAY_OF_WEEK:
    514         case RTC_DAY_OF_MONTH:
    515         case RTC_MONTH:
    516         case RTC_YEAR:
    517             ret = s->cmos_data[s->cmos_index[0]];
    518             break;
    519         case RTC_REG_A:
    520             ret = s->cmos_data[s->cmos_index[0]];
    521             break;
    522         case RTC_REG_C:
    523             ret = s->cmos_data[s->cmos_index[0]];
    524             rtc_raise_irq(s, 0);
    525             s->cmos_data[RTC_REG_C] = 0x00;
    526             break;
    527         default:
    528             ret = s->cmos_data[s->cmos_index[bank]];
    529             break;
    530         }
    531         Log(("CMOS: Read bank %d idx %#04x: %#04x\n", bank, s->cmos_index[bank], ret));
    532         return ret;
    533     }
    534 }
    535 
    536 #ifdef IN_RING3
    537 static void rtc_set_memory(RTCState *s, int addr, int val)
    538 {
    539     if (addr >= 0 && addr <= 127)
    540         s->cmos_data[addr] = val;
    541 }
    542 
    543 static void rtc_set_date(RTCState *s, const struct my_tm *tm)
    544 {
    545     s->current_tm = *tm;
    546     rtc_copy_date(s);
    547 }
    548 
    549 #endif /* IN_RING3 */
    550 
    551 /* -=-=-=-=-=- wrappers / stuff -=-=-=-=-=- */
    552 
    553 /**
    554  * Port I/O Handler for IN operations.
    555  *
    556  * @returns VBox status code.
    557  *
    558  * @param   pDevIns     The device instance.
    559  * @param   pvUser      User argument - ignored.
    560  * @param   uPort       Port number used for the IN operation.
    561  * @param   pu32        Where to store the result.
    562  * @param   cb          Number of bytes read.
    563  */
    564 PDMBOTHCBDECL(int) rtcIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
    565 {
    566     NOREF(pvUser);
    567     if (cb == 1)
    568     {
    569         *pu32 = cmos_ioport_read(PDMINS_2_DATA(pDevIns, RTCState *), Port);
    570         return VINF_SUCCESS;
    571     }
    572     return VERR_IOM_IOPORT_UNUSED;
    573 }
    574 
    575 
    576 /**
    577  * Port I/O Handler for OUT operations.
    578  *
    579  * @returns VBox status code.
    580  *
    581  * @param   pDevIns     The device instance.
    582  * @param   pvUser      User argument - ignored.
    583  * @param   uPort       Port number used for the IN operation.
    584  * @param   u32         The value to output.
    585  * @param   cb          The value size in bytes.
    586  */
    587 PDMBOTHCBDECL(int) rtcIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
    588 {
    589     NOREF(pvUser);
    590     if (cb == 1)
    591         cmos_ioport_write(PDMINS_2_DATA(pDevIns, RTCState *), Port, u32);
    592     return VINF_SUCCESS;
    593 }
    594 
    595 
    596 /**
    597  * Device timer callback function, periodic.
     529/**
     530 * Device timer callback function, second.
    598531 *
    599532 * @param   pDevIns         Device instance of the device which registered the timer.
     
    601534 * @param   pvUser          Pointer to the RTC state.
    602535 */
    603 PDMBOTHCBDECL(void) rtcTimerPeriodic(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
    604 {
    605     rtc_periodic_timer((RTCState *)pvUser);
    606 }
    607 
    608 
    609 /**
    610  * Device timer callback function, second.
     536static DECLCALLBACK(void) rtcTimerSecond(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
     537{
     538    RTCState *pThis = PDMINS_2_DATA(pDevIns, RTCState *);
     539
     540    /* if the oscillator is not in normal operation, we do not update */
     541    if ((pThis->cmos_data[RTC_REG_A] & 0x70) != 0x20)
     542    {
     543        pThis->next_second_time += TMTimerGetFreq(pThis->CTX_SUFF(pSecondTimer));
     544        TMTimerSet(pThis->CTX_SUFF(pSecondTimer), pThis->next_second_time);
     545    }
     546    else
     547    {
     548        rtc_next_second(&pThis->current_tm);
     549
     550        if (!(pThis->cmos_data[RTC_REG_B] & REG_B_SET))
     551        {
     552            /* update in progress bit */
     553            Log2(("RTC: UIP %x -> 1\n", !!(pThis->cmos_data[RTC_REG_A] & REG_A_UIP)));
     554            pThis->cmos_data[RTC_REG_A] |= REG_A_UIP;
     555        }
     556
     557        /* 244140 ns = 8 / 32768 seconds */
     558        uint64_t delay = TMTimerFromNano(pThis->CTX_SUFF(pSecondTimer2), 244140);
     559        TMTimerSet(pThis->CTX_SUFF(pSecondTimer2), pThis->next_second_time + delay);
     560    }
     561}
     562
     563
     564/* Used by rtc_set_date and rtcTimerSecond2. */
     565static void rtc_copy_date(RTCState *pThis)
     566{
     567    const struct my_tm *tm = &pThis->current_tm;
     568
     569    pThis->cmos_data[RTC_SECONDS] = to_bcd(pThis, tm->tm_sec);
     570    pThis->cmos_data[RTC_MINUTES] = to_bcd(pThis, tm->tm_min);
     571    if (pThis->cmos_data[RTC_REG_B] & 0x02)
     572    {
     573        /* 24 hour format */
     574        pThis->cmos_data[RTC_HOURS] = to_bcd(pThis, tm->tm_hour);
     575    }
     576    else
     577    {
     578        /* 12 hour format */
     579        pThis->cmos_data[RTC_HOURS] = to_bcd(pThis, tm->tm_hour % 12);
     580        if (tm->tm_hour >= 12)
     581            pThis->cmos_data[RTC_HOURS] |= 0x80;
     582    }
     583    pThis->cmos_data[RTC_DAY_OF_WEEK] = to_bcd(pThis, tm->tm_wday);
     584    pThis->cmos_data[RTC_DAY_OF_MONTH] = to_bcd(pThis, tm->tm_mday);
     585    pThis->cmos_data[RTC_MONTH] = to_bcd(pThis, tm->tm_mon + 1);
     586    pThis->cmos_data[RTC_YEAR] = to_bcd(pThis, tm->tm_year % 100);
     587}
     588
     589
     590/**
     591 * Device timer callback function, second2.
    611592 *
    612593 * @param   pDevIns         Device instance of the device which registered the timer.
     
    614595 * @param   pvUser          Pointer to the RTC state.
    615596 */
    616 PDMBOTHCBDECL(void) rtcTimerSecond(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
    617 {
    618     rtc_update_second((RTCState *)pvUser);
    619 }
    620 
    621 
    622 /**
    623  * Device timer callback function, second2.
    624  *
    625  * @param   pDevIns         Device instance of the device which registered the timer.
    626  * @param   pTimer          The timer handle.
    627  * @param   pvUser          Pointer to the RTC state.
    628  */
    629 PDMBOTHCBDECL(void) rtcTimerSecond2(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
    630 {
    631     rtc_update_second2((RTCState *)pvUser);
    632 }
    633 
    634 #ifdef IN_RING3
     597static DECLCALLBACK(void) rtcTimerSecond2(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
     598{
     599    RTCState *pThis = PDMINS_2_DATA(pDevIns, RTCState *);
     600
     601    if (!(pThis->cmos_data[RTC_REG_B] & REG_B_SET))
     602        rtc_copy_date(pThis);
     603
     604    /* check alarm */
     605    if (pThis->cmos_data[RTC_REG_B] & REG_B_AIE)
     606    {
     607        if (   (   (pThis->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0
     608                || from_bcd(pThis, pThis->cmos_data[RTC_SECONDS_ALARM]) == pThis->current_tm.tm_sec)
     609            && (   (pThis->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0
     610                || from_bcd(pThis, pThis->cmos_data[RTC_MINUTES_ALARM]) == pThis->current_tm.tm_min)
     611            && (   (pThis->cmos_data[RTC_HOURS_ALARM  ] & 0xc0) == 0xc0
     612                || from_bcd(pThis, pThis->cmos_data[RTC_HOURS_ALARM  ]) == pThis->current_tm.tm_hour)
     613            )
     614        {
     615            pThis->cmos_data[RTC_REG_C] |= 0xa0;
     616            rtc_raise_irq(pThis, 1);
     617        }
     618    }
     619
     620    /* update ended interrupt */
     621    if (pThis->cmos_data[RTC_REG_B] & REG_B_UIE)
     622    {
     623        pThis->cmos_data[RTC_REG_C] |= 0x90;
     624        rtc_raise_irq(pThis, 1);
     625    }
     626
     627    /* clear update in progress bit */
     628    Log2(("RTC: UIP %x -> 0\n", !!(pThis->cmos_data[RTC_REG_A] & REG_A_UIP)));
     629    pThis->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
     630
     631    pThis->next_second_time += TMTimerGetFreq(pThis->CTX_SUFF(pSecondTimer));
     632    TMTimerSet(pThis->CTX_SUFF(pSecondTimer), pThis->next_second_time);
     633}
     634
     635
     636/* -=-=-=-=-=- Saved State -=-=-=-=-=- */
     637
    635638
    636639/**
     
    787790    for (i = RTC_CRC_START, u16 = 0; i <= RTC_CRC_LAST; i++)
    788791        u16 += pThis->cmos_data[i];
    789     pThis->cmos_data[RTC_CRC_LOW] = u16 & 0xff;
     792    pThis->cmos_data[RTC_CRC_LOW]  = u16 & 0xff;
    790793    pThis->cmos_data[RTC_CRC_HIGH] = (u16 >> 8) & 0xff;
    791794}
     
    805808    if (iReg < RT_ELEMENTS(pThis->cmos_data))
    806809    {
     810        PDMCritSectEnter(pDevIns->pCritSectRoR3, VERR_IGNORED);
     811
    807812        pThis->cmos_data[iReg] = u8Value;
    808813
     
    812817            rtcCalcCRC(pThis);
    813818
     819        PDMCritSectLeave(pDevIns->pCritSectRoR3);
    814820        return VINF_SUCCESS;
    815821    }
     822
    816823    AssertMsgFailed(("iReg=%d\n", iReg));
    817824    return VERR_INVALID_PARAMETER;
     
    832839    if (iReg < RT_ELEMENTS(pThis->cmos_data))
    833840    {
     841        PDMCritSectEnter(pDevIns->pCritSectRoR3, VERR_IGNORED);
     842
    834843        *pu8Value = pThis->cmos_data[iReg];
     844
     845        PDMCritSectLeave(pDevIns->pCritSectRoR3);
    835846        return VINF_SUCCESS;
    836847    }
     
    840851
    841852
     853/**
     854 * @interface_method_impl{PDMIHPETLEGACYNOTIFY,pfnModeChanged}
     855 */
     856static DECLCALLBACK(void) rtcHpetLegacyNotify_ModeChanged(PPDMIHPETLEGACYNOTIFY pInterface, bool fActivated)
     857{
     858    RTCState *pThis = RT_FROM_MEMBER(pInterface, RTCState, IHpetLegacyNotify);
     859    PDMCritSectEnter(pThis->pDevInsR3->pCritSectRoR3, VERR_IGNORED);
     860
     861    pThis->fDisabledByHpet = fActivated;
     862
     863    PDMCritSectLeave(pThis->pDevInsR3->pCritSectRoR3);
     864}
     865
     866
    842867/* -=-=-=-=-=- based on bits from pc.c -=-=-=-=-=- */
     868
     869
     870static void rtc_set_memory(RTCState *pThis, int addr, int val)
     871{
     872    if (addr >= 0 && addr <= 127)
     873        pThis->cmos_data[addr] = val;
     874}
     875
     876
     877static void rtc_set_date(RTCState *pThis, const struct my_tm *tm)
     878{
     879    pThis->current_tm = *tm;
     880    rtc_copy_date(pThis);
     881}
     882
    843883
    844884/** @copydoc FNPDMDEVINITCOMPLETE */
     
    900940    return NULL;
    901941}
    902 
    903 
    904 /**
    905  * @interface_method_impl{PDMIHPETLEGACYNOTIFY,pfnModeChanged}
    906  */
    907 static DECLCALLBACK(void) rtcHpetLegacyNotify_ModeChanged(PPDMIHPETLEGACYNOTIFY pInterface, bool fActivated)
    908 {
    909     RTCState *pThis = RT_FROM_MEMBER(pInterface, RTCState, IHpetLegacyNotify);
    910     pThis->fDisabledByHpet = fActivated;
    911 }
    912 
    913942
    914943/**
     
    10311060        return rc;
    10321061
     1062
    10331063    rc = PDMDevHlpIOPortRegister(pDevIns, pThis->IOPortBase, 4, NULL,
    10341064                                 rtcIOPortWrite, rtcIOPortRead, NULL, NULL, "MC146818 RTC/CMOS");
     
    10371067    if (fGCEnabled)
    10381068    {
    1039         rc = PDMDevHlpIOPortRegisterRC(pDevIns, pThis->IOPortBase, 4, 0,
     1069        rc = PDMDevHlpIOPortRegisterRC(pDevIns, pThis->IOPortBase, 4, NIL_RTRCPTR,
    10401070                                       "rtcIOPortWrite", "rtcIOPortRead", NULL, NULL, "MC146818 RTC/CMOS");
    10411071        if (RT_FAILURE(rc))
     
    10441074    if (fR0Enabled)
    10451075    {
    1046         rc = PDMDevHlpIOPortRegisterR0(pDevIns, pThis->IOPortBase, 4, 0,
     1076        rc = PDMDevHlpIOPortRegisterR0(pDevIns, pThis->IOPortBase, 4, NIL_RTR0PTR,
    10471077                                       "rtcIOPortWrite", "rtcIOPortRead", NULL, NULL, "MC146818 RTC/CMOS");
    10481078        if (RT_FAILURE(rc))
Note: See TracChangeset for help on using the changeset viewer.

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