mos6522.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  1. /*
  2. * QEMU MOS6522 VIA emulation
  3. *
  4. * Copyright (c) 2004-2007 Fabrice Bellard
  5. * Copyright (c) 2007 Jocelyn Mayer
  6. * Copyright (c) 2018 Mark Cave-Ayland
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documentation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included in
  16. * all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  21. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. * THE SOFTWARE.
  25. */
  26. #include "qemu/osdep.h"
  27. #include "hw/irq.h"
  28. #include "hw/misc/mos6522.h"
  29. #include "hw/qdev-properties.h"
  30. #include "migration/vmstate.h"
  31. #include "monitor/monitor.h"
  32. #include "monitor/hmp.h"
  33. #include "qapi/type-helpers.h"
  34. #include "qemu/timer.h"
  35. #include "qemu/cutils.h"
  36. #include "qemu/log.h"
  37. #include "qemu/module.h"
  38. #include "trace.h"
  39. static const char *mos6522_reg_names[MOS6522_NUM_REGS] = {
  40. "ORB", "ORA", "DDRB", "DDRA", "T1CL", "T1CH", "T1LL", "T1LH",
  41. "T2CL", "T2CH", "SR", "ACR", "PCR", "IFR", "IER", "ANH"
  42. };
  43. /* XXX: implement all timer modes */
  44. static void mos6522_timer1_update(MOS6522State *s, MOS6522Timer *ti,
  45. int64_t current_time);
  46. static void mos6522_timer2_update(MOS6522State *s, MOS6522Timer *ti,
  47. int64_t current_time);
  48. static void mos6522_update_irq(MOS6522State *s)
  49. {
  50. if (s->ifr & s->ier) {
  51. qemu_irq_raise(s->irq);
  52. } else {
  53. qemu_irq_lower(s->irq);
  54. }
  55. }
  56. static void mos6522_set_irq(void *opaque, int n, int level)
  57. {
  58. MOS6522State *s = MOS6522(opaque);
  59. int last_level = !!(s->last_irq_levels & (1 << n));
  60. uint8_t last_ifr = s->ifr;
  61. bool positive_edge = true;
  62. int ctrl;
  63. /*
  64. * SR_INT is managed by mos6522 instances and cleared upon SR
  65. * read. It is only the external CA1/2 and CB1/2 lines that
  66. * are edge-triggered and latched in IFR
  67. */
  68. if (n != SR_INT_BIT && level == last_level) {
  69. return;
  70. }
  71. /* Detect negative edge trigger */
  72. if (last_level == 1 && level == 0) {
  73. positive_edge = false;
  74. }
  75. switch (n) {
  76. case CA2_INT_BIT:
  77. ctrl = (s->pcr & CA2_CTRL_MASK) >> CA2_CTRL_SHIFT;
  78. if ((positive_edge && (ctrl & C2_POS)) ||
  79. (!positive_edge && !(ctrl & C2_POS))) {
  80. s->ifr |= 1 << n;
  81. }
  82. break;
  83. case CA1_INT_BIT:
  84. ctrl = (s->pcr & CA1_CTRL_MASK) >> CA1_CTRL_SHIFT;
  85. if ((positive_edge && (ctrl & C1_POS)) ||
  86. (!positive_edge && !(ctrl & C1_POS))) {
  87. s->ifr |= 1 << n;
  88. }
  89. break;
  90. case SR_INT_BIT:
  91. s->ifr |= 1 << n;
  92. break;
  93. case CB2_INT_BIT:
  94. ctrl = (s->pcr & CB2_CTRL_MASK) >> CB2_CTRL_SHIFT;
  95. if ((positive_edge && (ctrl & C2_POS)) ||
  96. (!positive_edge && !(ctrl & C2_POS))) {
  97. s->ifr |= 1 << n;
  98. }
  99. break;
  100. case CB1_INT_BIT:
  101. ctrl = (s->pcr & CB1_CTRL_MASK) >> CB1_CTRL_SHIFT;
  102. if ((positive_edge && (ctrl & C1_POS)) ||
  103. (!positive_edge && !(ctrl & C1_POS))) {
  104. s->ifr |= 1 << n;
  105. }
  106. break;
  107. }
  108. if (s->ifr != last_ifr) {
  109. mos6522_update_irq(s);
  110. }
  111. if (level) {
  112. s->last_irq_levels |= 1 << n;
  113. } else {
  114. s->last_irq_levels &= ~(1 << n);
  115. }
  116. }
  117. static uint64_t get_counter_value(MOS6522State *s, MOS6522Timer *ti)
  118. {
  119. MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(s);
  120. if (ti->index == 0) {
  121. return mdc->get_timer1_counter_value(s, ti);
  122. } else {
  123. return mdc->get_timer2_counter_value(s, ti);
  124. }
  125. }
  126. static uint64_t get_load_time(MOS6522State *s, MOS6522Timer *ti)
  127. {
  128. MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(s);
  129. if (ti->index == 0) {
  130. return mdc->get_timer1_load_time(s, ti);
  131. } else {
  132. return mdc->get_timer2_load_time(s, ti);
  133. }
  134. }
  135. static unsigned int get_counter(MOS6522State *s, MOS6522Timer *ti)
  136. {
  137. int64_t d;
  138. unsigned int counter;
  139. d = get_counter_value(s, ti);
  140. if (ti->index == 0) {
  141. /* the timer goes down from latch to -1 (period of latch + 2) */
  142. if (d <= (ti->counter_value + 1)) {
  143. counter = (ti->counter_value - d) & 0xffff;
  144. } else {
  145. counter = (d - (ti->counter_value + 1)) % (ti->latch + 2);
  146. counter = (ti->latch - counter) & 0xffff;
  147. }
  148. } else {
  149. counter = (ti->counter_value - d) & 0xffff;
  150. }
  151. return counter;
  152. }
  153. static void set_counter(MOS6522State *s, MOS6522Timer *ti, unsigned int val)
  154. {
  155. trace_mos6522_set_counter(1 + ti->index, val);
  156. ti->load_time = get_load_time(s, ti);
  157. ti->counter_value = val;
  158. if (ti->index == 0) {
  159. mos6522_timer1_update(s, ti, ti->load_time);
  160. } else {
  161. mos6522_timer2_update(s, ti, ti->load_time);
  162. }
  163. }
  164. static int64_t get_next_irq_time(MOS6522State *s, MOS6522Timer *ti,
  165. int64_t current_time)
  166. {
  167. int64_t d, next_time;
  168. unsigned int counter;
  169. if (ti->frequency == 0) {
  170. return INT64_MAX;
  171. }
  172. /* current counter value */
  173. d = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - ti->load_time,
  174. ti->frequency, NANOSECONDS_PER_SECOND);
  175. /* the timer goes down from latch to -1 (period of latch + 2) */
  176. if (d <= (ti->counter_value + 1)) {
  177. counter = (ti->counter_value - d) & 0xffff;
  178. } else {
  179. counter = (d - (ti->counter_value + 1)) % (ti->latch + 2);
  180. counter = (ti->latch - counter) & 0xffff;
  181. }
  182. /* Note: we consider the irq is raised on 0 */
  183. if (counter == 0xffff) {
  184. next_time = d + ti->latch + 1;
  185. } else if (counter == 0) {
  186. next_time = d + ti->latch + 2;
  187. } else {
  188. next_time = d + counter;
  189. }
  190. trace_mos6522_get_next_irq_time(ti->latch, d, next_time - d);
  191. next_time = muldiv64(next_time, NANOSECONDS_PER_SECOND, ti->frequency) +
  192. ti->load_time;
  193. if (next_time <= current_time) {
  194. next_time = current_time + 1;
  195. }
  196. return next_time;
  197. }
  198. static void mos6522_timer1_update(MOS6522State *s, MOS6522Timer *ti,
  199. int64_t current_time)
  200. {
  201. if (!ti->timer) {
  202. return;
  203. }
  204. ti->next_irq_time = get_next_irq_time(s, ti, current_time);
  205. if ((s->ier & T1_INT) == 0 || (s->acr & T1MODE) != T1MODE_CONT) {
  206. timer_del(ti->timer);
  207. } else {
  208. timer_mod(ti->timer, ti->next_irq_time);
  209. }
  210. }
  211. static void mos6522_timer2_update(MOS6522State *s, MOS6522Timer *ti,
  212. int64_t current_time)
  213. {
  214. if (!ti->timer) {
  215. return;
  216. }
  217. ti->next_irq_time = get_next_irq_time(s, ti, current_time);
  218. if ((s->ier & T2_INT) == 0) {
  219. timer_del(ti->timer);
  220. } else {
  221. timer_mod(ti->timer, ti->next_irq_time);
  222. }
  223. }
  224. static void mos6522_timer1(void *opaque)
  225. {
  226. MOS6522State *s = opaque;
  227. MOS6522Timer *ti = &s->timers[0];
  228. mos6522_timer1_update(s, ti, ti->next_irq_time);
  229. s->ifr |= T1_INT;
  230. mos6522_update_irq(s);
  231. }
  232. static void mos6522_timer2(void *opaque)
  233. {
  234. MOS6522State *s = opaque;
  235. MOS6522Timer *ti = &s->timers[1];
  236. mos6522_timer2_update(s, ti, ti->next_irq_time);
  237. s->ifr |= T2_INT;
  238. mos6522_update_irq(s);
  239. }
  240. static uint64_t mos6522_get_counter_value(MOS6522State *s, MOS6522Timer *ti)
  241. {
  242. return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - ti->load_time,
  243. ti->frequency, NANOSECONDS_PER_SECOND);
  244. }
  245. static uint64_t mos6522_get_load_time(MOS6522State *s, MOS6522Timer *ti)
  246. {
  247. uint64_t load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
  248. return load_time;
  249. }
  250. static void mos6522_portA_write(MOS6522State *s)
  251. {
  252. qemu_log_mask(LOG_UNIMP, "portA_write unimplemented\n");
  253. }
  254. static void mos6522_portB_write(MOS6522State *s)
  255. {
  256. qemu_log_mask(LOG_UNIMP, "portB_write unimplemented\n");
  257. }
  258. uint64_t mos6522_read(void *opaque, hwaddr addr, unsigned size)
  259. {
  260. MOS6522State *s = opaque;
  261. uint32_t val;
  262. int ctrl;
  263. int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
  264. if (now >= s->timers[0].next_irq_time) {
  265. mos6522_timer1_update(s, &s->timers[0], now);
  266. s->ifr |= T1_INT;
  267. }
  268. if (now >= s->timers[1].next_irq_time) {
  269. mos6522_timer2_update(s, &s->timers[1], now);
  270. s->ifr |= T2_INT;
  271. }
  272. switch (addr) {
  273. case VIA_REG_B:
  274. val = s->b;
  275. ctrl = (s->pcr & CB2_CTRL_MASK) >> CB2_CTRL_SHIFT;
  276. if (!(ctrl & C2_IND)) {
  277. s->ifr &= ~CB2_INT;
  278. }
  279. s->ifr &= ~CB1_INT;
  280. mos6522_update_irq(s);
  281. break;
  282. case VIA_REG_A:
  283. qemu_log_mask(LOG_UNIMP, "Read access to register A with handshake");
  284. /* fall through */
  285. case VIA_REG_ANH:
  286. val = s->a;
  287. ctrl = (s->pcr & CA2_CTRL_MASK) >> CA2_CTRL_SHIFT;
  288. if (!(ctrl & C2_IND)) {
  289. s->ifr &= ~CA2_INT;
  290. }
  291. s->ifr &= ~CA1_INT;
  292. mos6522_update_irq(s);
  293. break;
  294. case VIA_REG_DIRB:
  295. val = s->dirb;
  296. break;
  297. case VIA_REG_DIRA:
  298. val = s->dira;
  299. break;
  300. case VIA_REG_T1CL:
  301. val = get_counter(s, &s->timers[0]) & 0xff;
  302. s->ifr &= ~T1_INT;
  303. mos6522_update_irq(s);
  304. break;
  305. case VIA_REG_T1CH:
  306. val = get_counter(s, &s->timers[0]) >> 8;
  307. mos6522_update_irq(s);
  308. break;
  309. case VIA_REG_T1LL:
  310. val = s->timers[0].latch & 0xff;
  311. break;
  312. case VIA_REG_T1LH:
  313. /* XXX: check this */
  314. val = (s->timers[0].latch >> 8) & 0xff;
  315. break;
  316. case VIA_REG_T2CL:
  317. val = get_counter(s, &s->timers[1]) & 0xff;
  318. s->ifr &= ~T2_INT;
  319. mos6522_update_irq(s);
  320. break;
  321. case VIA_REG_T2CH:
  322. val = get_counter(s, &s->timers[1]) >> 8;
  323. break;
  324. case VIA_REG_SR:
  325. val = s->sr;
  326. s->ifr &= ~SR_INT;
  327. mos6522_update_irq(s);
  328. break;
  329. case VIA_REG_ACR:
  330. val = s->acr;
  331. break;
  332. case VIA_REG_PCR:
  333. val = s->pcr;
  334. break;
  335. case VIA_REG_IFR:
  336. val = s->ifr;
  337. if (s->ifr & s->ier) {
  338. val |= 0x80;
  339. }
  340. break;
  341. case VIA_REG_IER:
  342. val = s->ier | 0x80;
  343. break;
  344. default:
  345. g_assert_not_reached();
  346. }
  347. if (addr != VIA_REG_IFR || val != 0) {
  348. trace_mos6522_read(addr, mos6522_reg_names[addr], val);
  349. }
  350. return val;
  351. }
  352. void mos6522_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
  353. {
  354. MOS6522State *s = opaque;
  355. MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(s);
  356. int ctrl;
  357. trace_mos6522_write(addr, mos6522_reg_names[addr], val);
  358. switch (addr) {
  359. case VIA_REG_B:
  360. s->b = (s->b & ~s->dirb) | (val & s->dirb);
  361. mdc->portB_write(s);
  362. ctrl = (s->pcr & CB2_CTRL_MASK) >> CB2_CTRL_SHIFT;
  363. if (!(ctrl & C2_IND)) {
  364. s->ifr &= ~CB2_INT;
  365. }
  366. s->ifr &= ~CB1_INT;
  367. mos6522_update_irq(s);
  368. break;
  369. case VIA_REG_A:
  370. qemu_log_mask(LOG_UNIMP, "Write access to register A with handshake");
  371. /* fall through */
  372. case VIA_REG_ANH:
  373. s->a = (s->a & ~s->dira) | (val & s->dira);
  374. mdc->portA_write(s);
  375. ctrl = (s->pcr & CA2_CTRL_MASK) >> CA2_CTRL_SHIFT;
  376. if (!(ctrl & C2_IND)) {
  377. s->ifr &= ~CA2_INT;
  378. }
  379. s->ifr &= ~CA1_INT;
  380. mos6522_update_irq(s);
  381. break;
  382. case VIA_REG_DIRB:
  383. s->dirb = val;
  384. break;
  385. case VIA_REG_DIRA:
  386. s->dira = val;
  387. break;
  388. case VIA_REG_T1CL:
  389. s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
  390. mos6522_timer1_update(s, &s->timers[0],
  391. qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
  392. break;
  393. case VIA_REG_T1CH:
  394. s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
  395. s->ifr &= ~T1_INT;
  396. set_counter(s, &s->timers[0], s->timers[0].latch);
  397. break;
  398. case VIA_REG_T1LL:
  399. s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
  400. mos6522_timer1_update(s, &s->timers[0],
  401. qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
  402. break;
  403. case VIA_REG_T1LH:
  404. s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
  405. s->ifr &= ~T1_INT;
  406. mos6522_timer1_update(s, &s->timers[0],
  407. qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
  408. break;
  409. case VIA_REG_T2CL:
  410. s->timers[1].latch = (s->timers[1].latch & 0xff00) | val;
  411. break;
  412. case VIA_REG_T2CH:
  413. /* To ensure T2 generates an interrupt on zero crossing with the
  414. common timer code, write the value directly from the latch to
  415. the counter */
  416. s->timers[1].latch = (s->timers[1].latch & 0xff) | (val << 8);
  417. s->ifr &= ~T2_INT;
  418. set_counter(s, &s->timers[1], s->timers[1].latch);
  419. break;
  420. case VIA_REG_SR:
  421. s->sr = val;
  422. break;
  423. case VIA_REG_ACR:
  424. s->acr = val;
  425. mos6522_timer1_update(s, &s->timers[0],
  426. qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
  427. break;
  428. case VIA_REG_PCR:
  429. s->pcr = val;
  430. break;
  431. case VIA_REG_IFR:
  432. /* reset bits */
  433. s->ifr &= ~val;
  434. mos6522_update_irq(s);
  435. break;
  436. case VIA_REG_IER:
  437. if (val & IER_SET) {
  438. /* set bits */
  439. s->ier |= val & 0x7f;
  440. } else {
  441. /* reset bits */
  442. s->ier &= ~val;
  443. }
  444. mos6522_update_irq(s);
  445. /* if IER is modified starts needed timers */
  446. mos6522_timer1_update(s, &s->timers[0],
  447. qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
  448. mos6522_timer2_update(s, &s->timers[1],
  449. qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
  450. break;
  451. default:
  452. g_assert_not_reached();
  453. }
  454. }
  455. static int qmp_x_query_via_foreach(Object *obj, void *opaque)
  456. {
  457. GString *buf = opaque;
  458. if (object_dynamic_cast(obj, TYPE_MOS6522)) {
  459. MOS6522State *s = MOS6522(obj);
  460. int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
  461. uint16_t t1counter = get_counter(s, &s->timers[0]);
  462. uint16_t t2counter = get_counter(s, &s->timers[1]);
  463. g_string_append_printf(buf, "%s:\n", object_get_typename(obj));
  464. g_string_append_printf(buf, " Registers:\n");
  465. g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
  466. mos6522_reg_names[0], s->b);
  467. g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
  468. mos6522_reg_names[1], s->a);
  469. g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
  470. mos6522_reg_names[2], s->dirb);
  471. g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
  472. mos6522_reg_names[3], s->dira);
  473. g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
  474. mos6522_reg_names[4], t1counter & 0xff);
  475. g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
  476. mos6522_reg_names[5], t1counter >> 8);
  477. g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
  478. mos6522_reg_names[6],
  479. s->timers[0].latch & 0xff);
  480. g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
  481. mos6522_reg_names[7],
  482. s->timers[0].latch >> 8);
  483. g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
  484. mos6522_reg_names[8], t2counter & 0xff);
  485. g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
  486. mos6522_reg_names[9], t2counter >> 8);
  487. g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
  488. mos6522_reg_names[10], s->sr);
  489. g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
  490. mos6522_reg_names[11], s->acr);
  491. g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
  492. mos6522_reg_names[12], s->pcr);
  493. g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
  494. mos6522_reg_names[13], s->ifr);
  495. g_string_append_printf(buf, " %-*s: 0x%x\n", 4,
  496. mos6522_reg_names[14], s->ier);
  497. g_string_append_printf(buf, " Timers:\n");
  498. g_string_append_printf(buf, " Using current time now(ns)=%"PRId64
  499. "\n", now);
  500. g_string_append_printf(buf, " T1 freq(hz)=%"PRId64
  501. " mode=%s"
  502. " counter=0x%x"
  503. " latch=0x%x\n"
  504. " load_time(ns)=%"PRId64
  505. " next_irq_time(ns)=%"PRId64 "\n",
  506. s->timers[0].frequency,
  507. ((s->acr & T1MODE) == T1MODE_CONT) ? "continuous"
  508. : "one-shot",
  509. t1counter,
  510. s->timers[0].latch,
  511. s->timers[0].load_time,
  512. get_next_irq_time(s, &s->timers[0], now));
  513. g_string_append_printf(buf, " T2 freq(hz)=%"PRId64
  514. " mode=%s"
  515. " counter=0x%x"
  516. " latch=0x%x\n"
  517. " load_time(ns)=%"PRId64
  518. " next_irq_time(ns)=%"PRId64 "\n",
  519. s->timers[1].frequency,
  520. "one-shot",
  521. t2counter,
  522. s->timers[1].latch,
  523. s->timers[1].load_time,
  524. get_next_irq_time(s, &s->timers[1], now));
  525. }
  526. return 0;
  527. }
  528. static HumanReadableText *qmp_x_query_via(Error **errp)
  529. {
  530. g_autoptr(GString) buf = g_string_new("");
  531. object_child_foreach_recursive(object_get_root(),
  532. qmp_x_query_via_foreach, buf);
  533. return human_readable_text_from_str(buf);
  534. }
  535. void hmp_info_via(Monitor *mon, const QDict *qdict)
  536. {
  537. Error *err = NULL;
  538. g_autoptr(HumanReadableText) info = qmp_x_query_via(&err);
  539. if (hmp_handle_error(mon, err)) {
  540. return;
  541. }
  542. monitor_puts(mon, info->human_readable_text);
  543. }
  544. static const MemoryRegionOps mos6522_ops = {
  545. .read = mos6522_read,
  546. .write = mos6522_write,
  547. .endianness = DEVICE_NATIVE_ENDIAN,
  548. .valid = {
  549. .min_access_size = 1,
  550. .max_access_size = 1,
  551. },
  552. };
  553. static const VMStateDescription vmstate_mos6522_timer = {
  554. .name = "mos6522_timer",
  555. .version_id = 0,
  556. .minimum_version_id = 0,
  557. .fields = (VMStateField[]) {
  558. VMSTATE_UINT16(latch, MOS6522Timer),
  559. VMSTATE_UINT16(counter_value, MOS6522Timer),
  560. VMSTATE_INT64(load_time, MOS6522Timer),
  561. VMSTATE_INT64(next_irq_time, MOS6522Timer),
  562. VMSTATE_TIMER_PTR(timer, MOS6522Timer),
  563. VMSTATE_END_OF_LIST()
  564. }
  565. };
  566. const VMStateDescription vmstate_mos6522 = {
  567. .name = "mos6522",
  568. .version_id = 1,
  569. .minimum_version_id = 1,
  570. .fields = (VMStateField[]) {
  571. VMSTATE_UINT8(a, MOS6522State),
  572. VMSTATE_UINT8(b, MOS6522State),
  573. VMSTATE_UINT8(dira, MOS6522State),
  574. VMSTATE_UINT8(dirb, MOS6522State),
  575. VMSTATE_UINT8(sr, MOS6522State),
  576. VMSTATE_UINT8(acr, MOS6522State),
  577. VMSTATE_UINT8(pcr, MOS6522State),
  578. VMSTATE_UINT8(ifr, MOS6522State),
  579. VMSTATE_UINT8(ier, MOS6522State),
  580. VMSTATE_UINT8(last_irq_levels, MOS6522State),
  581. VMSTATE_STRUCT_ARRAY(timers, MOS6522State, 2, 0,
  582. vmstate_mos6522_timer, MOS6522Timer),
  583. VMSTATE_END_OF_LIST()
  584. }
  585. };
  586. static void mos6522_reset_hold(Object *obj)
  587. {
  588. MOS6522State *s = MOS6522(obj);
  589. s->b = 0;
  590. s->a = 0;
  591. s->dirb = 0xff;
  592. s->dira = 0;
  593. s->sr = 0;
  594. s->acr = 0;
  595. s->pcr = 0;
  596. s->ifr = 0;
  597. s->ier = 0;
  598. /* s->ier = T1_INT | SR_INT; */
  599. s->timers[0].frequency = s->frequency;
  600. s->timers[0].latch = 0xffff;
  601. set_counter(s, &s->timers[0], 0xffff);
  602. timer_del(s->timers[0].timer);
  603. s->timers[1].frequency = s->frequency;
  604. s->timers[1].latch = 0xffff;
  605. timer_del(s->timers[1].timer);
  606. }
  607. static void mos6522_init(Object *obj)
  608. {
  609. SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
  610. MOS6522State *s = MOS6522(obj);
  611. int i;
  612. memory_region_init_io(&s->mem, obj, &mos6522_ops, s, "mos6522",
  613. MOS6522_NUM_REGS);
  614. sysbus_init_mmio(sbd, &s->mem);
  615. sysbus_init_irq(sbd, &s->irq);
  616. for (i = 0; i < ARRAY_SIZE(s->timers); i++) {
  617. s->timers[i].index = i;
  618. }
  619. s->timers[0].timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, mos6522_timer1, s);
  620. s->timers[1].timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, mos6522_timer2, s);
  621. qdev_init_gpio_in(DEVICE(obj), mos6522_set_irq, VIA_NUM_INTS);
  622. }
  623. static void mos6522_finalize(Object *obj)
  624. {
  625. MOS6522State *s = MOS6522(obj);
  626. timer_free(s->timers[0].timer);
  627. timer_free(s->timers[1].timer);
  628. }
  629. static Property mos6522_properties[] = {
  630. DEFINE_PROP_UINT64("frequency", MOS6522State, frequency, 0),
  631. DEFINE_PROP_END_OF_LIST()
  632. };
  633. static void mos6522_class_init(ObjectClass *oc, void *data)
  634. {
  635. DeviceClass *dc = DEVICE_CLASS(oc);
  636. ResettableClass *rc = RESETTABLE_CLASS(oc);
  637. MOS6522DeviceClass *mdc = MOS6522_CLASS(oc);
  638. rc->phases.hold = mos6522_reset_hold;
  639. dc->vmsd = &vmstate_mos6522;
  640. device_class_set_props(dc, mos6522_properties);
  641. mdc->portB_write = mos6522_portB_write;
  642. mdc->portA_write = mos6522_portA_write;
  643. mdc->get_timer1_counter_value = mos6522_get_counter_value;
  644. mdc->get_timer2_counter_value = mos6522_get_counter_value;
  645. mdc->get_timer1_load_time = mos6522_get_load_time;
  646. mdc->get_timer2_load_time = mos6522_get_load_time;
  647. }
  648. static const TypeInfo mos6522_type_info = {
  649. .name = TYPE_MOS6522,
  650. .parent = TYPE_SYS_BUS_DEVICE,
  651. .instance_size = sizeof(MOS6522State),
  652. .instance_init = mos6522_init,
  653. .instance_finalize = mos6522_finalize,
  654. .abstract = true,
  655. .class_size = sizeof(MOS6522DeviceClass),
  656. .class_init = mos6522_class_init,
  657. };
  658. static void mos6522_register_types(void)
  659. {
  660. type_register_static(&mos6522_type_info);
  661. }
  662. type_init(mos6522_register_types)