2
0

i8254.c 11 KB

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