Home | History | Annotate | Download | only in hw
      1 /*
      2  * QEMU 8253/8254 interval timer emulation
      3  *
      4  * Copyright (c) 2003-2004 Fabrice Bellard
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a copy
      7  * of this software and associated documentation files (the "Software"), to deal
      8  * in the Software without restriction, including without limitation the rights
      9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10  * copies of the Software, and to permit persons to whom the Software is
     11  * furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included in
     14  * all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     22  * THE SOFTWARE.
     23  */
     24 #include "hw.h"
     25 #include "pc.h"
     26 #include "isa.h"
     27 #include "qemu-timer.h"
     28 
     29 //#define DEBUG_PIT
     30 
     31 #define RW_STATE_LSB 1
     32 #define RW_STATE_MSB 2
     33 #define RW_STATE_WORD0 3
     34 #define RW_STATE_WORD1 4
     35 
     36 typedef struct PITChannelState {
     37     int count; /* can be 65536 */
     38     uint16_t latched_count;
     39     uint8_t count_latched;
     40     uint8_t status_latched;
     41     uint8_t status;
     42     uint8_t read_state;
     43     uint8_t write_state;
     44     uint8_t write_latch;
     45     uint8_t rw_mode;
     46     uint8_t mode;
     47     uint8_t bcd; /* not supported */
     48     uint8_t gate; /* timer start */
     49     int64_t count_load_time;
     50     /* irq handling */
     51     int64_t next_transition_time;
     52     QEMUTimer *irq_timer;
     53     qemu_irq irq;
     54 } PITChannelState;
     55 
     56 struct PITState {
     57     PITChannelState channels[3];
     58 };
     59 
     60 static PITState pit_state;
     61 
     62 static void pit_irq_timer_update(PITChannelState *s, int64_t current_time);
     63 
     64 static int pit_get_count(PITChannelState *s)
     65 {
     66     uint64_t d;
     67     int counter;
     68 
     69     d = muldiv64(qemu_get_clock_ns(vm_clock) - s->count_load_time, PIT_FREQ, get_ticks_per_sec());
     70     switch(s->mode) {
     71     case 0:
     72     case 1:
     73     case 4:
     74     case 5:
     75         counter = (s->count - d) & 0xffff;
     76         break;
     77     case 3:
     78         /* XXX: may be incorrect for odd counts */
     79         counter = s->count - ((2 * d) % s->count);
     80         break;
     81     default:
     82         counter = s->count - (d % s->count);
     83         break;
     84     }
     85     return counter;
     86 }
     87 
     88 /* get pit output bit */
     89 static int pit_get_out1(PITChannelState *s, int64_t current_time)
     90 {
     91     uint64_t d;
     92     int out;
     93 
     94     d = muldiv64(current_time - s->count_load_time, PIT_FREQ, get_ticks_per_sec());
     95     switch(s->mode) {
     96     default:
     97     case 0:
     98         out = (d >= s->count);
     99         break;
    100     case 1:
    101         out = (d < s->count);
    102         break;
    103     case 2:
    104         if ((d % s->count) == 0 && d != 0)
    105             out = 1;
    106         else
    107             out = 0;
    108         break;
    109     case 3:
    110         out = (d % s->count) < ((s->count + 1) >> 1);
    111         break;
    112     case 4:
    113     case 5:
    114         out = (d == s->count);
    115         break;
    116     }
    117     return out;
    118 }
    119 
    120 int pit_get_out(PITState *pit, int channel, int64_t current_time)
    121 {
    122     PITChannelState *s = &pit->channels[channel];
    123     return pit_get_out1(s, current_time);
    124 }
    125 
    126 /* return -1 if no transition will occur.  */
    127 static int64_t pit_get_next_transition_time(PITChannelState *s,
    128                                             int64_t current_time)
    129 {
    130     uint64_t d, next_time, base;
    131     int period2;
    132 
    133     d = muldiv64(current_time - s->count_load_time, PIT_FREQ, get_ticks_per_sec());
    134     switch(s->mode) {
    135     default:
    136     case 0:
    137     case 1:
    138         if (d < s->count)
    139             next_time = s->count;
    140         else
    141             return -1;
    142         break;
    143     case 2:
    144         base = (d / s->count) * s->count;
    145         if ((d - base) == 0 && d != 0)
    146             next_time = base + s->count;
    147         else
    148             next_time = base + s->count + 1;
    149         break;
    150     case 3:
    151         base = (d / s->count) * s->count;
    152         period2 = ((s->count + 1) >> 1);
    153         if ((d - base) < period2)
    154             next_time = base + period2;
    155         else
    156             next_time = base + s->count;
    157         break;
    158     case 4:
    159     case 5:
    160         if (d < s->count)
    161             next_time = s->count;
    162         else if (d == s->count)
    163             next_time = s->count + 1;
    164         else
    165             return -1;
    166         break;
    167     }
    168     /* convert to timer units */
    169     next_time = s->count_load_time + muldiv64(next_time, get_ticks_per_sec(), PIT_FREQ);
    170     /* fix potential rounding problems */
    171     /* XXX: better solution: use a clock at PIT_FREQ Hz */
    172     if (next_time <= current_time)
    173         next_time = current_time + 1;
    174     return next_time;
    175 }
    176 
    177 /* val must be 0 or 1 */
    178 void pit_set_gate(PITState *pit, int channel, int val)
    179 {
    180     PITChannelState *s = &pit->channels[channel];
    181 
    182     switch(s->mode) {
    183     default:
    184     case 0:
    185     case 4:
    186         /* XXX: just disable/enable counting */
    187         break;
    188     case 1:
    189     case 5:
    190         if (s->gate < val) {
    191             /* restart counting on rising edge */
    192             s->count_load_time = qemu_get_clock_ns(vm_clock);
    193             pit_irq_timer_update(s, s->count_load_time);
    194         }
    195         break;
    196     case 2:
    197     case 3:
    198         if (s->gate < val) {
    199             /* restart counting on rising edge */
    200             s->count_load_time = qemu_get_clock_ns(vm_clock);
    201             pit_irq_timer_update(s, s->count_load_time);
    202         }
    203         /* XXX: disable/enable counting */
    204         break;
    205     }
    206     s->gate = val;
    207 }
    208 
    209 int pit_get_gate(PITState *pit, int channel)
    210 {
    211     PITChannelState *s = &pit->channels[channel];
    212     return s->gate;
    213 }
    214 
    215 int pit_get_initial_count(PITState *pit, int channel)
    216 {
    217     PITChannelState *s = &pit->channels[channel];
    218     return s->count;
    219 }
    220 
    221 int pit_get_mode(PITState *pit, int channel)
    222 {
    223     PITChannelState *s = &pit->channels[channel];
    224     return s->mode;
    225 }
    226 
    227 static inline void pit_load_count(PITChannelState *s, int val)
    228 {
    229     if (val == 0)
    230         val = 0x10000;
    231     s->count_load_time = qemu_get_clock_ns(vm_clock);
    232     s->count = val;
    233     pit_irq_timer_update(s, s->count_load_time);
    234 }
    235 
    236 /* if already latched, do not latch again */
    237 static void pit_latch_count(PITChannelState *s)
    238 {
    239     if (!s->count_latched) {
    240         s->latched_count = pit_get_count(s);
    241         s->count_latched = s->rw_mode;
    242     }
    243 }
    244 
    245 static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val)
    246 {
    247     PITState *pit = opaque;
    248     int channel, access;
    249     PITChannelState *s;
    250 
    251     addr &= 3;
    252     if (addr == 3) {
    253         channel = val >> 6;
    254         if (channel == 3) {
    255             /* read back command */
    256             for(channel = 0; channel < 3; channel++) {
    257                 s = &pit->channels[channel];
    258                 if (val & (2 << channel)) {
    259                     if (!(val & 0x20)) {
    260                         pit_latch_count(s);
    261                     }
    262                     if (!(val & 0x10) && !s->status_latched) {
    263                         /* status latch */
    264                         /* XXX: add BCD and null count */
    265                         s->status =  (pit_get_out1(s, qemu_get_clock_ns(vm_clock)) << 7) |
    266                             (s->rw_mode << 4) |
    267                             (s->mode << 1) |
    268                             s->bcd;
    269                         s->status_latched = 1;
    270                     }
    271                 }
    272             }
    273         } else {
    274             s = &pit->channels[channel];
    275             access = (val >> 4) & 3;
    276             if (access == 0) {
    277                 pit_latch_count(s);
    278             } else {
    279                 s->rw_mode = access;
    280                 s->read_state = access;
    281                 s->write_state = access;
    282 
    283                 s->mode = (val >> 1) & 7;
    284                 s->bcd = val & 1;
    285                 /* XXX: update irq timer ? */
    286             }
    287         }
    288     } else {
    289         s = &pit->channels[addr];
    290         switch(s->write_state) {
    291         default:
    292         case RW_STATE_LSB:
    293             pit_load_count(s, val);
    294             break;
    295         case RW_STATE_MSB:
    296             pit_load_count(s, val << 8);
    297             break;
    298         case RW_STATE_WORD0:
    299             s->write_latch = val;
    300             s->write_state = RW_STATE_WORD1;
    301             break;
    302         case RW_STATE_WORD1:
    303             pit_load_count(s, s->write_latch | (val << 8));
    304             s->write_state = RW_STATE_WORD0;
    305             break;
    306         }
    307     }
    308 }
    309 
    310 static uint32_t pit_ioport_read(void *opaque, uint32_t addr)
    311 {
    312     PITState *pit = opaque;
    313     int ret, count;
    314     PITChannelState *s;
    315 
    316     addr &= 3;
    317     s = &pit->channels[addr];
    318     if (s->status_latched) {
    319         s->status_latched = 0;
    320         ret = s->status;
    321     } else if (s->count_latched) {
    322         switch(s->count_latched) {
    323         default:
    324         case RW_STATE_LSB:
    325             ret = s->latched_count & 0xff;
    326             s->count_latched = 0;
    327             break;
    328         case RW_STATE_MSB:
    329             ret = s->latched_count >> 8;
    330             s->count_latched = 0;
    331             break;
    332         case RW_STATE_WORD0:
    333             ret = s->latched_count & 0xff;
    334             s->count_latched = RW_STATE_MSB;
    335             break;
    336         }
    337     } else {
    338         switch(s->read_state) {
    339         default:
    340         case RW_STATE_LSB:
    341             count = pit_get_count(s);
    342             ret = count & 0xff;
    343             break;
    344         case RW_STATE_MSB:
    345             count = pit_get_count(s);
    346             ret = (count >> 8) & 0xff;
    347             break;
    348         case RW_STATE_WORD0:
    349             count = pit_get_count(s);
    350             ret = count & 0xff;
    351             s->read_state = RW_STATE_WORD1;
    352             break;
    353         case RW_STATE_WORD1:
    354             count = pit_get_count(s);
    355             ret = (count >> 8) & 0xff;
    356             s->read_state = RW_STATE_WORD0;
    357             break;
    358         }
    359     }
    360     return ret;
    361 }
    362 
    363 static void pit_irq_timer_update(PITChannelState *s, int64_t current_time)
    364 {
    365     int64_t expire_time;
    366     int irq_level;
    367 
    368     if (!s->irq_timer)
    369         return;
    370     expire_time = pit_get_next_transition_time(s, current_time);
    371     irq_level = pit_get_out1(s, current_time);
    372     qemu_set_irq(s->irq, irq_level);
    373 #ifdef DEBUG_PIT
    374     printf("irq_level=%d next_delay=%f\n",
    375            irq_level,
    376            (double)(expire_time - current_time) / get_ticks_per_sec());
    377 #endif
    378     s->next_transition_time = expire_time;
    379     if (expire_time != -1)
    380         qemu_mod_timer(s->irq_timer, expire_time);
    381     else
    382         qemu_del_timer(s->irq_timer);
    383 }
    384 
    385 static void pit_irq_timer(void *opaque)
    386 {
    387     PITChannelState *s = opaque;
    388 
    389     pit_irq_timer_update(s, s->next_transition_time);
    390 }
    391 
    392 static void pit_save(QEMUFile *f, void *opaque)
    393 {
    394     PITState *pit = opaque;
    395     PITChannelState *s;
    396     int i;
    397 
    398     for(i = 0; i < 3; i++) {
    399         s = &pit->channels[i];
    400         qemu_put_be32(f, s->count);
    401         qemu_put_be16s(f, &s->latched_count);
    402         qemu_put_8s(f, &s->count_latched);
    403         qemu_put_8s(f, &s->status_latched);
    404         qemu_put_8s(f, &s->status);
    405         qemu_put_8s(f, &s->read_state);
    406         qemu_put_8s(f, &s->write_state);
    407         qemu_put_8s(f, &s->write_latch);
    408         qemu_put_8s(f, &s->rw_mode);
    409         qemu_put_8s(f, &s->mode);
    410         qemu_put_8s(f, &s->bcd);
    411         qemu_put_8s(f, &s->gate);
    412         qemu_put_be64(f, s->count_load_time);
    413         if (s->irq_timer) {
    414             qemu_put_be64(f, s->next_transition_time);
    415             qemu_put_timer(f, s->irq_timer);
    416         }
    417     }
    418 }
    419 
    420 static int pit_load(QEMUFile *f, void *opaque, int version_id)
    421 {
    422     PITState *pit = opaque;
    423     PITChannelState *s;
    424     int i;
    425 
    426     if (version_id != 1)
    427         return -EINVAL;
    428 
    429     for(i = 0; i < 3; i++) {
    430         s = &pit->channels[i];
    431         s->count=qemu_get_be32(f);
    432         qemu_get_be16s(f, &s->latched_count);
    433         qemu_get_8s(f, &s->count_latched);
    434         qemu_get_8s(f, &s->status_latched);
    435         qemu_get_8s(f, &s->status);
    436         qemu_get_8s(f, &s->read_state);
    437         qemu_get_8s(f, &s->write_state);
    438         qemu_get_8s(f, &s->write_latch);
    439         qemu_get_8s(f, &s->rw_mode);
    440         qemu_get_8s(f, &s->mode);
    441         qemu_get_8s(f, &s->bcd);
    442         qemu_get_8s(f, &s->gate);
    443         s->count_load_time=qemu_get_be64(f);
    444         if (s->irq_timer) {
    445             s->next_transition_time=qemu_get_be64(f);
    446             qemu_get_timer(f, s->irq_timer);
    447         }
    448     }
    449     return 0;
    450 }
    451 
    452 static void pit_reset(void *opaque)
    453 {
    454     PITState *pit = opaque;
    455     PITChannelState *s;
    456     int i;
    457 
    458     for(i = 0;i < 3; i++) {
    459         s = &pit->channels[i];
    460         s->mode = 3;
    461         s->gate = (i != 2);
    462         pit_load_count(s, 0);
    463     }
    464 }
    465 
    466 /* When HPET is operating in legacy mode, i8254 timer0 is disabled */
    467 void hpet_pit_disable(void) {
    468     PITChannelState *s;
    469     s = &pit_state.channels[0];
    470     if (s->irq_timer)
    471         qemu_del_timer(s->irq_timer);
    472 }
    473 
    474 /* When HPET is reset or leaving legacy mode, it must reenable i8254
    475  * timer 0
    476  */
    477 
    478 void hpet_pit_enable(void)
    479 {
    480     PITState *pit = &pit_state;
    481     PITChannelState *s;
    482     s = &pit->channels[0];
    483     s->mode = 3;
    484     s->gate = 1;
    485     pit_load_count(s, 0);
    486 }
    487 
    488 PITState *pit_init(int base, qemu_irq irq)
    489 {
    490     PITState *pit = &pit_state;
    491     PITChannelState *s;
    492 
    493     s = &pit->channels[0];
    494     /* the timer 0 is connected to an IRQ */
    495     s->irq_timer = qemu_new_timer_ns(vm_clock, pit_irq_timer, s);
    496     s->irq = irq;
    497 
    498     register_savevm("i8254", base, 1, pit_save, pit_load, pit);
    499 
    500     qemu_register_reset(pit_reset, 0, pit);
    501     register_ioport_write(base, 4, 1, pit_ioport_write, pit);
    502     register_ioport_read(base, 3, 1, pit_ioport_read, pit);
    503 
    504     pit_reset(pit);
    505 
    506     return pit;
    507 }
    508