artist.c 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443
  1. /*
  2. * QEMU HP Artist Emulation
  3. *
  4. * Copyright (c) 2019 Sven Schnelle <svens@stackframe.org>
  5. *
  6. * This work is licensed under the terms of the GNU GPL, version 2 or later.
  7. */
  8. #include "qemu/osdep.h"
  9. #include "qemu-common.h"
  10. #include "qemu/error-report.h"
  11. #include "qemu/typedefs.h"
  12. #include "qemu/log.h"
  13. #include "qemu/module.h"
  14. #include "qemu/units.h"
  15. #include "qapi/error.h"
  16. #include "hw/sysbus.h"
  17. #include "hw/loader.h"
  18. #include "hw/qdev-core.h"
  19. #include "hw/qdev-properties.h"
  20. #include "migration/vmstate.h"
  21. #include "ui/console.h"
  22. #include "trace.h"
  23. #include "framebuffer.h"
  24. #define TYPE_ARTIST "artist"
  25. #define ARTIST(obj) OBJECT_CHECK(ARTISTState, (obj), TYPE_ARTIST)
  26. #ifdef HOST_WORDS_BIGENDIAN
  27. #define ROP8OFF(_i) (3 - (_i))
  28. #else
  29. #define ROP8OFF
  30. #endif
  31. struct vram_buffer {
  32. MemoryRegion mr;
  33. uint8_t *data;
  34. int size;
  35. int width;
  36. int height;
  37. };
  38. typedef struct ARTISTState {
  39. SysBusDevice parent_obj;
  40. QemuConsole *con;
  41. MemoryRegion vram_mem;
  42. MemoryRegion mem_as_root;
  43. MemoryRegion reg;
  44. MemoryRegionSection fbsection;
  45. void *vram_int_mr;
  46. AddressSpace as;
  47. struct vram_buffer vram_buffer[16];
  48. uint16_t width;
  49. uint16_t height;
  50. uint16_t depth;
  51. uint32_t fg_color;
  52. uint32_t bg_color;
  53. uint32_t vram_char_y;
  54. uint32_t vram_bitmask;
  55. uint32_t vram_start;
  56. uint32_t vram_pos;
  57. uint32_t vram_size;
  58. uint32_t blockmove_source;
  59. uint32_t blockmove_dest;
  60. uint32_t blockmove_size;
  61. uint32_t line_size;
  62. uint32_t line_end;
  63. uint32_t line_xy;
  64. uint32_t line_pattern_start;
  65. uint32_t line_pattern_skip;
  66. uint32_t cursor_pos;
  67. uint32_t cursor_height;
  68. uint32_t cursor_width;
  69. uint32_t plane_mask;
  70. uint32_t reg_100080;
  71. uint32_t reg_300200;
  72. uint32_t reg_300208;
  73. uint32_t reg_300218;
  74. uint32_t cmap_bm_access;
  75. uint32_t dst_bm_access;
  76. uint32_t src_bm_access;
  77. uint32_t control_plane;
  78. uint32_t transfer_data;
  79. uint32_t image_bitmap_op;
  80. uint32_t font_write1;
  81. uint32_t font_write2;
  82. uint32_t font_write_pos_y;
  83. int draw_line_pattern;
  84. } ARTISTState;
  85. typedef enum {
  86. ARTIST_BUFFER_AP = 1,
  87. ARTIST_BUFFER_OVERLAY = 2,
  88. ARTIST_BUFFER_CURSOR1 = 6,
  89. ARTIST_BUFFER_CURSOR2 = 7,
  90. ARTIST_BUFFER_ATTRIBUTE = 13,
  91. ARTIST_BUFFER_CMAP = 15,
  92. } artist_buffer_t;
  93. typedef enum {
  94. VRAM_IDX = 0x1004a0,
  95. VRAM_BITMASK = 0x1005a0,
  96. VRAM_WRITE_INCR_X = 0x100600,
  97. VRAM_WRITE_INCR_X2 = 0x100604,
  98. VRAM_WRITE_INCR_Y = 0x100620,
  99. VRAM_START = 0x100800,
  100. BLOCK_MOVE_SIZE = 0x100804,
  101. BLOCK_MOVE_SOURCE = 0x100808,
  102. TRANSFER_DATA = 0x100820,
  103. FONT_WRITE_INCR_Y = 0x1008a0,
  104. VRAM_START_TRIGGER = 0x100a00,
  105. VRAM_SIZE_TRIGGER = 0x100a04,
  106. FONT_WRITE_START = 0x100aa0,
  107. BLOCK_MOVE_DEST_TRIGGER = 0x100b00,
  108. BLOCK_MOVE_SIZE_TRIGGER = 0x100b04,
  109. LINE_XY = 0x100ccc,
  110. PATTERN_LINE_START = 0x100ecc,
  111. LINE_SIZE = 0x100e04,
  112. LINE_END = 0x100e44,
  113. CMAP_BM_ACCESS = 0x118000,
  114. DST_BM_ACCESS = 0x118004,
  115. SRC_BM_ACCESS = 0x118008,
  116. CONTROL_PLANE = 0x11800c,
  117. FG_COLOR = 0x118010,
  118. BG_COLOR = 0x118014,
  119. PLANE_MASK = 0x118018,
  120. IMAGE_BITMAP_OP = 0x11801c,
  121. CURSOR_POS = 0x300100,
  122. CURSOR_CTRL = 0x300104,
  123. } artist_reg_t;
  124. typedef enum {
  125. ARTIST_ROP_CLEAR = 0,
  126. ARTIST_ROP_COPY = 3,
  127. ARTIST_ROP_XOR = 6,
  128. ARTIST_ROP_NOT_DST = 10,
  129. ARTIST_ROP_SET = 15,
  130. } artist_rop_t;
  131. #define REG_NAME(_x) case _x: return " "#_x;
  132. static const char *artist_reg_name(uint64_t addr)
  133. {
  134. switch ((artist_reg_t)addr) {
  135. REG_NAME(VRAM_IDX);
  136. REG_NAME(VRAM_BITMASK);
  137. REG_NAME(VRAM_WRITE_INCR_X);
  138. REG_NAME(VRAM_WRITE_INCR_X2);
  139. REG_NAME(VRAM_WRITE_INCR_Y);
  140. REG_NAME(VRAM_START);
  141. REG_NAME(BLOCK_MOVE_SIZE);
  142. REG_NAME(BLOCK_MOVE_SOURCE);
  143. REG_NAME(FG_COLOR);
  144. REG_NAME(BG_COLOR);
  145. REG_NAME(PLANE_MASK);
  146. REG_NAME(VRAM_START_TRIGGER);
  147. REG_NAME(VRAM_SIZE_TRIGGER);
  148. REG_NAME(BLOCK_MOVE_DEST_TRIGGER);
  149. REG_NAME(BLOCK_MOVE_SIZE_TRIGGER);
  150. REG_NAME(TRANSFER_DATA);
  151. REG_NAME(CONTROL_PLANE);
  152. REG_NAME(IMAGE_BITMAP_OP);
  153. REG_NAME(CMAP_BM_ACCESS);
  154. REG_NAME(DST_BM_ACCESS);
  155. REG_NAME(SRC_BM_ACCESS);
  156. REG_NAME(CURSOR_POS);
  157. REG_NAME(CURSOR_CTRL);
  158. REG_NAME(LINE_XY);
  159. REG_NAME(PATTERN_LINE_START);
  160. REG_NAME(LINE_SIZE);
  161. REG_NAME(LINE_END);
  162. REG_NAME(FONT_WRITE_INCR_Y);
  163. REG_NAME(FONT_WRITE_START);
  164. }
  165. return "";
  166. }
  167. #undef REG_NAME
  168. static int16_t artist_get_x(uint32_t reg)
  169. {
  170. return reg >> 16;
  171. }
  172. static int16_t artist_get_y(uint32_t reg)
  173. {
  174. return reg & 0xffff;
  175. }
  176. static void artist_invalidate_lines(struct vram_buffer *buf,
  177. int starty, int height)
  178. {
  179. int start = starty * buf->width;
  180. int size = height * buf->width;
  181. if (start + size <= buf->size) {
  182. memory_region_set_dirty(&buf->mr, start, size);
  183. }
  184. }
  185. static int vram_write_pix_per_transfer(ARTISTState *s)
  186. {
  187. if (s->cmap_bm_access) {
  188. return 1 << ((s->cmap_bm_access >> 27) & 0x0f);
  189. } else {
  190. return 1 << ((s->dst_bm_access >> 27) & 0x0f);
  191. }
  192. }
  193. static int vram_pixel_length(ARTISTState *s)
  194. {
  195. if (s->cmap_bm_access) {
  196. return (s->cmap_bm_access >> 24) & 0x07;
  197. } else {
  198. return (s->dst_bm_access >> 24) & 0x07;
  199. }
  200. }
  201. static int vram_write_bufidx(ARTISTState *s)
  202. {
  203. if (s->cmap_bm_access) {
  204. return (s->cmap_bm_access >> 12) & 0x0f;
  205. } else {
  206. return (s->dst_bm_access >> 12) & 0x0f;
  207. }
  208. }
  209. static int vram_read_bufidx(ARTISTState *s)
  210. {
  211. if (s->cmap_bm_access) {
  212. return (s->cmap_bm_access >> 12) & 0x0f;
  213. } else {
  214. return (s->src_bm_access >> 12) & 0x0f;
  215. }
  216. }
  217. static struct vram_buffer *vram_read_buffer(ARTISTState *s)
  218. {
  219. return &s->vram_buffer[vram_read_bufidx(s)];
  220. }
  221. static struct vram_buffer *vram_write_buffer(ARTISTState *s)
  222. {
  223. return &s->vram_buffer[vram_write_bufidx(s)];
  224. }
  225. static uint8_t artist_get_color(ARTISTState *s)
  226. {
  227. if (s->image_bitmap_op & 2) {
  228. return s->fg_color;
  229. } else {
  230. return s->bg_color;
  231. }
  232. }
  233. static artist_rop_t artist_get_op(ARTISTState *s)
  234. {
  235. return (s->image_bitmap_op >> 8) & 0xf;
  236. }
  237. static void artist_rop8(ARTISTState *s, uint8_t *dst, uint8_t val)
  238. {
  239. const artist_rop_t op = artist_get_op(s);
  240. uint8_t plane_mask = s->plane_mask & 0xff;
  241. switch (op) {
  242. case ARTIST_ROP_CLEAR:
  243. *dst &= ~plane_mask;
  244. break;
  245. case ARTIST_ROP_COPY:
  246. *dst &= ~plane_mask;
  247. *dst |= val & plane_mask;
  248. break;
  249. case ARTIST_ROP_XOR:
  250. *dst ^= val & plane_mask;
  251. break;
  252. case ARTIST_ROP_NOT_DST:
  253. *dst ^= plane_mask;
  254. break;
  255. case ARTIST_ROP_SET:
  256. *dst |= plane_mask;
  257. break;
  258. default:
  259. qemu_log_mask(LOG_UNIMP, "%s: unsupported rop %d\n", __func__, op);
  260. break;
  261. }
  262. }
  263. static void artist_get_cursor_pos(ARTISTState *s, int *x, int *y)
  264. {
  265. /*
  266. * Don't know whether these magic offset values are configurable via
  267. * some register. They are the same for all resolutions, so don't
  268. * bother about it.
  269. */
  270. *y = 0x47a - artist_get_y(s->cursor_pos);
  271. *x = ((artist_get_x(s->cursor_pos) - 338) / 2);
  272. if (*x > s->width) {
  273. *x = 0;
  274. }
  275. if (*y > s->height) {
  276. *y = 0;
  277. }
  278. }
  279. static void artist_invalidate_cursor(ARTISTState *s)
  280. {
  281. int x, y;
  282. artist_get_cursor_pos(s, &x, &y);
  283. artist_invalidate_lines(&s->vram_buffer[ARTIST_BUFFER_AP],
  284. y, s->cursor_height);
  285. }
  286. static void vram_bit_write(ARTISTState *s, int posx, int posy, bool incr_x,
  287. int size, uint32_t data)
  288. {
  289. struct vram_buffer *buf;
  290. uint32_t vram_bitmask = s->vram_bitmask;
  291. int mask, i, pix_count, pix_length, offset, height, width;
  292. uint8_t *data8, *p;
  293. pix_count = vram_write_pix_per_transfer(s);
  294. pix_length = vram_pixel_length(s);
  295. buf = vram_write_buffer(s);
  296. height = buf->height;
  297. width = buf->width;
  298. if (s->cmap_bm_access) {
  299. offset = s->vram_pos;
  300. } else {
  301. offset = posy * width + posx;
  302. }
  303. if (!buf->size) {
  304. qemu_log("write to non-existent buffer\n");
  305. return;
  306. }
  307. p = buf->data;
  308. if (pix_count > size * 8) {
  309. pix_count = size * 8;
  310. }
  311. if (posy * width + posx + pix_count > buf->size) {
  312. qemu_log("write outside bounds: wants %dx%d, max size %dx%d\n",
  313. posx, posy, width, height);
  314. return;
  315. }
  316. switch (pix_length) {
  317. case 0:
  318. if (s->image_bitmap_op & 0x20000000) {
  319. data &= vram_bitmask;
  320. }
  321. for (i = 0; i < pix_count; i++) {
  322. artist_rop8(s, p + offset + pix_count - 1 - i,
  323. (data & 1) ? (s->plane_mask >> 24) : 0);
  324. data >>= 1;
  325. }
  326. memory_region_set_dirty(&buf->mr, offset, pix_count);
  327. break;
  328. case 3:
  329. if (s->cmap_bm_access) {
  330. *(uint32_t *)(p + offset) = data;
  331. break;
  332. }
  333. data8 = (uint8_t *)&data;
  334. for (i = 3; i >= 0; i--) {
  335. if (!(s->image_bitmap_op & 0x20000000) ||
  336. s->vram_bitmask & (1 << (28 + i))) {
  337. artist_rop8(s, p + offset + 3 - i, data8[ROP8OFF(i)]);
  338. }
  339. }
  340. memory_region_set_dirty(&buf->mr, offset, 3);
  341. break;
  342. case 6:
  343. switch (size) {
  344. default:
  345. case 4:
  346. vram_bitmask = s->vram_bitmask;
  347. break;
  348. case 2:
  349. vram_bitmask = s->vram_bitmask >> 16;
  350. break;
  351. case 1:
  352. vram_bitmask = s->vram_bitmask >> 24;
  353. break;
  354. }
  355. for (i = 0; i < pix_count; i++) {
  356. mask = 1 << (pix_count - 1 - i);
  357. if (!(s->image_bitmap_op & 0x20000000) ||
  358. (vram_bitmask & mask)) {
  359. if (data & mask) {
  360. artist_rop8(s, p + offset + i, s->fg_color);
  361. } else {
  362. if (!(s->image_bitmap_op & 0x10000002)) {
  363. artist_rop8(s, p + offset + i, s->bg_color);
  364. }
  365. }
  366. }
  367. }
  368. memory_region_set_dirty(&buf->mr, offset, pix_count);
  369. break;
  370. default:
  371. qemu_log_mask(LOG_UNIMP, "%s: unknown pixel length %d\n",
  372. __func__, pix_length);
  373. break;
  374. }
  375. if (incr_x) {
  376. if (s->cmap_bm_access) {
  377. s->vram_pos += 4;
  378. } else {
  379. s->vram_pos += pix_count << 2;
  380. }
  381. }
  382. if (vram_write_bufidx(s) == ARTIST_BUFFER_CURSOR1 ||
  383. vram_write_bufidx(s) == ARTIST_BUFFER_CURSOR2) {
  384. artist_invalidate_cursor(s);
  385. }
  386. }
  387. static void block_move(ARTISTState *s, int source_x, int source_y, int dest_x,
  388. int dest_y, int width, int height)
  389. {
  390. struct vram_buffer *buf;
  391. int line, endline, lineincr, startcolumn, endcolumn, columnincr, column;
  392. uint32_t dst, src;
  393. trace_artist_block_move(source_x, source_y, dest_x, dest_y, width, height);
  394. if (s->control_plane != 0) {
  395. /* We don't support CONTROL_PLANE accesses */
  396. qemu_log_mask(LOG_UNIMP, "%s: CONTROL_PLANE: %08x\n", __func__,
  397. s->control_plane);
  398. return;
  399. }
  400. buf = &s->vram_buffer[ARTIST_BUFFER_AP];
  401. if (dest_y > source_y) {
  402. /* move down */
  403. line = height - 1;
  404. endline = -1;
  405. lineincr = -1;
  406. } else {
  407. /* move up */
  408. line = 0;
  409. endline = height;
  410. lineincr = 1;
  411. }
  412. if (dest_x > source_x) {
  413. /* move right */
  414. startcolumn = width - 1;
  415. endcolumn = -1;
  416. columnincr = -1;
  417. } else {
  418. /* move left */
  419. startcolumn = 0;
  420. endcolumn = width;
  421. columnincr = 1;
  422. }
  423. for ( ; line != endline; line += lineincr) {
  424. src = source_x + ((line + source_y) * buf->width);
  425. dst = dest_x + ((line + dest_y) * buf->width);
  426. for (column = startcolumn; column != endcolumn; column += columnincr) {
  427. if (dst + column > buf->size || src + column > buf->size) {
  428. continue;
  429. }
  430. artist_rop8(s, buf->data + dst + column, buf->data[src + column]);
  431. }
  432. }
  433. artist_invalidate_lines(buf, dest_y, height);
  434. }
  435. static void fill_window(ARTISTState *s, int startx, int starty,
  436. int width, int height)
  437. {
  438. uint32_t offset;
  439. uint8_t color = artist_get_color(s);
  440. struct vram_buffer *buf;
  441. int x, y;
  442. trace_artist_fill_window(startx, starty, width, height,
  443. s->image_bitmap_op, s->control_plane);
  444. if (s->control_plane != 0) {
  445. /* We don't support CONTROL_PLANE accesses */
  446. qemu_log_mask(LOG_UNIMP, "%s: CONTROL_PLANE: %08x\n", __func__,
  447. s->control_plane);
  448. return;
  449. }
  450. if (s->reg_100080 == 0x7d) {
  451. /*
  452. * Not sure what this register really does, but
  453. * 0x7d seems to enable autoincremt of the Y axis
  454. * by the current block move height.
  455. */
  456. height = artist_get_y(s->blockmove_size);
  457. s->vram_start += height;
  458. }
  459. buf = &s->vram_buffer[ARTIST_BUFFER_AP];
  460. for (y = starty; y < starty + height; y++) {
  461. offset = y * s->width;
  462. for (x = startx; x < startx + width; x++) {
  463. artist_rop8(s, buf->data + offset + x, color);
  464. }
  465. }
  466. artist_invalidate_lines(buf, starty, height);
  467. }
  468. static void draw_line(ARTISTState *s, int x1, int y1, int x2, int y2,
  469. bool update_start, int skip_pix, int max_pix)
  470. {
  471. struct vram_buffer *buf;
  472. uint8_t color;
  473. int dx, dy, t, e, x, y, incy, diago, horiz;
  474. bool c1;
  475. uint8_t *p;
  476. trace_artist_draw_line(x1, y1, x2, y2);
  477. if (update_start) {
  478. s->vram_start = (x2 << 16) | y2;
  479. }
  480. if (x2 > x1) {
  481. dx = x2 - x1;
  482. } else {
  483. dx = x1 - x2;
  484. }
  485. if (y2 > y1) {
  486. dy = y2 - y1;
  487. } else {
  488. dy = y1 - y2;
  489. }
  490. if (!dx || !dy) {
  491. return;
  492. }
  493. c1 = false;
  494. if (dy > dx) {
  495. t = y2;
  496. y2 = x2;
  497. x2 = t;
  498. t = y1;
  499. y1 = x1;
  500. x1 = t;
  501. t = dx;
  502. dx = dy;
  503. dy = t;
  504. c1 = true;
  505. }
  506. if (x1 > x2) {
  507. t = y2;
  508. y2 = y1;
  509. y1 = t;
  510. t = x1;
  511. x1 = x2;
  512. x2 = t;
  513. }
  514. horiz = dy << 1;
  515. diago = (dy - dx) << 1;
  516. e = (dy << 1) - dx;
  517. if (y1 <= y2) {
  518. incy = 1;
  519. } else {
  520. incy = -1;
  521. }
  522. x = x1;
  523. y = y1;
  524. color = artist_get_color(s);
  525. buf = &s->vram_buffer[ARTIST_BUFFER_AP];
  526. do {
  527. if (c1) {
  528. p = buf->data + x * s->width + y;
  529. } else {
  530. p = buf->data + y * s->width + x;
  531. }
  532. if (skip_pix > 0) {
  533. skip_pix--;
  534. } else {
  535. artist_rop8(s, p, color);
  536. }
  537. if (e > 0) {
  538. artist_invalidate_lines(buf, y, 1);
  539. y += incy;
  540. e += diago;
  541. } else {
  542. e += horiz;
  543. }
  544. x++;
  545. } while (x <= x2 && (max_pix == -1 || --max_pix > 0));
  546. }
  547. static void draw_line_pattern_start(ARTISTState *s)
  548. {
  549. int startx = artist_get_x(s->vram_start);
  550. int starty = artist_get_y(s->vram_start);
  551. int endx = artist_get_x(s->blockmove_size);
  552. int endy = artist_get_y(s->blockmove_size);
  553. int pstart = s->line_pattern_start >> 16;
  554. draw_line(s, startx, starty, endx, endy, false, -1, pstart);
  555. s->line_pattern_skip = pstart;
  556. }
  557. static void draw_line_pattern_next(ARTISTState *s)
  558. {
  559. int startx = artist_get_x(s->vram_start);
  560. int starty = artist_get_y(s->vram_start);
  561. int endx = artist_get_x(s->blockmove_size);
  562. int endy = artist_get_y(s->blockmove_size);
  563. int line_xy = s->line_xy >> 16;
  564. draw_line(s, startx, starty, endx, endy, false, s->line_pattern_skip,
  565. s->line_pattern_skip + line_xy);
  566. s->line_pattern_skip += line_xy;
  567. s->image_bitmap_op ^= 2;
  568. }
  569. static void draw_line_size(ARTISTState *s, bool update_start)
  570. {
  571. int startx = artist_get_x(s->vram_start);
  572. int starty = artist_get_y(s->vram_start);
  573. int endx = artist_get_x(s->line_size);
  574. int endy = artist_get_y(s->line_size);
  575. draw_line(s, startx, starty, endx, endy, update_start, -1, -1);
  576. }
  577. static void draw_line_xy(ARTISTState *s, bool update_start)
  578. {
  579. int startx = artist_get_x(s->vram_start);
  580. int starty = artist_get_y(s->vram_start);
  581. int sizex = artist_get_x(s->blockmove_size);
  582. int sizey = artist_get_y(s->blockmove_size);
  583. int linexy = s->line_xy >> 16;
  584. int endx, endy;
  585. endx = startx;
  586. endy = starty;
  587. if (sizex > 0) {
  588. endx = startx + linexy;
  589. }
  590. if (sizex < 0) {
  591. endx = startx;
  592. startx -= linexy;
  593. }
  594. if (sizey > 0) {
  595. endy = starty + linexy;
  596. }
  597. if (sizey < 0) {
  598. endy = starty;
  599. starty -= linexy;
  600. }
  601. if (startx < 0) {
  602. startx = 0;
  603. }
  604. if (endx < 0) {
  605. endx = 0;
  606. }
  607. if (starty < 0) {
  608. starty = 0;
  609. }
  610. if (endy < 0) {
  611. endy = 0;
  612. }
  613. draw_line(s, startx, starty, endx, endy, false, -1, -1);
  614. }
  615. static void draw_line_end(ARTISTState *s, bool update_start)
  616. {
  617. int startx = artist_get_x(s->vram_start);
  618. int starty = artist_get_y(s->vram_start);
  619. int endx = artist_get_x(s->line_end);
  620. int endy = artist_get_y(s->line_end);
  621. draw_line(s, startx, starty, endx, endy, update_start, -1, -1);
  622. }
  623. static void font_write16(ARTISTState *s, uint16_t val)
  624. {
  625. struct vram_buffer *buf;
  626. uint32_t color = (s->image_bitmap_op & 2) ? s->fg_color : s->bg_color;
  627. uint16_t mask;
  628. int i;
  629. int startx = artist_get_x(s->vram_start);
  630. int starty = artist_get_y(s->vram_start) + s->font_write_pos_y;
  631. int offset = starty * s->width + startx;
  632. buf = &s->vram_buffer[ARTIST_BUFFER_AP];
  633. if (offset + 16 > buf->size) {
  634. return;
  635. }
  636. for (i = 0; i < 16; i++) {
  637. mask = 1 << (15 - i);
  638. if (val & mask) {
  639. artist_rop8(s, buf->data + offset + i, color);
  640. } else {
  641. if (!(s->image_bitmap_op & 0x20000000)) {
  642. artist_rop8(s, buf->data + offset + i, s->bg_color);
  643. }
  644. }
  645. }
  646. artist_invalidate_lines(buf, starty, 1);
  647. }
  648. static void font_write(ARTISTState *s, uint32_t val)
  649. {
  650. font_write16(s, val >> 16);
  651. if (++s->font_write_pos_y == artist_get_y(s->blockmove_size)) {
  652. s->vram_start += (s->blockmove_size & 0xffff0000);
  653. return;
  654. }
  655. font_write16(s, val & 0xffff);
  656. if (++s->font_write_pos_y == artist_get_y(s->blockmove_size)) {
  657. s->vram_start += (s->blockmove_size & 0xffff0000);
  658. return;
  659. }
  660. }
  661. static void combine_write_reg(hwaddr addr, uint64_t val, int size, void *out)
  662. {
  663. /*
  664. * FIXME: is there a qemu helper for this?
  665. */
  666. #ifndef HOST_WORDS_BIGENDIAN
  667. addr ^= 3;
  668. #endif
  669. switch (size) {
  670. case 1:
  671. *(uint8_t *)(out + (addr & 3)) = val;
  672. break;
  673. case 2:
  674. *(uint16_t *)(out + (addr & 2)) = val;
  675. break;
  676. case 4:
  677. *(uint32_t *)out = val;
  678. break;
  679. default:
  680. qemu_log_mask(LOG_UNIMP, "unsupported write size: %d\n", size);
  681. }
  682. }
  683. static void artist_reg_write(void *opaque, hwaddr addr, uint64_t val,
  684. unsigned size)
  685. {
  686. ARTISTState *s = opaque;
  687. int posx, posy;
  688. int width, height;
  689. trace_artist_reg_write(size, addr, artist_reg_name(addr & ~3ULL), val);
  690. switch (addr & ~3ULL) {
  691. case 0x100080:
  692. combine_write_reg(addr, val, size, &s->reg_100080);
  693. break;
  694. case FG_COLOR:
  695. combine_write_reg(addr, val, size, &s->fg_color);
  696. break;
  697. case BG_COLOR:
  698. combine_write_reg(addr, val, size, &s->bg_color);
  699. break;
  700. case VRAM_BITMASK:
  701. combine_write_reg(addr, val, size, &s->vram_bitmask);
  702. break;
  703. case VRAM_WRITE_INCR_Y:
  704. posx = (s->vram_pos >> 2) & 0x7ff;
  705. posy = (s->vram_pos >> 13) & 0x3ff;
  706. vram_bit_write(s, posx, posy + s->vram_char_y++, false, size, val);
  707. break;
  708. case VRAM_WRITE_INCR_X:
  709. case VRAM_WRITE_INCR_X2:
  710. posx = (s->vram_pos >> 2) & 0x7ff;
  711. posy = (s->vram_pos >> 13) & 0x3ff;
  712. vram_bit_write(s, posx, posy + s->vram_char_y, true, size, val);
  713. break;
  714. case VRAM_IDX:
  715. combine_write_reg(addr, val, size, &s->vram_pos);
  716. s->vram_char_y = 0;
  717. s->draw_line_pattern = 0;
  718. break;
  719. case VRAM_START:
  720. combine_write_reg(addr, val, size, &s->vram_start);
  721. s->draw_line_pattern = 0;
  722. break;
  723. case VRAM_START_TRIGGER:
  724. combine_write_reg(addr, val, size, &s->vram_start);
  725. fill_window(s, artist_get_x(s->vram_start),
  726. artist_get_y(s->vram_start),
  727. artist_get_x(s->blockmove_size),
  728. artist_get_y(s->blockmove_size));
  729. break;
  730. case VRAM_SIZE_TRIGGER:
  731. combine_write_reg(addr, val, size, &s->vram_size);
  732. if (size == 2 && !(addr & 2)) {
  733. height = artist_get_y(s->blockmove_size);
  734. } else {
  735. height = artist_get_y(s->vram_size);
  736. }
  737. if (size == 2 && (addr & 2)) {
  738. width = artist_get_x(s->blockmove_size);
  739. } else {
  740. width = artist_get_x(s->vram_size);
  741. }
  742. fill_window(s, artist_get_x(s->vram_start),
  743. artist_get_y(s->vram_start),
  744. width, height);
  745. break;
  746. case LINE_XY:
  747. combine_write_reg(addr, val, size, &s->line_xy);
  748. if (s->draw_line_pattern) {
  749. draw_line_pattern_next(s);
  750. } else {
  751. draw_line_xy(s, true);
  752. }
  753. break;
  754. case PATTERN_LINE_START:
  755. combine_write_reg(addr, val, size, &s->line_pattern_start);
  756. s->draw_line_pattern = 1;
  757. draw_line_pattern_start(s);
  758. break;
  759. case LINE_SIZE:
  760. combine_write_reg(addr, val, size, &s->line_size);
  761. draw_line_size(s, true);
  762. break;
  763. case LINE_END:
  764. combine_write_reg(addr, val, size, &s->line_end);
  765. draw_line_end(s, true);
  766. break;
  767. case BLOCK_MOVE_SIZE:
  768. combine_write_reg(addr, val, size, &s->blockmove_size);
  769. break;
  770. case BLOCK_MOVE_SOURCE:
  771. combine_write_reg(addr, val, size, &s->blockmove_source);
  772. break;
  773. case BLOCK_MOVE_DEST_TRIGGER:
  774. combine_write_reg(addr, val, size, &s->blockmove_dest);
  775. block_move(s, artist_get_x(s->blockmove_source),
  776. artist_get_y(s->blockmove_source),
  777. artist_get_x(s->blockmove_dest),
  778. artist_get_y(s->blockmove_dest),
  779. artist_get_x(s->blockmove_size),
  780. artist_get_y(s->blockmove_size));
  781. break;
  782. case BLOCK_MOVE_SIZE_TRIGGER:
  783. combine_write_reg(addr, val, size, &s->blockmove_size);
  784. block_move(s,
  785. artist_get_x(s->blockmove_source),
  786. artist_get_y(s->blockmove_source),
  787. artist_get_x(s->vram_start),
  788. artist_get_y(s->vram_start),
  789. artist_get_x(s->blockmove_size),
  790. artist_get_y(s->blockmove_size));
  791. break;
  792. case PLANE_MASK:
  793. combine_write_reg(addr, val, size, &s->plane_mask);
  794. break;
  795. case CMAP_BM_ACCESS:
  796. combine_write_reg(addr, val, size, &s->cmap_bm_access);
  797. break;
  798. case DST_BM_ACCESS:
  799. combine_write_reg(addr, val, size, &s->dst_bm_access);
  800. s->cmap_bm_access = 0;
  801. break;
  802. case SRC_BM_ACCESS:
  803. combine_write_reg(addr, val, size, &s->src_bm_access);
  804. s->cmap_bm_access = 0;
  805. break;
  806. case CONTROL_PLANE:
  807. combine_write_reg(addr, val, size, &s->control_plane);
  808. break;
  809. case TRANSFER_DATA:
  810. combine_write_reg(addr, val, size, &s->transfer_data);
  811. break;
  812. case 0x300200:
  813. combine_write_reg(addr, val, size, &s->reg_300200);
  814. break;
  815. case 0x300208:
  816. combine_write_reg(addr, val, size, &s->reg_300208);
  817. break;
  818. case 0x300218:
  819. combine_write_reg(addr, val, size, &s->reg_300218);
  820. break;
  821. case CURSOR_POS:
  822. artist_invalidate_cursor(s);
  823. combine_write_reg(addr, val, size, &s->cursor_pos);
  824. artist_invalidate_cursor(s);
  825. break;
  826. case CURSOR_CTRL:
  827. break;
  828. case IMAGE_BITMAP_OP:
  829. combine_write_reg(addr, val, size, &s->image_bitmap_op);
  830. break;
  831. case FONT_WRITE_INCR_Y:
  832. combine_write_reg(addr, val, size, &s->font_write1);
  833. font_write(s, s->font_write1);
  834. break;
  835. case FONT_WRITE_START:
  836. combine_write_reg(addr, val, size, &s->font_write2);
  837. s->font_write_pos_y = 0;
  838. font_write(s, s->font_write2);
  839. break;
  840. case 300104:
  841. break;
  842. default:
  843. qemu_log_mask(LOG_UNIMP, "%s: unknown register: reg=%08" HWADDR_PRIx
  844. " val=%08" PRIx64 " size=%d\n",
  845. __func__, addr, val, size);
  846. break;
  847. }
  848. }
  849. static uint64_t combine_read_reg(hwaddr addr, int size, void *in)
  850. {
  851. /*
  852. * FIXME: is there a qemu helper for this?
  853. */
  854. #ifndef HOST_WORDS_BIGENDIAN
  855. addr ^= 3;
  856. #endif
  857. switch (size) {
  858. case 1:
  859. return *(uint8_t *)(in + (addr & 3));
  860. case 2:
  861. return *(uint16_t *)(in + (addr & 2));
  862. case 4:
  863. return *(uint32_t *)in;
  864. default:
  865. qemu_log_mask(LOG_UNIMP, "unsupported read size: %d\n", size);
  866. return 0;
  867. }
  868. }
  869. static uint64_t artist_reg_read(void *opaque, hwaddr addr, unsigned size)
  870. {
  871. ARTISTState *s = opaque;
  872. uint32_t val = 0;
  873. switch (addr & ~3ULL) {
  874. /* Unknown status registers */
  875. case 0:
  876. break;
  877. case 0x211110:
  878. val = (s->width << 16) | s->height;
  879. if (s->depth == 1) {
  880. val |= 1 << 31;
  881. }
  882. break;
  883. case 0x100000:
  884. case 0x300000:
  885. case 0x300004:
  886. case 0x300308:
  887. case 0x380000:
  888. break;
  889. case 0x300008:
  890. case 0x380008:
  891. /*
  892. * FIFO ready flag. we're not emulating the FIFOs
  893. * so we're always ready
  894. */
  895. val = 0x10;
  896. break;
  897. case 0x300200:
  898. val = s->reg_300200;
  899. break;
  900. case 0x300208:
  901. val = s->reg_300208;
  902. break;
  903. case 0x300218:
  904. val = s->reg_300218;
  905. break;
  906. case 0x30023c:
  907. val = 0xac4ffdac;
  908. break;
  909. case 0x380004:
  910. /* 0x02000000 Buserror */
  911. val = 0x6dc20006;
  912. break;
  913. default:
  914. qemu_log_mask(LOG_UNIMP, "%s: unknown register: %08" HWADDR_PRIx
  915. " size %d\n", __func__, addr, size);
  916. break;
  917. }
  918. val = combine_read_reg(addr, size, &val);
  919. trace_artist_reg_read(size, addr, artist_reg_name(addr & ~3ULL), val);
  920. return val;
  921. }
  922. static void artist_vram_write(void *opaque, hwaddr addr, uint64_t val,
  923. unsigned size)
  924. {
  925. ARTISTState *s = opaque;
  926. struct vram_buffer *buf;
  927. int posy = (addr >> 11) & 0x3ff;
  928. int posx = addr & 0x7ff;
  929. uint32_t offset;
  930. trace_artist_vram_write(size, addr, val);
  931. if (s->cmap_bm_access) {
  932. buf = &s->vram_buffer[ARTIST_BUFFER_CMAP];
  933. if (addr + 3 < buf->size) {
  934. *(uint32_t *)(buf->data + addr) = val;
  935. }
  936. return;
  937. }
  938. buf = vram_write_buffer(s);
  939. if (!buf->size) {
  940. return;
  941. }
  942. if (posy > buf->height || posx > buf->width) {
  943. return;
  944. }
  945. offset = posy * buf->width + posx;
  946. switch (size) {
  947. case 4:
  948. *(uint32_t *)(buf->data + offset) = be32_to_cpu(val);
  949. memory_region_set_dirty(&buf->mr, offset, 4);
  950. break;
  951. case 2:
  952. *(uint16_t *)(buf->data + offset) = be16_to_cpu(val);
  953. memory_region_set_dirty(&buf->mr, offset, 2);
  954. break;
  955. case 1:
  956. *(uint8_t *)(buf->data + offset) = val;
  957. memory_region_set_dirty(&buf->mr, offset, 1);
  958. break;
  959. default:
  960. break;
  961. }
  962. }
  963. static uint64_t artist_vram_read(void *opaque, hwaddr addr, unsigned size)
  964. {
  965. ARTISTState *s = opaque;
  966. struct vram_buffer *buf;
  967. uint64_t val;
  968. int posy, posx;
  969. if (s->cmap_bm_access) {
  970. buf = &s->vram_buffer[ARTIST_BUFFER_CMAP];
  971. val = *(uint32_t *)(buf->data + addr);
  972. trace_artist_vram_read(size, addr, 0, 0, val);
  973. return 0;
  974. }
  975. buf = vram_read_buffer(s);
  976. if (!buf->size) {
  977. return 0;
  978. }
  979. posy = (addr >> 13) & 0x3ff;
  980. posx = (addr >> 2) & 0x7ff;
  981. if (posy > buf->height || posx > buf->width) {
  982. return 0;
  983. }
  984. val = cpu_to_be32(*(uint32_t *)(buf->data + posy * buf->width + posx));
  985. trace_artist_vram_read(size, addr, posx, posy, val);
  986. return val;
  987. }
  988. static const MemoryRegionOps artist_reg_ops = {
  989. .read = artist_reg_read,
  990. .write = artist_reg_write,
  991. .endianness = DEVICE_NATIVE_ENDIAN,
  992. .valid = {
  993. .min_access_size = 1,
  994. .max_access_size = 4,
  995. },
  996. };
  997. static const MemoryRegionOps artist_vram_ops = {
  998. .read = artist_vram_read,
  999. .write = artist_vram_write,
  1000. .endianness = DEVICE_NATIVE_ENDIAN,
  1001. .valid = {
  1002. .min_access_size = 1,
  1003. .max_access_size = 4,
  1004. },
  1005. };
  1006. static void artist_draw_cursor(ARTISTState *s)
  1007. {
  1008. DisplaySurface *surface = qemu_console_surface(s->con);
  1009. uint32_t *data = (uint32_t *)surface_data(surface);
  1010. struct vram_buffer *cursor0, *cursor1 , *buf;
  1011. int cx, cy, cursor_pos_x, cursor_pos_y;
  1012. cursor0 = &s->vram_buffer[ARTIST_BUFFER_CURSOR1];
  1013. cursor1 = &s->vram_buffer[ARTIST_BUFFER_CURSOR2];
  1014. buf = &s->vram_buffer[ARTIST_BUFFER_AP];
  1015. artist_get_cursor_pos(s, &cursor_pos_x, &cursor_pos_y);
  1016. for (cy = 0; cy < s->cursor_height; cy++) {
  1017. for (cx = 0; cx < s->cursor_width; cx++) {
  1018. if (cursor_pos_y + cy < 0 ||
  1019. cursor_pos_x + cx < 0 ||
  1020. cursor_pos_y + cy > buf->height - 1 ||
  1021. cursor_pos_x + cx > buf->width) {
  1022. continue;
  1023. }
  1024. int dstoffset = (cursor_pos_y + cy) * s->width +
  1025. (cursor_pos_x + cx);
  1026. if (cursor0->data[cy * cursor0->width + cx]) {
  1027. data[dstoffset] = 0;
  1028. } else {
  1029. if (cursor1->data[cy * cursor1->width + cx]) {
  1030. data[dstoffset] = 0xffffff;
  1031. }
  1032. }
  1033. }
  1034. }
  1035. }
  1036. static void artist_draw_line(void *opaque, uint8_t *d, const uint8_t *src,
  1037. int width, int pitch)
  1038. {
  1039. ARTISTState *s = ARTIST(opaque);
  1040. uint32_t *cmap, *data = (uint32_t *)d;
  1041. int x;
  1042. cmap = (uint32_t *)(s->vram_buffer[ARTIST_BUFFER_CMAP].data + 0x400);
  1043. for (x = 0; x < s->width; x++) {
  1044. *data++ = cmap[*src++];
  1045. }
  1046. }
  1047. static void artist_update_display(void *opaque)
  1048. {
  1049. ARTISTState *s = opaque;
  1050. DisplaySurface *surface = qemu_console_surface(s->con);
  1051. int first = 0, last;
  1052. framebuffer_update_display(surface, &s->fbsection, s->width, s->height,
  1053. s->width, s->width * 4, 0, 0, artist_draw_line,
  1054. s, &first, &last);
  1055. artist_draw_cursor(s);
  1056. dpy_gfx_update(s->con, 0, 0, s->width, s->height);
  1057. }
  1058. static void artist_invalidate(void *opaque)
  1059. {
  1060. ARTISTState *s = ARTIST(opaque);
  1061. struct vram_buffer *buf = &s->vram_buffer[ARTIST_BUFFER_AP];
  1062. memory_region_set_dirty(&buf->mr, 0, buf->size);
  1063. }
  1064. static const GraphicHwOps artist_ops = {
  1065. .invalidate = artist_invalidate,
  1066. .gfx_update = artist_update_display,
  1067. };
  1068. static void artist_initfn(Object *obj)
  1069. {
  1070. SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
  1071. ARTISTState *s = ARTIST(obj);
  1072. memory_region_init_io(&s->reg, obj, &artist_reg_ops, s, "artist.reg",
  1073. 4 * MiB);
  1074. memory_region_init_io(&s->vram_mem, obj, &artist_vram_ops, s, "artist.vram",
  1075. 8 * MiB);
  1076. sysbus_init_mmio(sbd, &s->reg);
  1077. sysbus_init_mmio(sbd, &s->vram_mem);
  1078. }
  1079. static void artist_create_buffer(ARTISTState *s, const char *name,
  1080. hwaddr *offset, unsigned int idx,
  1081. int width, int height)
  1082. {
  1083. struct vram_buffer *buf = s->vram_buffer + idx;
  1084. memory_region_init_ram(&buf->mr, NULL, name, width * height,
  1085. &error_fatal);
  1086. memory_region_add_subregion_overlap(&s->mem_as_root, *offset, &buf->mr, 0);
  1087. buf->data = memory_region_get_ram_ptr(&buf->mr);
  1088. buf->size = height * width;
  1089. buf->width = width;
  1090. buf->height = height;
  1091. *offset += buf->size;
  1092. }
  1093. static void artist_realizefn(DeviceState *dev, Error **errp)
  1094. {
  1095. ARTISTState *s = ARTIST(dev);
  1096. struct vram_buffer *buf;
  1097. hwaddr offset = 0;
  1098. memory_region_init(&s->mem_as_root, OBJECT(dev), "artist", ~0ull);
  1099. address_space_init(&s->as, &s->mem_as_root, "artist");
  1100. artist_create_buffer(s, "cmap", &offset, ARTIST_BUFFER_CMAP, 2048, 4);
  1101. artist_create_buffer(s, "ap", &offset, ARTIST_BUFFER_AP,
  1102. s->width, s->height);
  1103. artist_create_buffer(s, "cursor1", &offset, ARTIST_BUFFER_CURSOR1, 64, 64);
  1104. artist_create_buffer(s, "cursor2", &offset, ARTIST_BUFFER_CURSOR2, 64, 64);
  1105. artist_create_buffer(s, "attribute", &offset, ARTIST_BUFFER_ATTRIBUTE,
  1106. 64, 64);
  1107. buf = &s->vram_buffer[ARTIST_BUFFER_AP];
  1108. framebuffer_update_memory_section(&s->fbsection, &buf->mr, 0,
  1109. buf->width, buf->height);
  1110. /*
  1111. * no idea whether the cursor is fixed size or not, so assume 32x32 which
  1112. * seems sufficient for HP-UX X11.
  1113. */
  1114. s->cursor_height = 32;
  1115. s->cursor_width = 32;
  1116. s->con = graphic_console_init(dev, 0, &artist_ops, s);
  1117. qemu_console_resize(s->con, s->width, s->height);
  1118. }
  1119. static int vmstate_artist_post_load(void *opaque, int version_id)
  1120. {
  1121. artist_invalidate(opaque);
  1122. return 0;
  1123. }
  1124. static const VMStateDescription vmstate_artist = {
  1125. .name = "artist",
  1126. .version_id = 1,
  1127. .minimum_version_id = 1,
  1128. .post_load = vmstate_artist_post_load,
  1129. .fields = (VMStateField[]) {
  1130. VMSTATE_UINT16(height, ARTISTState),
  1131. VMSTATE_UINT16(width, ARTISTState),
  1132. VMSTATE_UINT16(depth, ARTISTState),
  1133. VMSTATE_UINT32(fg_color, ARTISTState),
  1134. VMSTATE_UINT32(bg_color, ARTISTState),
  1135. VMSTATE_UINT32(vram_char_y, ARTISTState),
  1136. VMSTATE_UINT32(vram_bitmask, ARTISTState),
  1137. VMSTATE_UINT32(vram_start, ARTISTState),
  1138. VMSTATE_UINT32(vram_pos, ARTISTState),
  1139. VMSTATE_UINT32(vram_size, ARTISTState),
  1140. VMSTATE_UINT32(blockmove_source, ARTISTState),
  1141. VMSTATE_UINT32(blockmove_dest, ARTISTState),
  1142. VMSTATE_UINT32(blockmove_size, ARTISTState),
  1143. VMSTATE_UINT32(line_size, ARTISTState),
  1144. VMSTATE_UINT32(line_end, ARTISTState),
  1145. VMSTATE_UINT32(line_xy, ARTISTState),
  1146. VMSTATE_UINT32(cursor_pos, ARTISTState),
  1147. VMSTATE_UINT32(cursor_height, ARTISTState),
  1148. VMSTATE_UINT32(cursor_width, ARTISTState),
  1149. VMSTATE_UINT32(plane_mask, ARTISTState),
  1150. VMSTATE_UINT32(reg_100080, ARTISTState),
  1151. VMSTATE_UINT32(reg_300200, ARTISTState),
  1152. VMSTATE_UINT32(reg_300208, ARTISTState),
  1153. VMSTATE_UINT32(reg_300218, ARTISTState),
  1154. VMSTATE_UINT32(cmap_bm_access, ARTISTState),
  1155. VMSTATE_UINT32(dst_bm_access, ARTISTState),
  1156. VMSTATE_UINT32(src_bm_access, ARTISTState),
  1157. VMSTATE_UINT32(control_plane, ARTISTState),
  1158. VMSTATE_UINT32(transfer_data, ARTISTState),
  1159. VMSTATE_UINT32(image_bitmap_op, ARTISTState),
  1160. VMSTATE_UINT32(font_write1, ARTISTState),
  1161. VMSTATE_UINT32(font_write2, ARTISTState),
  1162. VMSTATE_UINT32(font_write_pos_y, ARTISTState),
  1163. VMSTATE_END_OF_LIST()
  1164. }
  1165. };
  1166. static Property artist_properties[] = {
  1167. DEFINE_PROP_UINT16("width", ARTISTState, width, 1280),
  1168. DEFINE_PROP_UINT16("height", ARTISTState, height, 1024),
  1169. DEFINE_PROP_UINT16("depth", ARTISTState, depth, 8),
  1170. DEFINE_PROP_END_OF_LIST(),
  1171. };
  1172. static void artist_reset(DeviceState *qdev)
  1173. {
  1174. }
  1175. static void artist_class_init(ObjectClass *klass, void *data)
  1176. {
  1177. DeviceClass *dc = DEVICE_CLASS(klass);
  1178. dc->realize = artist_realizefn;
  1179. dc->vmsd = &vmstate_artist;
  1180. dc->reset = artist_reset;
  1181. device_class_set_props(dc, artist_properties);
  1182. }
  1183. static const TypeInfo artist_info = {
  1184. .name = TYPE_ARTIST,
  1185. .parent = TYPE_SYS_BUS_DEVICE,
  1186. .instance_size = sizeof(ARTISTState),
  1187. .instance_init = artist_initfn,
  1188. .class_init = artist_class_init,
  1189. };
  1190. static void artist_register_types(void)
  1191. {
  1192. type_register_static(&artist_info);
  1193. }
  1194. type_init(artist_register_types)