2
0

pmu.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875
  1. /*
  2. * QEMU PowerMac PMU device support
  3. *
  4. * Copyright (c) 2016 Benjamin Herrenschmidt, IBM Corp.
  5. * Copyright (c) 2018 Mark Cave-Ayland
  6. *
  7. * Based on the CUDA device by:
  8. *
  9. * Copyright (c) 2004-2007 Fabrice Bellard
  10. * Copyright (c) 2007 Jocelyn Mayer
  11. *
  12. * Permission is hereby granted, free of charge, to any person obtaining a copy
  13. * of this software and associated documentation files (the "Software"), to deal
  14. * in the Software without restriction, including without limitation the rights
  15. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  16. * copies of the Software, and to permit persons to whom the Software is
  17. * furnished to do so, subject to the following conditions:
  18. *
  19. * The above copyright notice and this permission notice shall be included in
  20. * all copies or substantial portions of the Software.
  21. *
  22. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  23. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  24. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  25. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  26. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  27. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  28. * THE SOFTWARE.
  29. */
  30. #include "qemu/osdep.h"
  31. #include "qemu-common.h"
  32. #include "hw/ppc/mac.h"
  33. #include "hw/qdev-properties.h"
  34. #include "migration/vmstate.h"
  35. #include "hw/input/adb.h"
  36. #include "hw/irq.h"
  37. #include "hw/misc/mos6522.h"
  38. #include "hw/misc/macio/gpio.h"
  39. #include "hw/misc/macio/pmu.h"
  40. #include "qemu/timer.h"
  41. #include "sysemu/runstate.h"
  42. #include "qemu/cutils.h"
  43. #include "qemu/log.h"
  44. #include "qemu/module.h"
  45. #include "trace.h"
  46. /* Bits in B data register: all active low */
  47. #define TACK 0x08 /* Transfer request (input) */
  48. #define TREQ 0x10 /* Transfer acknowledge (output) */
  49. /* PMU returns time_t's offset from Jan 1, 1904, not 1970 */
  50. #define RTC_OFFSET 2082844800
  51. #define VIA_TIMER_FREQ (4700000 / 6)
  52. static void via_update_irq(PMUState *s)
  53. {
  54. MOS6522PMUState *mps = MOS6522_PMU(&s->mos6522_pmu);
  55. MOS6522State *ms = MOS6522(mps);
  56. bool new_state = !!(ms->ifr & ms->ier & (SR_INT | T1_INT | T2_INT));
  57. if (new_state != s->via_irq_state) {
  58. s->via_irq_state = new_state;
  59. qemu_set_irq(s->via_irq, new_state);
  60. }
  61. }
  62. static void via_set_sr_int(void *opaque)
  63. {
  64. PMUState *s = opaque;
  65. MOS6522PMUState *mps = MOS6522_PMU(&s->mos6522_pmu);
  66. MOS6522State *ms = MOS6522(mps);
  67. MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(ms);
  68. mdc->set_sr_int(ms);
  69. }
  70. static void pmu_update_extirq(PMUState *s)
  71. {
  72. if ((s->intbits & s->intmask) != 0) {
  73. macio_set_gpio(s->gpio, 1, false);
  74. } else {
  75. macio_set_gpio(s->gpio, 1, true);
  76. }
  77. }
  78. static void pmu_adb_poll(void *opaque)
  79. {
  80. PMUState *s = opaque;
  81. int olen;
  82. if (!(s->intbits & PMU_INT_ADB)) {
  83. olen = adb_poll(&s->adb_bus, s->adb_reply, s->adb_poll_mask);
  84. trace_pmu_adb_poll(olen);
  85. if (olen > 0) {
  86. s->adb_reply_size = olen;
  87. s->intbits |= PMU_INT_ADB | PMU_INT_ADB_AUTO;
  88. pmu_update_extirq(s);
  89. }
  90. }
  91. timer_mod(s->adb_poll_timer,
  92. qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 30);
  93. }
  94. static void pmu_one_sec_timer(void *opaque)
  95. {
  96. PMUState *s = opaque;
  97. trace_pmu_one_sec_timer();
  98. s->intbits |= PMU_INT_TICK;
  99. pmu_update_extirq(s);
  100. s->one_sec_target += 1000;
  101. timer_mod(s->one_sec_timer, s->one_sec_target);
  102. }
  103. static void pmu_cmd_int_ack(PMUState *s,
  104. const uint8_t *in_data, uint8_t in_len,
  105. uint8_t *out_data, uint8_t *out_len)
  106. {
  107. if (in_len != 0) {
  108. qemu_log_mask(LOG_GUEST_ERROR,
  109. "PMU: INT_ACK command, invalid len: %d want: 0\n",
  110. in_len);
  111. return;
  112. }
  113. /* Make appropriate reply packet */
  114. if (s->intbits & PMU_INT_ADB) {
  115. if (!s->adb_reply_size) {
  116. qemu_log_mask(LOG_GUEST_ERROR,
  117. "Odd, PMU_INT_ADB set with no reply in buffer\n");
  118. }
  119. memcpy(out_data + 1, s->adb_reply, s->adb_reply_size);
  120. out_data[0] = s->intbits & (PMU_INT_ADB | PMU_INT_ADB_AUTO);
  121. *out_len = s->adb_reply_size + 1;
  122. s->intbits &= ~(PMU_INT_ADB | PMU_INT_ADB_AUTO);
  123. s->adb_reply_size = 0;
  124. } else {
  125. out_data[0] = s->intbits;
  126. s->intbits = 0;
  127. *out_len = 1;
  128. }
  129. pmu_update_extirq(s);
  130. }
  131. static void pmu_cmd_set_int_mask(PMUState *s,
  132. const uint8_t *in_data, uint8_t in_len,
  133. uint8_t *out_data, uint8_t *out_len)
  134. {
  135. if (in_len != 1) {
  136. qemu_log_mask(LOG_GUEST_ERROR,
  137. "PMU: SET_INT_MASK command, invalid len: %d want: 1\n",
  138. in_len);
  139. return;
  140. }
  141. trace_pmu_cmd_set_int_mask(s->intmask);
  142. s->intmask = in_data[0];
  143. pmu_update_extirq(s);
  144. }
  145. static void pmu_cmd_set_adb_autopoll(PMUState *s, uint16_t mask)
  146. {
  147. trace_pmu_cmd_set_adb_autopoll(mask);
  148. if (s->autopoll_mask == mask) {
  149. return;
  150. }
  151. s->autopoll_mask = mask;
  152. if (mask) {
  153. timer_mod(s->adb_poll_timer,
  154. qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 30);
  155. } else {
  156. timer_del(s->adb_poll_timer);
  157. }
  158. }
  159. static void pmu_cmd_adb(PMUState *s,
  160. const uint8_t *in_data, uint8_t in_len,
  161. uint8_t *out_data, uint8_t *out_len)
  162. {
  163. int len, adblen;
  164. uint8_t adb_cmd[255];
  165. if (in_len < 2) {
  166. qemu_log_mask(LOG_GUEST_ERROR,
  167. "PMU: ADB PACKET, invalid len: %d want at least 2\n",
  168. in_len);
  169. return;
  170. }
  171. *out_len = 0;
  172. if (!s->has_adb) {
  173. trace_pmu_cmd_adb_nobus();
  174. return;
  175. }
  176. /* Set autopoll is a special form of the command */
  177. if (in_data[0] == 0 && in_data[1] == 0x86) {
  178. uint16_t mask = in_data[2];
  179. mask = (mask << 8) | in_data[3];
  180. if (in_len != 4) {
  181. qemu_log_mask(LOG_GUEST_ERROR,
  182. "PMU: ADB Autopoll requires 4 bytes, got %d\n",
  183. in_len);
  184. return;
  185. }
  186. pmu_cmd_set_adb_autopoll(s, mask);
  187. return;
  188. }
  189. trace_pmu_cmd_adb_request(in_len, in_data[0], in_data[1], in_data[2],
  190. in_data[3], in_data[4]);
  191. *out_len = 0;
  192. /* Check ADB len */
  193. adblen = in_data[2];
  194. if (adblen > (in_len - 3)) {
  195. qemu_log_mask(LOG_GUEST_ERROR,
  196. "PMU: ADB len is %d > %d (in_len -3)...erroring\n",
  197. adblen, in_len - 3);
  198. len = -1;
  199. } else if (adblen > 252) {
  200. qemu_log_mask(LOG_GUEST_ERROR, "PMU: ADB command too big!\n");
  201. len = -1;
  202. } else {
  203. /* Format command */
  204. adb_cmd[0] = in_data[0];
  205. memcpy(&adb_cmd[1], &in_data[3], in_len - 3);
  206. len = adb_request(&s->adb_bus, s->adb_reply + 2, adb_cmd, in_len - 2);
  207. trace_pmu_cmd_adb_reply(len);
  208. }
  209. if (len > 0) {
  210. /* XXX Check this */
  211. s->adb_reply_size = len + 2;
  212. s->adb_reply[0] = 0x01;
  213. s->adb_reply[1] = len;
  214. } else {
  215. /* XXX Check this */
  216. s->adb_reply_size = 1;
  217. s->adb_reply[0] = 0x00;
  218. }
  219. s->intbits |= PMU_INT_ADB;
  220. pmu_update_extirq(s);
  221. }
  222. static void pmu_cmd_adb_poll_off(PMUState *s,
  223. const uint8_t *in_data, uint8_t in_len,
  224. uint8_t *out_data, uint8_t *out_len)
  225. {
  226. if (in_len != 0) {
  227. qemu_log_mask(LOG_GUEST_ERROR,
  228. "PMU: ADB POLL OFF command, invalid len: %d want: 0\n",
  229. in_len);
  230. return;
  231. }
  232. if (s->has_adb && s->autopoll_mask) {
  233. timer_del(s->adb_poll_timer);
  234. s->autopoll_mask = false;
  235. }
  236. }
  237. static void pmu_cmd_shutdown(PMUState *s,
  238. const uint8_t *in_data, uint8_t in_len,
  239. uint8_t *out_data, uint8_t *out_len)
  240. {
  241. if (in_len != 4) {
  242. qemu_log_mask(LOG_GUEST_ERROR,
  243. "PMU: SHUTDOWN command, invalid len: %d want: 4\n",
  244. in_len);
  245. return;
  246. }
  247. *out_len = 1;
  248. out_data[0] = 0;
  249. if (in_data[0] != 'M' || in_data[1] != 'A' || in_data[2] != 'T' ||
  250. in_data[3] != 'T') {
  251. qemu_log_mask(LOG_GUEST_ERROR,
  252. "PMU: SHUTDOWN command, Bad MATT signature\n");
  253. return;
  254. }
  255. qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
  256. }
  257. static void pmu_cmd_reset(PMUState *s,
  258. const uint8_t *in_data, uint8_t in_len,
  259. uint8_t *out_data, uint8_t *out_len)
  260. {
  261. if (in_len != 0) {
  262. qemu_log_mask(LOG_GUEST_ERROR,
  263. "PMU: RESET command, invalid len: %d want: 0\n",
  264. in_len);
  265. return;
  266. }
  267. qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
  268. }
  269. static void pmu_cmd_get_rtc(PMUState *s,
  270. const uint8_t *in_data, uint8_t in_len,
  271. uint8_t *out_data, uint8_t *out_len)
  272. {
  273. uint32_t ti;
  274. if (in_len != 0) {
  275. qemu_log_mask(LOG_GUEST_ERROR,
  276. "PMU: GET_RTC command, invalid len: %d want: 0\n",
  277. in_len);
  278. return;
  279. }
  280. ti = s->tick_offset + (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)
  281. / NANOSECONDS_PER_SECOND);
  282. out_data[0] = ti >> 24;
  283. out_data[1] = ti >> 16;
  284. out_data[2] = ti >> 8;
  285. out_data[3] = ti;
  286. *out_len = 4;
  287. }
  288. static void pmu_cmd_set_rtc(PMUState *s,
  289. const uint8_t *in_data, uint8_t in_len,
  290. uint8_t *out_data, uint8_t *out_len)
  291. {
  292. uint32_t ti;
  293. if (in_len != 4) {
  294. qemu_log_mask(LOG_GUEST_ERROR,
  295. "PMU: SET_RTC command, invalid len: %d want: 4\n",
  296. in_len);
  297. return;
  298. }
  299. ti = (((uint32_t)in_data[0]) << 24) + (((uint32_t)in_data[1]) << 16)
  300. + (((uint32_t)in_data[2]) << 8) + in_data[3];
  301. s->tick_offset = ti - (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)
  302. / NANOSECONDS_PER_SECOND);
  303. }
  304. static void pmu_cmd_system_ready(PMUState *s,
  305. const uint8_t *in_data, uint8_t in_len,
  306. uint8_t *out_data, uint8_t *out_len)
  307. {
  308. /* Do nothing */
  309. }
  310. static void pmu_cmd_get_version(PMUState *s,
  311. const uint8_t *in_data, uint8_t in_len,
  312. uint8_t *out_data, uint8_t *out_len)
  313. {
  314. *out_len = 1;
  315. *out_data = 1; /* ??? Check what Apple does */
  316. }
  317. static void pmu_cmd_power_events(PMUState *s,
  318. const uint8_t *in_data, uint8_t in_len,
  319. uint8_t *out_data, uint8_t *out_len)
  320. {
  321. if (in_len < 1) {
  322. qemu_log_mask(LOG_GUEST_ERROR,
  323. "PMU: POWER EVENTS command, invalid len %d, want at least 1\n",
  324. in_len);
  325. return;
  326. }
  327. switch (in_data[0]) {
  328. /* Dummies for now */
  329. case PMU_PWR_GET_POWERUP_EVENTS:
  330. *out_len = 2;
  331. out_data[0] = 0;
  332. out_data[1] = 0;
  333. break;
  334. case PMU_PWR_SET_POWERUP_EVENTS:
  335. case PMU_PWR_CLR_POWERUP_EVENTS:
  336. break;
  337. case PMU_PWR_GET_WAKEUP_EVENTS:
  338. *out_len = 2;
  339. out_data[0] = 0;
  340. out_data[1] = 0;
  341. break;
  342. case PMU_PWR_SET_WAKEUP_EVENTS:
  343. case PMU_PWR_CLR_WAKEUP_EVENTS:
  344. break;
  345. default:
  346. qemu_log_mask(LOG_GUEST_ERROR,
  347. "PMU: POWER EVENTS unknown subcommand 0x%02x\n",
  348. in_data[0]);
  349. }
  350. }
  351. static void pmu_cmd_get_cover(PMUState *s,
  352. const uint8_t *in_data, uint8_t in_len,
  353. uint8_t *out_data, uint8_t *out_len)
  354. {
  355. /* Not 100% sure here, will have to check what a real Mac
  356. * returns other than byte 0 bit 0 is LID closed on laptops
  357. */
  358. *out_len = 1;
  359. *out_data = 0x00;
  360. }
  361. static void pmu_cmd_download_status(PMUState *s,
  362. const uint8_t *in_data, uint8_t in_len,
  363. uint8_t *out_data, uint8_t *out_len)
  364. {
  365. /* This has to do with PMU firmware updates as far as I can tell.
  366. *
  367. * We return 0x62 which is what OpenPMU expects
  368. */
  369. *out_len = 1;
  370. *out_data = 0x62;
  371. }
  372. static void pmu_cmd_read_pmu_ram(PMUState *s,
  373. const uint8_t *in_data, uint8_t in_len,
  374. uint8_t *out_data, uint8_t *out_len)
  375. {
  376. if (in_len < 3) {
  377. qemu_log_mask(LOG_GUEST_ERROR,
  378. "PMU: READ_PMU_RAM command, invalid len %d, expected 3\n",
  379. in_len);
  380. return;
  381. }
  382. qemu_log_mask(LOG_GUEST_ERROR,
  383. "PMU: Unsupported READ_PMU_RAM, args: %02x %02x %02x\n",
  384. in_data[0], in_data[1], in_data[2]);
  385. *out_len = 0;
  386. }
  387. /* description of commands */
  388. typedef struct PMUCmdHandler {
  389. uint8_t command;
  390. const char *name;
  391. void (*handler)(PMUState *s,
  392. const uint8_t *in_args, uint8_t in_len,
  393. uint8_t *out_args, uint8_t *out_len);
  394. } PMUCmdHandler;
  395. static const PMUCmdHandler PMUCmdHandlers[] = {
  396. { PMU_INT_ACK, "INT ACK", pmu_cmd_int_ack },
  397. { PMU_SET_INTR_MASK, "SET INT MASK", pmu_cmd_set_int_mask },
  398. { PMU_ADB_CMD, "ADB COMMAND", pmu_cmd_adb },
  399. { PMU_ADB_POLL_OFF, "ADB POLL OFF", pmu_cmd_adb_poll_off },
  400. { PMU_RESET, "REBOOT", pmu_cmd_reset },
  401. { PMU_SHUTDOWN, "SHUTDOWN", pmu_cmd_shutdown },
  402. { PMU_READ_RTC, "GET RTC", pmu_cmd_get_rtc },
  403. { PMU_SET_RTC, "SET RTC", pmu_cmd_set_rtc },
  404. { PMU_SYSTEM_READY, "SYSTEM READY", pmu_cmd_system_ready },
  405. { PMU_GET_VERSION, "GET VERSION", pmu_cmd_get_version },
  406. { PMU_POWER_EVENTS, "POWER EVENTS", pmu_cmd_power_events },
  407. { PMU_GET_COVER, "GET_COVER", pmu_cmd_get_cover },
  408. { PMU_DOWNLOAD_STATUS, "DOWNLOAD STATUS", pmu_cmd_download_status },
  409. { PMU_READ_PMU_RAM, "READ PMGR RAM", pmu_cmd_read_pmu_ram },
  410. };
  411. static void pmu_dispatch_cmd(PMUState *s)
  412. {
  413. unsigned int i;
  414. /* No response by default */
  415. s->cmd_rsp_sz = 0;
  416. for (i = 0; i < ARRAY_SIZE(PMUCmdHandlers); i++) {
  417. const PMUCmdHandler *desc = &PMUCmdHandlers[i];
  418. if (desc->command != s->cmd) {
  419. continue;
  420. }
  421. trace_pmu_dispatch_cmd(desc->name);
  422. desc->handler(s, s->cmd_buf, s->cmd_buf_pos,
  423. s->cmd_rsp, &s->cmd_rsp_sz);
  424. if (s->rsplen != -1 && s->rsplen != s->cmd_rsp_sz) {
  425. trace_pmu_debug_protocol_string("QEMU internal cmd resp mismatch!");
  426. } else {
  427. trace_pmu_debug_protocol_resp_size(s->cmd_rsp_sz);
  428. }
  429. return;
  430. }
  431. trace_pmu_dispatch_unknown_cmd(s->cmd);
  432. /* Manufacture fake response with 0's */
  433. if (s->rsplen == -1) {
  434. s->cmd_rsp_sz = 0;
  435. } else {
  436. s->cmd_rsp_sz = s->rsplen;
  437. memset(s->cmd_rsp, 0, s->rsplen);
  438. }
  439. }
  440. static void pmu_update(PMUState *s)
  441. {
  442. MOS6522PMUState *mps = &s->mos6522_pmu;
  443. MOS6522State *ms = MOS6522(mps);
  444. /* Only react to changes in reg B */
  445. if (ms->b == s->last_b) {
  446. return;
  447. }
  448. s->last_b = ms->b;
  449. /* Check the TREQ / TACK state */
  450. switch (ms->b & (TREQ | TACK)) {
  451. case TREQ:
  452. /* This is an ack release, handle it and bail out */
  453. ms->b |= TACK;
  454. s->last_b = ms->b;
  455. trace_pmu_debug_protocol_string("handshake: TREQ high, setting TACK");
  456. return;
  457. case TACK:
  458. /* This is a valid request, handle below */
  459. break;
  460. case TREQ | TACK:
  461. /* This is an idle state */
  462. return;
  463. default:
  464. /* Invalid state, log and ignore */
  465. trace_pmu_debug_protocol_error(ms->b);
  466. return;
  467. }
  468. /* If we wanted to handle commands asynchronously, this is where
  469. * we would delay the clearing of TACK until we are ready to send
  470. * the response
  471. */
  472. /* We have a request, handshake TACK so we don't stay in
  473. * an invalid state. If we were concurrent with the OS we
  474. * should only do this after we grabbed the SR but that isn't
  475. * a problem here.
  476. */
  477. trace_pmu_debug_protocol_clear_treq(s->cmd_state);
  478. ms->b &= ~TACK;
  479. s->last_b = ms->b;
  480. /* Act according to state */
  481. switch (s->cmd_state) {
  482. case pmu_state_idle:
  483. if (!(ms->acr & SR_OUT)) {
  484. trace_pmu_debug_protocol_string("protocol error! "
  485. "state idle, ACR reading");
  486. break;
  487. }
  488. s->cmd = ms->sr;
  489. via_set_sr_int(s);
  490. s->cmdlen = pmu_data_len[s->cmd][0];
  491. s->rsplen = pmu_data_len[s->cmd][1];
  492. s->cmd_buf_pos = 0;
  493. s->cmd_rsp_pos = 0;
  494. s->cmd_state = pmu_state_cmd;
  495. trace_pmu_debug_protocol_cmd(s->cmd, s->cmdlen, s->rsplen);
  496. break;
  497. case pmu_state_cmd:
  498. if (!(ms->acr & SR_OUT)) {
  499. trace_pmu_debug_protocol_string("protocol error! "
  500. "state cmd, ACR reading");
  501. break;
  502. }
  503. if (s->cmdlen == -1) {
  504. trace_pmu_debug_protocol_cmdlen(ms->sr);
  505. s->cmdlen = ms->sr;
  506. if (s->cmdlen > sizeof(s->cmd_buf)) {
  507. trace_pmu_debug_protocol_cmd_toobig(s->cmdlen);
  508. }
  509. } else if (s->cmd_buf_pos < sizeof(s->cmd_buf)) {
  510. s->cmd_buf[s->cmd_buf_pos++] = ms->sr;
  511. }
  512. via_set_sr_int(s);
  513. break;
  514. case pmu_state_rsp:
  515. if (ms->acr & SR_OUT) {
  516. trace_pmu_debug_protocol_string("protocol error! "
  517. "state resp, ACR writing");
  518. break;
  519. }
  520. if (s->rsplen == -1) {
  521. trace_pmu_debug_protocol_cmd_send_resp_size(s->cmd_rsp_sz);
  522. ms->sr = s->cmd_rsp_sz;
  523. s->rsplen = s->cmd_rsp_sz;
  524. } else if (s->cmd_rsp_pos < s->cmd_rsp_sz) {
  525. trace_pmu_debug_protocol_cmd_send_resp(s->cmd_rsp_pos, s->rsplen);
  526. ms->sr = s->cmd_rsp[s->cmd_rsp_pos++];
  527. }
  528. via_set_sr_int(s);
  529. break;
  530. }
  531. /* Check for state completion */
  532. if (s->cmd_state == pmu_state_cmd && s->cmdlen == s->cmd_buf_pos) {
  533. trace_pmu_debug_protocol_string("Command reception complete, "
  534. "dispatching...");
  535. pmu_dispatch_cmd(s);
  536. s->cmd_state = pmu_state_rsp;
  537. }
  538. if (s->cmd_state == pmu_state_rsp && s->rsplen == s->cmd_rsp_pos) {
  539. trace_pmu_debug_protocol_cmd_resp_complete(ms->ier);
  540. s->cmd_state = pmu_state_idle;
  541. }
  542. }
  543. static uint64_t mos6522_pmu_read(void *opaque, hwaddr addr, unsigned size)
  544. {
  545. PMUState *s = opaque;
  546. MOS6522PMUState *mps = &s->mos6522_pmu;
  547. MOS6522State *ms = MOS6522(mps);
  548. addr = (addr >> 9) & 0xf;
  549. return mos6522_read(ms, addr, size);
  550. }
  551. static void mos6522_pmu_write(void *opaque, hwaddr addr, uint64_t val,
  552. unsigned size)
  553. {
  554. PMUState *s = opaque;
  555. MOS6522PMUState *mps = &s->mos6522_pmu;
  556. MOS6522State *ms = MOS6522(mps);
  557. addr = (addr >> 9) & 0xf;
  558. mos6522_write(ms, addr, val, size);
  559. }
  560. static const MemoryRegionOps mos6522_pmu_ops = {
  561. .read = mos6522_pmu_read,
  562. .write = mos6522_pmu_write,
  563. .endianness = DEVICE_BIG_ENDIAN,
  564. .impl = {
  565. .min_access_size = 1,
  566. .max_access_size = 1,
  567. },
  568. };
  569. static bool pmu_adb_state_needed(void *opaque)
  570. {
  571. PMUState *s = opaque;
  572. return s->has_adb;
  573. }
  574. static const VMStateDescription vmstate_pmu_adb = {
  575. .name = "pmu/adb",
  576. .version_id = 0,
  577. .minimum_version_id = 0,
  578. .needed = pmu_adb_state_needed,
  579. .fields = (VMStateField[]) {
  580. VMSTATE_UINT16(adb_poll_mask, PMUState),
  581. VMSTATE_TIMER_PTR(adb_poll_timer, PMUState),
  582. VMSTATE_UINT8(adb_reply_size, PMUState),
  583. VMSTATE_BUFFER(adb_reply, PMUState),
  584. VMSTATE_END_OF_LIST()
  585. }
  586. };
  587. static const VMStateDescription vmstate_pmu = {
  588. .name = "pmu",
  589. .version_id = 0,
  590. .minimum_version_id = 0,
  591. .fields = (VMStateField[]) {
  592. VMSTATE_STRUCT(mos6522_pmu.parent_obj, PMUState, 0, vmstate_mos6522,
  593. MOS6522State),
  594. VMSTATE_UINT8(last_b, PMUState),
  595. VMSTATE_UINT8(cmd, PMUState),
  596. VMSTATE_UINT32(cmdlen, PMUState),
  597. VMSTATE_UINT32(rsplen, PMUState),
  598. VMSTATE_UINT8(cmd_buf_pos, PMUState),
  599. VMSTATE_BUFFER(cmd_buf, PMUState),
  600. VMSTATE_UINT8(cmd_rsp_pos, PMUState),
  601. VMSTATE_UINT8(cmd_rsp_sz, PMUState),
  602. VMSTATE_BUFFER(cmd_rsp, PMUState),
  603. VMSTATE_UINT8(intbits, PMUState),
  604. VMSTATE_UINT8(intmask, PMUState),
  605. VMSTATE_UINT8(autopoll_rate_ms, PMUState),
  606. VMSTATE_UINT8(autopoll_mask, PMUState),
  607. VMSTATE_UINT32(tick_offset, PMUState),
  608. VMSTATE_TIMER_PTR(one_sec_timer, PMUState),
  609. VMSTATE_INT64(one_sec_target, PMUState),
  610. VMSTATE_END_OF_LIST()
  611. },
  612. .subsections = (const VMStateDescription * []) {
  613. &vmstate_pmu_adb,
  614. }
  615. };
  616. static void pmu_reset(DeviceState *dev)
  617. {
  618. PMUState *s = VIA_PMU(dev);
  619. /* OpenBIOS needs to do this? MacOS 9 needs it */
  620. s->intmask = PMU_INT_ADB | PMU_INT_TICK;
  621. s->intbits = 0;
  622. s->cmd_state = pmu_state_idle;
  623. s->autopoll_mask = 0;
  624. }
  625. static void pmu_realize(DeviceState *dev, Error **errp)
  626. {
  627. PMUState *s = VIA_PMU(dev);
  628. SysBusDevice *sbd;
  629. MOS6522State *ms;
  630. DeviceState *d;
  631. struct tm tm;
  632. /* Pass IRQ from 6522 */
  633. d = DEVICE(&s->mos6522_pmu);
  634. ms = MOS6522(d);
  635. sbd = SYS_BUS_DEVICE(s);
  636. sysbus_pass_irq(sbd, SYS_BUS_DEVICE(ms));
  637. qemu_get_timedate(&tm, 0);
  638. s->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET;
  639. s->one_sec_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, pmu_one_sec_timer, s);
  640. s->one_sec_target = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000;
  641. timer_mod(s->one_sec_timer, s->one_sec_target);
  642. if (s->has_adb) {
  643. qbus_create_inplace(&s->adb_bus, sizeof(s->adb_bus), TYPE_ADB_BUS,
  644. DEVICE(dev), "adb.0");
  645. s->adb_poll_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, pmu_adb_poll, s);
  646. s->adb_poll_mask = 0xffff;
  647. s->autopoll_rate_ms = 20;
  648. }
  649. }
  650. static void pmu_init(Object *obj)
  651. {
  652. SysBusDevice *d = SYS_BUS_DEVICE(obj);
  653. PMUState *s = VIA_PMU(obj);
  654. object_property_add_link(obj, "gpio", TYPE_MACIO_GPIO,
  655. (Object **) &s->gpio,
  656. qdev_prop_allow_set_link_before_realize,
  657. 0, NULL);
  658. sysbus_init_child_obj(obj, "mos6522-pmu", &s->mos6522_pmu,
  659. sizeof(s->mos6522_pmu), TYPE_MOS6522_PMU);
  660. memory_region_init_io(&s->mem, obj, &mos6522_pmu_ops, s, "via-pmu",
  661. 0x2000);
  662. sysbus_init_mmio(d, &s->mem);
  663. }
  664. static Property pmu_properties[] = {
  665. DEFINE_PROP_BOOL("has-adb", PMUState, has_adb, true),
  666. DEFINE_PROP_END_OF_LIST()
  667. };
  668. static void pmu_class_init(ObjectClass *oc, void *data)
  669. {
  670. DeviceClass *dc = DEVICE_CLASS(oc);
  671. dc->realize = pmu_realize;
  672. dc->reset = pmu_reset;
  673. dc->vmsd = &vmstate_pmu;
  674. dc->props = pmu_properties;
  675. set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
  676. }
  677. static const TypeInfo pmu_type_info = {
  678. .name = TYPE_VIA_PMU,
  679. .parent = TYPE_SYS_BUS_DEVICE,
  680. .instance_size = sizeof(PMUState),
  681. .instance_init = pmu_init,
  682. .class_init = pmu_class_init,
  683. };
  684. static void mos6522_pmu_portB_write(MOS6522State *s)
  685. {
  686. MOS6522PMUState *mps = container_of(s, MOS6522PMUState, parent_obj);
  687. PMUState *ps = container_of(mps, PMUState, mos6522_pmu);
  688. if ((s->pcr & 0xe0) == 0x20 || (s->pcr & 0xe0) == 0x60) {
  689. s->ifr &= ~CB2_INT;
  690. }
  691. s->ifr &= ~CB1_INT;
  692. via_update_irq(ps);
  693. pmu_update(ps);
  694. }
  695. static void mos6522_pmu_portA_write(MOS6522State *s)
  696. {
  697. MOS6522PMUState *mps = container_of(s, MOS6522PMUState, parent_obj);
  698. PMUState *ps = container_of(mps, PMUState, mos6522_pmu);
  699. if ((s->pcr & 0x0e) == 0x02 || (s->pcr & 0x0e) == 0x06) {
  700. s->ifr &= ~CA2_INT;
  701. }
  702. s->ifr &= ~CA1_INT;
  703. via_update_irq(ps);
  704. }
  705. static void mos6522_pmu_reset(DeviceState *dev)
  706. {
  707. MOS6522State *ms = MOS6522(dev);
  708. MOS6522PMUState *mps = container_of(ms, MOS6522PMUState, parent_obj);
  709. PMUState *s = container_of(mps, PMUState, mos6522_pmu);
  710. MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(ms);
  711. mdc->parent_reset(dev);
  712. ms->timers[0].frequency = VIA_TIMER_FREQ;
  713. ms->timers[1].frequency = (SCALE_US * 6000) / 4700;
  714. s->last_b = ms->b = TACK | TREQ;
  715. }
  716. static void mos6522_pmu_class_init(ObjectClass *oc, void *data)
  717. {
  718. DeviceClass *dc = DEVICE_CLASS(oc);
  719. MOS6522DeviceClass *mdc = MOS6522_DEVICE_CLASS(oc);
  720. dc->reset = mos6522_pmu_reset;
  721. mdc->portB_write = mos6522_pmu_portB_write;
  722. mdc->portA_write = mos6522_pmu_portA_write;
  723. }
  724. static const TypeInfo mos6522_pmu_type_info = {
  725. .name = TYPE_MOS6522_PMU,
  726. .parent = TYPE_MOS6522,
  727. .instance_size = sizeof(MOS6522PMUState),
  728. .class_init = mos6522_pmu_class_init,
  729. };
  730. static void pmu_register_types(void)
  731. {
  732. type_register_static(&pmu_type_info);
  733. type_register_static(&mos6522_pmu_type_info);
  734. }
  735. type_init(pmu_register_types)