cuda.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740
  1. /*
  2. * QEMU PowerMac CUDA device support
  3. *
  4. * Copyright (c) 2004-2007 Fabrice Bellard
  5. * Copyright (c) 2007 Jocelyn Mayer
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. * THE SOFTWARE.
  24. */
  25. #include "hw.h"
  26. #include "ppc/mac.h"
  27. #include "adb.h"
  28. #include "qemu/timer.h"
  29. #include "sysemu/sysemu.h"
  30. /* XXX: implement all timer modes */
  31. /* debug CUDA */
  32. //#define DEBUG_CUDA
  33. /* debug CUDA packets */
  34. //#define DEBUG_CUDA_PACKET
  35. #ifdef DEBUG_CUDA
  36. #define CUDA_DPRINTF(fmt, ...) \
  37. do { printf("CUDA: " fmt , ## __VA_ARGS__); } while (0)
  38. #else
  39. #define CUDA_DPRINTF(fmt, ...)
  40. #endif
  41. /* Bits in B data register: all active low */
  42. #define TREQ 0x08 /* Transfer request (input) */
  43. #define TACK 0x10 /* Transfer acknowledge (output) */
  44. #define TIP 0x20 /* Transfer in progress (output) */
  45. /* Bits in ACR */
  46. #define SR_CTRL 0x1c /* Shift register control bits */
  47. #define SR_EXT 0x0c /* Shift on external clock */
  48. #define SR_OUT 0x10 /* Shift out if 1 */
  49. /* Bits in IFR and IER */
  50. #define IER_SET 0x80 /* set bits in IER */
  51. #define IER_CLR 0 /* clear bits in IER */
  52. #define SR_INT 0x04 /* Shift register full/empty */
  53. #define T1_INT 0x40 /* Timer 1 interrupt */
  54. #define T2_INT 0x20 /* Timer 2 interrupt */
  55. /* Bits in ACR */
  56. #define T1MODE 0xc0 /* Timer 1 mode */
  57. #define T1MODE_CONT 0x40 /* continuous interrupts */
  58. /* commands (1st byte) */
  59. #define ADB_PACKET 0
  60. #define CUDA_PACKET 1
  61. #define ERROR_PACKET 2
  62. #define TIMER_PACKET 3
  63. #define POWER_PACKET 4
  64. #define MACIIC_PACKET 5
  65. #define PMU_PACKET 6
  66. /* CUDA commands (2nd byte) */
  67. #define CUDA_WARM_START 0x0
  68. #define CUDA_AUTOPOLL 0x1
  69. #define CUDA_GET_6805_ADDR 0x2
  70. #define CUDA_GET_TIME 0x3
  71. #define CUDA_GET_PRAM 0x7
  72. #define CUDA_SET_6805_ADDR 0x8
  73. #define CUDA_SET_TIME 0x9
  74. #define CUDA_POWERDOWN 0xa
  75. #define CUDA_POWERUP_TIME 0xb
  76. #define CUDA_SET_PRAM 0xc
  77. #define CUDA_MS_RESET 0xd
  78. #define CUDA_SEND_DFAC 0xe
  79. #define CUDA_BATTERY_SWAP_SENSE 0x10
  80. #define CUDA_RESET_SYSTEM 0x11
  81. #define CUDA_SET_IPL 0x12
  82. #define CUDA_FILE_SERVER_FLAG 0x13
  83. #define CUDA_SET_AUTO_RATE 0x14
  84. #define CUDA_GET_AUTO_RATE 0x16
  85. #define CUDA_SET_DEVICE_LIST 0x19
  86. #define CUDA_GET_DEVICE_LIST 0x1a
  87. #define CUDA_SET_ONE_SECOND_MODE 0x1b
  88. #define CUDA_SET_POWER_MESSAGES 0x21
  89. #define CUDA_GET_SET_IIC 0x22
  90. #define CUDA_WAKEUP 0x23
  91. #define CUDA_TIMER_TICKLE 0x24
  92. #define CUDA_COMBINED_FORMAT_IIC 0x25
  93. #define CUDA_TIMER_FREQ (4700000 / 6)
  94. #define CUDA_ADB_POLL_FREQ 50
  95. /* CUDA returns time_t's offset from Jan 1, 1904, not 1970 */
  96. #define RTC_OFFSET 2082844800
  97. static void cuda_update(CUDAState *s);
  98. static void cuda_receive_packet_from_host(CUDAState *s,
  99. const uint8_t *data, int len);
  100. static void cuda_timer_update(CUDAState *s, CUDATimer *ti,
  101. int64_t current_time);
  102. static void cuda_update_irq(CUDAState *s)
  103. {
  104. if (s->ifr & s->ier & (SR_INT | T1_INT)) {
  105. qemu_irq_raise(s->irq);
  106. } else {
  107. qemu_irq_lower(s->irq);
  108. }
  109. }
  110. static unsigned int get_counter(CUDATimer *s)
  111. {
  112. int64_t d;
  113. unsigned int counter;
  114. d = muldiv64(qemu_get_clock_ns(vm_clock) - s->load_time,
  115. CUDA_TIMER_FREQ, get_ticks_per_sec());
  116. if (s->index == 0) {
  117. /* the timer goes down from latch to -1 (period of latch + 2) */
  118. if (d <= (s->counter_value + 1)) {
  119. counter = (s->counter_value - d) & 0xffff;
  120. } else {
  121. counter = (d - (s->counter_value + 1)) % (s->latch + 2);
  122. counter = (s->latch - counter) & 0xffff;
  123. }
  124. } else {
  125. counter = (s->counter_value - d) & 0xffff;
  126. }
  127. return counter;
  128. }
  129. static void set_counter(CUDAState *s, CUDATimer *ti, unsigned int val)
  130. {
  131. CUDA_DPRINTF("T%d.counter=%d\n", 1 + (ti->timer == NULL), val);
  132. ti->load_time = qemu_get_clock_ns(vm_clock);
  133. ti->counter_value = val;
  134. cuda_timer_update(s, ti, ti->load_time);
  135. }
  136. static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time)
  137. {
  138. int64_t d, next_time;
  139. unsigned int counter;
  140. /* current counter value */
  141. d = muldiv64(current_time - s->load_time,
  142. CUDA_TIMER_FREQ, get_ticks_per_sec());
  143. /* the timer goes down from latch to -1 (period of latch + 2) */
  144. if (d <= (s->counter_value + 1)) {
  145. counter = (s->counter_value - d) & 0xffff;
  146. } else {
  147. counter = (d - (s->counter_value + 1)) % (s->latch + 2);
  148. counter = (s->latch - counter) & 0xffff;
  149. }
  150. /* Note: we consider the irq is raised on 0 */
  151. if (counter == 0xffff) {
  152. next_time = d + s->latch + 1;
  153. } else if (counter == 0) {
  154. next_time = d + s->latch + 2;
  155. } else {
  156. next_time = d + counter;
  157. }
  158. CUDA_DPRINTF("latch=%d counter=%" PRId64 " delta_next=%" PRId64 "\n",
  159. s->latch, d, next_time - d);
  160. next_time = muldiv64(next_time, get_ticks_per_sec(), CUDA_TIMER_FREQ) +
  161. s->load_time;
  162. if (next_time <= current_time)
  163. next_time = current_time + 1;
  164. return next_time;
  165. }
  166. static void cuda_timer_update(CUDAState *s, CUDATimer *ti,
  167. int64_t current_time)
  168. {
  169. if (!ti->timer)
  170. return;
  171. if ((s->acr & T1MODE) != T1MODE_CONT) {
  172. qemu_del_timer(ti->timer);
  173. } else {
  174. ti->next_irq_time = get_next_irq_time(ti, current_time);
  175. qemu_mod_timer(ti->timer, ti->next_irq_time);
  176. }
  177. }
  178. static void cuda_timer1(void *opaque)
  179. {
  180. CUDAState *s = opaque;
  181. CUDATimer *ti = &s->timers[0];
  182. cuda_timer_update(s, ti, ti->next_irq_time);
  183. s->ifr |= T1_INT;
  184. cuda_update_irq(s);
  185. }
  186. static uint32_t cuda_readb(void *opaque, hwaddr addr)
  187. {
  188. CUDAState *s = opaque;
  189. uint32_t val;
  190. addr = (addr >> 9) & 0xf;
  191. switch(addr) {
  192. case 0:
  193. val = s->b;
  194. break;
  195. case 1:
  196. val = s->a;
  197. break;
  198. case 2:
  199. val = s->dirb;
  200. break;
  201. case 3:
  202. val = s->dira;
  203. break;
  204. case 4:
  205. val = get_counter(&s->timers[0]) & 0xff;
  206. s->ifr &= ~T1_INT;
  207. cuda_update_irq(s);
  208. break;
  209. case 5:
  210. val = get_counter(&s->timers[0]) >> 8;
  211. cuda_update_irq(s);
  212. break;
  213. case 6:
  214. val = s->timers[0].latch & 0xff;
  215. break;
  216. case 7:
  217. /* XXX: check this */
  218. val = (s->timers[0].latch >> 8) & 0xff;
  219. break;
  220. case 8:
  221. val = get_counter(&s->timers[1]) & 0xff;
  222. s->ifr &= ~T2_INT;
  223. break;
  224. case 9:
  225. val = get_counter(&s->timers[1]) >> 8;
  226. break;
  227. case 10:
  228. val = s->sr;
  229. s->ifr &= ~SR_INT;
  230. cuda_update_irq(s);
  231. break;
  232. case 11:
  233. val = s->acr;
  234. break;
  235. case 12:
  236. val = s->pcr;
  237. break;
  238. case 13:
  239. val = s->ifr;
  240. if (s->ifr & s->ier)
  241. val |= 0x80;
  242. break;
  243. case 14:
  244. val = s->ier | 0x80;
  245. break;
  246. default:
  247. case 15:
  248. val = s->anh;
  249. break;
  250. }
  251. if (addr != 13 || val != 0) {
  252. CUDA_DPRINTF("read: reg=0x%x val=%02x\n", (int)addr, val);
  253. }
  254. return val;
  255. }
  256. static void cuda_writeb(void *opaque, hwaddr addr, uint32_t val)
  257. {
  258. CUDAState *s = opaque;
  259. addr = (addr >> 9) & 0xf;
  260. CUDA_DPRINTF("write: reg=0x%x val=%02x\n", (int)addr, val);
  261. switch(addr) {
  262. case 0:
  263. s->b = val;
  264. cuda_update(s);
  265. break;
  266. case 1:
  267. s->a = val;
  268. break;
  269. case 2:
  270. s->dirb = val;
  271. break;
  272. case 3:
  273. s->dira = val;
  274. break;
  275. case 4:
  276. s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
  277. cuda_timer_update(s, &s->timers[0], qemu_get_clock_ns(vm_clock));
  278. break;
  279. case 5:
  280. s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
  281. s->ifr &= ~T1_INT;
  282. set_counter(s, &s->timers[0], s->timers[0].latch);
  283. break;
  284. case 6:
  285. s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
  286. cuda_timer_update(s, &s->timers[0], qemu_get_clock_ns(vm_clock));
  287. break;
  288. case 7:
  289. s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
  290. s->ifr &= ~T1_INT;
  291. cuda_timer_update(s, &s->timers[0], qemu_get_clock_ns(vm_clock));
  292. break;
  293. case 8:
  294. s->timers[1].latch = val;
  295. set_counter(s, &s->timers[1], val);
  296. break;
  297. case 9:
  298. set_counter(s, &s->timers[1], (val << 8) | s->timers[1].latch);
  299. break;
  300. case 10:
  301. s->sr = val;
  302. break;
  303. case 11:
  304. s->acr = val;
  305. cuda_timer_update(s, &s->timers[0], qemu_get_clock_ns(vm_clock));
  306. cuda_update(s);
  307. break;
  308. case 12:
  309. s->pcr = val;
  310. break;
  311. case 13:
  312. /* reset bits */
  313. s->ifr &= ~val;
  314. cuda_update_irq(s);
  315. break;
  316. case 14:
  317. if (val & IER_SET) {
  318. /* set bits */
  319. s->ier |= val & 0x7f;
  320. } else {
  321. /* reset bits */
  322. s->ier &= ~val;
  323. }
  324. cuda_update_irq(s);
  325. break;
  326. default:
  327. case 15:
  328. s->anh = val;
  329. break;
  330. }
  331. }
  332. /* NOTE: TIP and TREQ are negated */
  333. static void cuda_update(CUDAState *s)
  334. {
  335. int packet_received, len;
  336. packet_received = 0;
  337. if (!(s->b & TIP)) {
  338. /* transfer requested from host */
  339. if (s->acr & SR_OUT) {
  340. /* data output */
  341. if ((s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) {
  342. if (s->data_out_index < sizeof(s->data_out)) {
  343. CUDA_DPRINTF("send: %02x\n", s->sr);
  344. s->data_out[s->data_out_index++] = s->sr;
  345. s->ifr |= SR_INT;
  346. cuda_update_irq(s);
  347. }
  348. }
  349. } else {
  350. if (s->data_in_index < s->data_in_size) {
  351. /* data input */
  352. if ((s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) {
  353. s->sr = s->data_in[s->data_in_index++];
  354. CUDA_DPRINTF("recv: %02x\n", s->sr);
  355. /* indicate end of transfer */
  356. if (s->data_in_index >= s->data_in_size) {
  357. s->b = (s->b | TREQ);
  358. }
  359. s->ifr |= SR_INT;
  360. cuda_update_irq(s);
  361. }
  362. }
  363. }
  364. } else {
  365. /* no transfer requested: handle sync case */
  366. if ((s->last_b & TIP) && (s->b & TACK) != (s->last_b & TACK)) {
  367. /* update TREQ state each time TACK change state */
  368. if (s->b & TACK)
  369. s->b = (s->b | TREQ);
  370. else
  371. s->b = (s->b & ~TREQ);
  372. s->ifr |= SR_INT;
  373. cuda_update_irq(s);
  374. } else {
  375. if (!(s->last_b & TIP)) {
  376. /* handle end of host to cuda transfer */
  377. packet_received = (s->data_out_index > 0);
  378. /* always an IRQ at the end of transfer */
  379. s->ifr |= SR_INT;
  380. cuda_update_irq(s);
  381. }
  382. /* signal if there is data to read */
  383. if (s->data_in_index < s->data_in_size) {
  384. s->b = (s->b & ~TREQ);
  385. }
  386. }
  387. }
  388. s->last_acr = s->acr;
  389. s->last_b = s->b;
  390. /* NOTE: cuda_receive_packet_from_host() can call cuda_update()
  391. recursively */
  392. if (packet_received) {
  393. len = s->data_out_index;
  394. s->data_out_index = 0;
  395. cuda_receive_packet_from_host(s, s->data_out, len);
  396. }
  397. }
  398. static void cuda_send_packet_to_host(CUDAState *s,
  399. const uint8_t *data, int len)
  400. {
  401. #ifdef DEBUG_CUDA_PACKET
  402. {
  403. int i;
  404. printf("cuda_send_packet_to_host:\n");
  405. for(i = 0; i < len; i++)
  406. printf(" %02x", data[i]);
  407. printf("\n");
  408. }
  409. #endif
  410. memcpy(s->data_in, data, len);
  411. s->data_in_size = len;
  412. s->data_in_index = 0;
  413. cuda_update(s);
  414. s->ifr |= SR_INT;
  415. cuda_update_irq(s);
  416. }
  417. static void cuda_adb_poll(void *opaque)
  418. {
  419. CUDAState *s = opaque;
  420. uint8_t obuf[ADB_MAX_OUT_LEN + 2];
  421. int olen;
  422. olen = adb_poll(&s->adb_bus, obuf + 2);
  423. if (olen > 0) {
  424. obuf[0] = ADB_PACKET;
  425. obuf[1] = 0x40; /* polled data */
  426. cuda_send_packet_to_host(s, obuf, olen + 2);
  427. }
  428. qemu_mod_timer(s->adb_poll_timer,
  429. qemu_get_clock_ns(vm_clock) +
  430. (get_ticks_per_sec() / CUDA_ADB_POLL_FREQ));
  431. }
  432. static void cuda_receive_packet(CUDAState *s,
  433. const uint8_t *data, int len)
  434. {
  435. uint8_t obuf[16];
  436. int autopoll;
  437. uint32_t ti;
  438. switch(data[0]) {
  439. case CUDA_AUTOPOLL:
  440. autopoll = (data[1] != 0);
  441. if (autopoll != s->autopoll) {
  442. s->autopoll = autopoll;
  443. if (autopoll) {
  444. qemu_mod_timer(s->adb_poll_timer,
  445. qemu_get_clock_ns(vm_clock) +
  446. (get_ticks_per_sec() / CUDA_ADB_POLL_FREQ));
  447. } else {
  448. qemu_del_timer(s->adb_poll_timer);
  449. }
  450. }
  451. obuf[0] = CUDA_PACKET;
  452. obuf[1] = data[1];
  453. cuda_send_packet_to_host(s, obuf, 2);
  454. break;
  455. case CUDA_SET_TIME:
  456. ti = (((uint32_t)data[1]) << 24) + (((uint32_t)data[2]) << 16) + (((uint32_t)data[3]) << 8) + data[4];
  457. s->tick_offset = ti - (qemu_get_clock_ns(vm_clock) / get_ticks_per_sec());
  458. obuf[0] = CUDA_PACKET;
  459. obuf[1] = 0;
  460. obuf[2] = 0;
  461. cuda_send_packet_to_host(s, obuf, 3);
  462. break;
  463. case CUDA_GET_TIME:
  464. ti = s->tick_offset + (qemu_get_clock_ns(vm_clock) / get_ticks_per_sec());
  465. obuf[0] = CUDA_PACKET;
  466. obuf[1] = 0;
  467. obuf[2] = 0;
  468. obuf[3] = ti >> 24;
  469. obuf[4] = ti >> 16;
  470. obuf[5] = ti >> 8;
  471. obuf[6] = ti;
  472. cuda_send_packet_to_host(s, obuf, 7);
  473. break;
  474. case CUDA_FILE_SERVER_FLAG:
  475. case CUDA_SET_DEVICE_LIST:
  476. case CUDA_SET_AUTO_RATE:
  477. case CUDA_SET_POWER_MESSAGES:
  478. obuf[0] = CUDA_PACKET;
  479. obuf[1] = 0;
  480. cuda_send_packet_to_host(s, obuf, 2);
  481. break;
  482. case CUDA_POWERDOWN:
  483. obuf[0] = CUDA_PACKET;
  484. obuf[1] = 0;
  485. cuda_send_packet_to_host(s, obuf, 2);
  486. qemu_system_shutdown_request();
  487. break;
  488. case CUDA_RESET_SYSTEM:
  489. obuf[0] = CUDA_PACKET;
  490. obuf[1] = 0;
  491. cuda_send_packet_to_host(s, obuf, 2);
  492. qemu_system_reset_request();
  493. break;
  494. default:
  495. break;
  496. }
  497. }
  498. static void cuda_receive_packet_from_host(CUDAState *s,
  499. const uint8_t *data, int len)
  500. {
  501. #ifdef DEBUG_CUDA_PACKET
  502. {
  503. int i;
  504. printf("cuda_receive_packet_from_host:\n");
  505. for(i = 0; i < len; i++)
  506. printf(" %02x", data[i]);
  507. printf("\n");
  508. }
  509. #endif
  510. switch(data[0]) {
  511. case ADB_PACKET:
  512. {
  513. uint8_t obuf[ADB_MAX_OUT_LEN + 2];
  514. int olen;
  515. olen = adb_request(&s->adb_bus, obuf + 2, data + 1, len - 1);
  516. if (olen > 0) {
  517. obuf[0] = ADB_PACKET;
  518. obuf[1] = 0x00;
  519. } else {
  520. /* error */
  521. obuf[0] = ADB_PACKET;
  522. obuf[1] = -olen;
  523. olen = 0;
  524. }
  525. cuda_send_packet_to_host(s, obuf, olen + 2);
  526. }
  527. break;
  528. case CUDA_PACKET:
  529. cuda_receive_packet(s, data + 1, len - 1);
  530. break;
  531. }
  532. }
  533. static void cuda_writew (void *opaque, hwaddr addr, uint32_t value)
  534. {
  535. }
  536. static void cuda_writel (void *opaque, hwaddr addr, uint32_t value)
  537. {
  538. }
  539. static uint32_t cuda_readw (void *opaque, hwaddr addr)
  540. {
  541. return 0;
  542. }
  543. static uint32_t cuda_readl (void *opaque, hwaddr addr)
  544. {
  545. return 0;
  546. }
  547. static const MemoryRegionOps cuda_ops = {
  548. .old_mmio = {
  549. .write = {
  550. cuda_writeb,
  551. cuda_writew,
  552. cuda_writel,
  553. },
  554. .read = {
  555. cuda_readb,
  556. cuda_readw,
  557. cuda_readl,
  558. },
  559. },
  560. .endianness = DEVICE_NATIVE_ENDIAN,
  561. };
  562. static bool cuda_timer_exist(void *opaque, int version_id)
  563. {
  564. CUDATimer *s = opaque;
  565. return s->timer != NULL;
  566. }
  567. static const VMStateDescription vmstate_cuda_timer = {
  568. .name = "cuda_timer",
  569. .version_id = 0,
  570. .minimum_version_id = 0,
  571. .minimum_version_id_old = 0,
  572. .fields = (VMStateField[]) {
  573. VMSTATE_UINT16(latch, CUDATimer),
  574. VMSTATE_UINT16(counter_value, CUDATimer),
  575. VMSTATE_INT64(load_time, CUDATimer),
  576. VMSTATE_INT64(next_irq_time, CUDATimer),
  577. VMSTATE_TIMER_TEST(timer, CUDATimer, cuda_timer_exist),
  578. VMSTATE_END_OF_LIST()
  579. }
  580. };
  581. static const VMStateDescription vmstate_cuda = {
  582. .name = "cuda",
  583. .version_id = 1,
  584. .minimum_version_id = 1,
  585. .minimum_version_id_old = 1,
  586. .fields = (VMStateField[]) {
  587. VMSTATE_UINT8(a, CUDAState),
  588. VMSTATE_UINT8(b, CUDAState),
  589. VMSTATE_UINT8(dira, CUDAState),
  590. VMSTATE_UINT8(dirb, CUDAState),
  591. VMSTATE_UINT8(sr, CUDAState),
  592. VMSTATE_UINT8(acr, CUDAState),
  593. VMSTATE_UINT8(pcr, CUDAState),
  594. VMSTATE_UINT8(ifr, CUDAState),
  595. VMSTATE_UINT8(ier, CUDAState),
  596. VMSTATE_UINT8(anh, CUDAState),
  597. VMSTATE_INT32(data_in_size, CUDAState),
  598. VMSTATE_INT32(data_in_index, CUDAState),
  599. VMSTATE_INT32(data_out_index, CUDAState),
  600. VMSTATE_UINT8(autopoll, CUDAState),
  601. VMSTATE_BUFFER(data_in, CUDAState),
  602. VMSTATE_BUFFER(data_out, CUDAState),
  603. VMSTATE_UINT32(tick_offset, CUDAState),
  604. VMSTATE_STRUCT_ARRAY(timers, CUDAState, 2, 1,
  605. vmstate_cuda_timer, CUDATimer),
  606. VMSTATE_END_OF_LIST()
  607. }
  608. };
  609. static void cuda_reset(DeviceState *dev)
  610. {
  611. CUDAState *s = CUDA(dev);
  612. s->b = 0;
  613. s->a = 0;
  614. s->dirb = 0;
  615. s->dira = 0;
  616. s->sr = 0;
  617. s->acr = 0;
  618. s->pcr = 0;
  619. s->ifr = 0;
  620. s->ier = 0;
  621. // s->ier = T1_INT | SR_INT;
  622. s->anh = 0;
  623. s->data_in_size = 0;
  624. s->data_in_index = 0;
  625. s->data_out_index = 0;
  626. s->autopoll = 0;
  627. s->timers[0].latch = 0xffff;
  628. set_counter(s, &s->timers[0], 0xffff);
  629. s->timers[1].latch = 0;
  630. set_counter(s, &s->timers[1], 0xffff);
  631. }
  632. static void cuda_realizefn(DeviceState *dev, Error **errp)
  633. {
  634. CUDAState *s = CUDA(dev);
  635. struct tm tm;
  636. s->timers[0].timer = qemu_new_timer_ns(vm_clock, cuda_timer1, s);
  637. qemu_get_timedate(&tm, 0);
  638. s->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET;
  639. s->adb_poll_timer = qemu_new_timer_ns(vm_clock, cuda_adb_poll, s);
  640. }
  641. static void cuda_initfn(Object *obj)
  642. {
  643. SysBusDevice *d = SYS_BUS_DEVICE(obj);
  644. CUDAState *s = CUDA(obj);
  645. int i;
  646. memory_region_init_io(&s->mem, &cuda_ops, s, "cuda", 0x2000);
  647. sysbus_init_mmio(d, &s->mem);
  648. sysbus_init_irq(d, &s->irq);
  649. for (i = 0; i < ARRAY_SIZE(s->timers); i++) {
  650. s->timers[i].index = i;
  651. }
  652. qbus_create_inplace((BusState *)&s->adb_bus, TYPE_ADB_BUS, DEVICE(obj),
  653. "adb.0");
  654. }
  655. static void cuda_class_init(ObjectClass *oc, void *data)
  656. {
  657. DeviceClass *dc = DEVICE_CLASS(oc);
  658. dc->realize = cuda_realizefn;
  659. dc->reset = cuda_reset;
  660. dc->vmsd = &vmstate_cuda;
  661. }
  662. static const TypeInfo cuda_type_info = {
  663. .name = TYPE_CUDA,
  664. .parent = TYPE_SYS_BUS_DEVICE,
  665. .instance_size = sizeof(CUDAState),
  666. .instance_init = cuda_initfn,
  667. .class_init = cuda_class_init,
  668. };
  669. static void cuda_register_types(void)
  670. {
  671. type_register_static(&cuda_type_info);
  672. }
  673. type_init(cuda_register_types)