i8254.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  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. //#define DEBUG_PIT
  29. #define RW_STATE_LSB 1
  30. #define RW_STATE_MSB 2
  31. #define RW_STATE_WORD0 3
  32. #define RW_STATE_WORD1 4
  33. typedef struct PITChannelState {
  34. int count; /* can be 65536 */
  35. uint16_t latched_count;
  36. uint8_t count_latched;
  37. uint8_t status_latched;
  38. uint8_t status;
  39. uint8_t read_state;
  40. uint8_t write_state;
  41. uint8_t write_latch;
  42. uint8_t rw_mode;
  43. uint8_t mode;
  44. uint8_t bcd; /* not supported */
  45. uint8_t gate; /* timer start */
  46. int64_t count_load_time;
  47. /* irq handling */
  48. int64_t next_transition_time;
  49. QEMUTimer *irq_timer;
  50. qemu_irq irq;
  51. } PITChannelState;
  52. struct PITState {
  53. PITChannelState channels[3];
  54. };
  55. static PITState pit_state;
  56. static void pit_irq_timer_update(PITChannelState *s, int64_t current_time);
  57. static int pit_get_count(PITChannelState *s)
  58. {
  59. uint64_t d;
  60. int counter;
  61. d = muldiv64(qemu_get_clock(vm_clock) - s->count_load_time, PIT_FREQ, ticks_per_sec);
  62. switch(s->mode) {
  63. case 0:
  64. case 1:
  65. case 4:
  66. case 5:
  67. counter = (s->count - d) & 0xffff;
  68. break;
  69. case 3:
  70. /* XXX: may be incorrect for odd counts */
  71. counter = s->count - ((2 * d) % s->count);
  72. break;
  73. default:
  74. counter = s->count - (d % s->count);
  75. break;
  76. }
  77. return counter;
  78. }
  79. /* get pit output bit */
  80. static int pit_get_out1(PITChannelState *s, int64_t current_time)
  81. {
  82. uint64_t d;
  83. int out;
  84. d = muldiv64(current_time - s->count_load_time, PIT_FREQ, ticks_per_sec);
  85. switch(s->mode) {
  86. default:
  87. case 0:
  88. out = (d >= s->count);
  89. break;
  90. case 1:
  91. out = (d < s->count);
  92. break;
  93. case 2:
  94. if ((d % s->count) == 0 && d != 0)
  95. out = 1;
  96. else
  97. out = 0;
  98. break;
  99. case 3:
  100. out = (d % s->count) < ((s->count + 1) >> 1);
  101. break;
  102. case 4:
  103. case 5:
  104. out = (d == s->count);
  105. break;
  106. }
  107. return out;
  108. }
  109. int pit_get_out(PITState *pit, int channel, int64_t current_time)
  110. {
  111. PITChannelState *s = &pit->channels[channel];
  112. return pit_get_out1(s, current_time);
  113. }
  114. /* return -1 if no transition will occur. */
  115. static int64_t pit_get_next_transition_time(PITChannelState *s,
  116. int64_t current_time)
  117. {
  118. uint64_t d, next_time, base;
  119. int period2;
  120. d = muldiv64(current_time - s->count_load_time, PIT_FREQ, ticks_per_sec);
  121. switch(s->mode) {
  122. default:
  123. case 0:
  124. case 1:
  125. if (d < s->count)
  126. next_time = s->count;
  127. else
  128. return -1;
  129. break;
  130. case 2:
  131. base = (d / s->count) * s->count;
  132. if ((d - base) == 0 && d != 0)
  133. next_time = base + s->count;
  134. else
  135. next_time = base + s->count + 1;
  136. break;
  137. case 3:
  138. base = (d / s->count) * s->count;
  139. period2 = ((s->count + 1) >> 1);
  140. if ((d - base) < period2)
  141. next_time = base + period2;
  142. else
  143. next_time = base + s->count;
  144. break;
  145. case 4:
  146. case 5:
  147. if (d < s->count)
  148. next_time = s->count;
  149. else if (d == s->count)
  150. next_time = s->count + 1;
  151. else
  152. return -1;
  153. break;
  154. }
  155. /* convert to timer units */
  156. next_time = s->count_load_time + muldiv64(next_time, ticks_per_sec, PIT_FREQ);
  157. /* fix potential rounding problems */
  158. /* XXX: better solution: use a clock at PIT_FREQ Hz */
  159. if (next_time <= current_time)
  160. next_time = current_time + 1;
  161. return next_time;
  162. }
  163. /* val must be 0 or 1 */
  164. void pit_set_gate(PITState *pit, int channel, int val)
  165. {
  166. PITChannelState *s = &pit->channels[channel];
  167. switch(s->mode) {
  168. default:
  169. case 0:
  170. case 4:
  171. /* XXX: just disable/enable counting */
  172. break;
  173. case 1:
  174. case 5:
  175. if (s->gate < val) {
  176. /* restart counting on rising edge */
  177. s->count_load_time = qemu_get_clock(vm_clock);
  178. pit_irq_timer_update(s, s->count_load_time);
  179. }
  180. break;
  181. case 2:
  182. case 3:
  183. if (s->gate < val) {
  184. /* restart counting on rising edge */
  185. s->count_load_time = qemu_get_clock(vm_clock);
  186. pit_irq_timer_update(s, s->count_load_time);
  187. }
  188. /* XXX: disable/enable counting */
  189. break;
  190. }
  191. s->gate = val;
  192. }
  193. int pit_get_gate(PITState *pit, int channel)
  194. {
  195. PITChannelState *s = &pit->channels[channel];
  196. return s->gate;
  197. }
  198. int pit_get_initial_count(PITState *pit, int channel)
  199. {
  200. PITChannelState *s = &pit->channels[channel];
  201. return s->count;
  202. }
  203. int pit_get_mode(PITState *pit, int channel)
  204. {
  205. PITChannelState *s = &pit->channels[channel];
  206. return s->mode;
  207. }
  208. static inline void pit_load_count(PITChannelState *s, int val)
  209. {
  210. if (val == 0)
  211. val = 0x10000;
  212. s->count_load_time = qemu_get_clock(vm_clock);
  213. s->count = val;
  214. pit_irq_timer_update(s, s->count_load_time);
  215. }
  216. /* if already latched, do not latch again */
  217. static void pit_latch_count(PITChannelState *s)
  218. {
  219. if (!s->count_latched) {
  220. s->latched_count = pit_get_count(s);
  221. s->count_latched = s->rw_mode;
  222. }
  223. }
  224. static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val)
  225. {
  226. PITState *pit = opaque;
  227. int channel, access;
  228. PITChannelState *s;
  229. addr &= 3;
  230. if (addr == 3) {
  231. channel = val >> 6;
  232. if (channel == 3) {
  233. /* read back command */
  234. for(channel = 0; channel < 3; channel++) {
  235. s = &pit->channels[channel];
  236. if (val & (2 << channel)) {
  237. if (!(val & 0x20)) {
  238. pit_latch_count(s);
  239. }
  240. if (!(val & 0x10) && !s->status_latched) {
  241. /* status latch */
  242. /* XXX: add BCD and null count */
  243. s->status = (pit_get_out1(s, qemu_get_clock(vm_clock)) << 7) |
  244. (s->rw_mode << 4) |
  245. (s->mode << 1) |
  246. s->bcd;
  247. s->status_latched = 1;
  248. }
  249. }
  250. }
  251. } else {
  252. s = &pit->channels[channel];
  253. access = (val >> 4) & 3;
  254. if (access == 0) {
  255. pit_latch_count(s);
  256. } else {
  257. s->rw_mode = access;
  258. s->read_state = access;
  259. s->write_state = access;
  260. s->mode = (val >> 1) & 7;
  261. s->bcd = val & 1;
  262. /* XXX: update irq timer ? */
  263. }
  264. }
  265. } else {
  266. s = &pit->channels[addr];
  267. switch(s->write_state) {
  268. default:
  269. case RW_STATE_LSB:
  270. pit_load_count(s, val);
  271. break;
  272. case RW_STATE_MSB:
  273. pit_load_count(s, val << 8);
  274. break;
  275. case RW_STATE_WORD0:
  276. s->write_latch = val;
  277. s->write_state = RW_STATE_WORD1;
  278. break;
  279. case RW_STATE_WORD1:
  280. pit_load_count(s, s->write_latch | (val << 8));
  281. s->write_state = RW_STATE_WORD0;
  282. break;
  283. }
  284. }
  285. }
  286. static uint32_t pit_ioport_read(void *opaque, uint32_t addr)
  287. {
  288. PITState *pit = opaque;
  289. int ret, count;
  290. PITChannelState *s;
  291. addr &= 3;
  292. s = &pit->channels[addr];
  293. if (s->status_latched) {
  294. s->status_latched = 0;
  295. ret = s->status;
  296. } else if (s->count_latched) {
  297. switch(s->count_latched) {
  298. default:
  299. case RW_STATE_LSB:
  300. ret = s->latched_count & 0xff;
  301. s->count_latched = 0;
  302. break;
  303. case RW_STATE_MSB:
  304. ret = s->latched_count >> 8;
  305. s->count_latched = 0;
  306. break;
  307. case RW_STATE_WORD0:
  308. ret = s->latched_count & 0xff;
  309. s->count_latched = RW_STATE_MSB;
  310. break;
  311. }
  312. } else {
  313. switch(s->read_state) {
  314. default:
  315. case RW_STATE_LSB:
  316. count = pit_get_count(s);
  317. ret = count & 0xff;
  318. break;
  319. case RW_STATE_MSB:
  320. count = pit_get_count(s);
  321. ret = (count >> 8) & 0xff;
  322. break;
  323. case RW_STATE_WORD0:
  324. count = pit_get_count(s);
  325. ret = count & 0xff;
  326. s->read_state = RW_STATE_WORD1;
  327. break;
  328. case RW_STATE_WORD1:
  329. count = pit_get_count(s);
  330. ret = (count >> 8) & 0xff;
  331. s->read_state = RW_STATE_WORD0;
  332. break;
  333. }
  334. }
  335. return ret;
  336. }
  337. static void pit_irq_timer_update(PITChannelState *s, int64_t current_time)
  338. {
  339. int64_t expire_time;
  340. int irq_level;
  341. if (!s->irq_timer)
  342. return;
  343. expire_time = pit_get_next_transition_time(s, current_time);
  344. irq_level = pit_get_out1(s, current_time);
  345. qemu_set_irq(s->irq, irq_level);
  346. #ifdef DEBUG_PIT
  347. printf("irq_level=%d next_delay=%f\n",
  348. irq_level,
  349. (double)(expire_time - current_time) / ticks_per_sec);
  350. #endif
  351. s->next_transition_time = expire_time;
  352. if (expire_time != -1)
  353. qemu_mod_timer(s->irq_timer, expire_time);
  354. else
  355. qemu_del_timer(s->irq_timer);
  356. }
  357. static void pit_irq_timer(void *opaque)
  358. {
  359. PITChannelState *s = opaque;
  360. pit_irq_timer_update(s, s->next_transition_time);
  361. }
  362. static void pit_save(QEMUFile *f, void *opaque)
  363. {
  364. PITState *pit = opaque;
  365. PITChannelState *s;
  366. int i;
  367. for(i = 0; i < 3; i++) {
  368. s = &pit->channels[i];
  369. qemu_put_be32(f, s->count);
  370. qemu_put_be16s(f, &s->latched_count);
  371. qemu_put_8s(f, &s->count_latched);
  372. qemu_put_8s(f, &s->status_latched);
  373. qemu_put_8s(f, &s->status);
  374. qemu_put_8s(f, &s->read_state);
  375. qemu_put_8s(f, &s->write_state);
  376. qemu_put_8s(f, &s->write_latch);
  377. qemu_put_8s(f, &s->rw_mode);
  378. qemu_put_8s(f, &s->mode);
  379. qemu_put_8s(f, &s->bcd);
  380. qemu_put_8s(f, &s->gate);
  381. qemu_put_be64(f, s->count_load_time);
  382. if (s->irq_timer) {
  383. qemu_put_be64(f, s->next_transition_time);
  384. qemu_put_timer(f, s->irq_timer);
  385. }
  386. }
  387. }
  388. static int pit_load(QEMUFile *f, void *opaque, int version_id)
  389. {
  390. PITState *pit = opaque;
  391. PITChannelState *s;
  392. int i;
  393. if (version_id != 1)
  394. return -EINVAL;
  395. for(i = 0; i < 3; i++) {
  396. s = &pit->channels[i];
  397. s->count=qemu_get_be32(f);
  398. qemu_get_be16s(f, &s->latched_count);
  399. qemu_get_8s(f, &s->count_latched);
  400. qemu_get_8s(f, &s->status_latched);
  401. qemu_get_8s(f, &s->status);
  402. qemu_get_8s(f, &s->read_state);
  403. qemu_get_8s(f, &s->write_state);
  404. qemu_get_8s(f, &s->write_latch);
  405. qemu_get_8s(f, &s->rw_mode);
  406. qemu_get_8s(f, &s->mode);
  407. qemu_get_8s(f, &s->bcd);
  408. qemu_get_8s(f, &s->gate);
  409. s->count_load_time=qemu_get_be64(f);
  410. if (s->irq_timer) {
  411. s->next_transition_time=qemu_get_be64(f);
  412. qemu_get_timer(f, s->irq_timer);
  413. }
  414. }
  415. return 0;
  416. }
  417. static void pit_reset(void *opaque)
  418. {
  419. PITState *pit = opaque;
  420. PITChannelState *s;
  421. int i;
  422. for(i = 0;i < 3; i++) {
  423. s = &pit->channels[i];
  424. s->mode = 3;
  425. s->gate = (i != 2);
  426. pit_load_count(s, 0);
  427. }
  428. }
  429. /* When HPET is operating in legacy mode, i8254 timer0 is disabled */
  430. void hpet_pit_disable(void) {
  431. PITChannelState *s;
  432. s = &pit_state.channels[0];
  433. if (s->irq_timer)
  434. qemu_del_timer(s->irq_timer);
  435. }
  436. /* When HPET is reset or leaving legacy mode, it must reenable i8254
  437. * timer 0
  438. */
  439. void hpet_pit_enable(void)
  440. {
  441. PITState *pit = &pit_state;
  442. PITChannelState *s;
  443. s = &pit->channels[0];
  444. s->mode = 3;
  445. s->gate = 1;
  446. pit_load_count(s, 0);
  447. }
  448. PITState *pit_init(int base, qemu_irq irq)
  449. {
  450. PITState *pit = &pit_state;
  451. PITChannelState *s;
  452. s = &pit->channels[0];
  453. /* the timer 0 is connected to an IRQ */
  454. s->irq_timer = qemu_new_timer(vm_clock, pit_irq_timer, s);
  455. s->irq = irq;
  456. register_savevm("i8254", base, 1, pit_save, pit_load, pit);
  457. qemu_register_reset(pit_reset, pit);
  458. register_ioport_write(base, 4, 1, pit_ioport_write, pit);
  459. register_ioport_read(base, 3, 1, pit_ioport_read, pit);
  460. pit_reset(pit);
  461. return pit;
  462. }