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 "qemu/osdep.h" 25 #include "hw/hw.h" 26 #include "qemu/timer.h" 27 #include "hw/timer/i8254.h" 28 #include "hw/timer/i8254_internal.h" 29 30 //#define DEBUG_PIT 31 32 #define RW_STATE_LSB 1 33 #define RW_STATE_MSB 2 34 #define RW_STATE_WORD0 3 35 #define RW_STATE_WORD1 4 36 37 #define PIT_CLASS(class) OBJECT_CLASS_CHECK(PITClass, (class), TYPE_I8254) 38 #define PIT_GET_CLASS(obj) OBJECT_GET_CLASS(PITClass, (obj), TYPE_I8254) 39 40 typedef struct PITClass { 41 PITCommonClass parent_class; 42 43 DeviceRealize parent_realize; 44 } PITClass; 45 46 static void pit_irq_timer_update(PITChannelState *s, int64_t current_time); 47 48 static int pit_get_count(PITChannelState *s) 49 { 50 uint64_t d; 51 int counter; 52 53 d = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - s->count_load_time, PIT_FREQ, 54 NANOSECONDS_PER_SECOND); 55 switch(s->mode) { 56 case 0: 57 case 1: 58 case 4: 59 case 5: 60 counter = (s->count - d) & 0xffff; 61 break; 62 case 3: 63 /* XXX: may be incorrect for odd counts */ 64 counter = s->count - ((2 * d) % s->count); 65 break; 66 default: 67 counter = s->count - (d % s->count); 68 break; 69 } 70 return counter; 71 } 72 73 /* val must be 0 or 1 */ 74 static void pit_set_channel_gate(PITCommonState *s, PITChannelState *sc, 75 int val) 76 { 77 switch (sc->mode) { 78 default: 79 case 0: 80 case 4: 81 /* XXX: just disable/enable counting */ 82 break; 83 case 1: 84 case 5: 85 if (sc->gate < val) { 86 /* restart counting on rising edge */ 87 sc->count_load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 88 pit_irq_timer_update(sc, sc->count_load_time); 89 } 90 break; 91 case 2: 92 case 3: 93 if (sc->gate < val) { 94 /* restart counting on rising edge */ 95 sc->count_load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 96 pit_irq_timer_update(sc, sc->count_load_time); 97 } 98 /* XXX: disable/enable counting */ 99 break; 100 } 101 sc->gate = val; 102 } 103 104 static inline void pit_load_count(PITChannelState *s, int val) 105 { 106 if (val == 0) 107 val = 0x10000; 108 s->count_load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 109 s->count = val; 110 pit_irq_timer_update(s, s->count_load_time); 111 } 112 113 /* if already latched, do not latch again */ 114 static void pit_latch_count(PITChannelState *s) 115 { 116 if (!s->count_latched) { 117 s->latched_count = pit_get_count(s); 118 s->count_latched = s->rw_mode; 119 } 120 } 121 122 static void pit_ioport_write(void *opaque, hwaddr addr, 123 uint64_t val, unsigned size) 124 { 125 PITCommonState *pit = opaque; 126 int channel, access; 127 PITChannelState *s; 128 129 addr &= 3; 130 if (addr == 3) { 131 channel = val >> 6; 132 if (channel == 3) { 133 /* read back command */ 134 for(channel = 0; channel < 3; channel++) { 135 s = &pit->channels[channel]; 136 if (val & (2 << channel)) { 137 if (!(val & 0x20)) { 138 pit_latch_count(s); 139 } 140 if (!(val & 0x10) && !s->status_latched) { 141 /* status latch */ 142 /* XXX: add BCD and null count */ 143 s->status = 144 (pit_get_out(s, 145 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)) << 7) | 146 (s->rw_mode << 4) | 147 (s->mode << 1) | 148 s->bcd; 149 s->status_latched = 1; 150 } 151 } 152 } 153 } else { 154 s = &pit->channels[channel]; 155 access = (val >> 4) & 3; 156 if (access == 0) { 157 pit_latch_count(s); 158 } else { 159 s->rw_mode = access; 160 s->read_state = access; 161 s->write_state = access; 162 163 s->mode = (val >> 1) & 7; 164 s->bcd = val & 1; 165 /* XXX: update irq timer ? */ 166 } 167 } 168 } else { 169 s = &pit->channels[addr]; 170 switch(s->write_state) { 171 default: 172 case RW_STATE_LSB: 173 pit_load_count(s, val); 174 break; 175 case RW_STATE_MSB: 176 pit_load_count(s, val << 8); 177 break; 178 case RW_STATE_WORD0: 179 s->write_latch = val; 180 s->write_state = RW_STATE_WORD1; 181 break; 182 case RW_STATE_WORD1: 183 pit_load_count(s, s->write_latch | (val << 8)); 184 s->write_state = RW_STATE_WORD0; 185 break; 186 } 187 } 188 } 189 190 static uint64_t pit_ioport_read(void *opaque, hwaddr addr, 191 unsigned size) 192 { 193 PITCommonState *pit = opaque; 194 int ret, count; 195 PITChannelState *s; 196 197 addr &= 3; 198 199 if (addr == 3) { 200 /* Mode/Command register is write only, read is ignored */ 201 return 0; 202 } 203 204 s = &pit->channels[addr]; 205 if (s->status_latched) { 206 s->status_latched = 0; 207 ret = s->status; 208 } else if (s->count_latched) { 209 switch(s->count_latched) { 210 default: 211 case RW_STATE_LSB: 212 ret = s->latched_count & 0xff; 213 s->count_latched = 0; 214 break; 215 case RW_STATE_MSB: 216 ret = s->latched_count >> 8; 217 s->count_latched = 0; 218 break; 219 case RW_STATE_WORD0: 220 ret = s->latched_count & 0xff; 221 s->count_latched = RW_STATE_MSB; 222 break; 223 } 224 } else { 225 switch(s->read_state) { 226 default: 227 case RW_STATE_LSB: 228 count = pit_get_count(s); 229 ret = count & 0xff; 230 break; 231 case RW_STATE_MSB: 232 count = pit_get_count(s); 233 ret = (count >> 8) & 0xff; 234 break; 235 case RW_STATE_WORD0: 236 count = pit_get_count(s); 237 ret = count & 0xff; 238 s->read_state = RW_STATE_WORD1; 239 break; 240 case RW_STATE_WORD1: 241 count = pit_get_count(s); 242 ret = (count >> 8) & 0xff; 243 s->read_state = RW_STATE_WORD0; 244 break; 245 } 246 } 247 return ret; 248 } 249 250 static void pit_irq_timer_update(PITChannelState *s, int64_t current_time) 251 { 252 int64_t expire_time; 253 int irq_level; 254 255 if (!s->irq_timer || s->irq_disabled) { 256 return; 257 } 258 expire_time = pit_get_next_transition_time(s, current_time); 259 irq_level = pit_get_out(s, current_time); 260 qemu_set_irq(s->irq, irq_level); 261 #ifdef DEBUG_PIT 262 printf("irq_level=%d next_delay=%f\n", 263 irq_level, 264 (double)(expire_time - current_time) / NANOSECONDS_PER_SECOND); 265 #endif 266 s->next_transition_time = expire_time; 267 if (expire_time != -1) 268 timer_mod(s->irq_timer, expire_time); 269 else 270 timer_del(s->irq_timer); 271 } 272 273 static void pit_irq_timer(void *opaque) 274 { 275 PITChannelState *s = opaque; 276 277 pit_irq_timer_update(s, s->next_transition_time); 278 } 279 280 static void pit_reset(DeviceState *dev) 281 { 282 PITCommonState *pit = PIT_COMMON(dev); 283 PITChannelState *s; 284 285 pit_reset_common(pit); 286 287 s = &pit->channels[0]; 288 if (!s->irq_disabled) { 289 timer_mod(s->irq_timer, s->next_transition_time); 290 } 291 } 292 293 /* When HPET is operating in legacy mode, suppress the ignored timer IRQ, 294 * reenable it when legacy mode is left again. */ 295 static void pit_irq_control(void *opaque, int n, int enable) 296 { 297 PITCommonState *pit = opaque; 298 PITChannelState *s = &pit->channels[0]; 299 300 if (enable) { 301 s->irq_disabled = 0; 302 pit_irq_timer_update(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); 303 } else { 304 s->irq_disabled = 1; 305 timer_del(s->irq_timer); 306 } 307 } 308 309 static const MemoryRegionOps pit_ioport_ops = { 310 .read = pit_ioport_read, 311 .write = pit_ioport_write, 312 .impl = { 313 .min_access_size = 1, 314 .max_access_size = 1, 315 }, 316 .endianness = DEVICE_LITTLE_ENDIAN, 317 }; 318 319 static void pit_post_load(PITCommonState *s) 320 { 321 PITChannelState *sc = &s->channels[0]; 322 323 if (sc->next_transition_time != -1) { 324 timer_mod(sc->irq_timer, sc->next_transition_time); 325 } else { 326 timer_del(sc->irq_timer); 327 } 328 } 329 330 static void pit_realizefn(DeviceState *dev, Error **errp) 331 { 332 PITCommonState *pit = PIT_COMMON(dev); 333 PITClass *pc = PIT_GET_CLASS(dev); 334 PITChannelState *s; 335 336 s = &pit->channels[0]; 337 /* the timer 0 is connected to an IRQ */ 338 s->irq_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pit_irq_timer, s); 339 qdev_init_gpio_out(dev, &s->irq, 1); 340 341 memory_region_init_io(&pit->ioports, OBJECT(pit), &pit_ioport_ops, 342 pit, "pit", 4); 343 344 qdev_init_gpio_in(dev, pit_irq_control, 1); 345 346 pc->parent_realize(dev, errp); 347 } 348 349 static Property pit_properties[] = { 350 DEFINE_PROP_UINT32("iobase", PITCommonState, iobase, -1), 351 DEFINE_PROP_END_OF_LIST(), 352 }; 353 354 static void pit_class_initfn(ObjectClass *klass, void *data) 355 { 356 PITClass *pc = PIT_CLASS(klass); 357 PITCommonClass *k = PIT_COMMON_CLASS(klass); 358 DeviceClass *dc = DEVICE_CLASS(klass); 359 360 device_class_set_parent_realize(dc, pit_realizefn, &pc->parent_realize); 361 k->set_channel_gate = pit_set_channel_gate; 362 k->get_channel_info = pit_get_channel_info_common; 363 k->post_load = pit_post_load; 364 dc->reset = pit_reset; 365 dc->props = pit_properties; 366 } 367 368 static const TypeInfo pit_info = { 369 .name = TYPE_I8254, 370 .parent = TYPE_PIT_COMMON, 371 .instance_size = sizeof(PITCommonState), 372 .class_init = pit_class_initfn, 373 .class_size = sizeof(PITClass), 374 }; 375 376 static void pit_register_types(void) 377 { 378 type_register_static(&pit_info); 379 } 380 381 type_init(pit_register_types) 382