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