macfb.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847
  1. /*
  2. * QEMU Motorola 680x0 Macintosh Video Card Emulation
  3. * Copyright (c) 2012-2018 Laurent Vivier
  4. *
  5. * some parts from QEMU G364 framebuffer Emulator.
  6. * Copyright (c) 2007-2011 Herve Poussineau
  7. *
  8. * This work is licensed under the terms of the GNU GPL, version 2 or later.
  9. * See the COPYING file in the top-level directory.
  10. *
  11. */
  12. #include "qemu/osdep.h"
  13. #include "qemu/units.h"
  14. #include "hw/sysbus.h"
  15. #include "ui/console.h"
  16. #include "ui/pixel_ops.h"
  17. #include "hw/nubus/nubus.h"
  18. #include "hw/display/macfb.h"
  19. #include "qapi/error.h"
  20. #include "hw/qdev-properties.h"
  21. #include "migration/vmstate.h"
  22. #include "trace.h"
  23. #define VIDEO_BASE 0x0
  24. #define DAFB_BASE 0x00800000
  25. #define MACFB_PAGE_SIZE 4096
  26. #define MACFB_VRAM_SIZE (4 * MiB)
  27. #define DAFB_MODE_VADDR1 0x0
  28. #define DAFB_MODE_VADDR2 0x4
  29. #define DAFB_MODE_CTRL1 0x8
  30. #define DAFB_MODE_CTRL2 0xc
  31. #define DAFB_MODE_SENSE 0x1c
  32. #define DAFB_INTR_MASK 0x104
  33. #define DAFB_INTR_STAT 0x108
  34. #define DAFB_INTR_CLEAR 0x10c
  35. #define DAFB_LUT_INDEX 0x200
  36. #define DAFB_LUT 0x210
  37. #define DAFB_INTR_VBL 0x4
  38. /* Vertical Blank period (60.15Hz) */
  39. #define DAFB_INTR_VBL_PERIOD_NS 16625800
  40. /*
  41. * Quadra sense codes taken from Apple Technical Note HW26:
  42. * "Macintosh Quadra Built-In Video". The sense codes and
  43. * extended sense codes have different meanings:
  44. *
  45. * Sense:
  46. * bit 2: SENSE2 (pin 10)
  47. * bit 1: SENSE1 (pin 7)
  48. * bit 0: SENSE0 (pin 4)
  49. *
  50. * 0 = pin tied to ground
  51. * 1 = pin unconnected
  52. *
  53. * Extended Sense:
  54. * bit 2: pins 4-10
  55. * bit 1: pins 10-7
  56. * bit 0: pins 7-4
  57. *
  58. * 0 = pins tied together
  59. * 1 = pins unconnected
  60. *
  61. * Reads from the sense register appear to be active low, i.e. a 1 indicates
  62. * that the pin is tied to ground, a 0 indicates the pin is disconnected.
  63. *
  64. * Writes to the sense register appear to activate pulldowns i.e. a 1 enables
  65. * a pulldown on a particular pin.
  66. *
  67. * The MacOS toolbox appears to use a series of reads and writes to first
  68. * determine if extended sense is to be used, and then check which pins are
  69. * tied together in order to determine the display type.
  70. */
  71. typedef struct MacFbSense {
  72. uint8_t type;
  73. uint8_t sense;
  74. uint8_t ext_sense;
  75. } MacFbSense;
  76. static MacFbSense macfb_sense_table[] = {
  77. { MACFB_DISPLAY_APPLE_21_COLOR, 0x0, 0 },
  78. { MACFB_DISPLAY_APPLE_PORTRAIT, 0x1, 0 },
  79. { MACFB_DISPLAY_APPLE_12_RGB, 0x2, 0 },
  80. { MACFB_DISPLAY_APPLE_2PAGE_MONO, 0x3, 0 },
  81. { MACFB_DISPLAY_NTSC_UNDERSCAN, 0x4, 0 },
  82. { MACFB_DISPLAY_NTSC_OVERSCAN, 0x4, 0 },
  83. { MACFB_DISPLAY_APPLE_12_MONO, 0x6, 0 },
  84. { MACFB_DISPLAY_APPLE_13_RGB, 0x6, 0 },
  85. { MACFB_DISPLAY_16_COLOR, 0x7, 0x3 },
  86. { MACFB_DISPLAY_PAL1_UNDERSCAN, 0x7, 0x0 },
  87. { MACFB_DISPLAY_PAL1_OVERSCAN, 0x7, 0x0 },
  88. { MACFB_DISPLAY_PAL2_UNDERSCAN, 0x7, 0x6 },
  89. { MACFB_DISPLAY_PAL2_OVERSCAN, 0x7, 0x6 },
  90. { MACFB_DISPLAY_VGA, 0x7, 0x5 },
  91. { MACFB_DISPLAY_SVGA, 0x7, 0x5 },
  92. };
  93. static MacFbMode macfb_mode_table[] = {
  94. { MACFB_DISPLAY_VGA, 1, 0x100, 0x71e, 640, 480, 0x400, 0x1000 },
  95. { MACFB_DISPLAY_VGA, 2, 0x100, 0x70e, 640, 480, 0x400, 0x1000 },
  96. { MACFB_DISPLAY_VGA, 4, 0x100, 0x706, 640, 480, 0x400, 0x1000 },
  97. { MACFB_DISPLAY_VGA, 8, 0x100, 0x702, 640, 480, 0x400, 0x1000 },
  98. { MACFB_DISPLAY_VGA, 24, 0x100, 0x7ff, 640, 480, 0x1000, 0x1000 },
  99. { MACFB_DISPLAY_VGA, 1, 0xd0 , 0x70e, 800, 600, 0x340, 0xe00 },
  100. { MACFB_DISPLAY_VGA, 2, 0xd0 , 0x706, 800, 600, 0x340, 0xe00 },
  101. { MACFB_DISPLAY_VGA, 4, 0xd0 , 0x702, 800, 600, 0x340, 0xe00 },
  102. { MACFB_DISPLAY_VGA, 8, 0xd0, 0x700, 800, 600, 0x340, 0xe00 },
  103. { MACFB_DISPLAY_VGA, 24, 0x340, 0x100, 800, 600, 0xd00, 0xe00 },
  104. { MACFB_DISPLAY_APPLE_21_COLOR, 1, 0x90, 0x506, 1152, 870, 0x240, 0x80 },
  105. { MACFB_DISPLAY_APPLE_21_COLOR, 2, 0x90, 0x502, 1152, 870, 0x240, 0x80 },
  106. { MACFB_DISPLAY_APPLE_21_COLOR, 4, 0x90, 0x500, 1152, 870, 0x240, 0x80 },
  107. { MACFB_DISPLAY_APPLE_21_COLOR, 8, 0x120, 0x5ff, 1152, 870, 0x480, 0x80 },
  108. };
  109. typedef void macfb_draw_line_func(MacfbState *s, uint8_t *d, uint32_t addr,
  110. int width);
  111. static inline uint8_t macfb_read_byte(MacfbState *s, uint32_t addr)
  112. {
  113. return s->vram[addr & s->vram_bit_mask];
  114. }
  115. /* 1-bit color */
  116. static void macfb_draw_line1(MacfbState *s, uint8_t *d, uint32_t addr,
  117. int width)
  118. {
  119. uint8_t r, g, b;
  120. int x;
  121. for (x = 0; x < width; x++) {
  122. int bit = x & 7;
  123. int idx = (macfb_read_byte(s, addr) >> (7 - bit)) & 1;
  124. r = s->color_palette[idx * 3];
  125. g = s->color_palette[idx * 3 + 1];
  126. b = s->color_palette[idx * 3 + 2];
  127. addr += (bit == 7);
  128. *(uint32_t *)d = rgb_to_pixel32(r, g, b);
  129. d += 4;
  130. }
  131. }
  132. /* 2-bit color */
  133. static void macfb_draw_line2(MacfbState *s, uint8_t *d, uint32_t addr,
  134. int width)
  135. {
  136. uint8_t r, g, b;
  137. int x;
  138. for (x = 0; x < width; x++) {
  139. int bit = (x & 3);
  140. int idx = (macfb_read_byte(s, addr) >> ((3 - bit) << 1)) & 3;
  141. r = s->color_palette[idx * 3];
  142. g = s->color_palette[idx * 3 + 1];
  143. b = s->color_palette[idx * 3 + 2];
  144. addr += (bit == 3);
  145. *(uint32_t *)d = rgb_to_pixel32(r, g, b);
  146. d += 4;
  147. }
  148. }
  149. /* 4-bit color */
  150. static void macfb_draw_line4(MacfbState *s, uint8_t *d, uint32_t addr,
  151. int width)
  152. {
  153. uint8_t r, g, b;
  154. int x;
  155. for (x = 0; x < width; x++) {
  156. int bit = x & 1;
  157. int idx = (macfb_read_byte(s, addr) >> ((1 - bit) << 2)) & 15;
  158. r = s->color_palette[idx * 3];
  159. g = s->color_palette[idx * 3 + 1];
  160. b = s->color_palette[idx * 3 + 2];
  161. addr += (bit == 1);
  162. *(uint32_t *)d = rgb_to_pixel32(r, g, b);
  163. d += 4;
  164. }
  165. }
  166. /* 8-bit color */
  167. static void macfb_draw_line8(MacfbState *s, uint8_t *d, uint32_t addr,
  168. int width)
  169. {
  170. uint8_t r, g, b;
  171. int x;
  172. for (x = 0; x < width; x++) {
  173. r = s->color_palette[macfb_read_byte(s, addr) * 3];
  174. g = s->color_palette[macfb_read_byte(s, addr) * 3 + 1];
  175. b = s->color_palette[macfb_read_byte(s, addr) * 3 + 2];
  176. addr++;
  177. *(uint32_t *)d = rgb_to_pixel32(r, g, b);
  178. d += 4;
  179. }
  180. }
  181. /* 16-bit color */
  182. static void macfb_draw_line16(MacfbState *s, uint8_t *d, uint32_t addr,
  183. int width)
  184. {
  185. uint8_t r, g, b;
  186. int x;
  187. for (x = 0; x < width; x++) {
  188. uint16_t pixel;
  189. pixel = (macfb_read_byte(s, addr) << 8) | macfb_read_byte(s, addr + 1);
  190. r = ((pixel >> 10) & 0x1f) << 3;
  191. g = ((pixel >> 5) & 0x1f) << 3;
  192. b = (pixel & 0x1f) << 3;
  193. addr += 2;
  194. *(uint32_t *)d = rgb_to_pixel32(r, g, b);
  195. d += 4;
  196. }
  197. }
  198. /* 24-bit color */
  199. static void macfb_draw_line24(MacfbState *s, uint8_t *d, uint32_t addr,
  200. int width)
  201. {
  202. uint8_t r, g, b;
  203. int x;
  204. for (x = 0; x < width; x++) {
  205. r = macfb_read_byte(s, addr + 1);
  206. g = macfb_read_byte(s, addr + 2);
  207. b = macfb_read_byte(s, addr + 3);
  208. addr += 4;
  209. *(uint32_t *)d = rgb_to_pixel32(r, g, b);
  210. d += 4;
  211. }
  212. }
  213. enum {
  214. MACFB_DRAW_LINE1,
  215. MACFB_DRAW_LINE2,
  216. MACFB_DRAW_LINE4,
  217. MACFB_DRAW_LINE8,
  218. MACFB_DRAW_LINE16,
  219. MACFB_DRAW_LINE24,
  220. MACFB_DRAW_LINE_NB,
  221. };
  222. static macfb_draw_line_func * const
  223. macfb_draw_line_table[MACFB_DRAW_LINE_NB] = {
  224. macfb_draw_line1,
  225. macfb_draw_line2,
  226. macfb_draw_line4,
  227. macfb_draw_line8,
  228. macfb_draw_line16,
  229. macfb_draw_line24,
  230. };
  231. static int macfb_check_dirty(MacfbState *s, DirtyBitmapSnapshot *snap,
  232. ram_addr_t addr, int len)
  233. {
  234. return memory_region_snapshot_get_dirty(&s->mem_vram, snap, addr, len);
  235. }
  236. static void macfb_draw_graphic(MacfbState *s)
  237. {
  238. DisplaySurface *surface = qemu_console_surface(s->con);
  239. DirtyBitmapSnapshot *snap = NULL;
  240. ram_addr_t page;
  241. uint32_t v = 0;
  242. int y, ymin;
  243. int macfb_stride = s->mode->stride;
  244. macfb_draw_line_func *macfb_draw_line;
  245. switch (s->depth) {
  246. case 1:
  247. v = MACFB_DRAW_LINE1;
  248. break;
  249. case 2:
  250. v = MACFB_DRAW_LINE2;
  251. break;
  252. case 4:
  253. v = MACFB_DRAW_LINE4;
  254. break;
  255. case 8:
  256. v = MACFB_DRAW_LINE8;
  257. break;
  258. case 16:
  259. v = MACFB_DRAW_LINE16;
  260. break;
  261. case 24:
  262. v = MACFB_DRAW_LINE24;
  263. break;
  264. }
  265. macfb_draw_line = macfb_draw_line_table[v];
  266. assert(macfb_draw_line != NULL);
  267. snap = memory_region_snapshot_and_clear_dirty(&s->mem_vram, 0x0,
  268. memory_region_size(&s->mem_vram),
  269. DIRTY_MEMORY_VGA);
  270. ymin = -1;
  271. page = s->mode->offset;
  272. for (y = 0; y < s->height; y++, page += macfb_stride) {
  273. if (macfb_check_dirty(s, snap, page, macfb_stride)) {
  274. uint8_t *data_display;
  275. data_display = surface_data(surface) + y * surface_stride(surface);
  276. macfb_draw_line(s, data_display, page, s->width);
  277. if (ymin < 0) {
  278. ymin = y;
  279. }
  280. } else {
  281. if (ymin >= 0) {
  282. dpy_gfx_update(s->con, 0, ymin, s->width, y - ymin);
  283. ymin = -1;
  284. }
  285. }
  286. }
  287. if (ymin >= 0) {
  288. dpy_gfx_update(s->con, 0, ymin, s->width, y - ymin);
  289. }
  290. g_free(snap);
  291. }
  292. static void macfb_invalidate_display(void *opaque)
  293. {
  294. MacfbState *s = opaque;
  295. memory_region_set_dirty(&s->mem_vram, 0, MACFB_VRAM_SIZE);
  296. }
  297. static uint32_t macfb_sense_read(MacfbState *s)
  298. {
  299. MacFbSense *macfb_sense;
  300. uint8_t sense;
  301. assert(s->type < ARRAY_SIZE(macfb_sense_table));
  302. macfb_sense = &macfb_sense_table[s->type];
  303. if (macfb_sense->sense == 0x7) {
  304. /* Extended sense */
  305. sense = 0;
  306. if (!(macfb_sense->ext_sense & 1)) {
  307. /* Pins 7-4 together */
  308. if (~s->regs[DAFB_MODE_SENSE >> 2] & 3) {
  309. sense = (~s->regs[DAFB_MODE_SENSE >> 2] & 7) | 3;
  310. }
  311. }
  312. if (!(macfb_sense->ext_sense & 2)) {
  313. /* Pins 10-7 together */
  314. if (~s->regs[DAFB_MODE_SENSE >> 2] & 6) {
  315. sense = (~s->regs[DAFB_MODE_SENSE >> 2] & 7) | 6;
  316. }
  317. }
  318. if (!(macfb_sense->ext_sense & 4)) {
  319. /* Pins 4-10 together */
  320. if (~s->regs[DAFB_MODE_SENSE >> 2] & 5) {
  321. sense = (~s->regs[DAFB_MODE_SENSE >> 2] & 7) | 5;
  322. }
  323. }
  324. } else {
  325. /* Normal sense */
  326. sense = (~macfb_sense->sense & 7) |
  327. (~s->regs[DAFB_MODE_SENSE >> 2] & 7);
  328. }
  329. trace_macfb_sense_read(sense);
  330. return sense;
  331. }
  332. static void macfb_sense_write(MacfbState *s, uint32_t val)
  333. {
  334. s->regs[DAFB_MODE_SENSE >> 2] = val;
  335. trace_macfb_sense_write(val);
  336. return;
  337. }
  338. static void macfb_update_mode(MacfbState *s)
  339. {
  340. s->width = s->mode->width;
  341. s->height = s->mode->height;
  342. s->depth = s->mode->depth;
  343. trace_macfb_update_mode(s->width, s->height, s->depth);
  344. macfb_invalidate_display(s);
  345. }
  346. static void macfb_mode_write(MacfbState *s)
  347. {
  348. MacFbMode *macfb_mode;
  349. int i;
  350. for (i = 0; i < ARRAY_SIZE(macfb_mode_table); i++) {
  351. macfb_mode = &macfb_mode_table[i];
  352. if (s->type != macfb_mode->type) {
  353. continue;
  354. }
  355. if ((s->regs[DAFB_MODE_CTRL1 >> 2] & 0xff) ==
  356. (macfb_mode->mode_ctrl1 & 0xff) &&
  357. (s->regs[DAFB_MODE_CTRL2 >> 2] & 0xff) ==
  358. (macfb_mode->mode_ctrl2 & 0xff)) {
  359. s->mode = macfb_mode;
  360. macfb_update_mode(s);
  361. break;
  362. }
  363. }
  364. }
  365. static MacFbMode *macfb_find_mode(MacfbDisplayType display_type,
  366. uint16_t width, uint16_t height,
  367. uint8_t depth)
  368. {
  369. MacFbMode *macfb_mode;
  370. int i;
  371. for (i = 0; i < ARRAY_SIZE(macfb_mode_table); i++) {
  372. macfb_mode = &macfb_mode_table[i];
  373. if (display_type == macfb_mode->type && width == macfb_mode->width &&
  374. height == macfb_mode->height && depth == macfb_mode->depth) {
  375. return macfb_mode;
  376. }
  377. }
  378. return NULL;
  379. }
  380. static gchar *macfb_mode_list(void)
  381. {
  382. GString *list = g_string_new("");
  383. MacFbMode *macfb_mode;
  384. int i;
  385. for (i = 0; i < ARRAY_SIZE(macfb_mode_table); i++) {
  386. macfb_mode = &macfb_mode_table[i];
  387. g_string_append_printf(list, " %dx%dx%d\n", macfb_mode->width,
  388. macfb_mode->height, macfb_mode->depth);
  389. }
  390. return g_string_free(list, FALSE);
  391. }
  392. static void macfb_update_display(void *opaque)
  393. {
  394. MacfbState *s = opaque;
  395. DisplaySurface *surface = qemu_console_surface(s->con);
  396. qemu_flush_coalesced_mmio_buffer();
  397. if (s->width == 0 || s->height == 0) {
  398. return;
  399. }
  400. if (s->width != surface_width(surface) ||
  401. s->height != surface_height(surface)) {
  402. qemu_console_resize(s->con, s->width, s->height);
  403. }
  404. macfb_draw_graphic(s);
  405. }
  406. static void macfb_update_irq(MacfbState *s)
  407. {
  408. uint32_t irq_state = s->regs[DAFB_INTR_STAT >> 2] &
  409. s->regs[DAFB_INTR_MASK >> 2];
  410. if (irq_state) {
  411. qemu_irq_raise(s->irq);
  412. } else {
  413. qemu_irq_lower(s->irq);
  414. }
  415. }
  416. static int64_t macfb_next_vbl(void)
  417. {
  418. return (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + DAFB_INTR_VBL_PERIOD_NS) /
  419. DAFB_INTR_VBL_PERIOD_NS * DAFB_INTR_VBL_PERIOD_NS;
  420. }
  421. static void macfb_vbl_timer(void *opaque)
  422. {
  423. MacfbState *s = opaque;
  424. int64_t next_vbl;
  425. s->regs[DAFB_INTR_STAT >> 2] |= DAFB_INTR_VBL;
  426. macfb_update_irq(s);
  427. /* 60 Hz irq */
  428. next_vbl = macfb_next_vbl();
  429. timer_mod(s->vbl_timer, next_vbl);
  430. }
  431. static void macfb_reset(MacfbState *s)
  432. {
  433. int i;
  434. s->palette_current = 0;
  435. for (i = 0; i < 256; i++) {
  436. s->color_palette[i * 3] = 255 - i;
  437. s->color_palette[i * 3 + 1] = 255 - i;
  438. s->color_palette[i * 3 + 2] = 255 - i;
  439. }
  440. memset(s->vram, 0, MACFB_VRAM_SIZE);
  441. macfb_invalidate_display(s);
  442. }
  443. static uint64_t macfb_ctrl_read(void *opaque,
  444. hwaddr addr,
  445. unsigned int size)
  446. {
  447. MacfbState *s = opaque;
  448. uint64_t val = 0;
  449. switch (addr) {
  450. case DAFB_MODE_VADDR1:
  451. case DAFB_MODE_VADDR2:
  452. case DAFB_MODE_CTRL1:
  453. case DAFB_MODE_CTRL2:
  454. case DAFB_INTR_STAT:
  455. val = s->regs[addr >> 2];
  456. break;
  457. case DAFB_MODE_SENSE:
  458. val = macfb_sense_read(s);
  459. break;
  460. case DAFB_LUT ... DAFB_LUT + 3:
  461. val = s->color_palette[s->palette_current];
  462. s->palette_current = (s->palette_current + 1) %
  463. ARRAY_SIZE(s->color_palette);
  464. break;
  465. default:
  466. if (addr < MACFB_CTRL_TOPADDR) {
  467. val = s->regs[addr >> 2];
  468. }
  469. }
  470. trace_macfb_ctrl_read(addr, val, size);
  471. return val;
  472. }
  473. static void macfb_ctrl_write(void *opaque,
  474. hwaddr addr,
  475. uint64_t val,
  476. unsigned int size)
  477. {
  478. MacfbState *s = opaque;
  479. int64_t next_vbl;
  480. switch (addr) {
  481. case DAFB_MODE_VADDR1:
  482. case DAFB_MODE_VADDR2:
  483. s->regs[addr >> 2] = val;
  484. break;
  485. case DAFB_MODE_CTRL1 ... DAFB_MODE_CTRL1 + 3:
  486. case DAFB_MODE_CTRL2 ... DAFB_MODE_CTRL2 + 3:
  487. s->regs[addr >> 2] = val;
  488. if (val) {
  489. macfb_mode_write(s);
  490. }
  491. break;
  492. case DAFB_MODE_SENSE:
  493. macfb_sense_write(s, val);
  494. break;
  495. case DAFB_INTR_MASK:
  496. s->regs[addr >> 2] = val;
  497. if (val & DAFB_INTR_VBL) {
  498. next_vbl = macfb_next_vbl();
  499. timer_mod(s->vbl_timer, next_vbl);
  500. } else {
  501. timer_del(s->vbl_timer);
  502. }
  503. break;
  504. case DAFB_INTR_CLEAR:
  505. s->regs[DAFB_INTR_STAT >> 2] &= ~DAFB_INTR_VBL;
  506. macfb_update_irq(s);
  507. break;
  508. case DAFB_LUT_INDEX:
  509. s->palette_current = (val & 0xff) * 3;
  510. break;
  511. case DAFB_LUT ... DAFB_LUT + 3:
  512. s->color_palette[s->palette_current] = val & 0xff;
  513. s->palette_current = (s->palette_current + 1) %
  514. ARRAY_SIZE(s->color_palette);
  515. if (s->palette_current % 3) {
  516. macfb_invalidate_display(s);
  517. }
  518. break;
  519. default:
  520. if (addr < MACFB_CTRL_TOPADDR) {
  521. s->regs[addr >> 2] = val;
  522. }
  523. }
  524. trace_macfb_ctrl_write(addr, val, size);
  525. }
  526. static const MemoryRegionOps macfb_ctrl_ops = {
  527. .read = macfb_ctrl_read,
  528. .write = macfb_ctrl_write,
  529. .endianness = DEVICE_BIG_ENDIAN,
  530. .impl.min_access_size = 1,
  531. .impl.max_access_size = 4,
  532. };
  533. static int macfb_post_load(void *opaque, int version_id)
  534. {
  535. macfb_mode_write(opaque);
  536. return 0;
  537. }
  538. static const VMStateDescription vmstate_macfb = {
  539. .name = "macfb",
  540. .version_id = 1,
  541. .minimum_version_id = 1,
  542. .post_load = macfb_post_load,
  543. .fields = (const VMStateField[]) {
  544. VMSTATE_UINT8(type, MacfbState),
  545. VMSTATE_UINT8_ARRAY(color_palette, MacfbState, 256 * 3),
  546. VMSTATE_UINT32(palette_current, MacfbState),
  547. VMSTATE_UINT32_ARRAY(regs, MacfbState, MACFB_NUM_REGS),
  548. VMSTATE_TIMER_PTR(vbl_timer, MacfbState),
  549. VMSTATE_END_OF_LIST()
  550. }
  551. };
  552. static const GraphicHwOps macfb_ops = {
  553. .invalidate = macfb_invalidate_display,
  554. .gfx_update = macfb_update_display,
  555. };
  556. static bool macfb_common_realize(DeviceState *dev, MacfbState *s, Error **errp)
  557. {
  558. DisplaySurface *surface;
  559. s->mode = macfb_find_mode(s->type, s->width, s->height, s->depth);
  560. if (!s->mode) {
  561. gchar *list;
  562. error_setg(errp, "unknown display mode: width %d, height %d, depth %d",
  563. s->width, s->height, s->depth);
  564. list = macfb_mode_list();
  565. error_append_hint(errp, "Available modes:\n%s", list);
  566. g_free(list);
  567. return false;
  568. }
  569. /*
  570. * Set mode control registers to match the mode found above so that
  571. * macfb_mode_write() does the right thing if no MacOS toolbox ROM
  572. * is present to initialise them
  573. */
  574. s->regs[DAFB_MODE_CTRL1 >> 2] = s->mode->mode_ctrl1;
  575. s->regs[DAFB_MODE_CTRL2 >> 2] = s->mode->mode_ctrl2;
  576. s->con = graphic_console_init(dev, 0, &macfb_ops, s);
  577. surface = qemu_console_surface(s->con);
  578. if (surface_bits_per_pixel(surface) != 32) {
  579. error_setg(errp, "unknown host depth %d",
  580. surface_bits_per_pixel(surface));
  581. return false;
  582. }
  583. memory_region_init_io(&s->mem_ctrl, OBJECT(dev), &macfb_ctrl_ops, s,
  584. "macfb-ctrl", 0x1000);
  585. memory_region_init_ram(&s->mem_vram, OBJECT(dev), "macfb-vram",
  586. MACFB_VRAM_SIZE, &error_abort);
  587. memory_region_set_log(&s->mem_vram, true, DIRTY_MEMORY_VGA);
  588. s->vram = memory_region_get_ram_ptr(&s->mem_vram);
  589. s->vram_bit_mask = MACFB_VRAM_SIZE - 1;
  590. s->vbl_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, macfb_vbl_timer, s);
  591. macfb_update_mode(s);
  592. return true;
  593. }
  594. static void macfb_sysbus_realize(DeviceState *dev, Error **errp)
  595. {
  596. MacfbSysBusState *s = MACFB(dev);
  597. MacfbState *ms = &s->macfb;
  598. if (!macfb_common_realize(dev, ms, errp)) {
  599. return;
  600. }
  601. sysbus_init_mmio(SYS_BUS_DEVICE(s), &ms->mem_ctrl);
  602. sysbus_init_mmio(SYS_BUS_DEVICE(s), &ms->mem_vram);
  603. qdev_init_gpio_out(dev, &ms->irq, 1);
  604. }
  605. static void macfb_nubus_set_irq(void *opaque, int n, int level)
  606. {
  607. MacfbNubusState *s = NUBUS_MACFB(opaque);
  608. NubusDevice *nd = NUBUS_DEVICE(s);
  609. nubus_set_irq(nd, level);
  610. }
  611. static void macfb_nubus_realize(DeviceState *dev, Error **errp)
  612. {
  613. ERRP_GUARD();
  614. NubusDevice *nd = NUBUS_DEVICE(dev);
  615. MacfbNubusState *s = NUBUS_MACFB(dev);
  616. MacfbNubusDeviceClass *ndc = NUBUS_MACFB_GET_CLASS(dev);
  617. MacfbState *ms = &s->macfb;
  618. ndc->parent_realize(dev, errp);
  619. if (*errp) {
  620. return;
  621. }
  622. if (!macfb_common_realize(dev, ms, errp)) {
  623. return;
  624. }
  625. memory_region_add_subregion(&nd->slot_mem, DAFB_BASE, &ms->mem_ctrl);
  626. memory_region_add_subregion(&nd->slot_mem, VIDEO_BASE, &ms->mem_vram);
  627. ms->irq = qemu_allocate_irq(macfb_nubus_set_irq, s, 0);
  628. }
  629. static void macfb_nubus_unrealize(DeviceState *dev)
  630. {
  631. MacfbNubusState *s = NUBUS_MACFB(dev);
  632. MacfbNubusDeviceClass *ndc = NUBUS_MACFB_GET_CLASS(dev);
  633. MacfbState *ms = &s->macfb;
  634. ndc->parent_unrealize(dev);
  635. qemu_free_irq(ms->irq);
  636. }
  637. static void macfb_sysbus_reset(DeviceState *d)
  638. {
  639. MacfbSysBusState *s = MACFB(d);
  640. macfb_reset(&s->macfb);
  641. }
  642. static void macfb_nubus_reset(DeviceState *d)
  643. {
  644. MacfbNubusState *s = NUBUS_MACFB(d);
  645. macfb_reset(&s->macfb);
  646. }
  647. static Property macfb_sysbus_properties[] = {
  648. DEFINE_PROP_UINT32("width", MacfbSysBusState, macfb.width, 640),
  649. DEFINE_PROP_UINT32("height", MacfbSysBusState, macfb.height, 480),
  650. DEFINE_PROP_UINT8("depth", MacfbSysBusState, macfb.depth, 8),
  651. DEFINE_PROP_UINT8("display", MacfbSysBusState, macfb.type,
  652. MACFB_DISPLAY_VGA),
  653. DEFINE_PROP_END_OF_LIST(),
  654. };
  655. static const VMStateDescription vmstate_macfb_sysbus = {
  656. .name = "macfb-sysbus",
  657. .version_id = 1,
  658. .minimum_version_id = 1,
  659. .fields = (const VMStateField[]) {
  660. VMSTATE_STRUCT(macfb, MacfbSysBusState, 1, vmstate_macfb, MacfbState),
  661. VMSTATE_END_OF_LIST()
  662. }
  663. };
  664. static Property macfb_nubus_properties[] = {
  665. DEFINE_PROP_UINT32("width", MacfbNubusState, macfb.width, 640),
  666. DEFINE_PROP_UINT32("height", MacfbNubusState, macfb.height, 480),
  667. DEFINE_PROP_UINT8("depth", MacfbNubusState, macfb.depth, 8),
  668. DEFINE_PROP_UINT8("display", MacfbNubusState, macfb.type,
  669. MACFB_DISPLAY_VGA),
  670. DEFINE_PROP_END_OF_LIST(),
  671. };
  672. static const VMStateDescription vmstate_macfb_nubus = {
  673. .name = "macfb-nubus",
  674. .version_id = 1,
  675. .minimum_version_id = 1,
  676. .fields = (const VMStateField[]) {
  677. VMSTATE_STRUCT(macfb, MacfbNubusState, 1, vmstate_macfb, MacfbState),
  678. VMSTATE_END_OF_LIST()
  679. }
  680. };
  681. static void macfb_sysbus_class_init(ObjectClass *klass, void *data)
  682. {
  683. DeviceClass *dc = DEVICE_CLASS(klass);
  684. dc->realize = macfb_sysbus_realize;
  685. dc->desc = "SysBus Macintosh framebuffer";
  686. device_class_set_legacy_reset(dc, macfb_sysbus_reset);
  687. dc->vmsd = &vmstate_macfb_sysbus;
  688. device_class_set_props(dc, macfb_sysbus_properties);
  689. }
  690. static void macfb_nubus_class_init(ObjectClass *klass, void *data)
  691. {
  692. DeviceClass *dc = DEVICE_CLASS(klass);
  693. MacfbNubusDeviceClass *ndc = NUBUS_MACFB_CLASS(klass);
  694. device_class_set_parent_realize(dc, macfb_nubus_realize,
  695. &ndc->parent_realize);
  696. device_class_set_parent_unrealize(dc, macfb_nubus_unrealize,
  697. &ndc->parent_unrealize);
  698. dc->desc = "Nubus Macintosh framebuffer";
  699. device_class_set_legacy_reset(dc, macfb_nubus_reset);
  700. dc->vmsd = &vmstate_macfb_nubus;
  701. set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
  702. device_class_set_props(dc, macfb_nubus_properties);
  703. }
  704. static const TypeInfo macfb_sysbus_info = {
  705. .name = TYPE_MACFB,
  706. .parent = TYPE_SYS_BUS_DEVICE,
  707. .instance_size = sizeof(MacfbSysBusState),
  708. .class_init = macfb_sysbus_class_init,
  709. };
  710. static const TypeInfo macfb_nubus_info = {
  711. .name = TYPE_NUBUS_MACFB,
  712. .parent = TYPE_NUBUS_DEVICE,
  713. .instance_size = sizeof(MacfbNubusState),
  714. .class_init = macfb_nubus_class_init,
  715. .class_size = sizeof(MacfbNubusDeviceClass),
  716. };
  717. static void macfb_register_types(void)
  718. {
  719. type_register_static(&macfb_sysbus_info);
  720. type_register_static(&macfb_nubus_info);
  721. }
  722. type_init(macfb_register_types)