i8254.c 10 KB

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