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/hw.h" 25#include "hw/i386/pc.h" 26#include "hw/isa/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 36typedef 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 56struct PITState { 57 PITChannelState channels[3]; 58}; 59 60static PITState pit_state; 61 62static void pit_irq_timer_update(PITChannelState *s, int64_t current_time); 63 64static int pit_get_count(PITChannelState *s) 65{ 66 uint64_t d; 67 int counter; 68 69 d = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - 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 */ 89static 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 120int 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. */ 127static 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 */ 178void 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_clock_get_ns(QEMU_CLOCK_VIRTUAL); 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_clock_get_ns(QEMU_CLOCK_VIRTUAL); 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 209int pit_get_gate(PITState *pit, int channel) 210{ 211 PITChannelState *s = &pit->channels[channel]; 212 return s->gate; 213} 214 215int pit_get_initial_count(PITState *pit, int channel) 216{ 217 PITChannelState *s = &pit->channels[channel]; 218 return s->count; 219} 220 221int pit_get_mode(PITState *pit, int channel) 222{ 223 PITChannelState *s = &pit->channels[channel]; 224 return s->mode; 225} 226 227static inline void pit_load_count(PITChannelState *s, int val) 228{ 229 if (val == 0) 230 val = 0x10000; 231 s->count_load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 232 s->count = val; 233 pit_irq_timer_update(s, s->count_load_time); 234} 235 236/* if already latched, do not latch again */ 237static 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 245static 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_clock_get_ns(QEMU_CLOCK_VIRTUAL)) << 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 310static 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 363static 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 timer_mod(s->irq_timer, expire_time); 381 else 382 timer_del(s->irq_timer); 383} 384 385static void pit_irq_timer(void *opaque) 386{ 387 PITChannelState *s = opaque; 388 389 pit_irq_timer_update(s, s->next_transition_time); 390} 391 392static 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 timer_put(f, s->irq_timer); 416 } 417 } 418} 419 420static 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 timer_get(f, s->irq_timer); 447 } 448 } 449 return 0; 450} 451 452static 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 */ 467void hpet_pit_disable(void) { 468 PITChannelState *s; 469 s = &pit_state.channels[0]; 470 if (s->irq_timer) 471 timer_del(s->irq_timer); 472} 473 474/* When HPET is reset or leaving legacy mode, it must reenable i8254 475 * timer 0 476 */ 477 478void 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 488PITState *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 = timer_new(QEMU_CLOCK_VIRTUAL, SCALE_NS, pit_irq_timer, s); 496 s->irq = irq; 497 498 register_savevm(NULL, "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