cuda.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965
  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 "qemu/osdep.h"
  26. #include "hw/hw.h"
  27. #include "hw/ppc/mac.h"
  28. #include "hw/input/adb.h"
  29. #include "qemu/timer.h"
  30. #include "sysemu/sysemu.h"
  31. #include "qemu/cutils.h"
  32. #include "qemu/log.h"
  33. /* XXX: implement all timer modes */
  34. /* debug CUDA */
  35. //#define DEBUG_CUDA
  36. /* debug CUDA packets */
  37. //#define DEBUG_CUDA_PACKET
  38. #ifdef DEBUG_CUDA
  39. #define CUDA_DPRINTF(fmt, ...) \
  40. do { printf("CUDA: " fmt , ## __VA_ARGS__); } while (0)
  41. #else
  42. #define CUDA_DPRINTF(fmt, ...)
  43. #endif
  44. /* Bits in B data register: all active low */
  45. #define TREQ 0x08 /* Transfer request (input) */
  46. #define TACK 0x10 /* Transfer acknowledge (output) */
  47. #define TIP 0x20 /* Transfer in progress (output) */
  48. /* Bits in ACR */
  49. #define SR_CTRL 0x1c /* Shift register control bits */
  50. #define SR_EXT 0x0c /* Shift on external clock */
  51. #define SR_OUT 0x10 /* Shift out if 1 */
  52. /* Bits in IFR and IER */
  53. #define IER_SET 0x80 /* set bits in IER */
  54. #define IER_CLR 0 /* clear bits in IER */
  55. #define SR_INT 0x04 /* Shift register full/empty */
  56. #define SR_DATA_INT 0x08
  57. #define SR_CLOCK_INT 0x10
  58. #define T1_INT 0x40 /* Timer 1 interrupt */
  59. #define T2_INT 0x20 /* Timer 2 interrupt */
  60. /* Bits in ACR */
  61. #define T1MODE 0xc0 /* Timer 1 mode */
  62. #define T1MODE_CONT 0x40 /* continuous interrupts */
  63. /* commands (1st byte) */
  64. #define ADB_PACKET 0
  65. #define CUDA_PACKET 1
  66. #define ERROR_PACKET 2
  67. #define TIMER_PACKET 3
  68. #define POWER_PACKET 4
  69. #define MACIIC_PACKET 5
  70. #define PMU_PACKET 6
  71. /* CUDA commands (2nd byte) */
  72. #define CUDA_WARM_START 0x0
  73. #define CUDA_AUTOPOLL 0x1
  74. #define CUDA_GET_6805_ADDR 0x2
  75. #define CUDA_GET_TIME 0x3
  76. #define CUDA_GET_PRAM 0x7
  77. #define CUDA_SET_6805_ADDR 0x8
  78. #define CUDA_SET_TIME 0x9
  79. #define CUDA_POWERDOWN 0xa
  80. #define CUDA_POWERUP_TIME 0xb
  81. #define CUDA_SET_PRAM 0xc
  82. #define CUDA_MS_RESET 0xd
  83. #define CUDA_SEND_DFAC 0xe
  84. #define CUDA_BATTERY_SWAP_SENSE 0x10
  85. #define CUDA_RESET_SYSTEM 0x11
  86. #define CUDA_SET_IPL 0x12
  87. #define CUDA_FILE_SERVER_FLAG 0x13
  88. #define CUDA_SET_AUTO_RATE 0x14
  89. #define CUDA_GET_AUTO_RATE 0x16
  90. #define CUDA_SET_DEVICE_LIST 0x19
  91. #define CUDA_GET_DEVICE_LIST 0x1a
  92. #define CUDA_SET_ONE_SECOND_MODE 0x1b
  93. #define CUDA_SET_POWER_MESSAGES 0x21
  94. #define CUDA_GET_SET_IIC 0x22
  95. #define CUDA_WAKEUP 0x23
  96. #define CUDA_TIMER_TICKLE 0x24
  97. #define CUDA_COMBINED_FORMAT_IIC 0x25
  98. #define CUDA_TIMER_FREQ (4700000 / 6)
  99. /* CUDA returns time_t's offset from Jan 1, 1904, not 1970 */
  100. #define RTC_OFFSET 2082844800
  101. /* CUDA registers */
  102. #define CUDA_REG_B 0x00
  103. #define CUDA_REG_A 0x01
  104. #define CUDA_REG_DIRB 0x02
  105. #define CUDA_REG_DIRA 0x03
  106. #define CUDA_REG_T1CL 0x04
  107. #define CUDA_REG_T1CH 0x05
  108. #define CUDA_REG_T1LL 0x06
  109. #define CUDA_REG_T1LH 0x07
  110. #define CUDA_REG_T2CL 0x08
  111. #define CUDA_REG_T2CH 0x09
  112. #define CUDA_REG_SR 0x0a
  113. #define CUDA_REG_ACR 0x0b
  114. #define CUDA_REG_PCR 0x0c
  115. #define CUDA_REG_IFR 0x0d
  116. #define CUDA_REG_IER 0x0e
  117. #define CUDA_REG_ANH 0x0f
  118. static void cuda_update(CUDAState *s);
  119. static void cuda_receive_packet_from_host(CUDAState *s,
  120. const uint8_t *data, int len);
  121. static void cuda_timer_update(CUDAState *s, CUDATimer *ti,
  122. int64_t current_time);
  123. static void cuda_update_irq(CUDAState *s)
  124. {
  125. if (s->ifr & s->ier & (SR_INT | T1_INT | T2_INT)) {
  126. qemu_irq_raise(s->irq);
  127. } else {
  128. qemu_irq_lower(s->irq);
  129. }
  130. }
  131. static uint64_t get_tb(uint64_t time, uint64_t freq)
  132. {
  133. return muldiv64(time, freq, NANOSECONDS_PER_SECOND);
  134. }
  135. static unsigned int get_counter(CUDATimer *ti)
  136. {
  137. int64_t d;
  138. unsigned int counter;
  139. uint64_t tb_diff;
  140. uint64_t current_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
  141. /* Reverse of the tb calculation algorithm that Mac OS X uses on bootup. */
  142. tb_diff = get_tb(current_time, ti->frequency) - ti->load_time;
  143. d = (tb_diff * 0xBF401675E5DULL) / (ti->frequency << 24);
  144. if (ti->index == 0) {
  145. /* the timer goes down from latch to -1 (period of latch + 2) */
  146. if (d <= (ti->counter_value + 1)) {
  147. counter = (ti->counter_value - d) & 0xffff;
  148. } else {
  149. counter = (d - (ti->counter_value + 1)) % (ti->latch + 2);
  150. counter = (ti->latch - counter) & 0xffff;
  151. }
  152. } else {
  153. counter = (ti->counter_value - d) & 0xffff;
  154. }
  155. return counter;
  156. }
  157. static void set_counter(CUDAState *s, CUDATimer *ti, unsigned int val)
  158. {
  159. CUDA_DPRINTF("T%d.counter=%d\n", 1 + ti->index, val);
  160. ti->load_time = get_tb(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
  161. s->frequency);
  162. ti->counter_value = val;
  163. cuda_timer_update(s, ti, ti->load_time);
  164. }
  165. static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time)
  166. {
  167. int64_t d, next_time;
  168. unsigned int counter;
  169. /* current counter value */
  170. d = muldiv64(current_time - s->load_time,
  171. CUDA_TIMER_FREQ, NANOSECONDS_PER_SECOND);
  172. /* the timer goes down from latch to -1 (period of latch + 2) */
  173. if (d <= (s->counter_value + 1)) {
  174. counter = (s->counter_value - d) & 0xffff;
  175. } else {
  176. counter = (d - (s->counter_value + 1)) % (s->latch + 2);
  177. counter = (s->latch - counter) & 0xffff;
  178. }
  179. /* Note: we consider the irq is raised on 0 */
  180. if (counter == 0xffff) {
  181. next_time = d + s->latch + 1;
  182. } else if (counter == 0) {
  183. next_time = d + s->latch + 2;
  184. } else {
  185. next_time = d + counter;
  186. }
  187. CUDA_DPRINTF("latch=%d counter=%" PRId64 " delta_next=%" PRId64 "\n",
  188. s->latch, d, next_time - d);
  189. next_time = muldiv64(next_time, NANOSECONDS_PER_SECOND, CUDA_TIMER_FREQ) +
  190. s->load_time;
  191. if (next_time <= current_time)
  192. next_time = current_time + 1;
  193. return next_time;
  194. }
  195. static void cuda_timer_update(CUDAState *s, CUDATimer *ti,
  196. int64_t current_time)
  197. {
  198. if (!ti->timer)
  199. return;
  200. if (ti->index == 0 && (s->acr & T1MODE) != T1MODE_CONT) {
  201. timer_del(ti->timer);
  202. } else {
  203. ti->next_irq_time = get_next_irq_time(ti, current_time);
  204. timer_mod(ti->timer, ti->next_irq_time);
  205. }
  206. }
  207. static void cuda_timer1(void *opaque)
  208. {
  209. CUDAState *s = opaque;
  210. CUDATimer *ti = &s->timers[0];
  211. cuda_timer_update(s, ti, ti->next_irq_time);
  212. s->ifr |= T1_INT;
  213. cuda_update_irq(s);
  214. }
  215. static void cuda_timer2(void *opaque)
  216. {
  217. CUDAState *s = opaque;
  218. CUDATimer *ti = &s->timers[1];
  219. cuda_timer_update(s, ti, ti->next_irq_time);
  220. s->ifr |= T2_INT;
  221. cuda_update_irq(s);
  222. }
  223. static void cuda_set_sr_int(void *opaque)
  224. {
  225. CUDAState *s = opaque;
  226. CUDA_DPRINTF("CUDA: %s:%d\n", __func__, __LINE__);
  227. s->ifr |= SR_INT;
  228. cuda_update_irq(s);
  229. }
  230. static void cuda_delay_set_sr_int(CUDAState *s)
  231. {
  232. int64_t expire;
  233. if (s->dirb == 0xff) {
  234. /* Not in Mac OS, fire the IRQ directly */
  235. cuda_set_sr_int(s);
  236. return;
  237. }
  238. CUDA_DPRINTF("CUDA: %s:%d\n", __func__, __LINE__);
  239. expire = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 300 * SCALE_US;
  240. timer_mod(s->sr_delay_timer, expire);
  241. }
  242. static uint32_t cuda_readb(void *opaque, hwaddr addr)
  243. {
  244. CUDAState *s = opaque;
  245. uint32_t val;
  246. addr = (addr >> 9) & 0xf;
  247. switch(addr) {
  248. case CUDA_REG_B:
  249. val = s->b;
  250. break;
  251. case CUDA_REG_A:
  252. val = s->a;
  253. break;
  254. case CUDA_REG_DIRB:
  255. val = s->dirb;
  256. break;
  257. case CUDA_REG_DIRA:
  258. val = s->dira;
  259. break;
  260. case CUDA_REG_T1CL:
  261. val = get_counter(&s->timers[0]) & 0xff;
  262. s->ifr &= ~T1_INT;
  263. cuda_update_irq(s);
  264. break;
  265. case CUDA_REG_T1CH:
  266. val = get_counter(&s->timers[0]) >> 8;
  267. cuda_update_irq(s);
  268. break;
  269. case CUDA_REG_T1LL:
  270. val = s->timers[0].latch & 0xff;
  271. break;
  272. case CUDA_REG_T1LH:
  273. /* XXX: check this */
  274. val = (s->timers[0].latch >> 8) & 0xff;
  275. break;
  276. case CUDA_REG_T2CL:
  277. val = get_counter(&s->timers[1]) & 0xff;
  278. s->ifr &= ~T2_INT;
  279. cuda_update_irq(s);
  280. break;
  281. case CUDA_REG_T2CH:
  282. val = get_counter(&s->timers[1]) >> 8;
  283. break;
  284. case CUDA_REG_SR:
  285. val = s->sr;
  286. s->ifr &= ~(SR_INT | SR_CLOCK_INT | SR_DATA_INT);
  287. cuda_update_irq(s);
  288. break;
  289. case CUDA_REG_ACR:
  290. val = s->acr;
  291. break;
  292. case CUDA_REG_PCR:
  293. val = s->pcr;
  294. break;
  295. case CUDA_REG_IFR:
  296. val = s->ifr;
  297. if (s->ifr & s->ier) {
  298. val |= 0x80;
  299. }
  300. break;
  301. case CUDA_REG_IER:
  302. val = s->ier | 0x80;
  303. break;
  304. default:
  305. case CUDA_REG_ANH:
  306. val = s->anh;
  307. break;
  308. }
  309. if (addr != CUDA_REG_IFR || val != 0) {
  310. CUDA_DPRINTF("read: reg=0x%x val=%02x\n", (int)addr, val);
  311. }
  312. return val;
  313. }
  314. static void cuda_writeb(void *opaque, hwaddr addr, uint32_t val)
  315. {
  316. CUDAState *s = opaque;
  317. addr = (addr >> 9) & 0xf;
  318. CUDA_DPRINTF("write: reg=0x%x val=%02x\n", (int)addr, val);
  319. switch(addr) {
  320. case CUDA_REG_B:
  321. s->b = val;
  322. cuda_update(s);
  323. break;
  324. case CUDA_REG_A:
  325. s->a = val;
  326. break;
  327. case CUDA_REG_DIRB:
  328. s->dirb = val;
  329. break;
  330. case CUDA_REG_DIRA:
  331. s->dira = val;
  332. break;
  333. case CUDA_REG_T1CL:
  334. s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
  335. cuda_timer_update(s, &s->timers[0], qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
  336. break;
  337. case CUDA_REG_T1CH:
  338. s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
  339. s->ifr &= ~T1_INT;
  340. set_counter(s, &s->timers[0], s->timers[0].latch);
  341. break;
  342. case CUDA_REG_T1LL:
  343. s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
  344. cuda_timer_update(s, &s->timers[0], qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
  345. break;
  346. case CUDA_REG_T1LH:
  347. s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
  348. s->ifr &= ~T1_INT;
  349. cuda_timer_update(s, &s->timers[0], qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
  350. break;
  351. case CUDA_REG_T2CL:
  352. s->timers[1].latch = (s->timers[1].latch & 0xff00) | val;
  353. break;
  354. case CUDA_REG_T2CH:
  355. /* To ensure T2 generates an interrupt on zero crossing with the
  356. common timer code, write the value directly from the latch to
  357. the counter */
  358. s->timers[1].latch = (s->timers[1].latch & 0xff) | (val << 8);
  359. s->ifr &= ~T2_INT;
  360. set_counter(s, &s->timers[1], s->timers[1].latch);
  361. break;
  362. case CUDA_REG_SR:
  363. s->sr = val;
  364. break;
  365. case CUDA_REG_ACR:
  366. s->acr = val;
  367. cuda_timer_update(s, &s->timers[0], qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
  368. cuda_update(s);
  369. break;
  370. case CUDA_REG_PCR:
  371. s->pcr = val;
  372. break;
  373. case CUDA_REG_IFR:
  374. /* reset bits */
  375. s->ifr &= ~val;
  376. cuda_update_irq(s);
  377. break;
  378. case CUDA_REG_IER:
  379. if (val & IER_SET) {
  380. /* set bits */
  381. s->ier |= val & 0x7f;
  382. } else {
  383. /* reset bits */
  384. s->ier &= ~val;
  385. }
  386. cuda_update_irq(s);
  387. break;
  388. default:
  389. case CUDA_REG_ANH:
  390. s->anh = val;
  391. break;
  392. }
  393. }
  394. /* NOTE: TIP and TREQ are negated */
  395. static void cuda_update(CUDAState *s)
  396. {
  397. int packet_received, len;
  398. packet_received = 0;
  399. if (!(s->b & TIP)) {
  400. /* transfer requested from host */
  401. if (s->acr & SR_OUT) {
  402. /* data output */
  403. if ((s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) {
  404. if (s->data_out_index < sizeof(s->data_out)) {
  405. CUDA_DPRINTF("send: %02x\n", s->sr);
  406. s->data_out[s->data_out_index++] = s->sr;
  407. cuda_delay_set_sr_int(s);
  408. }
  409. }
  410. } else {
  411. if (s->data_in_index < s->data_in_size) {
  412. /* data input */
  413. if ((s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) {
  414. s->sr = s->data_in[s->data_in_index++];
  415. CUDA_DPRINTF("recv: %02x\n", s->sr);
  416. /* indicate end of transfer */
  417. if (s->data_in_index >= s->data_in_size) {
  418. s->b = (s->b | TREQ);
  419. }
  420. cuda_delay_set_sr_int(s);
  421. }
  422. }
  423. }
  424. } else {
  425. /* no transfer requested: handle sync case */
  426. if ((s->last_b & TIP) && (s->b & TACK) != (s->last_b & TACK)) {
  427. /* update TREQ state each time TACK change state */
  428. if (s->b & TACK)
  429. s->b = (s->b | TREQ);
  430. else
  431. s->b = (s->b & ~TREQ);
  432. cuda_delay_set_sr_int(s);
  433. } else {
  434. if (!(s->last_b & TIP)) {
  435. /* handle end of host to cuda transfer */
  436. packet_received = (s->data_out_index > 0);
  437. /* always an IRQ at the end of transfer */
  438. cuda_delay_set_sr_int(s);
  439. }
  440. /* signal if there is data to read */
  441. if (s->data_in_index < s->data_in_size) {
  442. s->b = (s->b & ~TREQ);
  443. }
  444. }
  445. }
  446. s->last_acr = s->acr;
  447. s->last_b = s->b;
  448. /* NOTE: cuda_receive_packet_from_host() can call cuda_update()
  449. recursively */
  450. if (packet_received) {
  451. len = s->data_out_index;
  452. s->data_out_index = 0;
  453. cuda_receive_packet_from_host(s, s->data_out, len);
  454. }
  455. }
  456. static void cuda_send_packet_to_host(CUDAState *s,
  457. const uint8_t *data, int len)
  458. {
  459. #ifdef DEBUG_CUDA_PACKET
  460. {
  461. int i;
  462. printf("cuda_send_packet_to_host:\n");
  463. for(i = 0; i < len; i++)
  464. printf(" %02x", data[i]);
  465. printf("\n");
  466. }
  467. #endif
  468. memcpy(s->data_in, data, len);
  469. s->data_in_size = len;
  470. s->data_in_index = 0;
  471. cuda_update(s);
  472. cuda_delay_set_sr_int(s);
  473. }
  474. static void cuda_adb_poll(void *opaque)
  475. {
  476. CUDAState *s = opaque;
  477. uint8_t obuf[ADB_MAX_OUT_LEN + 2];
  478. int olen;
  479. olen = adb_poll(&s->adb_bus, obuf + 2, s->adb_poll_mask);
  480. if (olen > 0) {
  481. obuf[0] = ADB_PACKET;
  482. obuf[1] = 0x40; /* polled data */
  483. cuda_send_packet_to_host(s, obuf, olen + 2);
  484. }
  485. timer_mod(s->adb_poll_timer,
  486. qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
  487. (NANOSECONDS_PER_SECOND / (1000 / s->autopoll_rate_ms)));
  488. }
  489. /* description of commands */
  490. typedef struct CudaCommand {
  491. uint8_t command;
  492. const char *name;
  493. bool (*handler)(CUDAState *s,
  494. const uint8_t *in_args, int in_len,
  495. uint8_t *out_args, int *out_len);
  496. } CudaCommand;
  497. static bool cuda_cmd_autopoll(CUDAState *s,
  498. const uint8_t *in_data, int in_len,
  499. uint8_t *out_data, int *out_len)
  500. {
  501. int autopoll;
  502. if (in_len != 1) {
  503. return false;
  504. }
  505. autopoll = (in_data[0] != 0);
  506. if (autopoll != s->autopoll) {
  507. s->autopoll = autopoll;
  508. if (autopoll) {
  509. timer_mod(s->adb_poll_timer,
  510. qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
  511. (NANOSECONDS_PER_SECOND / (1000 / s->autopoll_rate_ms)));
  512. } else {
  513. timer_del(s->adb_poll_timer);
  514. }
  515. }
  516. return true;
  517. }
  518. static bool cuda_cmd_set_autorate(CUDAState *s,
  519. const uint8_t *in_data, int in_len,
  520. uint8_t *out_data, int *out_len)
  521. {
  522. if (in_len != 1) {
  523. return false;
  524. }
  525. /* we don't want a period of 0 ms */
  526. /* FIXME: check what real hardware does */
  527. if (in_data[0] == 0) {
  528. return false;
  529. }
  530. s->autopoll_rate_ms = in_data[0];
  531. if (s->autopoll) {
  532. timer_mod(s->adb_poll_timer,
  533. qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
  534. (NANOSECONDS_PER_SECOND / (1000 / s->autopoll_rate_ms)));
  535. }
  536. return true;
  537. }
  538. static bool cuda_cmd_set_device_list(CUDAState *s,
  539. const uint8_t *in_data, int in_len,
  540. uint8_t *out_data, int *out_len)
  541. {
  542. if (in_len != 2) {
  543. return false;
  544. }
  545. s->adb_poll_mask = (((uint16_t)in_data[0]) << 8) | in_data[1];
  546. return true;
  547. }
  548. static bool cuda_cmd_powerdown(CUDAState *s,
  549. const uint8_t *in_data, int in_len,
  550. uint8_t *out_data, int *out_len)
  551. {
  552. if (in_len != 0) {
  553. return false;
  554. }
  555. qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
  556. return true;
  557. }
  558. static bool cuda_cmd_reset_system(CUDAState *s,
  559. const uint8_t *in_data, int in_len,
  560. uint8_t *out_data, int *out_len)
  561. {
  562. if (in_len != 0) {
  563. return false;
  564. }
  565. qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
  566. return true;
  567. }
  568. static bool cuda_cmd_set_file_server_flag(CUDAState *s,
  569. const uint8_t *in_data, int in_len,
  570. uint8_t *out_data, int *out_len)
  571. {
  572. if (in_len != 1) {
  573. return false;
  574. }
  575. qemu_log_mask(LOG_UNIMP,
  576. "CUDA: unimplemented command FILE_SERVER_FLAG %d\n",
  577. in_data[0]);
  578. return true;
  579. }
  580. static bool cuda_cmd_set_power_message(CUDAState *s,
  581. const uint8_t *in_data, int in_len,
  582. uint8_t *out_data, int *out_len)
  583. {
  584. if (in_len != 1) {
  585. return false;
  586. }
  587. qemu_log_mask(LOG_UNIMP,
  588. "CUDA: unimplemented command SET_POWER_MESSAGE %d\n",
  589. in_data[0]);
  590. return true;
  591. }
  592. static bool cuda_cmd_get_time(CUDAState *s,
  593. const uint8_t *in_data, int in_len,
  594. uint8_t *out_data, int *out_len)
  595. {
  596. uint32_t ti;
  597. if (in_len != 0) {
  598. return false;
  599. }
  600. ti = s->tick_offset + (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)
  601. / NANOSECONDS_PER_SECOND);
  602. out_data[0] = ti >> 24;
  603. out_data[1] = ti >> 16;
  604. out_data[2] = ti >> 8;
  605. out_data[3] = ti;
  606. *out_len = 4;
  607. return true;
  608. }
  609. static bool cuda_cmd_set_time(CUDAState *s,
  610. const uint8_t *in_data, int in_len,
  611. uint8_t *out_data, int *out_len)
  612. {
  613. uint32_t ti;
  614. if (in_len != 4) {
  615. return false;
  616. }
  617. ti = (((uint32_t)in_data[0]) << 24) + (((uint32_t)in_data[1]) << 16)
  618. + (((uint32_t)in_data[2]) << 8) + in_data[3];
  619. s->tick_offset = ti - (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)
  620. / NANOSECONDS_PER_SECOND);
  621. return true;
  622. }
  623. static const CudaCommand handlers[] = {
  624. { CUDA_AUTOPOLL, "AUTOPOLL", cuda_cmd_autopoll },
  625. { CUDA_SET_AUTO_RATE, "SET_AUTO_RATE", cuda_cmd_set_autorate },
  626. { CUDA_SET_DEVICE_LIST, "SET_DEVICE_LIST", cuda_cmd_set_device_list },
  627. { CUDA_POWERDOWN, "POWERDOWN", cuda_cmd_powerdown },
  628. { CUDA_RESET_SYSTEM, "RESET_SYSTEM", cuda_cmd_reset_system },
  629. { CUDA_FILE_SERVER_FLAG, "FILE_SERVER_FLAG",
  630. cuda_cmd_set_file_server_flag },
  631. { CUDA_SET_POWER_MESSAGES, "SET_POWER_MESSAGES",
  632. cuda_cmd_set_power_message },
  633. { CUDA_GET_TIME, "GET_TIME", cuda_cmd_get_time },
  634. { CUDA_SET_TIME, "SET_TIME", cuda_cmd_set_time },
  635. };
  636. static void cuda_receive_packet(CUDAState *s,
  637. const uint8_t *data, int len)
  638. {
  639. uint8_t obuf[16] = { CUDA_PACKET, 0, data[0] };
  640. int i, out_len = 0;
  641. for (i = 0; i < ARRAY_SIZE(handlers); i++) {
  642. const CudaCommand *desc = &handlers[i];
  643. if (desc->command == data[0]) {
  644. CUDA_DPRINTF("handling command %s\n", desc->name);
  645. out_len = 0;
  646. if (desc->handler(s, data + 1, len - 1, obuf + 3, &out_len)) {
  647. cuda_send_packet_to_host(s, obuf, 3 + out_len);
  648. } else {
  649. qemu_log_mask(LOG_GUEST_ERROR,
  650. "CUDA: %s: wrong parameters %d\n",
  651. desc->name, len);
  652. obuf[0] = ERROR_PACKET;
  653. obuf[1] = 0x5; /* bad parameters */
  654. obuf[2] = CUDA_PACKET;
  655. obuf[3] = data[0];
  656. cuda_send_packet_to_host(s, obuf, 4);
  657. }
  658. return;
  659. }
  660. }
  661. qemu_log_mask(LOG_GUEST_ERROR, "CUDA: unknown command 0x%02x\n", data[0]);
  662. obuf[0] = ERROR_PACKET;
  663. obuf[1] = 0x2; /* unknown command */
  664. obuf[2] = CUDA_PACKET;
  665. obuf[3] = data[0];
  666. cuda_send_packet_to_host(s, obuf, 4);
  667. }
  668. static void cuda_receive_packet_from_host(CUDAState *s,
  669. const uint8_t *data, int len)
  670. {
  671. #ifdef DEBUG_CUDA_PACKET
  672. {
  673. int i;
  674. printf("cuda_receive_packet_from_host:\n");
  675. for(i = 0; i < len; i++)
  676. printf(" %02x", data[i]);
  677. printf("\n");
  678. }
  679. #endif
  680. switch(data[0]) {
  681. case ADB_PACKET:
  682. {
  683. uint8_t obuf[ADB_MAX_OUT_LEN + 3];
  684. int olen;
  685. olen = adb_request(&s->adb_bus, obuf + 2, data + 1, len - 1);
  686. if (olen > 0) {
  687. obuf[0] = ADB_PACKET;
  688. obuf[1] = 0x00;
  689. cuda_send_packet_to_host(s, obuf, olen + 2);
  690. } else {
  691. /* error */
  692. obuf[0] = ADB_PACKET;
  693. obuf[1] = -olen;
  694. obuf[2] = data[1];
  695. olen = 0;
  696. cuda_send_packet_to_host(s, obuf, olen + 3);
  697. }
  698. }
  699. break;
  700. case CUDA_PACKET:
  701. cuda_receive_packet(s, data + 1, len - 1);
  702. break;
  703. }
  704. }
  705. static void cuda_writew (void *opaque, hwaddr addr, uint32_t value)
  706. {
  707. }
  708. static void cuda_writel (void *opaque, hwaddr addr, uint32_t value)
  709. {
  710. }
  711. static uint32_t cuda_readw (void *opaque, hwaddr addr)
  712. {
  713. return 0;
  714. }
  715. static uint32_t cuda_readl (void *opaque, hwaddr addr)
  716. {
  717. return 0;
  718. }
  719. static const MemoryRegionOps cuda_ops = {
  720. .old_mmio = {
  721. .write = {
  722. cuda_writeb,
  723. cuda_writew,
  724. cuda_writel,
  725. },
  726. .read = {
  727. cuda_readb,
  728. cuda_readw,
  729. cuda_readl,
  730. },
  731. },
  732. .endianness = DEVICE_NATIVE_ENDIAN,
  733. };
  734. static bool cuda_timer_exist(void *opaque, int version_id)
  735. {
  736. CUDATimer *s = opaque;
  737. return s->timer != NULL;
  738. }
  739. static const VMStateDescription vmstate_cuda_timer = {
  740. .name = "cuda_timer",
  741. .version_id = 0,
  742. .minimum_version_id = 0,
  743. .fields = (VMStateField[]) {
  744. VMSTATE_UINT16(latch, CUDATimer),
  745. VMSTATE_UINT16(counter_value, CUDATimer),
  746. VMSTATE_INT64(load_time, CUDATimer),
  747. VMSTATE_INT64(next_irq_time, CUDATimer),
  748. VMSTATE_TIMER_PTR_TEST(timer, CUDATimer, cuda_timer_exist),
  749. VMSTATE_END_OF_LIST()
  750. }
  751. };
  752. static const VMStateDescription vmstate_cuda = {
  753. .name = "cuda",
  754. .version_id = 4,
  755. .minimum_version_id = 4,
  756. .fields = (VMStateField[]) {
  757. VMSTATE_UINT8(a, CUDAState),
  758. VMSTATE_UINT8(b, CUDAState),
  759. VMSTATE_UINT8(last_b, CUDAState),
  760. VMSTATE_UINT8(dira, CUDAState),
  761. VMSTATE_UINT8(dirb, CUDAState),
  762. VMSTATE_UINT8(sr, CUDAState),
  763. VMSTATE_UINT8(acr, CUDAState),
  764. VMSTATE_UINT8(last_acr, CUDAState),
  765. VMSTATE_UINT8(pcr, CUDAState),
  766. VMSTATE_UINT8(ifr, CUDAState),
  767. VMSTATE_UINT8(ier, CUDAState),
  768. VMSTATE_UINT8(anh, CUDAState),
  769. VMSTATE_INT32(data_in_size, CUDAState),
  770. VMSTATE_INT32(data_in_index, CUDAState),
  771. VMSTATE_INT32(data_out_index, CUDAState),
  772. VMSTATE_UINT8(autopoll, CUDAState),
  773. VMSTATE_UINT8(autopoll_rate_ms, CUDAState),
  774. VMSTATE_UINT16(adb_poll_mask, CUDAState),
  775. VMSTATE_BUFFER(data_in, CUDAState),
  776. VMSTATE_BUFFER(data_out, CUDAState),
  777. VMSTATE_UINT32(tick_offset, CUDAState),
  778. VMSTATE_STRUCT_ARRAY(timers, CUDAState, 2, 1,
  779. vmstate_cuda_timer, CUDATimer),
  780. VMSTATE_TIMER_PTR(adb_poll_timer, CUDAState),
  781. VMSTATE_TIMER_PTR(sr_delay_timer, CUDAState),
  782. VMSTATE_END_OF_LIST()
  783. }
  784. };
  785. static void cuda_reset(DeviceState *dev)
  786. {
  787. CUDAState *s = CUDA(dev);
  788. s->b = 0;
  789. s->a = 0;
  790. s->dirb = 0xff;
  791. s->dira = 0;
  792. s->sr = 0;
  793. s->acr = 0;
  794. s->pcr = 0;
  795. s->ifr = 0;
  796. s->ier = 0;
  797. // s->ier = T1_INT | SR_INT;
  798. s->anh = 0;
  799. s->data_in_size = 0;
  800. s->data_in_index = 0;
  801. s->data_out_index = 0;
  802. s->autopoll = 0;
  803. s->timers[0].latch = 0xffff;
  804. set_counter(s, &s->timers[0], 0xffff);
  805. s->timers[1].latch = 0xffff;
  806. s->sr_delay_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_set_sr_int, s);
  807. }
  808. static void cuda_realizefn(DeviceState *dev, Error **errp)
  809. {
  810. CUDAState *s = CUDA(dev);
  811. struct tm tm;
  812. s->timers[0].timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_timer1, s);
  813. s->timers[0].frequency = s->frequency;
  814. s->timers[1].timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_timer2, s);
  815. s->timers[1].frequency = (SCALE_US * 6000) / 4700;
  816. qemu_get_timedate(&tm, 0);
  817. s->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET;
  818. s->adb_poll_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_adb_poll, s);
  819. s->autopoll_rate_ms = 20;
  820. s->adb_poll_mask = 0xffff;
  821. }
  822. static void cuda_initfn(Object *obj)
  823. {
  824. SysBusDevice *d = SYS_BUS_DEVICE(obj);
  825. CUDAState *s = CUDA(obj);
  826. int i;
  827. memory_region_init_io(&s->mem, obj, &cuda_ops, s, "cuda", 0x2000);
  828. sysbus_init_mmio(d, &s->mem);
  829. sysbus_init_irq(d, &s->irq);
  830. for (i = 0; i < ARRAY_SIZE(s->timers); i++) {
  831. s->timers[i].index = i;
  832. }
  833. qbus_create_inplace(&s->adb_bus, sizeof(s->adb_bus), TYPE_ADB_BUS,
  834. DEVICE(obj), "adb.0");
  835. }
  836. static Property cuda_properties[] = {
  837. DEFINE_PROP_UINT64("frequency", CUDAState, frequency, 0),
  838. DEFINE_PROP_END_OF_LIST()
  839. };
  840. static void cuda_class_init(ObjectClass *oc, void *data)
  841. {
  842. DeviceClass *dc = DEVICE_CLASS(oc);
  843. dc->realize = cuda_realizefn;
  844. dc->reset = cuda_reset;
  845. dc->vmsd = &vmstate_cuda;
  846. dc->props = cuda_properties;
  847. set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
  848. }
  849. static const TypeInfo cuda_type_info = {
  850. .name = TYPE_CUDA,
  851. .parent = TYPE_SYS_BUS_DEVICE,
  852. .instance_size = sizeof(CUDAState),
  853. .instance_init = cuda_initfn,
  854. .class_init = cuda_class_init,
  855. };
  856. static void cuda_register_types(void)
  857. {
  858. type_register_static(&cuda_type_info);
  859. }
  860. type_init(cuda_register_types)