source: trunk/packages/xen-3.1/xen-3.1/tools/ioemu/hw/cirrus_vga.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 98.5 KB
Line 
1/*
2 * QEMU Cirrus CLGD 54xx VGA Emulator.
3 *
4 * Copyright (c) 2004 Fabrice Bellard
5 * Copyright (c) 2004 Makoto Suzuki (suzu)
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/*
26 * Reference: Finn Thogersons' VGADOC4b
27 *   available at http://home.worldonline.dk/~finth/
28 */
29#include "vl.h"
30#include "vga_int.h"
31#ifndef _WIN32
32#include <sys/mman.h>
33#endif
34
35/*
36 * TODO:
37 *    - destination write mask support not complete (bits 5..7)
38 *    - optimize linear mappings
39 *    - optimize bitblt functions
40 */
41
42//#define DEBUG_CIRRUS
43//#define DEBUG_BITBLT
44
45/***************************************
46 *
47 *  definitions
48 *
49 ***************************************/
50
51#define qemu_MIN(a,b) ((a) < (b) ? (a) : (b))
52
53// ID
54#define CIRRUS_ID_CLGD5422  (0x23<<2)
55#define CIRRUS_ID_CLGD5426  (0x24<<2)
56#define CIRRUS_ID_CLGD5424  (0x25<<2)
57#define CIRRUS_ID_CLGD5428  (0x26<<2)
58#define CIRRUS_ID_CLGD5430  (0x28<<2)
59#define CIRRUS_ID_CLGD5434  (0x2A<<2)
60#define CIRRUS_ID_CLGD5436  (0x2B<<2)
61#define CIRRUS_ID_CLGD5446  (0x2E<<2)
62
63// sequencer 0x07
64#define CIRRUS_SR7_BPP_VGA            0x00
65#define CIRRUS_SR7_BPP_SVGA           0x01
66#define CIRRUS_SR7_BPP_MASK           0x0e
67#define CIRRUS_SR7_BPP_8              0x00
68#define CIRRUS_SR7_BPP_16_DOUBLEVCLK  0x02
69#define CIRRUS_SR7_BPP_24             0x04
70#define CIRRUS_SR7_BPP_16             0x06
71#define CIRRUS_SR7_BPP_32             0x08
72#define CIRRUS_SR7_ISAADDR_MASK       0xe0
73
74// sequencer 0x0f
75#define CIRRUS_MEMSIZE_512k        0x08
76#define CIRRUS_MEMSIZE_1M          0x10
77#define CIRRUS_MEMSIZE_2M          0x18
78#define CIRRUS_MEMFLAGS_BANKSWITCH 0x80 // bank switching is enabled.
79
80// sequencer 0x12
81#define CIRRUS_CURSOR_SHOW         0x01
82#define CIRRUS_CURSOR_HIDDENPEL    0x02
83#define CIRRUS_CURSOR_LARGE        0x04 // 64x64 if set, 32x32 if clear
84
85// sequencer 0x17
86#define CIRRUS_BUSTYPE_VLBFAST   0x10
87#define CIRRUS_BUSTYPE_PCI       0x20
88#define CIRRUS_BUSTYPE_VLBSLOW   0x30
89#define CIRRUS_BUSTYPE_ISA       0x38
90#define CIRRUS_MMIO_ENABLE       0x04
91#define CIRRUS_MMIO_USE_PCIADDR  0x40   // 0xb8000 if cleared.
92#define CIRRUS_MEMSIZEEXT_DOUBLE 0x80
93
94// control 0x0b
95#define CIRRUS_BANKING_DUAL             0x01
96#define CIRRUS_BANKING_GRANULARITY_16K  0x20    // set:16k, clear:4k
97
98// control 0x30
99#define CIRRUS_BLTMODE_BACKWARDS        0x01
100#define CIRRUS_BLTMODE_MEMSYSDEST       0x02
101#define CIRRUS_BLTMODE_MEMSYSSRC        0x04
102#define CIRRUS_BLTMODE_TRANSPARENTCOMP  0x08
103#define CIRRUS_BLTMODE_PATTERNCOPY      0x40
104#define CIRRUS_BLTMODE_COLOREXPAND      0x80
105#define CIRRUS_BLTMODE_PIXELWIDTHMASK   0x30
106#define CIRRUS_BLTMODE_PIXELWIDTH8      0x00
107#define CIRRUS_BLTMODE_PIXELWIDTH16     0x10
108#define CIRRUS_BLTMODE_PIXELWIDTH24     0x20
109#define CIRRUS_BLTMODE_PIXELWIDTH32     0x30
110
111// control 0x31
112#define CIRRUS_BLT_BUSY                 0x01
113#define CIRRUS_BLT_START                0x02
114#define CIRRUS_BLT_RESET                0x04
115#define CIRRUS_BLT_FIFOUSED             0x10
116#define CIRRUS_BLT_AUTOSTART            0x80
117
118// control 0x32
119#define CIRRUS_ROP_0                    0x00
120#define CIRRUS_ROP_SRC_AND_DST          0x05
121#define CIRRUS_ROP_NOP                  0x06
122#define CIRRUS_ROP_SRC_AND_NOTDST       0x09
123#define CIRRUS_ROP_NOTDST               0x0b
124#define CIRRUS_ROP_SRC                  0x0d
125#define CIRRUS_ROP_1                    0x0e
126#define CIRRUS_ROP_NOTSRC_AND_DST       0x50
127#define CIRRUS_ROP_SRC_XOR_DST          0x59
128#define CIRRUS_ROP_SRC_OR_DST           0x6d
129#define CIRRUS_ROP_NOTSRC_OR_NOTDST     0x90
130#define CIRRUS_ROP_SRC_NOTXOR_DST       0x95
131#define CIRRUS_ROP_SRC_OR_NOTDST        0xad
132#define CIRRUS_ROP_NOTSRC               0xd0
133#define CIRRUS_ROP_NOTSRC_OR_DST        0xd6
134#define CIRRUS_ROP_NOTSRC_AND_NOTDST    0xda
135
136#define CIRRUS_ROP_NOP_INDEX 2
137#define CIRRUS_ROP_SRC_INDEX 5
138
139// control 0x33
140#define CIRRUS_BLTMODEEXT_SOLIDFILL        0x04
141#define CIRRUS_BLTMODEEXT_COLOREXPINV      0x02
142#define CIRRUS_BLTMODEEXT_DWORDGRANULARITY 0x01
143
144// memory-mapped IO
145#define CIRRUS_MMIO_BLTBGCOLOR        0x00      // dword
146#define CIRRUS_MMIO_BLTFGCOLOR        0x04      // dword
147#define CIRRUS_MMIO_BLTWIDTH          0x08      // word
148#define CIRRUS_MMIO_BLTHEIGHT         0x0a      // word
149#define CIRRUS_MMIO_BLTDESTPITCH      0x0c      // word
150#define CIRRUS_MMIO_BLTSRCPITCH       0x0e      // word
151#define CIRRUS_MMIO_BLTDESTADDR       0x10      // dword
152#define CIRRUS_MMIO_BLTSRCADDR        0x14      // dword
153#define CIRRUS_MMIO_BLTWRITEMASK      0x17      // byte
154#define CIRRUS_MMIO_BLTMODE           0x18      // byte
155#define CIRRUS_MMIO_BLTROP            0x1a      // byte
156#define CIRRUS_MMIO_BLTMODEEXT        0x1b      // byte
157#define CIRRUS_MMIO_BLTTRANSPARENTCOLOR 0x1c    // word?
158#define CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK 0x20        // word?
159#define CIRRUS_MMIO_LINEARDRAW_START_X 0x24     // word
160#define CIRRUS_MMIO_LINEARDRAW_START_Y 0x26     // word
161#define CIRRUS_MMIO_LINEARDRAW_END_X  0x28      // word
162#define CIRRUS_MMIO_LINEARDRAW_END_Y  0x2a      // word
163#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_INC 0x2c       // byte
164#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ROLLOVER 0x2d  // byte
165#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_MASK 0x2e      // byte
166#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ACCUM 0x2f     // byte
167#define CIRRUS_MMIO_BRESENHAM_K1      0x30      // word
168#define CIRRUS_MMIO_BRESENHAM_K3      0x32      // word
169#define CIRRUS_MMIO_BRESENHAM_ERROR   0x34      // word
170#define CIRRUS_MMIO_BRESENHAM_DELTA_MAJOR 0x36  // word
171#define CIRRUS_MMIO_BRESENHAM_DIRECTION 0x38    // byte
172#define CIRRUS_MMIO_LINEDRAW_MODE     0x39      // byte
173#define CIRRUS_MMIO_BLTSTATUS         0x40      // byte
174
175// PCI 0x00: vendor, 0x02: device
176#define PCI_VENDOR_CIRRUS             0x1013
177#define PCI_DEVICE_CLGD5462           0x00d0
178#define PCI_DEVICE_CLGD5465           0x00d6
179
180// PCI 0x04: command(word), 0x06(word): status
181#define PCI_COMMAND_IOACCESS                0x0001
182#define PCI_COMMAND_MEMACCESS               0x0002
183#define PCI_COMMAND_BUSMASTER               0x0004
184#define PCI_COMMAND_SPECIALCYCLE            0x0008
185#define PCI_COMMAND_MEMWRITEINVALID         0x0010
186#define PCI_COMMAND_PALETTESNOOPING         0x0020
187#define PCI_COMMAND_PARITYDETECTION         0x0040
188#define PCI_COMMAND_ADDRESSDATASTEPPING     0x0080
189#define PCI_COMMAND_SERR                    0x0100
190#define PCI_COMMAND_BACKTOBACKTRANS         0x0200
191// PCI 0x08, 0xff000000 (0x09-0x0b:class,0x08:rev)
192#define PCI_CLASS_BASE_DISPLAY        0x03
193// PCI 0x08, 0x00ff0000
194#define PCI_CLASS_SUB_VGA             0x00
195// PCI 0x0c, 0x00ff0000 (0x0c:cacheline,0x0d:latency,0x0e:headertype,0x0f:Built-in self test)
196#define PCI_CLASS_HEADERTYPE_00h  0x00
197// 0x10-0x3f (headertype 00h)
198// PCI 0x10,0x14,0x18,0x1c,0x20,0x24: base address mapping registers
199//   0x10: MEMBASE, 0x14: IOBASE(hard-coded in XFree86 3.x)
200#define PCI_MAP_MEM                 0x0
201#define PCI_MAP_IO                  0x1
202#define PCI_MAP_MEM_ADDR_MASK       (~0xf)
203#define PCI_MAP_IO_ADDR_MASK        (~0x3)
204#define PCI_MAP_MEMFLAGS_32BIT      0x0
205#define PCI_MAP_MEMFLAGS_32BIT_1M   0x1
206#define PCI_MAP_MEMFLAGS_64BIT      0x4
207#define PCI_MAP_MEMFLAGS_CACHEABLE  0x8
208// PCI 0x28: cardbus CIS pointer
209// PCI 0x2c: subsystem vendor id, 0x2e: subsystem id
210// PCI 0x30: expansion ROM base address
211#define PCI_ROMBIOS_ENABLED         0x1
212// PCI 0x34: 0xffffff00=reserved, 0x000000ff=capabilities pointer
213// PCI 0x38: reserved
214// PCI 0x3c: 0x3c=int-line, 0x3d=int-pin, 0x3e=min-gnt, 0x3f=maax-lat
215
216#define CIRRUS_PNPMMIO_SIZE         0x1000
217
218
219/* I/O and memory hook */
220#define CIRRUS_HOOK_NOT_HANDLED 0
221#define CIRRUS_HOOK_HANDLED 1
222
223struct CirrusVGAState;
224typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s,
225                                     uint8_t * dst, const uint8_t * src,
226                                     int dstpitch, int srcpitch,
227                                     int bltwidth, int bltheight);
228typedef void (*cirrus_fill_t)(struct CirrusVGAState *s,
229                              uint8_t *dst, int dst_pitch, int width, int height);
230
231typedef struct CirrusVGAState {
232    VGA_STATE_COMMON
233
234    int cirrus_linear_io_addr;
235    int cirrus_linear_bitblt_io_addr;
236    int cirrus_mmio_io_addr;
237    unsigned long cirrus_lfb_addr;
238    unsigned long cirrus_lfb_end;
239    uint32_t cirrus_addr_mask;
240    uint32_t linear_mmio_mask;
241    uint8_t cirrus_shadow_gr0;
242    uint8_t cirrus_shadow_gr1;
243    uint8_t cirrus_hidden_dac_lockindex;
244    uint8_t cirrus_hidden_dac_data;
245    uint32_t cirrus_bank_base[2];
246    uint32_t cirrus_bank_limit[2];
247    uint8_t cirrus_hidden_palette[48];
248    uint32_t hw_cursor_x;
249    uint32_t hw_cursor_y;
250    int cirrus_blt_pixelwidth;
251    int cirrus_blt_width;
252    int cirrus_blt_height;
253    int cirrus_blt_dstpitch;
254    int cirrus_blt_srcpitch;
255    uint32_t cirrus_blt_fgcol;
256    uint32_t cirrus_blt_bgcol;
257    uint32_t cirrus_blt_dstaddr;
258    uint32_t cirrus_blt_srcaddr;
259    uint8_t cirrus_blt_mode;
260    uint8_t cirrus_blt_modeext;
261    cirrus_bitblt_rop_t cirrus_rop;
262#define CIRRUS_BLTBUFSIZE (2048 * 4) /* one line width */
263    uint8_t cirrus_bltbuf[CIRRUS_BLTBUFSIZE];
264    uint8_t *cirrus_srcptr;
265    uint8_t *cirrus_srcptr_end;
266    uint32_t cirrus_srccounter;
267    /* hwcursor display state */
268    int last_hw_cursor_size;
269    int last_hw_cursor_x;
270    int last_hw_cursor_y;
271    int last_hw_cursor_y_start;
272    int last_hw_cursor_y_end;
273    int real_vram_size; /* XXX: suppress that */
274    CPUWriteMemoryFunc **cirrus_linear_write;
275    unsigned long map_addr;
276    unsigned long map_end;
277} CirrusVGAState;
278
279typedef struct PCICirrusVGAState {
280    PCIDevice dev;
281    CirrusVGAState cirrus_vga;
282} PCICirrusVGAState;
283
284static uint8_t rop_to_index[256];
285   
286void *shared_vram;
287
288/***************************************
289 *
290 *  prototypes.
291 *
292 ***************************************/
293
294
295static void cirrus_bitblt_reset(CirrusVGAState *s);
296static void cirrus_update_memory_access(CirrusVGAState *s);
297
298/***************************************
299 *
300 *  raster operations
301 *
302 ***************************************/
303
304static void cirrus_bitblt_rop_nop(CirrusVGAState *s,
305                                  uint8_t *dst,const uint8_t *src,
306                                  int dstpitch,int srcpitch,
307                                  int bltwidth,int bltheight)
308{
309}
310
311static void cirrus_bitblt_fill_nop(CirrusVGAState *s,
312                                   uint8_t *dst,
313                                   int dstpitch, int bltwidth,int bltheight)
314{
315}
316
317#define ROP_NAME 0
318#define ROP_OP(d, s) d = 0
319#include "cirrus_vga_rop.h"
320
321#define ROP_NAME src_and_dst
322#define ROP_OP(d, s) d = (s) & (d)
323#include "cirrus_vga_rop.h"
324
325#define ROP_NAME src_and_notdst
326#define ROP_OP(d, s) d = (s) & (~(d))
327#include "cirrus_vga_rop.h"
328
329#define ROP_NAME notdst
330#define ROP_OP(d, s) d = ~(d)
331#include "cirrus_vga_rop.h"
332
333#define ROP_NAME src
334#define ROP_OP(d, s) d = s
335#include "cirrus_vga_rop.h"
336
337#define ROP_NAME 1
338#define ROP_OP(d, s) d = ~0
339#include "cirrus_vga_rop.h"
340
341#define ROP_NAME notsrc_and_dst
342#define ROP_OP(d, s) d = (~(s)) & (d)
343#include "cirrus_vga_rop.h"
344
345#define ROP_NAME src_xor_dst
346#define ROP_OP(d, s) d = (s) ^ (d)
347#include "cirrus_vga_rop.h"
348
349#define ROP_NAME src_or_dst
350#define ROP_OP(d, s) d = (s) | (d)
351#include "cirrus_vga_rop.h"
352
353#define ROP_NAME notsrc_or_notdst
354#define ROP_OP(d, s) d = (~(s)) | (~(d))
355#include "cirrus_vga_rop.h"
356
357#define ROP_NAME src_notxor_dst
358#define ROP_OP(d, s) d = ~((s) ^ (d))
359#include "cirrus_vga_rop.h"
360
361#define ROP_NAME src_or_notdst
362#define ROP_OP(d, s) d = (s) | (~(d))
363#include "cirrus_vga_rop.h"
364
365#define ROP_NAME notsrc
366#define ROP_OP(d, s) d = (~(s))
367#include "cirrus_vga_rop.h"
368
369#define ROP_NAME notsrc_or_dst
370#define ROP_OP(d, s) d = (~(s)) | (d)
371#include "cirrus_vga_rop.h"
372
373#define ROP_NAME notsrc_and_notdst
374#define ROP_OP(d, s) d = (~(s)) & (~(d))
375#include "cirrus_vga_rop.h"
376
377static const cirrus_bitblt_rop_t cirrus_fwd_rop[16] = {
378    cirrus_bitblt_rop_fwd_0,
379    cirrus_bitblt_rop_fwd_src_and_dst,
380    cirrus_bitblt_rop_nop,
381    cirrus_bitblt_rop_fwd_src_and_notdst,
382    cirrus_bitblt_rop_fwd_notdst,
383    cirrus_bitblt_rop_fwd_src,
384    cirrus_bitblt_rop_fwd_1,
385    cirrus_bitblt_rop_fwd_notsrc_and_dst,
386    cirrus_bitblt_rop_fwd_src_xor_dst,
387    cirrus_bitblt_rop_fwd_src_or_dst,
388    cirrus_bitblt_rop_fwd_notsrc_or_notdst,
389    cirrus_bitblt_rop_fwd_src_notxor_dst,
390    cirrus_bitblt_rop_fwd_src_or_notdst,
391    cirrus_bitblt_rop_fwd_notsrc,
392    cirrus_bitblt_rop_fwd_notsrc_or_dst,
393    cirrus_bitblt_rop_fwd_notsrc_and_notdst,
394};
395
396static const cirrus_bitblt_rop_t cirrus_bkwd_rop[16] = {
397    cirrus_bitblt_rop_bkwd_0,
398    cirrus_bitblt_rop_bkwd_src_and_dst,
399    cirrus_bitblt_rop_nop,
400    cirrus_bitblt_rop_bkwd_src_and_notdst,
401    cirrus_bitblt_rop_bkwd_notdst,
402    cirrus_bitblt_rop_bkwd_src,
403    cirrus_bitblt_rop_bkwd_1,
404    cirrus_bitblt_rop_bkwd_notsrc_and_dst,
405    cirrus_bitblt_rop_bkwd_src_xor_dst,
406    cirrus_bitblt_rop_bkwd_src_or_dst,
407    cirrus_bitblt_rop_bkwd_notsrc_or_notdst,
408    cirrus_bitblt_rop_bkwd_src_notxor_dst,
409    cirrus_bitblt_rop_bkwd_src_or_notdst,
410    cirrus_bitblt_rop_bkwd_notsrc,
411    cirrus_bitblt_rop_bkwd_notsrc_or_dst,
412    cirrus_bitblt_rop_bkwd_notsrc_and_notdst,
413};
414   
415#define ROP2(name) {\
416    name ## _8,\
417    name ## _16,\
418    name ## _24,\
419    name ## _32,\
420        }
421
422#define ROP_NOP2(func) {\
423    func,\
424    func,\
425    func,\
426    func,\
427        }
428
429static const cirrus_bitblt_rop_t cirrus_patternfill[16][4] = {
430    ROP2(cirrus_patternfill_0),
431    ROP2(cirrus_patternfill_src_and_dst),
432    ROP_NOP2(cirrus_bitblt_rop_nop),
433    ROP2(cirrus_patternfill_src_and_notdst),
434    ROP2(cirrus_patternfill_notdst),
435    ROP2(cirrus_patternfill_src),
436    ROP2(cirrus_patternfill_1),
437    ROP2(cirrus_patternfill_notsrc_and_dst),
438    ROP2(cirrus_patternfill_src_xor_dst),
439    ROP2(cirrus_patternfill_src_or_dst),
440    ROP2(cirrus_patternfill_notsrc_or_notdst),
441    ROP2(cirrus_patternfill_src_notxor_dst),
442    ROP2(cirrus_patternfill_src_or_notdst),
443    ROP2(cirrus_patternfill_notsrc),
444    ROP2(cirrus_patternfill_notsrc_or_dst),
445    ROP2(cirrus_patternfill_notsrc_and_notdst),
446};
447
448static const cirrus_bitblt_rop_t cirrus_colorexpand_transp[16][4] = {
449    ROP2(cirrus_colorexpand_transp_0),
450    ROP2(cirrus_colorexpand_transp_src_and_dst),
451    ROP_NOP2(cirrus_bitblt_rop_nop),
452    ROP2(cirrus_colorexpand_transp_src_and_notdst),
453    ROP2(cirrus_colorexpand_transp_notdst),
454    ROP2(cirrus_colorexpand_transp_src),
455    ROP2(cirrus_colorexpand_transp_1),
456    ROP2(cirrus_colorexpand_transp_notsrc_and_dst),
457    ROP2(cirrus_colorexpand_transp_src_xor_dst),
458    ROP2(cirrus_colorexpand_transp_src_or_dst),
459    ROP2(cirrus_colorexpand_transp_notsrc_or_notdst),
460    ROP2(cirrus_colorexpand_transp_src_notxor_dst),
461    ROP2(cirrus_colorexpand_transp_src_or_notdst),
462    ROP2(cirrus_colorexpand_transp_notsrc),
463    ROP2(cirrus_colorexpand_transp_notsrc_or_dst),
464    ROP2(cirrus_colorexpand_transp_notsrc_and_notdst),
465};
466
467static const cirrus_bitblt_rop_t cirrus_colorexpand[16][4] = {
468    ROP2(cirrus_colorexpand_0),
469    ROP2(cirrus_colorexpand_src_and_dst),
470    ROP_NOP2(cirrus_bitblt_rop_nop),
471    ROP2(cirrus_colorexpand_src_and_notdst),
472    ROP2(cirrus_colorexpand_notdst),
473    ROP2(cirrus_colorexpand_src),
474    ROP2(cirrus_colorexpand_1),
475    ROP2(cirrus_colorexpand_notsrc_and_dst),
476    ROP2(cirrus_colorexpand_src_xor_dst),
477    ROP2(cirrus_colorexpand_src_or_dst),
478    ROP2(cirrus_colorexpand_notsrc_or_notdst),
479    ROP2(cirrus_colorexpand_src_notxor_dst),
480    ROP2(cirrus_colorexpand_src_or_notdst),
481    ROP2(cirrus_colorexpand_notsrc),
482    ROP2(cirrus_colorexpand_notsrc_or_dst),
483    ROP2(cirrus_colorexpand_notsrc_and_notdst),
484};
485
486static const cirrus_bitblt_rop_t cirrus_colorexpand_pattern_transp[16][4] = {
487    ROP2(cirrus_colorexpand_pattern_transp_0),
488    ROP2(cirrus_colorexpand_pattern_transp_src_and_dst),
489    ROP_NOP2(cirrus_bitblt_rop_nop),
490    ROP2(cirrus_colorexpand_pattern_transp_src_and_notdst),
491    ROP2(cirrus_colorexpand_pattern_transp_notdst),
492    ROP2(cirrus_colorexpand_pattern_transp_src),
493    ROP2(cirrus_colorexpand_pattern_transp_1),
494    ROP2(cirrus_colorexpand_pattern_transp_notsrc_and_dst),
495    ROP2(cirrus_colorexpand_pattern_transp_src_xor_dst),
496    ROP2(cirrus_colorexpand_pattern_transp_src_or_dst),
497    ROP2(cirrus_colorexpand_pattern_transp_notsrc_or_notdst),
498    ROP2(cirrus_colorexpand_pattern_transp_src_notxor_dst),
499    ROP2(cirrus_colorexpand_pattern_transp_src_or_notdst),
500    ROP2(cirrus_colorexpand_pattern_transp_notsrc),
501    ROP2(cirrus_colorexpand_pattern_transp_notsrc_or_dst),
502    ROP2(cirrus_colorexpand_pattern_transp_notsrc_and_notdst),
503};
504
505static const cirrus_bitblt_rop_t cirrus_colorexpand_pattern[16][4] = {
506    ROP2(cirrus_colorexpand_pattern_0),
507    ROP2(cirrus_colorexpand_pattern_src_and_dst),
508    ROP_NOP2(cirrus_bitblt_rop_nop),
509    ROP2(cirrus_colorexpand_pattern_src_and_notdst),
510    ROP2(cirrus_colorexpand_pattern_notdst),
511    ROP2(cirrus_colorexpand_pattern_src),
512    ROP2(cirrus_colorexpand_pattern_1),
513    ROP2(cirrus_colorexpand_pattern_notsrc_and_dst),
514    ROP2(cirrus_colorexpand_pattern_src_xor_dst),
515    ROP2(cirrus_colorexpand_pattern_src_or_dst),
516    ROP2(cirrus_colorexpand_pattern_notsrc_or_notdst),
517    ROP2(cirrus_colorexpand_pattern_src_notxor_dst),
518    ROP2(cirrus_colorexpand_pattern_src_or_notdst),
519    ROP2(cirrus_colorexpand_pattern_notsrc),
520    ROP2(cirrus_colorexpand_pattern_notsrc_or_dst),
521    ROP2(cirrus_colorexpand_pattern_notsrc_and_notdst),
522};
523
524static const cirrus_fill_t cirrus_fill[16][4] = {
525    ROP2(cirrus_fill_0),
526    ROP2(cirrus_fill_src_and_dst),
527    ROP_NOP2(cirrus_bitblt_fill_nop),
528    ROP2(cirrus_fill_src_and_notdst),
529    ROP2(cirrus_fill_notdst),
530    ROP2(cirrus_fill_src),
531    ROP2(cirrus_fill_1),
532    ROP2(cirrus_fill_notsrc_and_dst),
533    ROP2(cirrus_fill_src_xor_dst),
534    ROP2(cirrus_fill_src_or_dst),
535    ROP2(cirrus_fill_notsrc_or_notdst),
536    ROP2(cirrus_fill_src_notxor_dst),
537    ROP2(cirrus_fill_src_or_notdst),
538    ROP2(cirrus_fill_notsrc),
539    ROP2(cirrus_fill_notsrc_or_dst),
540    ROP2(cirrus_fill_notsrc_and_notdst),
541};
542
543static inline void cirrus_bitblt_fgcol(CirrusVGAState *s)
544{
545    unsigned int color;
546    switch (s->cirrus_blt_pixelwidth) {
547    case 1:
548        s->cirrus_blt_fgcol = s->cirrus_shadow_gr1;
549        break;
550    case 2:
551        color = s->cirrus_shadow_gr1 | (s->gr[0x11] << 8);
552        s->cirrus_blt_fgcol = le16_to_cpu(color);
553        break;
554    case 3:
555        s->cirrus_blt_fgcol = s->cirrus_shadow_gr1 | 
556            (s->gr[0x11] << 8) | (s->gr[0x13] << 16);
557        break;
558    default:
559    case 4:
560        color = s->cirrus_shadow_gr1 | (s->gr[0x11] << 8) |
561            (s->gr[0x13] << 16) | (s->gr[0x15] << 24);
562        s->cirrus_blt_fgcol = le32_to_cpu(color);
563        break;
564    }
565}
566
567static inline void cirrus_bitblt_bgcol(CirrusVGAState *s)
568{
569    unsigned int color;
570    switch (s->cirrus_blt_pixelwidth) {
571    case 1:
572        s->cirrus_blt_bgcol = s->cirrus_shadow_gr0;
573        break;
574    case 2:
575        color = s->cirrus_shadow_gr0 | (s->gr[0x10] << 8);
576        s->cirrus_blt_bgcol = le16_to_cpu(color);
577        break;
578    case 3:
579        s->cirrus_blt_bgcol = s->cirrus_shadow_gr0 | 
580            (s->gr[0x10] << 8) | (s->gr[0x12] << 16);
581        break;
582    default:
583    case 4:
584        color = s->cirrus_shadow_gr0 | (s->gr[0x10] << 8) |
585            (s->gr[0x12] << 16) | (s->gr[0x14] << 24);
586        s->cirrus_blt_bgcol = le32_to_cpu(color);
587        break;
588    }
589}
590
591static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin,
592                                     int off_pitch, int bytesperline,
593                                     int lines)
594{
595    int y;
596    int off_cur;
597    int off_cur_end;
598
599    for (y = 0; y < lines; y++) {
600        off_cur = off_begin;
601        off_cur_end = off_cur + bytesperline;
602        off_cur &= TARGET_PAGE_MASK;
603        while (off_cur < off_cur_end) {
604            cpu_physical_memory_set_dirty(s->vram_offset +
605                                          (off_cur & s->cirrus_addr_mask));
606            off_cur += TARGET_PAGE_SIZE;
607        }
608        off_begin += off_pitch;
609    }
610}
611
612static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s,
613                                            const uint8_t * src)
614{
615    uint8_t *dst;
616
617    dst = s->vram_ptr + s->cirrus_blt_dstaddr;
618    (*s->cirrus_rop) (s, dst, src,
619                      s->cirrus_blt_dstpitch, 0, 
620                      s->cirrus_blt_width, s->cirrus_blt_height);
621    cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
622                             s->cirrus_blt_dstpitch, s->cirrus_blt_width,
623                             s->cirrus_blt_height);
624    return 1;
625}
626
627/* fill */
628
629static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop)
630{
631    cirrus_fill_t rop_func;
632
633    rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
634    rop_func(s, s->vram_ptr + s->cirrus_blt_dstaddr, 
635             s->cirrus_blt_dstpitch,
636             s->cirrus_blt_width, s->cirrus_blt_height);
637    cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
638                             s->cirrus_blt_dstpitch, s->cirrus_blt_width,
639                             s->cirrus_blt_height);
640    cirrus_bitblt_reset(s);
641    return 1;
642}
643
644/***************************************
645 *
646 *  bitblt (video-to-video)
647 *
648 ***************************************/
649
650static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
651{
652    return cirrus_bitblt_common_patterncopy(s,
653                                            s->vram_ptr + 
654                                            (s->cirrus_blt_srcaddr & ~7));
655}
656
657static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
658{
659    int sx, sy;
660    int dx, dy;
661    int width, height;
662    int depth;
663    int notify = 0;
664
665    depth = s->get_bpp((VGAState *)s) / 8;
666    s->get_resolution((VGAState *)s, &width, &height);
667
668    /* extra x, y */
669    sx = (src % (width * depth)) / depth;
670    sy = (src / (width * depth));
671    dx = (dst % (width *depth)) / depth;
672    dy = (dst / (width * depth));
673
674    /* normalize width */
675    w /= depth;
676
677    /* if we're doing a backward copy, we have to adjust
678       our x/y to be the upper left corner (instead of the lower
679       right corner) */
680    if (s->cirrus_blt_dstpitch < 0) {
681        sx -= (s->cirrus_blt_width / depth) - 1;
682        dx -= (s->cirrus_blt_width / depth) - 1;
683        sy -= s->cirrus_blt_height - 1;
684        dy -= s->cirrus_blt_height - 1;
685    }
686
687    /* are we in the visible portion of memory? */
688    if (sx >= 0 && sy >= 0 && dx >= 0 && dy >= 0 &&
689        (sx + w) <= width && (sy + h) <= height &&
690        (dx + w) <= width && (dy + h) <= height) {
691        notify = 1;
692    }
693
694    /* make to sure only copy if it's a plain copy ROP */
695    if (*s->cirrus_rop != cirrus_bitblt_rop_fwd_src &&
696        *s->cirrus_rop != cirrus_bitblt_rop_bkwd_src)
697        notify = 0;
698
699    /* we have to flush all pending changes so that the copy
700       is generated at the appropriate moment in time */
701    if (notify)
702        vga_hw_update();
703
704    (*s->cirrus_rop) (s, s->vram_ptr + s->cirrus_blt_dstaddr,
705                      s->vram_ptr + s->cirrus_blt_srcaddr,
706                      s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
707                      s->cirrus_blt_width, s->cirrus_blt_height);
708
709    if (notify)
710        s->ds->dpy_copy(s->ds,
711                        sx, sy, dx, dy,
712                        s->cirrus_blt_width / depth,
713                        s->cirrus_blt_height);
714
715    /* we don't have to notify the display that this portion has
716       changed since dpy_copy implies this */
717
718    if (!notify)
719        cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
720                                 s->cirrus_blt_dstpitch, s->cirrus_blt_width,
721                                 s->cirrus_blt_height);
722}
723
724static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
725{
726    if (s->ds->dpy_copy) {
727        cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->start_addr,
728                       s->cirrus_blt_srcaddr - s->start_addr,
729                       s->cirrus_blt_width, s->cirrus_blt_height);
730    } else {
731        (*s->cirrus_rop) (s, s->vram_ptr + s->cirrus_blt_dstaddr,
732                          s->vram_ptr + s->cirrus_blt_srcaddr,
733                          s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
734                          s->cirrus_blt_width, s->cirrus_blt_height);
735
736        cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
737                                 s->cirrus_blt_dstpitch, s->cirrus_blt_width,
738                                 s->cirrus_blt_height);
739    }
740
741    return 1;
742}
743
744/***************************************
745 *
746 *  bitblt (cpu-to-video)
747 *
748 ***************************************/
749
750static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s)
751{
752    int copy_count;
753    uint8_t *end_ptr;
754   
755    if (s->cirrus_srccounter > 0) {
756        if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
757            cirrus_bitblt_common_patterncopy(s, s->cirrus_bltbuf);
758        the_end:
759            s->cirrus_srccounter = 0;
760            cirrus_bitblt_reset(s);
761        } else {
762            /* at least one scan line */
763            do {
764                (*s->cirrus_rop)(s, s->vram_ptr + s->cirrus_blt_dstaddr,
765                                 s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1);
766                cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0,
767                                         s->cirrus_blt_width, 1);
768                s->cirrus_blt_dstaddr += s->cirrus_blt_dstpitch;
769                s->cirrus_srccounter -= s->cirrus_blt_srcpitch;
770                if (s->cirrus_srccounter <= 0)
771                    goto the_end;
772                /* more bytes than needed can be transfered because of
773                   word alignment, so we keep them for the next line */
774                /* XXX: keep alignment to speed up transfer */
775                end_ptr = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
776                copy_count = s->cirrus_srcptr_end - end_ptr;
777                memmove(s->cirrus_bltbuf, end_ptr, copy_count);
778                s->cirrus_srcptr = s->cirrus_bltbuf + copy_count;
779                s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
780            } while (s->cirrus_srcptr >= s->cirrus_srcptr_end);
781        }
782    }
783}
784
785/***************************************
786 *
787 *  bitblt wrapper
788 *
789 ***************************************/
790
791static void cirrus_bitblt_reset(CirrusVGAState * s)
792{
793    s->gr[0x31] &=
794        ~(CIRRUS_BLT_START | CIRRUS_BLT_BUSY | CIRRUS_BLT_FIFOUSED);
795    s->cirrus_srcptr = &s->cirrus_bltbuf[0];
796    s->cirrus_srcptr_end = &s->cirrus_bltbuf[0];
797    s->cirrus_srccounter = 0;
798    cirrus_update_memory_access(s);
799}
800
801static int cirrus_bitblt_cputovideo(CirrusVGAState * s)
802{
803    int w;
804
805    s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_MEMSYSSRC;
806    s->cirrus_srcptr = &s->cirrus_bltbuf[0];
807    s->cirrus_srcptr_end = &s->cirrus_bltbuf[0];
808
809    if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
810        if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
811            s->cirrus_blt_srcpitch = 8;
812        } else {
813            /* XXX: check for 24 bpp */
814            s->cirrus_blt_srcpitch = 8 * 8 * s->cirrus_blt_pixelwidth;
815        }
816        s->cirrus_srccounter = s->cirrus_blt_srcpitch;
817    } else {
818        if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
819            w = s->cirrus_blt_width / s->cirrus_blt_pixelwidth;
820            if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY) 
821                s->cirrus_blt_srcpitch = ((w + 31) >> 5);
822            else
823                s->cirrus_blt_srcpitch = ((w + 7) >> 3);
824        } else {
825            /* always align input size to 32 bits */
826            s->cirrus_blt_srcpitch = (s->cirrus_blt_width + 3) & ~3;
827        }
828        s->cirrus_srccounter = s->cirrus_blt_srcpitch * s->cirrus_blt_height;
829    }
830    s->cirrus_srcptr = s->cirrus_bltbuf;
831    s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
832    cirrus_update_memory_access(s);
833    return 1;
834}
835
836static int cirrus_bitblt_videotocpu(CirrusVGAState * s)
837{
838    /* XXX */
839#ifdef DEBUG_BITBLT
840    printf("cirrus: bitblt (video to cpu) is not implemented yet\n");
841#endif
842    return 0;
843}
844
845static int cirrus_bitblt_videotovideo(CirrusVGAState * s)
846{
847    int ret;
848
849    if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
850        ret = cirrus_bitblt_videotovideo_patterncopy(s);
851    } else {
852        ret = cirrus_bitblt_videotovideo_copy(s);
853    }
854    if (ret)
855        cirrus_bitblt_reset(s);
856    return ret;
857}
858
859static void cirrus_bitblt_start(CirrusVGAState * s)
860{
861    uint8_t blt_rop;
862
863    s->gr[0x31] |= CIRRUS_BLT_BUSY;
864
865    s->cirrus_blt_width = (s->gr[0x20] | (s->gr[0x21] << 8)) + 1;
866    s->cirrus_blt_height = (s->gr[0x22] | (s->gr[0x23] << 8)) + 1;
867    s->cirrus_blt_dstpitch = (s->gr[0x24] | (s->gr[0x25] << 8));
868    s->cirrus_blt_srcpitch = (s->gr[0x26] | (s->gr[0x27] << 8));
869    s->cirrus_blt_dstaddr =
870        (s->gr[0x28] | (s->gr[0x29] << 8) | (s->gr[0x2a] << 16));
871    s->cirrus_blt_srcaddr =
872        (s->gr[0x2c] | (s->gr[0x2d] << 8) | (s->gr[0x2e] << 16));
873    s->cirrus_blt_mode = s->gr[0x30];
874    s->cirrus_blt_modeext = s->gr[0x33];
875    blt_rop = s->gr[0x32];
876
877#ifdef DEBUG_BITBLT
878    printf("rop=0x%02x mode=0x%02x modeext=0x%02x w=%d h=%d dpitch=%d spitch=%d daddr=0x%08x saddr=0x%08x writemask=0x%02x\n",
879           blt_rop, 
880           s->cirrus_blt_mode,
881           s->cirrus_blt_modeext,
882           s->cirrus_blt_width,
883           s->cirrus_blt_height,
884           s->cirrus_blt_dstpitch,
885           s->cirrus_blt_srcpitch,
886           s->cirrus_blt_dstaddr,
887           s->cirrus_blt_srcaddr,
888           s->gr[0x2f]);
889#endif
890
891    switch (s->cirrus_blt_mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) {
892    case CIRRUS_BLTMODE_PIXELWIDTH8:
893        s->cirrus_blt_pixelwidth = 1;
894        break;
895    case CIRRUS_BLTMODE_PIXELWIDTH16:
896        s->cirrus_blt_pixelwidth = 2;
897        break;
898    case CIRRUS_BLTMODE_PIXELWIDTH24:
899        s->cirrus_blt_pixelwidth = 3;
900        break;
901    case CIRRUS_BLTMODE_PIXELWIDTH32:
902        s->cirrus_blt_pixelwidth = 4;
903        break;
904    default:
905#ifdef DEBUG_BITBLT
906        printf("cirrus: bitblt - pixel width is unknown\n");
907#endif
908        goto bitblt_ignore;
909    }
910    s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_PIXELWIDTHMASK;
911
912    if ((s->
913         cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSSRC |
914                            CIRRUS_BLTMODE_MEMSYSDEST))
915        == (CIRRUS_BLTMODE_MEMSYSSRC | CIRRUS_BLTMODE_MEMSYSDEST)) {
916#ifdef DEBUG_BITBLT
917        printf("cirrus: bitblt - memory-to-memory copy is requested\n");
918#endif
919        goto bitblt_ignore;
920    }
921
922    if ((s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_SOLIDFILL) &&
923        (s->cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSDEST | 
924                               CIRRUS_BLTMODE_TRANSPARENTCOMP |
925                               CIRRUS_BLTMODE_PATTERNCOPY | 
926                               CIRRUS_BLTMODE_COLOREXPAND)) == 
927         (CIRRUS_BLTMODE_PATTERNCOPY | CIRRUS_BLTMODE_COLOREXPAND)) {
928        cirrus_bitblt_fgcol(s);
929        cirrus_bitblt_solidfill(s, blt_rop);
930    } else {
931        if ((s->cirrus_blt_mode & (CIRRUS_BLTMODE_COLOREXPAND | 
932                                   CIRRUS_BLTMODE_PATTERNCOPY)) == 
933            CIRRUS_BLTMODE_COLOREXPAND) {
934
935            if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) {
936                if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV)
937                    cirrus_bitblt_bgcol(s);
938                else
939                    cirrus_bitblt_fgcol(s);
940                s->cirrus_rop = cirrus_colorexpand_transp[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
941            } else {
942                cirrus_bitblt_fgcol(s);
943                cirrus_bitblt_bgcol(s);
944                s->cirrus_rop = cirrus_colorexpand[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
945            }
946        } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
947            if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
948                if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) {
949                    if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV)
950                        cirrus_bitblt_bgcol(s);
951                    else
952                        cirrus_bitblt_fgcol(s);
953                    s->cirrus_rop = cirrus_colorexpand_pattern_transp[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
954                } else {
955                    cirrus_bitblt_fgcol(s);
956                    cirrus_bitblt_bgcol(s);
957                    s->cirrus_rop = cirrus_colorexpand_pattern[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
958                }
959            } else {
960                s->cirrus_rop = cirrus_patternfill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
961            }
962        } else {
963            if (s->cirrus_blt_mode & CIRRUS_BLTMODE_BACKWARDS) {
964                s->cirrus_blt_dstpitch = -s->cirrus_blt_dstpitch;
965                s->cirrus_blt_srcpitch = -s->cirrus_blt_srcpitch;
966                s->cirrus_rop = cirrus_bkwd_rop[rop_to_index[blt_rop]];
967            } else {
968                s->cirrus_rop = cirrus_fwd_rop[rop_to_index[blt_rop]];
969            }
970        }
971       
972        // setup bitblt engine.
973        if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSSRC) {
974            if (!cirrus_bitblt_cputovideo(s))
975                goto bitblt_ignore;
976        } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST) {
977            if (!cirrus_bitblt_videotocpu(s))
978                goto bitblt_ignore;
979        } else {
980            if (!cirrus_bitblt_videotovideo(s))
981                goto bitblt_ignore;
982        }
983    }
984    return;
985  bitblt_ignore:;
986    cirrus_bitblt_reset(s);
987}
988
989static void cirrus_write_bitblt(CirrusVGAState * s, unsigned reg_value)
990{
991    unsigned old_value;
992
993    old_value = s->gr[0x31];
994    s->gr[0x31] = reg_value;
995
996    if (((old_value & CIRRUS_BLT_RESET) != 0) &&
997        ((reg_value & CIRRUS_BLT_RESET) == 0)) {
998        cirrus_bitblt_reset(s);
999    } else if (((old_value & CIRRUS_BLT_START) == 0) &&
1000               ((reg_value & CIRRUS_BLT_START) != 0)) {
1001        cirrus_bitblt_start(s);
1002    }
1003}
1004
1005
1006/***************************************
1007 *
1008 *  basic parameters
1009 *
1010 ***************************************/
1011
1012static void cirrus_get_offsets(VGAState *s1, 
1013                                   uint32_t *pline_offset,
1014                                   uint32_t *pstart_addr)
1015{
1016    CirrusVGAState * s = (CirrusVGAState *)s1;
1017    uint32_t start_addr;
1018    uint32_t line_offset;
1019
1020    line_offset = s->cr[0x13]
1021        | ((s->cr[0x1b] & 0x10) << 4);
1022    line_offset <<= 3;
1023    *pline_offset = line_offset;
1024
1025    start_addr = (s->cr[0x0c] << 8)
1026        | s->cr[0x0d]
1027        | ((s->cr[0x1b] & 0x01) << 16)
1028        | ((s->cr[0x1b] & 0x0c) << 15)
1029        | ((s->cr[0x1d] & 0x80) << 12);
1030    *pstart_addr = start_addr;
1031}
1032
1033static uint32_t cirrus_get_bpp16_depth(CirrusVGAState * s)
1034{
1035    uint32_t ret = 16;
1036
1037    switch (s->cirrus_hidden_dac_data & 0xf) {
1038    case 0:
1039        ret = 15;
1040        break;                  /* Sierra HiColor */
1041    case 1:
1042        ret = 16;
1043        break;                  /* XGA HiColor */
1044    default:
1045#ifdef DEBUG_CIRRUS
1046        printf("cirrus: invalid DAC value %x in 16bpp\n",
1047               (s->cirrus_hidden_dac_data & 0xf));
1048#endif
1049        ret = 15;               /* XXX */
1050        break;
1051    }
1052    return ret;
1053}
1054
1055static int cirrus_get_bpp(VGAState *s1)
1056{
1057    CirrusVGAState * s = (CirrusVGAState *)s1;
1058    uint32_t ret = 8;
1059
1060    if ((s->sr[0x07] & 0x01) != 0) {
1061        /* Cirrus SVGA */
1062        switch (s->sr[0x07] & CIRRUS_SR7_BPP_MASK) {
1063        case CIRRUS_SR7_BPP_8:
1064            ret = 8;
1065            break;
1066        case CIRRUS_SR7_BPP_16_DOUBLEVCLK:
1067            ret = cirrus_get_bpp16_depth(s);
1068            break;
1069        case CIRRUS_SR7_BPP_24:
1070            ret = 24;
1071            break;
1072        case CIRRUS_SR7_BPP_16:
1073            ret = cirrus_get_bpp16_depth(s);
1074            break;
1075        case CIRRUS_SR7_BPP_32:
1076            ret = 32;
1077            break;
1078        default:
1079#ifdef DEBUG_CIRRUS
1080            printf("cirrus: unknown bpp - sr7=%x\n", s->sr[0x7]);
1081#endif
1082            ret = 8;
1083            break;
1084        }
1085    } else {
1086        /* VGA */
1087        ret = 0;
1088    }
1089
1090    return ret;
1091}
1092
1093static void cirrus_get_resolution(VGAState *s, int *pwidth, int *pheight)
1094{
1095    int width, height;
1096   
1097    width = (s->cr[0x01] + 1) * 8;
1098    height = s->cr[0x12] | 
1099        ((s->cr[0x07] & 0x02) << 7) | 
1100        ((s->cr[0x07] & 0x40) << 3);
1101    height = (height + 1);
1102    /* interlace support */
1103    if (s->cr[0x1a] & 0x01)
1104        height = height * 2;
1105    *pwidth = width;
1106    *pheight = height;
1107}
1108
1109/***************************************
1110 *
1111 * bank memory
1112 *
1113 ***************************************/
1114
1115static void cirrus_update_bank_ptr(CirrusVGAState * s, unsigned bank_index)
1116{
1117    unsigned offset;
1118    unsigned limit;
1119
1120    if ((s->gr[0x0b] & 0x01) != 0)      /* dual bank */
1121        offset = s->gr[0x09 + bank_index];
1122    else                        /* single bank */
1123        offset = s->gr[0x09];
1124
1125    if ((s->gr[0x0b] & 0x20) != 0)
1126        offset <<= 14;
1127    else
1128        offset <<= 12;
1129
1130    if (s->real_vram_size <= offset)
1131        limit = 0;
1132    else
1133        limit = s->real_vram_size - offset;
1134
1135    if (((s->gr[0x0b] & 0x01) == 0) && (bank_index != 0)) {
1136        if (limit > 0x8000) {
1137            offset += 0x8000;
1138            limit -= 0x8000;
1139        } else {
1140            limit = 0;
1141        }
1142    }
1143
1144    if (limit > 0) {
1145        s->cirrus_bank_base[bank_index] = offset;
1146        s->cirrus_bank_limit[bank_index] = limit;
1147    } else {
1148        s->cirrus_bank_base[bank_index] = 0;
1149        s->cirrus_bank_limit[bank_index] = 0;
1150    }
1151}
1152
1153/***************************************
1154 *
1155 *  I/O access between 0x3c4-0x3c5
1156 *
1157 ***************************************/
1158
1159static int
1160cirrus_hook_read_sr(CirrusVGAState * s, unsigned reg_index, int *reg_value)
1161{
1162    switch (reg_index) {
1163    case 0x00:                  // Standard VGA
1164    case 0x01:                  // Standard VGA
1165    case 0x02:                  // Standard VGA
1166    case 0x03:                  // Standard VGA
1167    case 0x04:                  // Standard VGA
1168        return CIRRUS_HOOK_NOT_HANDLED;
1169    case 0x06:                  // Unlock Cirrus extensions
1170        *reg_value = s->sr[reg_index];
1171        break;
1172    case 0x10:
1173    case 0x30:
1174    case 0x50:
1175    case 0x70:                  // Graphics Cursor X
1176    case 0x90:
1177    case 0xb0:
1178    case 0xd0:
1179    case 0xf0:                  // Graphics Cursor X
1180        *reg_value = s->sr[0x10];
1181        break;
1182    case 0x11:
1183    case 0x31:
1184    case 0x51:
1185    case 0x71:                  // Graphics Cursor Y
1186    case 0x91:
1187    case 0xb1:
1188    case 0xd1:
1189    case 0xf1:                  // Graphics Cursor Y
1190        *reg_value = s->sr[0x11];
1191        break;
1192    case 0x05:                  // ???
1193    case 0x07:                  // Extended Sequencer Mode
1194    case 0x08:                  // EEPROM Control
1195    case 0x09:                  // Scratch Register 0
1196    case 0x0a:                  // Scratch Register 1
1197    case 0x0b:                  // VCLK 0
1198    case 0x0c:                  // VCLK 1
1199    case 0x0d:                  // VCLK 2
1200    case 0x0e:                  // VCLK 3
1201    case 0x0f:                  // DRAM Control
1202    case 0x12:                  // Graphics Cursor Attribute
1203    case 0x13:                  // Graphics Cursor Pattern Address
1204    case 0x14:                  // Scratch Register 2
1205    case 0x15:                  // Scratch Register 3
1206    case 0x16:                  // Performance Tuning Register
1207    case 0x17:                  // Configuration Readback and Extended Control
1208    case 0x18:                  // Signature Generator Control
1209    case 0x19:                  // Signal Generator Result
1210    case 0x1a:                  // Signal Generator Result
1211    case 0x1b:                  // VCLK 0 Denominator & Post
1212    case 0x1c:                  // VCLK 1 Denominator & Post
1213    case 0x1d:                  // VCLK 2 Denominator & Post
1214    case 0x1e:                  // VCLK 3 Denominator & Post
1215    case 0x1f:                  // BIOS Write Enable and MCLK select
1216#ifdef DEBUG_CIRRUS
1217        printf("cirrus: handled inport sr_index %02x\n", reg_index);
1218#endif
1219        *reg_value = s->sr[reg_index];
1220        break;
1221    default:
1222#ifdef DEBUG_CIRRUS
1223        printf("cirrus: inport sr_index %02x\n", reg_index);
1224#endif
1225        *reg_value = 0xff;
1226        break;
1227    }
1228
1229    return CIRRUS_HOOK_HANDLED;
1230}
1231
1232static int
1233cirrus_hook_write_sr(CirrusVGAState * s, unsigned reg_index, int reg_value)
1234{
1235    switch (reg_index) {
1236    case 0x00:                  // Standard VGA
1237    case 0x01:                  // Standard VGA
1238    case 0x02:                  // Standard VGA
1239    case 0x03:                  // Standard VGA
1240    case 0x04:                  // Standard VGA
1241        return CIRRUS_HOOK_NOT_HANDLED;
1242    case 0x06:                  // Unlock Cirrus extensions
1243        reg_value &= 0x17;
1244        if (reg_value == 0x12) {
1245            s->sr[reg_index] = 0x12;
1246        } else {
1247            s->sr[reg_index] = 0x0f;
1248        }
1249        break;
1250    case 0x10:
1251    case 0x30:
1252    case 0x50:
1253    case 0x70:                  // Graphics Cursor X
1254    case 0x90:
1255    case 0xb0:
1256    case 0xd0:
1257    case 0xf0:                  // Graphics Cursor X
1258        s->sr[0x10] = reg_value;
1259        s->hw_cursor_x = (reg_value << 3) | (reg_index >> 5);
1260        break;
1261    case 0x11:
1262    case 0x31:
1263    case 0x51:
1264    case 0x71:                  // Graphics Cursor Y
1265    case 0x91:
1266    case 0xb1:
1267    case 0xd1:
1268    case 0xf1:                  // Graphics Cursor Y
1269        s->sr[0x11] = reg_value;
1270        s->hw_cursor_y = (reg_value << 3) | (reg_index >> 5);
1271        break;
1272    case 0x07:                  // Extended Sequencer Mode
1273    case 0x08:                  // EEPROM Control
1274    case 0x09:                  // Scratch Register 0
1275    case 0x0a:                  // Scratch Register 1
1276    case 0x0b:                  // VCLK 0
1277    case 0x0c:                  // VCLK 1
1278    case 0x0d:                  // VCLK 2
1279    case 0x0e:                  // VCLK 3
1280    case 0x0f:                  // DRAM Control
1281    case 0x12:                  // Graphics Cursor Attribute
1282    case 0x13:                  // Graphics Cursor Pattern Address
1283    case 0x14:                  // Scratch Register 2
1284    case 0x15:                  // Scratch Register 3
1285    case 0x16:                  // Performance Tuning Register
1286    case 0x18:                  // Signature Generator Control
1287    case 0x19:                  // Signature Generator Result
1288    case 0x1a:                  // Signature Generator Result
1289    case 0x1b:                  // VCLK 0 Denominator & Post
1290    case 0x1c:                  // VCLK 1 Denominator & Post
1291    case 0x1d:                  // VCLK 2 Denominator & Post
1292    case 0x1e:                  // VCLK 3 Denominator & Post
1293    case 0x1f:                  // BIOS Write Enable and MCLK select
1294        s->sr[reg_index] = reg_value;
1295#ifdef DEBUG_CIRRUS
1296        printf("cirrus: handled outport sr_index %02x, sr_value %02x\n",
1297               reg_index, reg_value);
1298#endif
1299        break;
1300    case 0x17:                  // Configuration Readback and Extended Control
1301        s->sr[reg_index] = (s->sr[reg_index] & 0x38) | (reg_value & 0xc7);
1302        cirrus_update_memory_access(s);
1303        break;
1304    default:
1305#ifdef DEBUG_CIRRUS
1306        printf("cirrus: outport sr_index %02x, sr_value %02x\n", reg_index,
1307               reg_value);
1308#endif
1309        break;
1310    }
1311
1312    return CIRRUS_HOOK_HANDLED;
1313}
1314
1315/***************************************
1316 *
1317 *  I/O access at 0x3c6
1318 *
1319 ***************************************/
1320
1321static void cirrus_read_hidden_dac(CirrusVGAState * s, int *reg_value)
1322{
1323    *reg_value = 0xff;
1324    if (++s->cirrus_hidden_dac_lockindex == 5) {
1325        *reg_value = s->cirrus_hidden_dac_data;
1326        s->cirrus_hidden_dac_lockindex = 0;
1327    }
1328}
1329
1330static void cirrus_write_hidden_dac(CirrusVGAState * s, int reg_value)
1331{
1332    if (s->cirrus_hidden_dac_lockindex == 4) {
1333        s->cirrus_hidden_dac_data = reg_value;
1334#if defined(DEBUG_CIRRUS)
1335        printf("cirrus: outport hidden DAC, value %02x\n", reg_value);
1336#endif
1337    }
1338    s->cirrus_hidden_dac_lockindex = 0;
1339}
1340
1341/***************************************
1342 *
1343 *  I/O access at 0x3c9
1344 *
1345 ***************************************/
1346
1347static int cirrus_hook_read_palette(CirrusVGAState * s, int *reg_value)
1348{
1349    if (!(s->sr[0x12] & CIRRUS_CURSOR_HIDDENPEL))
1350        return CIRRUS_HOOK_NOT_HANDLED;
1351    *reg_value =
1352        s->cirrus_hidden_palette[(s->dac_read_index & 0x0f) * 3 +
1353                                 s->dac_sub_index];
1354    if (++s->dac_sub_index == 3) {
1355        s->dac_sub_index = 0;
1356        s->dac_read_index++;
1357    }
1358    return CIRRUS_HOOK_HANDLED;
1359}
1360
1361static int cirrus_hook_write_palette(CirrusVGAState * s, int reg_value)
1362{
1363    if (!(s->sr[0x12] & CIRRUS_CURSOR_HIDDENPEL))
1364        return CIRRUS_HOOK_NOT_HANDLED;
1365    s->dac_cache[s->dac_sub_index] = reg_value;
1366    if (++s->dac_sub_index == 3) {
1367        memcpy(&s->cirrus_hidden_palette[(s->dac_write_index & 0x0f) * 3],
1368               s->dac_cache, 3);
1369        /* XXX update cursor */
1370        s->dac_sub_index = 0;
1371        s->dac_write_index++;
1372    }
1373    return CIRRUS_HOOK_HANDLED;
1374}
1375
1376/***************************************
1377 *
1378 *  I/O access between 0x3ce-0x3cf
1379 *
1380 ***************************************/
1381
1382static int
1383cirrus_hook_read_gr(CirrusVGAState * s, unsigned reg_index, int *reg_value)
1384{
1385    switch (reg_index) {
1386    case 0x00: // Standard VGA, BGCOLOR 0x000000ff
1387      *reg_value = s->cirrus_shadow_gr0;
1388      return CIRRUS_HOOK_HANDLED;
1389    case 0x01: // Standard VGA, FGCOLOR 0x000000ff
1390      *reg_value = s->cirrus_shadow_gr1;
1391      return CIRRUS_HOOK_HANDLED;
1392    case 0x02:                  // Standard VGA
1393    case 0x03:                  // Standard VGA
1394    case 0x04:                  // Standard VGA
1395    case 0x06:                  // Standard VGA
1396    case 0x07:                  // Standard VGA
1397    case 0x08:                  // Standard VGA
1398        return CIRRUS_HOOK_NOT_HANDLED;
1399    case 0x05:                  // Standard VGA, Cirrus extended mode
1400    default:
1401        break;
1402    }
1403
1404    if (reg_index < 0x3a) {
1405        *reg_value = s->gr[reg_index];
1406    } else {
1407#ifdef DEBUG_CIRRUS
1408        printf("cirrus: inport gr_index %02x\n", reg_index);
1409#endif
1410        *reg_value = 0xff;
1411    }
1412
1413    return CIRRUS_HOOK_HANDLED;
1414}
1415
1416static int
1417cirrus_hook_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value)
1418{
1419#if defined(DEBUG_BITBLT) && 0
1420    printf("gr%02x: %02x\n", reg_index, reg_value);
1421#endif
1422    switch (reg_index) {
1423    case 0x00:                  // Standard VGA, BGCOLOR 0x000000ff
1424        s->cirrus_shadow_gr0 = reg_value;
1425        return CIRRUS_HOOK_NOT_HANDLED;
1426    case 0x01:                  // Standard VGA, FGCOLOR 0x000000ff
1427        s->cirrus_shadow_gr1 = reg_value;
1428        return CIRRUS_HOOK_NOT_HANDLED;
1429    case 0x02:                  // Standard VGA
1430    case 0x03:                  // Standard VGA
1431    case 0x04:                  // Standard VGA
1432    case 0x06:                  // Standard VGA
1433    case 0x07:                  // Standard VGA
1434    case 0x08:                  // Standard VGA
1435        return CIRRUS_HOOK_NOT_HANDLED;
1436    case 0x05:                  // Standard VGA, Cirrus extended mode
1437        s->gr[reg_index] = reg_value & 0x7f;
1438        cirrus_update_memory_access(s);
1439        break;
1440    case 0x09:                  // bank offset #0
1441    case 0x0A:                  // bank offset #1
1442        s->gr[reg_index] = reg_value;
1443        cirrus_update_bank_ptr(s, 0);
1444        cirrus_update_bank_ptr(s, 1);
1445        break;
1446    case 0x0B:
1447        s->gr[reg_index] = reg_value;
1448        cirrus_update_bank_ptr(s, 0);
1449        cirrus_update_bank_ptr(s, 1);
1450        cirrus_update_memory_access(s);
1451        break;
1452    case 0x10:                  // BGCOLOR 0x0000ff00
1453    case 0x11:                  // FGCOLOR 0x0000ff00
1454    case 0x12:                  // BGCOLOR 0x00ff0000
1455    case 0x13:                  // FGCOLOR 0x00ff0000
1456    case 0x14:                  // BGCOLOR 0xff000000
1457    case 0x15:                  // FGCOLOR 0xff000000
1458    case 0x20:                  // BLT WIDTH 0x0000ff
1459    case 0x22:                  // BLT HEIGHT 0x0000ff
1460    case 0x24:                  // BLT DEST PITCH 0x0000ff
1461    case 0x26:                  // BLT SRC PITCH 0x0000ff
1462    case 0x28:                  // BLT DEST ADDR 0x0000ff
1463    case 0x29:                  // BLT DEST ADDR 0x00ff00
1464    case 0x2c:                  // BLT SRC ADDR 0x0000ff
1465    case 0x2d:                  // BLT SRC ADDR 0x00ff00
1466    case 0x2f:                  // BLT WRITEMASK
1467    case 0x30:                  // BLT MODE
1468    case 0x32:                  // RASTER OP
1469    case 0x33:                  // BLT MODEEXT
1470    case 0x34:                  // BLT TRANSPARENT COLOR 0x00ff
1471    case 0x35:                  // BLT TRANSPARENT COLOR 0xff00
1472    case 0x38:                  // BLT TRANSPARENT COLOR MASK 0x00ff
1473    case 0x39:                  // BLT TRANSPARENT COLOR MASK 0xff00
1474        s->gr[reg_index] = reg_value;
1475        break;
1476    case 0x21:                  // BLT WIDTH 0x001f00
1477    case 0x23:                  // BLT HEIGHT 0x001f00
1478    case 0x25:                  // BLT DEST PITCH 0x001f00
1479    case 0x27:                  // BLT SRC PITCH 0x001f00
1480        s->gr[reg_index] = reg_value & 0x1f;
1481        break;
1482    case 0x2a:                  // BLT DEST ADDR 0x3f0000
1483        s->gr[reg_index] = reg_value & 0x3f;
1484        /* if auto start mode, starts bit blt now */
1485        if (s->gr[0x31] & CIRRUS_BLT_AUTOSTART) {
1486            cirrus_bitblt_start(s);
1487        }
1488        break;
1489    case 0x2e:                  // BLT SRC ADDR 0x3f0000
1490        s->gr[reg_index] = reg_value & 0x3f;
1491        break;
1492    case 0x31:                  // BLT STATUS/START
1493        cirrus_write_bitblt(s, reg_value);
1494        break;
1495    default:
1496#ifdef DEBUG_CIRRUS
1497        printf("cirrus: outport gr_index %02x, gr_value %02x\n", reg_index,
1498               reg_value);
1499#endif
1500        break;
1501    }
1502
1503    return CIRRUS_HOOK_HANDLED;
1504}
1505
1506/***************************************
1507 *
1508 *  I/O access between 0x3d4-0x3d5
1509 *
1510 ***************************************/
1511
1512static int
1513cirrus_hook_read_cr(CirrusVGAState * s, unsigned reg_index, int *reg_value)
1514{
1515    switch (reg_index) {
1516    case 0x00:                  // Standard VGA
1517    case 0x01:                  // Standard VGA
1518    case 0x02:                  // Standard VGA
1519    case 0x03:                  // Standard VGA
1520    case 0x04:                  // Standard VGA
1521    case 0x05:                  // Standard VGA
1522    case 0x06:                  // Standard VGA
1523    case 0x07:                  // Standard VGA
1524    case 0x08:                  // Standard VGA
1525    case 0x09:                  // Standard VGA
1526    case 0x0a:                  // Standard VGA
1527    case 0x0b:                  // Standard VGA
1528    case 0x0c:                  // Standard VGA
1529    case 0x0d:                  // Standard VGA
1530    case 0x0e:                  // Standard VGA
1531    case 0x0f:                  // Standard VGA
1532    case 0x10:                  // Standard VGA
1533    case 0x11:                  // Standard VGA
1534    case 0x12:                  // Standard VGA
1535    case 0x13:                  // Standard VGA
1536    case 0x14:                  // Standard VGA
1537    case 0x15:                  // Standard VGA
1538    case 0x16:                  // Standard VGA
1539    case 0x17:                  // Standard VGA
1540    case 0x18:                  // Standard VGA
1541        return CIRRUS_HOOK_NOT_HANDLED;
1542    case 0x19:                  // Interlace End
1543    case 0x1a:                  // Miscellaneous Control
1544    case 0x1b:                  // Extended Display Control
1545    case 0x1c:                  // Sync Adjust and Genlock
1546    case 0x1d:                  // Overlay Extended Control
1547    case 0x22:                  // Graphics Data Latches Readback (R)
1548    case 0x24:                  // Attribute Controller Toggle Readback (R)
1549    case 0x25:                  // Part Status
1550    case 0x27:                  // Part ID (R)
1551        *reg_value = s->cr[reg_index];
1552        break;
1553    case 0x26:                  // Attribute Controller Index Readback (R)
1554        *reg_value = s->ar_index & 0x3f;
1555        break;
1556    default:
1557#ifdef DEBUG_CIRRUS
1558        printf("cirrus: inport cr_index %02x\n", reg_index);
1559        *reg_value = 0xff;
1560#endif
1561        break;
1562    }
1563
1564    return CIRRUS_HOOK_HANDLED;
1565}
1566
1567static int
1568cirrus_hook_write_cr(CirrusVGAState * s, unsigned reg_index, int reg_value)
1569{
1570    switch (reg_index) {
1571    case 0x00:                  // Standard VGA
1572    case 0x01:                  // Standard VGA
1573    case 0x02:                  // Standard VGA
1574    case 0x03:                  // Standard VGA
1575    case 0x04:                  // Standard VGA
1576    case 0x05:                  // Standard VGA
1577    case 0x06:                  // Standard VGA
1578    case 0x07:                  // Standard VGA
1579    case 0x08:                  // Standard VGA
1580    case 0x09:                  // Standard VGA
1581    case 0x0a:                  // Standard VGA
1582    case 0x0b:                  // Standard VGA
1583    case 0x0c:                  // Standard VGA
1584    case 0x0d:                  // Standard VGA
1585    case 0x0e:                  // Standard VGA
1586    case 0x0f:                  // Standard VGA
1587    case 0x10:                  // Standard VGA
1588    case 0x11:                  // Standard VGA
1589    case 0x12:                  // Standard VGA
1590    case 0x13:                  // Standard VGA
1591    case 0x14:                  // Standard VGA
1592    case 0x15:                  // Standard VGA
1593    case 0x16:                  // Standard VGA
1594    case 0x17:                  // Standard VGA
1595    case 0x18:                  // Standard VGA
1596        return CIRRUS_HOOK_NOT_HANDLED;
1597    case 0x19:                  // Interlace End
1598    case 0x1a:                  // Miscellaneous Control
1599    case 0x1b:                  // Extended Display Control
1600    case 0x1c:                  // Sync Adjust and Genlock
1601    case 0x1d:                  // Overlay Extended Control
1602        s->cr[reg_index] = reg_value;
1603#ifdef DEBUG_CIRRUS
1604        printf("cirrus: handled outport cr_index %02x, cr_value %02x\n",
1605               reg_index, reg_value);
1606#endif
1607        break;
1608    case 0x22:                  // Graphics Data Latches Readback (R)
1609    case 0x24:                  // Attribute Controller Toggle Readback (R)
1610    case 0x26:                  // Attribute Controller Index Readback (R)
1611    case 0x27:                  // Part ID (R)
1612        break;
1613    case 0x25:                  // Part Status
1614    default:
1615#ifdef DEBUG_CIRRUS
1616        printf("cirrus: outport cr_index %02x, cr_value %02x\n", reg_index,
1617               reg_value);
1618#endif
1619        break;
1620    }
1621
1622    return CIRRUS_HOOK_HANDLED;
1623}
1624
1625/***************************************
1626 *
1627 *  memory-mapped I/O (bitblt)
1628 *
1629 ***************************************/
1630
1631static uint8_t cirrus_mmio_blt_read(CirrusVGAState * s, unsigned address)
1632{
1633    int value = 0xff;
1634
1635    switch (address) {
1636    case (CIRRUS_MMIO_BLTBGCOLOR + 0):
1637        cirrus_hook_read_gr(s, 0x00, &value);
1638        break;
1639    case (CIRRUS_MMIO_BLTBGCOLOR + 1):
1640        cirrus_hook_read_gr(s, 0x10, &value);
1641        break;
1642    case (CIRRUS_MMIO_BLTBGCOLOR + 2):
1643        cirrus_hook_read_gr(s, 0x12, &value);
1644        break;
1645    case (CIRRUS_MMIO_BLTBGCOLOR + 3):
1646        cirrus_hook_read_gr(s, 0x14, &value);
1647        break;
1648    case (CIRRUS_MMIO_BLTFGCOLOR + 0):
1649        cirrus_hook_read_gr(s, 0x01, &value);
1650        break;
1651    case (CIRRUS_MMIO_BLTFGCOLOR + 1):
1652        cirrus_hook_read_gr(s, 0x11, &value);
1653        break;
1654    case (CIRRUS_MMIO_BLTFGCOLOR + 2):
1655        cirrus_hook_read_gr(s, 0x13, &value);
1656        break;
1657    case (CIRRUS_MMIO_BLTFGCOLOR + 3):
1658        cirrus_hook_read_gr(s, 0x15, &value);
1659        break;
1660    case (CIRRUS_MMIO_BLTWIDTH + 0):
1661        cirrus_hook_read_gr(s, 0x20, &value);
1662        break;
1663    case (CIRRUS_MMIO_BLTWIDTH + 1):
1664        cirrus_hook_read_gr(s, 0x21, &value);
1665        break;
1666    case (CIRRUS_MMIO_BLTHEIGHT + 0):
1667        cirrus_hook_read_gr(s, 0x22, &value);
1668        break;
1669    case (CIRRUS_MMIO_BLTHEIGHT + 1):
1670        cirrus_hook_read_gr(s, 0x23, &value);
1671        break;
1672    case (CIRRUS_MMIO_BLTDESTPITCH + 0):
1673        cirrus_hook_read_gr(s, 0x24, &value);
1674        break;
1675    case (CIRRUS_MMIO_BLTDESTPITCH + 1):
1676        cirrus_hook_read_gr(s, 0x25, &value);
1677        break;
1678    case (CIRRUS_MMIO_BLTSRCPITCH + 0):
1679        cirrus_hook_read_gr(s, 0x26, &value);
1680        break;
1681    case (CIRRUS_MMIO_BLTSRCPITCH + 1):
1682        cirrus_hook_read_gr(s, 0x27, &value);
1683        break;
1684    case (CIRRUS_MMIO_BLTDESTADDR + 0):
1685        cirrus_hook_read_gr(s, 0x28, &value);
1686        break;
1687    case (CIRRUS_MMIO_BLTDESTADDR + 1):
1688        cirrus_hook_read_gr(s, 0x29, &value);
1689        break;
1690    case (CIRRUS_MMIO_BLTDESTADDR + 2):
1691        cirrus_hook_read_gr(s, 0x2a, &value);
1692        break;
1693    case (CIRRUS_MMIO_BLTSRCADDR + 0):
1694        cirrus_hook_read_gr(s, 0x2c, &value);
1695        break;
1696    case (CIRRUS_MMIO_BLTSRCADDR + 1):
1697        cirrus_hook_read_gr(s, 0x2d, &value);
1698        break;
1699    case (CIRRUS_MMIO_BLTSRCADDR + 2):
1700        cirrus_hook_read_gr(s, 0x2e, &value);
1701        break;
1702    case CIRRUS_MMIO_BLTWRITEMASK:
1703        cirrus_hook_read_gr(s, 0x2f, &value);
1704        break;
1705    case CIRRUS_MMIO_BLTMODE:
1706        cirrus_hook_read_gr(s, 0x30, &value);
1707        break;
1708    case CIRRUS_MMIO_BLTROP:
1709        cirrus_hook_read_gr(s, 0x32, &value);
1710        break;
1711    case CIRRUS_MMIO_BLTMODEEXT:
1712        cirrus_hook_read_gr(s, 0x33, &value);
1713        break;
1714    case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0):
1715        cirrus_hook_read_gr(s, 0x34, &value);
1716        break;
1717    case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1):
1718        cirrus_hook_read_gr(s, 0x35, &value);
1719        break;
1720    case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0):
1721        cirrus_hook_read_gr(s, 0x38, &value);
1722        break;
1723    case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1):
1724        cirrus_hook_read_gr(s, 0x39, &value);
1725        break;
1726    case CIRRUS_MMIO_BLTSTATUS:
1727        cirrus_hook_read_gr(s, 0x31, &value);
1728        break;
1729    default:
1730#ifdef DEBUG_CIRRUS
1731        printf("cirrus: mmio read - address 0x%04x\n", address);
1732#endif
1733        break;
1734    }
1735
1736    return (uint8_t) value;
1737}
1738
1739static void cirrus_mmio_blt_write(CirrusVGAState * s, unsigned address,
1740                                  uint8_t value)
1741{
1742    switch (address) {
1743    case (CIRRUS_MMIO_BLTBGCOLOR + 0):
1744        cirrus_hook_write_gr(s, 0x00, value);
1745        break;
1746    case (CIRRUS_MMIO_BLTBGCOLOR + 1):
1747        cirrus_hook_write_gr(s, 0x10, value);
1748        break;
1749    case (CIRRUS_MMIO_BLTBGCOLOR + 2):
1750        cirrus_hook_write_gr(s, 0x12, value);
1751        break;
1752    case (CIRRUS_MMIO_BLTBGCOLOR + 3):
1753        cirrus_hook_write_gr(s, 0x14, value);
1754        break;
1755    case (CIRRUS_MMIO_BLTFGCOLOR + 0):
1756        cirrus_hook_write_gr(s, 0x01, value);
1757        break;
1758    case (CIRRUS_MMIO_BLTFGCOLOR + 1):
1759        cirrus_hook_write_gr(s, 0x11, value);
1760        break;
1761    case (CIRRUS_MMIO_BLTFGCOLOR + 2):
1762        cirrus_hook_write_gr(s, 0x13, value);
1763        break;
1764    case (CIRRUS_MMIO_BLTFGCOLOR + 3):
1765        cirrus_hook_write_gr(s, 0x15, value);
1766        break;
1767    case (CIRRUS_MMIO_BLTWIDTH + 0):
1768        cirrus_hook_write_gr(s, 0x20, value);
1769        break;
1770    case (CIRRUS_MMIO_BLTWIDTH + 1):
1771        cirrus_hook_write_gr(s, 0x21, value);
1772        break;
1773    case (CIRRUS_MMIO_BLTHEIGHT + 0):
1774        cirrus_hook_write_gr(s, 0x22, value);
1775        break;
1776    case (CIRRUS_MMIO_BLTHEIGHT + 1):
1777        cirrus_hook_write_gr(s, 0x23, value);
1778        break;
1779    case (CIRRUS_MMIO_BLTDESTPITCH + 0):
1780        cirrus_hook_write_gr(s, 0x24, value);
1781        break;
1782    case (CIRRUS_MMIO_BLTDESTPITCH + 1):
1783        cirrus_hook_write_gr(s, 0x25, value);
1784        break;
1785    case (CIRRUS_MMIO_BLTSRCPITCH + 0):
1786        cirrus_hook_write_gr(s, 0x26, value);
1787        break;
1788    case (CIRRUS_MMIO_BLTSRCPITCH + 1):
1789        cirrus_hook_write_gr(s, 0x27, value);
1790        break;
1791    case (CIRRUS_MMIO_BLTDESTADDR + 0):
1792        cirrus_hook_write_gr(s, 0x28, value);
1793        break;
1794    case (CIRRUS_MMIO_BLTDESTADDR + 1):
1795        cirrus_hook_write_gr(s, 0x29, value);
1796        break;
1797    case (CIRRUS_MMIO_BLTDESTADDR + 2):
1798        cirrus_hook_write_gr(s, 0x2a, value);
1799        break;
1800    case (CIRRUS_MMIO_BLTDESTADDR + 3):
1801        /* ignored */
1802        break;
1803    case (CIRRUS_MMIO_BLTSRCADDR + 0):
1804        cirrus_hook_write_gr(s, 0x2c, value);
1805        break;
1806    case (CIRRUS_MMIO_BLTSRCADDR + 1):
1807        cirrus_hook_write_gr(s, 0x2d, value);
1808        break;
1809    case (CIRRUS_MMIO_BLTSRCADDR + 2):
1810        cirrus_hook_write_gr(s, 0x2e, value);
1811        break;
1812    case CIRRUS_MMIO_BLTWRITEMASK:
1813        cirrus_hook_write_gr(s, 0x2f, value);
1814        break;
1815    case CIRRUS_MMIO_BLTMODE:
1816        cirrus_hook_write_gr(s, 0x30, value);
1817        break;
1818    case CIRRUS_MMIO_BLTROP:
1819        cirrus_hook_write_gr(s, 0x32, value);
1820        break;
1821    case CIRRUS_MMIO_BLTMODEEXT:
1822        cirrus_hook_write_gr(s, 0x33, value);
1823        break;
1824    case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0):
1825        cirrus_hook_write_gr(s, 0x34, value);
1826        break;
1827    case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1):
1828        cirrus_hook_write_gr(s, 0x35, value);
1829        break;
1830    case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0):
1831        cirrus_hook_write_gr(s, 0x38, value);
1832        break;
1833    case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1):
1834        cirrus_hook_write_gr(s, 0x39, value);
1835        break;
1836    case CIRRUS_MMIO_BLTSTATUS:
1837        cirrus_hook_write_gr(s, 0x31, value);
1838        break;
1839    default:
1840#ifdef DEBUG_CIRRUS
1841        printf("cirrus: mmio write - addr 0x%04x val 0x%02x (ignored)\n",
1842               address, value);
1843#endif
1844        break;
1845    }
1846}
1847
1848/***************************************
1849 *
1850 *  write mode 4/5
1851 *
1852 * assume TARGET_PAGE_SIZE >= 16
1853 *
1854 ***************************************/
1855
1856static void cirrus_mem_writeb_mode4and5_8bpp(CirrusVGAState * s,
1857                                             unsigned mode,
1858                                             unsigned offset,
1859                                             uint32_t mem_value)
1860{
1861    int x;
1862    unsigned val = mem_value;
1863    uint8_t *dst;
1864
1865    dst = s->vram_ptr + offset;
1866    for (x = 0; x < 8; x++) {
1867        if (val & 0x80) {
1868            *dst = s->cirrus_shadow_gr1;
1869        } else if (mode == 5) {
1870            *dst = s->cirrus_shadow_gr0;
1871        }
1872        val <<= 1;
1873        dst++;
1874    }
1875    cpu_physical_memory_set_dirty(s->vram_offset + offset);
1876    cpu_physical_memory_set_dirty(s->vram_offset + offset + 7);
1877}
1878
1879static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,
1880                                              unsigned mode,
1881                                              unsigned offset,
1882                                              uint32_t mem_value)
1883{
1884    int x;
1885    unsigned val = mem_value;
1886    uint8_t *dst;
1887
1888    dst = s->vram_ptr + offset;
1889    for (x = 0; x < 8; x++) {
1890        if (val & 0x80) {
1891            *dst = s->cirrus_shadow_gr1;
1892            *(dst + 1) = s->gr[0x11];
1893        } else if (mode == 5) {
1894            *dst = s->cirrus_shadow_gr0;
1895            *(dst + 1) = s->gr[0x10];
1896        }
1897        val <<= 1;
1898        dst += 2;
1899    }
1900    cpu_physical_memory_set_dirty(s->vram_offset + offset);
1901    cpu_physical_memory_set_dirty(s->vram_offset + offset + 15);
1902}
1903
1904/***************************************
1905 *
1906 *  memory access between 0xa0000-0xbffff
1907 *
1908 ***************************************/
1909
1910static uint32_t cirrus_vga_mem_readb(void *opaque, target_phys_addr_t addr)
1911{
1912    CirrusVGAState *s = opaque;
1913    unsigned bank_index;
1914    unsigned bank_offset;
1915    uint32_t val;
1916
1917    if ((s->sr[0x07] & 0x01) == 0) {
1918        return vga_mem_readb(s, addr);
1919    }
1920
1921    addr &= 0x1ffff;
1922
1923    if (addr < 0x10000) {
1924        /* XXX handle bitblt */
1925        /* video memory */
1926        bank_index = addr >> 15;
1927        bank_offset = addr & 0x7fff;
1928        if (bank_offset < s->cirrus_bank_limit[bank_index]) {
1929            bank_offset += s->cirrus_bank_base[bank_index];
1930            if ((s->gr[0x0B] & 0x14) == 0x14) {
1931                bank_offset <<= 4;
1932            } else if (s->gr[0x0B] & 0x02) {
1933                bank_offset <<= 3;
1934            }
1935            bank_offset &= s->cirrus_addr_mask;
1936            val = *(s->vram_ptr + bank_offset);
1937        } else
1938            val = 0xff;
1939    } else if (addr >= 0x18000 && addr < 0x18100) {
1940        /* memory-mapped I/O */
1941        val = 0xff;
1942        if ((s->sr[0x17] & 0x44) == 0x04) {
1943            val = cirrus_mmio_blt_read(s, addr & 0xff);
1944        }
1945    } else {
1946        val = 0xff;
1947#ifdef DEBUG_CIRRUS
1948        printf("cirrus: mem_readb %06x\n", addr);
1949#endif
1950    }
1951    return val;
1952}
1953
1954static uint32_t cirrus_vga_mem_readw(void *opaque, target_phys_addr_t addr)
1955{
1956    uint32_t v;
1957#ifdef TARGET_WORDS_BIGENDIAN
1958    v = cirrus_vga_mem_readb(opaque, addr) << 8;
1959    v |= cirrus_vga_mem_readb(opaque, addr + 1);
1960#else
1961    v = cirrus_vga_mem_readb(opaque, addr);
1962    v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
1963#endif
1964    return v;
1965}
1966
1967static uint32_t cirrus_vga_mem_readl(void *opaque, target_phys_addr_t addr)
1968{
1969    uint32_t v;
1970#ifdef TARGET_WORDS_BIGENDIAN
1971    v = cirrus_vga_mem_readb(opaque, addr) << 24;
1972    v |= cirrus_vga_mem_readb(opaque, addr + 1) << 16;
1973    v |= cirrus_vga_mem_readb(opaque, addr + 2) << 8;
1974    v |= cirrus_vga_mem_readb(opaque, addr + 3);
1975#else
1976    v = cirrus_vga_mem_readb(opaque, addr);
1977    v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
1978    v |= cirrus_vga_mem_readb(opaque, addr + 2) << 16;
1979    v |= cirrus_vga_mem_readb(opaque, addr + 3) << 24;
1980#endif
1981    return v;
1982}
1983
1984static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr, 
1985                                  uint32_t mem_value)
1986{
1987    CirrusVGAState *s = opaque;
1988    unsigned bank_index;
1989    unsigned bank_offset;
1990    unsigned mode;
1991
1992    if ((s->sr[0x07] & 0x01) == 0) {
1993        vga_mem_writeb(s, addr, mem_value);
1994        return;
1995    }
1996
1997    addr &= 0x1ffff;
1998
1999    if (addr < 0x10000) {
2000        if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
2001            /* bitblt */
2002            *s->cirrus_srcptr++ = (uint8_t) mem_value;
2003            if (s->cirrus_srcptr >= s->cirrus_srcptr_end) {
2004                cirrus_bitblt_cputovideo_next(s);
2005            }
2006        } else {
2007            /* video memory */
2008            bank_index = addr >> 15;
2009            bank_offset = addr & 0x7fff;
2010            if (bank_offset < s->cirrus_bank_limit[bank_index]) {
2011                bank_offset += s->cirrus_bank_base[bank_index];
2012                if ((s->gr[0x0B] & 0x14) == 0x14) {
2013                    bank_offset <<= 4;
2014                } else if (s->gr[0x0B] & 0x02) {
2015                    bank_offset <<= 3;
2016                }
2017                bank_offset &= s->cirrus_addr_mask;
2018                mode = s->gr[0x05] & 0x7;
2019                if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
2020                    *(s->vram_ptr + bank_offset) = mem_value;
2021                    cpu_physical_memory_set_dirty(s->vram_offset +
2022                                                  bank_offset);
2023                } else {
2024                    if ((s->gr[0x0B] & 0x14) != 0x14) {
2025                        cirrus_mem_writeb_mode4and5_8bpp(s, mode,
2026                                                         bank_offset,
2027                                                         mem_value);
2028                    } else {
2029                        cirrus_mem_writeb_mode4and5_16bpp(s, mode,
2030                                                          bank_offset,
2031                                                          mem_value);
2032                    }
2033                }
2034            }
2035        }
2036    } else if (addr >= 0x18000 && addr < 0x18100) {
2037        /* memory-mapped I/O */
2038        if ((s->sr[0x17] & 0x44) == 0x04) {
2039            cirrus_mmio_blt_write(s, addr & 0xff, mem_value);
2040        }
2041    } else {
2042#ifdef DEBUG_CIRRUS
2043        printf("cirrus: mem_writeb %06x value %02x\n", addr, mem_value);
2044#endif
2045    }
2046}
2047
2048static void cirrus_vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
2049{
2050#ifdef TARGET_WORDS_BIGENDIAN
2051    cirrus_vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
2052    cirrus_vga_mem_writeb(opaque, addr + 1, val & 0xff);
2053#else
2054    cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
2055    cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2056#endif
2057}
2058
2059static void cirrus_vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
2060{
2061#ifdef TARGET_WORDS_BIGENDIAN
2062    cirrus_vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
2063    cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
2064    cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
2065    cirrus_vga_mem_writeb(opaque, addr + 3, val & 0xff);
2066#else
2067    cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
2068    cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2069    cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
2070    cirrus_vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
2071#endif
2072}
2073
2074static CPUReadMemoryFunc *cirrus_vga_mem_read[3] = {
2075    cirrus_vga_mem_readb,
2076    cirrus_vga_mem_readw,
2077    cirrus_vga_mem_readl,
2078};
2079
2080static CPUWriteMemoryFunc *cirrus_vga_mem_write[3] = {
2081    cirrus_vga_mem_writeb,
2082    cirrus_vga_mem_writew,
2083    cirrus_vga_mem_writel,
2084};
2085
2086/***************************************
2087 *
2088 *  hardware cursor
2089 *
2090 ***************************************/
2091
2092static inline void invalidate_cursor1(CirrusVGAState *s)
2093{
2094    if (s->last_hw_cursor_size) {
2095        vga_invalidate_scanlines((VGAState *)s, 
2096                                 s->last_hw_cursor_y + s->last_hw_cursor_y_start,
2097                                 s->last_hw_cursor_y + s->last_hw_cursor_y_end);
2098    }
2099}
2100
2101static inline void cirrus_cursor_compute_yrange(CirrusVGAState *s)
2102{
2103    const uint8_t *src;
2104    uint32_t content;
2105    int y, y_min, y_max;
2106
2107    src = s->vram_ptr + s->real_vram_size - 16 * 1024;
2108    if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) {
2109        src += (s->sr[0x13] & 0x3c) * 256;
2110        y_min = 64;
2111        y_max = -1;
2112        for(y = 0; y < 64; y++) {
2113            content = ((uint32_t *)src)[0] |
2114                ((uint32_t *)src)[1] |
2115                ((uint32_t *)src)[2] |
2116                ((uint32_t *)src)[3];
2117            if (content) {
2118                if (y < y_min)
2119                    y_min = y;
2120                if (y > y_max)
2121                    y_max = y;
2122            }
2123            src += 16;
2124        }
2125    } else {
2126        src += (s->sr[0x13] & 0x3f) * 256;
2127        y_min = 32;
2128        y_max = -1;
2129        for(y = 0; y < 32; y++) {
2130            content = ((uint32_t *)src)[0] |
2131                ((uint32_t *)(src + 128))[0];
2132            if (content) {
2133                if (y < y_min)
2134                    y_min = y;
2135                if (y > y_max)
2136                    y_max = y;
2137            }
2138            src += 4;
2139        }
2140    }
2141    if (y_min > y_max) {
2142        s->last_hw_cursor_y_start = 0;
2143        s->last_hw_cursor_y_end = 0;
2144    } else {
2145        s->last_hw_cursor_y_start = y_min;
2146        s->last_hw_cursor_y_end = y_max + 1;
2147    }
2148}
2149
2150/* NOTE: we do not currently handle the cursor bitmap change, so we
2151   update the cursor only if it moves. */
2152static void cirrus_cursor_invalidate(VGAState *s1)
2153{
2154    CirrusVGAState *s = (CirrusVGAState *)s1;
2155    int size;
2156
2157    if (!s->sr[0x12] & CIRRUS_CURSOR_SHOW) {
2158        size = 0;
2159    } else {
2160        if (s->sr[0x12] & CIRRUS_CURSOR_LARGE)
2161            size = 64;
2162        else
2163            size = 32;
2164    }
2165    /* invalidate last cursor and new cursor if any change */
2166    if (s->last_hw_cursor_size != size ||
2167        s->last_hw_cursor_x != s->hw_cursor_x ||
2168        s->last_hw_cursor_y != s->hw_cursor_y) {
2169
2170        invalidate_cursor1(s);
2171       
2172        s->last_hw_cursor_size = size;
2173        s->last_hw_cursor_x = s->hw_cursor_x;
2174        s->last_hw_cursor_y = s->hw_cursor_y;
2175        /* compute the real cursor min and max y */
2176        cirrus_cursor_compute_yrange(s);
2177        invalidate_cursor1(s);
2178    }
2179}
2180
2181static void cirrus_cursor_draw_line(VGAState *s1, uint8_t *d1, int scr_y)
2182{
2183    CirrusVGAState *s = (CirrusVGAState *)s1;
2184    int w, h, bpp, x1, x2, poffset;
2185    unsigned int color0, color1;
2186    const uint8_t *palette, *src;
2187    uint32_t content;
2188   
2189    if (!(s->sr[0x12] & CIRRUS_CURSOR_SHOW)) 
2190        return;
2191    /* fast test to see if the cursor intersects with the scan line */
2192    if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) {
2193        h = 64;
2194    } else {
2195        h = 32;
2196    }
2197    if (scr_y < s->hw_cursor_y ||
2198        scr_y >= (s->hw_cursor_y + h))
2199        return;
2200   
2201    src = s->vram_ptr + s->real_vram_size - 16 * 1024;
2202    if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) {
2203        src += (s->sr[0x13] & 0x3c) * 256;
2204        src += (scr_y - s->hw_cursor_y) * 16;
2205        poffset = 8;
2206        content = ((uint32_t *)src)[0] |
2207            ((uint32_t *)src)[1] |
2208            ((uint32_t *)src)[2] |
2209            ((uint32_t *)src)[3];
2210    } else {
2211        src += (s->sr[0x13] & 0x3f) * 256;
2212        src += (scr_y - s->hw_cursor_y) * 4;
2213        poffset = 128;
2214        content = ((uint32_t *)src)[0] |
2215            ((uint32_t *)(src + 128))[0];
2216    }
2217    /* if nothing to draw, no need to continue */
2218    if (!content)
2219        return;
2220    w = h;
2221
2222    x1 = s->hw_cursor_x;
2223    if (x1 >= s->last_scr_width)
2224        return;
2225    x2 = s->hw_cursor_x + w;
2226    if (x2 > s->last_scr_width)
2227        x2 = s->last_scr_width;
2228    w = x2 - x1;
2229    palette = s->cirrus_hidden_palette;
2230    color0 = s->rgb_to_pixel(c6_to_8(palette[0x0 * 3]), 
2231                             c6_to_8(palette[0x0 * 3 + 1]), 
2232                             c6_to_8(palette[0x0 * 3 + 2]));
2233    color1 = s->rgb_to_pixel(c6_to_8(palette[0xf * 3]), 
2234                             c6_to_8(palette[0xf * 3 + 1]), 
2235                             c6_to_8(palette[0xf * 3 + 2]));
2236    bpp = ((s->ds->depth + 7) >> 3);
2237    d1 += x1 * bpp;
2238    switch(s->ds->depth) {
2239    default:
2240        break;
2241    case 8:
2242        vga_draw_cursor_line_8(d1, src, poffset, w, color0, color1, 0xff);
2243        break;
2244    case 15:
2245        vga_draw_cursor_line_16(d1, src, poffset, w, color0, color1, 0x7fff);
2246        break;
2247    case 16:
2248        vga_draw_cursor_line_16(d1, src, poffset, w, color0, color1, 0xffff);
2249        break;
2250    case 32:
2251        vga_draw_cursor_line_32(d1, src, poffset, w, color0, color1, 0xffffff);
2252        break;
2253    }
2254}
2255
2256/***************************************
2257 *
2258 *  LFB memory access
2259 *
2260 ***************************************/
2261
2262static uint32_t cirrus_linear_readb(void *opaque, target_phys_addr_t addr)
2263{
2264    CirrusVGAState *s = (CirrusVGAState *) opaque;
2265    uint32_t ret;
2266
2267    addr &= s->cirrus_addr_mask;
2268
2269    if (((s->sr[0x17] & 0x44) == 0x44) && 
2270        ((addr & s->linear_mmio_mask) == s->linear_mmio_mask)) {
2271        /* memory-mapped I/O */
2272        ret = cirrus_mmio_blt_read(s, addr & 0xff);
2273    } else if (0) {
2274        /* XXX handle bitblt */
2275        ret = 0xff;
2276    } else {
2277        /* video memory */
2278        if ((s->gr[0x0B] & 0x14) == 0x14) {
2279            addr <<= 4;
2280        } else if (s->gr[0x0B] & 0x02) {
2281            addr <<= 3;
2282        }
2283        addr &= s->cirrus_addr_mask;
2284        ret = *(s->vram_ptr + addr);
2285    }
2286
2287    return ret;
2288}
2289
2290static uint32_t cirrus_linear_readw(void *opaque, target_phys_addr_t addr)
2291{
2292    uint32_t v;
2293#ifdef TARGET_WORDS_BIGENDIAN
2294    v = cirrus_linear_readb(opaque, addr) << 8;
2295    v |= cirrus_linear_readb(opaque, addr + 1);
2296#else
2297    v = cirrus_linear_readb(opaque, addr);
2298    v |= cirrus_linear_readb(opaque, addr + 1) << 8;
2299#endif
2300    return v;
2301}
2302
2303static uint32_t cirrus_linear_readl(void *opaque, target_phys_addr_t addr)
2304{
2305    uint32_t v;
2306#ifdef TARGET_WORDS_BIGENDIAN
2307    v = cirrus_linear_readb(opaque, addr) << 24;
2308    v |= cirrus_linear_readb(opaque, addr + 1) << 16;
2309    v |= cirrus_linear_readb(opaque, addr + 2) << 8;
2310    v |= cirrus_linear_readb(opaque, addr + 3);
2311#else
2312    v = cirrus_linear_readb(opaque, addr);
2313    v |= cirrus_linear_readb(opaque, addr + 1) << 8;
2314    v |= cirrus_linear_readb(opaque, addr + 2) << 16;
2315    v |= cirrus_linear_readb(opaque, addr + 3) << 24;
2316#endif
2317    return v;
2318}
2319
2320static void cirrus_linear_writeb(void *opaque, target_phys_addr_t addr,
2321                                 uint32_t val)
2322{
2323    CirrusVGAState *s = (CirrusVGAState *) opaque;
2324    unsigned mode;
2325
2326    addr &= s->cirrus_addr_mask;
2327       
2328    if (((s->sr[0x17] & 0x44) == 0x44) && 
2329        ((addr & s->linear_mmio_mask) ==  s->linear_mmio_mask)) {
2330        /* memory-mapped I/O */
2331        cirrus_mmio_blt_write(s, addr & 0xff, val);
2332    } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
2333        /* bitblt */
2334        *s->cirrus_srcptr++ = (uint8_t) val;
2335        if (s->cirrus_srcptr >= s->cirrus_srcptr_end) {
2336            cirrus_bitblt_cputovideo_next(s);
2337        }
2338    } else {
2339        /* video memory */
2340        if ((s->gr[0x0B] & 0x14) == 0x14) {
2341            addr <<= 4;
2342        } else if (s->gr[0x0B] & 0x02) {
2343            addr <<= 3;
2344        }
2345        addr &= s->cirrus_addr_mask;
2346
2347        mode = s->gr[0x05] & 0x7;
2348        if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
2349            *(s->vram_ptr + addr) = (uint8_t) val;
2350            cpu_physical_memory_set_dirty(s->vram_offset + addr);
2351        } else {
2352            if ((s->gr[0x0B] & 0x14) != 0x14) {
2353                cirrus_mem_writeb_mode4and5_8bpp(s, mode, addr, val);
2354            } else {
2355                cirrus_mem_writeb_mode4and5_16bpp(s, mode, addr, val);
2356            }
2357        }
2358    }
2359}
2360
2361static void cirrus_linear_writew(void *opaque, target_phys_addr_t addr,
2362                                 uint32_t val)
2363{
2364#ifdef TARGET_WORDS_BIGENDIAN
2365    cirrus_linear_writeb(opaque, addr, (val >> 8) & 0xff);
2366    cirrus_linear_writeb(opaque, addr + 1, val & 0xff);
2367#else
2368    cirrus_linear_writeb(opaque, addr, val & 0xff);
2369    cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2370#endif
2371}
2372
2373static void cirrus_linear_writel(void *opaque, target_phys_addr_t addr,
2374                                 uint32_t val)
2375{
2376#ifdef TARGET_WORDS_BIGENDIAN
2377    cirrus_linear_writeb(opaque, addr, (val >> 24) & 0xff);
2378    cirrus_linear_writeb(opaque, addr + 1, (val >> 16) & 0xff);
2379    cirrus_linear_writeb(opaque, addr + 2, (val >> 8) & 0xff);
2380    cirrus_linear_writeb(opaque, addr + 3, val & 0xff);
2381#else
2382    cirrus_linear_writeb(opaque, addr, val & 0xff);
2383    cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2384    cirrus_linear_writeb(opaque, addr + 2, (val >> 16) & 0xff);
2385    cirrus_linear_writeb(opaque, addr + 3, (val >> 24) & 0xff);
2386#endif
2387}
2388
2389
2390static CPUReadMemoryFunc *cirrus_linear_read[3] = {
2391    cirrus_linear_readb,
2392    cirrus_linear_readw,
2393    cirrus_linear_readl,
2394};
2395
2396static CPUWriteMemoryFunc *cirrus_linear_write[3] = {
2397    cirrus_linear_writeb,
2398    cirrus_linear_writew,
2399    cirrus_linear_writel,
2400};
2401
2402static void cirrus_linear_mem_writeb(void *opaque, target_phys_addr_t addr,
2403                                     uint32_t val)
2404{
2405    CirrusVGAState *s = (CirrusVGAState *) opaque;
2406
2407    addr &= s->cirrus_addr_mask;
2408    *(s->vram_ptr + addr) = val;
2409    cpu_physical_memory_set_dirty(s->vram_offset + addr);
2410}
2411
2412static void cirrus_linear_mem_writew(void *opaque, target_phys_addr_t addr,
2413                                     uint32_t val)
2414{
2415    CirrusVGAState *s = (CirrusVGAState *) opaque;
2416
2417    addr &= s->cirrus_addr_mask;
2418    cpu_to_le16w((uint16_t *)(s->vram_ptr + addr), val);
2419    cpu_physical_memory_set_dirty(s->vram_offset + addr);
2420}
2421
2422static void cirrus_linear_mem_writel(void *opaque, target_phys_addr_t addr,
2423                                     uint32_t val)
2424{
2425    CirrusVGAState *s = (CirrusVGAState *) opaque;
2426
2427    addr &= s->cirrus_addr_mask;
2428    cpu_to_le32w((uint32_t *)(s->vram_ptr + addr), val);
2429    cpu_physical_memory_set_dirty(s->vram_offset + addr);
2430}
2431
2432/***************************************
2433 *
2434 *  system to screen memory access
2435 *
2436 ***************************************/
2437
2438
2439static uint32_t cirrus_linear_bitblt_readb(void *opaque, target_phys_addr_t addr)
2440{
2441    uint32_t ret;
2442
2443    /* XXX handle bitblt */
2444    ret = 0xff;
2445    return ret;
2446}
2447
2448static uint32_t cirrus_linear_bitblt_readw(void *opaque, target_phys_addr_t addr)
2449{
2450    uint32_t v;
2451#ifdef TARGET_WORDS_BIGENDIAN
2452    v = cirrus_linear_bitblt_readb(opaque, addr) << 8;
2453    v |= cirrus_linear_bitblt_readb(opaque, addr + 1);
2454#else
2455    v = cirrus_linear_bitblt_readb(opaque, addr);
2456    v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8;
2457#endif
2458    return v;
2459}
2460
2461static uint32_t cirrus_linear_bitblt_readl(void *opaque, target_phys_addr_t addr)
2462{
2463    uint32_t v;
2464#ifdef TARGET_WORDS_BIGENDIAN
2465    v = cirrus_linear_bitblt_readb(opaque, addr) << 24;
2466    v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 16;
2467    v |= cirrus_linear_bitblt_readb(opaque, addr + 2) << 8;
2468    v |= cirrus_linear_bitblt_readb(opaque, addr + 3);
2469#else
2470    v = cirrus_linear_bitblt_readb(opaque, addr);
2471    v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8;
2472    v |= cirrus_linear_bitblt_readb(opaque, addr + 2) << 16;
2473    v |= cirrus_linear_bitblt_readb(opaque, addr + 3) << 24;
2474#endif
2475    return v;
2476}
2477
2478static void cirrus_linear_bitblt_writeb(void *opaque, target_phys_addr_t addr,
2479                                 uint32_t val)
2480{
2481    CirrusVGAState *s = (CirrusVGAState *) opaque;
2482
2483    if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
2484        /* bitblt */
2485        *s->cirrus_srcptr++ = (uint8_t) val;
2486        if (s->cirrus_srcptr >= s->cirrus_srcptr_end) {
2487            cirrus_bitblt_cputovideo_next(s);
2488        }
2489    }
2490}
2491
2492static void cirrus_linear_bitblt_writew(void *opaque, target_phys_addr_t addr,
2493                                 uint32_t val)
2494{
2495#ifdef TARGET_WORDS_BIGENDIAN
2496    cirrus_linear_bitblt_writeb(opaque, addr, (val >> 8) & 0xff);
2497    cirrus_linear_bitblt_writeb(opaque, addr + 1, val & 0xff);
2498#else
2499    cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff);
2500    cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2501#endif
2502}
2503
2504static void cirrus_linear_bitblt_writel(void *opaque, target_phys_addr_t addr,
2505                                 uint32_t val)
2506{
2507#ifdef TARGET_WORDS_BIGENDIAN
2508    cirrus_linear_bitblt_writeb(opaque, addr, (val >> 24) & 0xff);
2509    cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 16) & 0xff);
2510    cirrus_linear_bitblt_writeb(opaque, addr + 2, (val >> 8) & 0xff);
2511    cirrus_linear_bitblt_writeb(opaque, addr + 3, val & 0xff);
2512#else
2513    cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff);
2514    cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2515    cirrus_linear_bitblt_writeb(opaque, addr + 2, (val >> 16) & 0xff);
2516    cirrus_linear_bitblt_writeb(opaque, addr + 3, (val >> 24) & 0xff);
2517#endif
2518}
2519
2520
2521static CPUReadMemoryFunc *cirrus_linear_bitblt_read[3] = {
2522    cirrus_linear_bitblt_readb,
2523    cirrus_linear_bitblt_readw,
2524    cirrus_linear_bitblt_readl,
2525};
2526
2527static CPUWriteMemoryFunc *cirrus_linear_bitblt_write[3] = {
2528    cirrus_linear_bitblt_writeb,
2529    cirrus_linear_bitblt_writew,
2530    cirrus_linear_bitblt_writel,
2531};
2532
2533static void *set_vram_mapping(unsigned long begin, unsigned long end)
2534{
2535    xen_pfn_t *extent_start = NULL;
2536    unsigned long nr_extents;
2537    void *vram_pointer = NULL;
2538    int i;
2539
2540    /* align begin and end address */
2541    begin = begin & TARGET_PAGE_MASK;
2542    end = begin + VGA_RAM_SIZE;
2543    end = (end + TARGET_PAGE_SIZE -1 ) & TARGET_PAGE_MASK;
2544    nr_extents = (end - begin) >> TARGET_PAGE_BITS;
2545
2546    extent_start = malloc(sizeof(xen_pfn_t) * nr_extents);
2547    if (extent_start == NULL) {
2548        fprintf(stderr, "Failed malloc on set_vram_mapping\n");
2549        return NULL;
2550    }
2551
2552    memset(extent_start, 0, sizeof(xen_pfn_t) * nr_extents);
2553
2554    for (i = 0; i < nr_extents; i++)
2555        extent_start[i] = (begin + i * TARGET_PAGE_SIZE) >> TARGET_PAGE_BITS;
2556
2557    set_mm_mapping(xc_handle, domid, nr_extents, 0, extent_start);
2558
2559    vram_pointer = xc_map_foreign_batch(xc_handle, domid,
2560                                        PROT_READ|PROT_WRITE,
2561                                        extent_start, nr_extents);
2562    if (vram_pointer == NULL) {
2563        fprintf(logfile, "xc_map_foreign_batch vgaram returned error %d\n",
2564                errno);
2565        return NULL;
2566    }
2567
2568    memset(vram_pointer, 0, nr_extents * TARGET_PAGE_SIZE);
2569
2570    free(extent_start);
2571
2572    return vram_pointer;
2573}
2574
2575static int unset_vram_mapping(unsigned long begin, unsigned long end, 
2576                              void *mapping)
2577{
2578    xen_pfn_t *extent_start = NULL;
2579    unsigned long nr_extents;
2580    int i;
2581
2582    /* align begin and end address */
2583
2584    end = begin + VGA_RAM_SIZE;
2585    begin = begin & TARGET_PAGE_MASK;
2586    end = (end + TARGET_PAGE_SIZE -1 ) & TARGET_PAGE_MASK;
2587    nr_extents = (end - begin) >> TARGET_PAGE_BITS;
2588
2589    extent_start = malloc(sizeof(xen_pfn_t) * nr_extents);
2590
2591    if (extent_start == NULL) {
2592        fprintf(stderr, "Failed malloc on set_mm_mapping\n");
2593        return -1;
2594    }
2595
2596    /* Drop our own references to the vram pages */
2597    munmap(mapping, nr_extents * TARGET_PAGE_SIZE);
2598
2599    /* Now drop the guest's mappings */
2600    memset(extent_start, 0, sizeof(xen_pfn_t) * nr_extents);
2601    for (i = 0; i < nr_extents; i++)
2602        extent_start[i] = (begin + (i * TARGET_PAGE_SIZE)) >> TARGET_PAGE_BITS;
2603    unset_mm_mapping(xc_handle, domid, nr_extents, 0, extent_start);
2604
2605    free(extent_start);
2606
2607    return 0;
2608}
2609
2610/* Compute the memory access functions */
2611static void cirrus_update_memory_access(CirrusVGAState *s)
2612{
2613    unsigned mode;
2614
2615    if ((s->sr[0x17] & 0x44) == 0x44) {
2616        goto generic_io;
2617    } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
2618        goto generic_io;
2619    } else {
2620        if ((s->gr[0x0B] & 0x14) == 0x14) {
2621            goto generic_io;
2622        } else if (s->gr[0x0B] & 0x02) {
2623            goto generic_io;
2624        }
2625       
2626        mode = s->gr[0x05] & 0x7;
2627        if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
2628            if (s->cirrus_lfb_addr && s->cirrus_lfb_end && !s->map_addr) {
2629                void *vram_pointer, *old_vram;
2630
2631                vram_pointer = set_vram_mapping(s->cirrus_lfb_addr,
2632                                                s->cirrus_lfb_end);
2633                if (!vram_pointer)
2634                    fprintf(stderr, "NULL vram_pointer\n");
2635                else {
2636                    old_vram = vga_update_vram((VGAState *)s, vram_pointer,
2637                                               VGA_RAM_SIZE);
2638                    qemu_free(old_vram);
2639                }
2640                s->map_addr = s->cirrus_lfb_addr;
2641                s->map_end = s->cirrus_lfb_end;
2642            }
2643            s->cirrus_linear_write[0] = cirrus_linear_mem_writeb;
2644            s->cirrus_linear_write[1] = cirrus_linear_mem_writew;
2645            s->cirrus_linear_write[2] = cirrus_linear_mem_writel;
2646        } else {
2647        generic_io:
2648            if (s->cirrus_lfb_addr && s->cirrus_lfb_end && s->map_addr) {
2649                void *old_vram;
2650
2651                old_vram = vga_update_vram((VGAState *)s, NULL, VGA_RAM_SIZE);
2652
2653                unset_vram_mapping(s->cirrus_lfb_addr,
2654                                   s->cirrus_lfb_end, 
2655                                   old_vram);
2656
2657                s->map_addr = s->map_end = 0;
2658            }
2659            s->cirrus_linear_write[0] = cirrus_linear_writeb;
2660            s->cirrus_linear_write[1] = cirrus_linear_writew;
2661            s->cirrus_linear_write[2] = cirrus_linear_writel;
2662        }
2663    }
2664}
2665
2666
2667/* I/O ports */
2668
2669static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
2670{
2671    CirrusVGAState *s = opaque;
2672    int val, index;
2673
2674    /* check port range access depending on color/monochrome mode */
2675    if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION))
2676        || (addr >= 0x3d0 && addr <= 0x3df
2677            && !(s->msr & MSR_COLOR_EMULATION))) {
2678        val = 0xff;
2679    } else {
2680        switch (addr) {
2681        case 0x3c0:
2682            if (s->ar_flip_flop == 0) {
2683                val = s->ar_index;
2684            } else {
2685                val = 0;
2686            }
2687            break;
2688        case 0x3c1:
2689            index = s->ar_index & 0x1f;
2690            if (index < 21)
2691                val = s->ar[index];
2692            else
2693                val = 0;
2694            break;
2695        case 0x3c2:
2696            val = s->st00;
2697            break;
2698        case 0x3c4:
2699            val = s->sr_index;
2700            break;
2701        case 0x3c5:
2702            if (cirrus_hook_read_sr(s, s->sr_index, &val))
2703                break;
2704            val = s->sr[s->sr_index];
2705#ifdef DEBUG_VGA_REG
2706            printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
2707#endif
2708            break;
2709        case 0x3c6:
2710            cirrus_read_hidden_dac(s, &val);
2711            break;
2712        case 0x3c7:
2713            val = s->dac_state;
2714            break;
2715        case 0x3c8:
2716            val = s->dac_write_index;
2717            s->cirrus_hidden_dac_lockindex = 0;
2718            break;
2719        case 0x3c9:
2720            if (cirrus_hook_read_palette(s, &val))
2721                break;
2722            val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
2723            if (++s->dac_sub_index == 3) {
2724                s->dac_sub_index = 0;
2725                s->dac_read_index++;
2726            }
2727            break;
2728        case 0x3ca:
2729            val = s->fcr;
2730            break;
2731        case 0x3cc:
2732            val = s->msr;
2733            break;
2734        case 0x3ce:
2735            val = s->gr_index;
2736            break;
2737        case 0x3cf:
2738            if (cirrus_hook_read_gr(s, s->gr_index, &val))
2739                break;
2740            val = s->gr[s->gr_index];
2741#ifdef DEBUG_VGA_REG
2742            printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
2743#endif
2744            break;
2745        case 0x3b4:
2746        case 0x3d4:
2747            val = s->cr_index;
2748            break;
2749        case 0x3b5:
2750        case 0x3d5:
2751            if (cirrus_hook_read_cr(s, s->cr_index, &val))
2752                break;
2753            val = s->cr[s->cr_index];
2754#ifdef DEBUG_VGA_REG
2755            printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
2756#endif
2757            break;
2758        case 0x3ba:
2759        case 0x3da:
2760            /* just toggle to fool polling */
2761            s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;
2762            val = s->st01;
2763            s->ar_flip_flop = 0;
2764            break;
2765        default:
2766            val = 0x00;
2767            break;
2768        }
2769    }
2770#if defined(DEBUG_VGA)
2771    printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
2772#endif
2773    return val;
2774}
2775
2776static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
2777{
2778    CirrusVGAState *s = opaque;
2779    int index;
2780
2781    /* check port range access depending on color/monochrome mode */
2782    if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION))
2783        || (addr >= 0x3d0 && addr <= 0x3df
2784            && !(s->msr & MSR_COLOR_EMULATION)))
2785        return;
2786
2787#ifdef DEBUG_VGA
2788    printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
2789#endif
2790
2791    switch (addr) {
2792    case 0x3c0:
2793        if (s->ar_flip_flop == 0) {
2794            val &= 0x3f;
2795            s->ar_index = val;
2796        } else {
2797            index = s->ar_index & 0x1f;
2798            switch (index) {
2799            case 0x00 ... 0x0f:
2800                s->ar[index] = val & 0x3f;
2801                break;
2802            case 0x10:
2803                s->ar[index] = val & ~0x10;
2804                break;
2805            case 0x11:
2806                s->ar[index] = val;
2807                break;
2808            case 0x12:
2809                s->ar[index] = val & ~0xc0;
2810                break;
2811            case 0x13:
2812                s->ar[index] = val & ~0xf0;
2813                break;
2814            case 0x14:
2815                s->ar[index] = val & ~0xf0;
2816                break;
2817            default:
2818                break;
2819            }
2820        }
2821        s->ar_flip_flop ^= 1;
2822        break;
2823    case 0x3c2:
2824        s->msr = val & ~0x10;
2825        break;
2826    case 0x3c4:
2827        s->sr_index = val;
2828        break;
2829    case 0x3c5:
2830        if (cirrus_hook_write_sr(s, s->sr_index, val))
2831            break;
2832#ifdef DEBUG_VGA_REG
2833        printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
2834#endif
2835        s->sr[s->sr_index] = val & sr_mask[s->sr_index];
2836        break;
2837    case 0x3c6:
2838        cirrus_write_hidden_dac(s, val);
2839        break;
2840    case 0x3c7:
2841        s->dac_read_index = val;
2842        s->dac_sub_index = 0;
2843        s->dac_state = 3;
2844        break;
2845    case 0x3c8:
2846        s->dac_write_index = val;
2847        s->dac_sub_index = 0;
2848        s->dac_state = 0;
2849        break;
2850    case 0x3c9:
2851        if (cirrus_hook_write_palette(s, val))
2852            break;
2853        s->dac_cache[s->dac_sub_index] = val;
2854        if (++s->dac_sub_index == 3) {
2855            memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
2856            s->dac_sub_index = 0;
2857            s->dac_write_index++;
2858        }
2859        break;
2860    case 0x3ce:
2861        s->gr_index = val;
2862        break;
2863    case 0x3cf:
2864        if (cirrus_hook_write_gr(s, s->gr_index, val))
2865            break;
2866#ifdef DEBUG_VGA_REG
2867        printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
2868#endif
2869        s->gr[s->gr_index] = val & gr_mask[s->gr_index];
2870        break;
2871    case 0x3b4:
2872    case 0x3d4:
2873        s->cr_index = val;
2874        break;
2875    case 0x3b5:
2876    case 0x3d5:
2877        if (cirrus_hook_write_cr(s, s->cr_index, val))
2878            break;
2879#ifdef DEBUG_VGA_REG
2880        printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
2881#endif
2882        /* handle CR0-7 protection */
2883        if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {
2884            /* can always write bit 4 of CR7 */
2885            if (s->cr_index == 7)
2886                s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
2887            return;
2888        }
2889        switch (s->cr_index) {
2890        case 0x01:              /* horizontal display end */
2891        case 0x07:
2892        case 0x09:
2893        case 0x0c:
2894        case 0x0d:
2895        case 0x12:              /* veritcal display end */
2896            s->cr[s->cr_index] = val;
2897            break;
2898
2899        default:
2900            s->cr[s->cr_index] = val;
2901            break;
2902        }
2903        break;
2904    case 0x3ba:
2905    case 0x3da:
2906        s->fcr = val & 0x10;
2907        break;
2908    }
2909}
2910
2911/***************************************
2912 *
2913 *  memory-mapped I/O access
2914 *
2915 ***************************************/
2916
2917static uint32_t cirrus_mmio_readb(void *opaque, target_phys_addr_t addr)
2918{
2919    CirrusVGAState *s = (CirrusVGAState *) opaque;
2920
2921    addr &= CIRRUS_PNPMMIO_SIZE - 1;
2922
2923    if (addr >= 0x100) {
2924        return cirrus_mmio_blt_read(s, addr - 0x100);
2925    } else {
2926        return vga_ioport_read(s, addr + 0x3c0);
2927    }
2928}
2929
2930static uint32_t cirrus_mmio_readw(void *opaque, target_phys_addr_t addr)
2931{
2932    uint32_t v;
2933#ifdef TARGET_WORDS_BIGENDIAN
2934    v = cirrus_mmio_readb(opaque, addr) << 8;
2935    v |= cirrus_mmio_readb(opaque, addr + 1);
2936#else
2937    v = cirrus_mmio_readb(opaque, addr);
2938    v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
2939#endif
2940    return v;
2941}
2942
2943static uint32_t cirrus_mmio_readl(void *opaque, target_phys_addr_t addr)
2944{
2945    uint32_t v;
2946#ifdef TARGET_WORDS_BIGENDIAN
2947    v = cirrus_mmio_readb(opaque, addr) << 24;
2948    v |= cirrus_mmio_readb(opaque, addr + 1) << 16;
2949    v |= cirrus_mmio_readb(opaque, addr + 2) << 8;
2950    v |= cirrus_mmio_readb(opaque, addr + 3);
2951#else
2952    v = cirrus_mmio_readb(opaque, addr);
2953    v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
2954    v |= cirrus_mmio_readb(opaque, addr + 2) << 16;
2955    v |= cirrus_mmio_readb(opaque, addr + 3) << 24;
2956#endif
2957    return v;
2958}
2959
2960static void cirrus_mmio_writeb(void *opaque, target_phys_addr_t addr,
2961                               uint32_t val)
2962{
2963    CirrusVGAState *s = (CirrusVGAState *) opaque;
2964
2965    addr &= CIRRUS_PNPMMIO_SIZE - 1;
2966
2967    if (addr >= 0x100) {
2968        cirrus_mmio_blt_write(s, addr - 0x100, val);
2969    } else {
2970        vga_ioport_write(s, addr + 0x3c0, val);
2971    }
2972}
2973
2974static void cirrus_mmio_writew(void *opaque, target_phys_addr_t addr,
2975                               uint32_t val)
2976{
2977#ifdef TARGET_WORDS_BIGENDIAN
2978    cirrus_mmio_writeb(opaque, addr, (val >> 8) & 0xff);
2979    cirrus_mmio_writeb(opaque, addr + 1, val & 0xff);
2980#else
2981    cirrus_mmio_writeb(opaque, addr, val & 0xff);
2982    cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2983#endif
2984}
2985
2986static void cirrus_mmio_writel(void *opaque, target_phys_addr_t addr,
2987                               uint32_t val)
2988{
2989#ifdef TARGET_WORDS_BIGENDIAN
2990    cirrus_mmio_writeb(opaque, addr, (val >> 24) & 0xff);
2991    cirrus_mmio_writeb(opaque, addr + 1, (val >> 16) & 0xff);
2992    cirrus_mmio_writeb(opaque, addr + 2, (val >> 8) & 0xff);
2993    cirrus_mmio_writeb(opaque, addr + 3, val & 0xff);
2994#else
2995    cirrus_mmio_writeb(opaque, addr, val & 0xff);
2996    cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2997    cirrus_mmio_writeb(opaque, addr + 2, (val >> 16) & 0xff);
2998    cirrus_mmio_writeb(opaque, addr + 3, (val >> 24) & 0xff);
2999#endif
3000}
3001
3002
3003static CPUReadMemoryFunc *cirrus_mmio_read[3] = {
3004    cirrus_mmio_readb,
3005    cirrus_mmio_readw,
3006    cirrus_mmio_readl,
3007};
3008
3009static CPUWriteMemoryFunc *cirrus_mmio_write[3] = {
3010    cirrus_mmio_writeb,
3011    cirrus_mmio_writew,
3012    cirrus_mmio_writel,
3013};
3014
3015void cirrus_stop_acc(CirrusVGAState *s)
3016{
3017    if (s->map_addr){
3018        int error;
3019        s->map_addr = 0;
3020        error = unset_vram_mapping(s->cirrus_lfb_addr,
3021                s->cirrus_lfb_end, s->vram_ptr);
3022        fprintf(stderr, "cirrus_stop_acc:unset_vram_mapping.\n");
3023    }
3024}
3025
3026void cirrus_restart_acc(CirrusVGAState *s)
3027{
3028    if (s->cirrus_lfb_addr && s->cirrus_lfb_end) {
3029        void *vram_pointer, *old_vram;
3030        fprintf(stderr, "cirrus_vga_load:re-enable vga acc.lfb_addr=0x%lx, lfb_end=0x%lx.\n",
3031                s->cirrus_lfb_addr, s->cirrus_lfb_end);
3032        vram_pointer = set_vram_mapping(s->cirrus_lfb_addr ,s->cirrus_lfb_end);
3033        if (!vram_pointer){
3034            fprintf(stderr, "cirrus_vga_load:NULL vram_pointer\n");
3035        } else {
3036            old_vram = vga_update_vram((VGAState *)s, vram_pointer,
3037                    VGA_RAM_SIZE);
3038            qemu_free(old_vram);
3039            s->map_addr = s->cirrus_lfb_addr;
3040            s->map_end = s->cirrus_lfb_end;
3041        }
3042    }
3043}
3044
3045/* load/save state */
3046
3047static void cirrus_vga_save(QEMUFile *f, void *opaque)
3048{
3049    CirrusVGAState *s = opaque;
3050    uint8_t vga_acc;
3051
3052    qemu_put_be32s(f, &s->latch);
3053    qemu_put_8s(f, &s->sr_index);
3054    qemu_put_buffer(f, s->sr, 256);
3055    qemu_put_8s(f, &s->gr_index);
3056    qemu_put_8s(f, &s->cirrus_shadow_gr0);
3057    qemu_put_8s(f, &s->cirrus_shadow_gr1);
3058    qemu_put_buffer(f, s->gr + 2, 254);
3059    qemu_put_8s(f, &s->ar_index);
3060    qemu_put_buffer(f, s->ar, 21);
3061    qemu_put_be32s(f, &s->ar_flip_flop);
3062    qemu_put_8s(f, &s->cr_index);
3063    qemu_put_buffer(f, s->cr, 256);
3064    qemu_put_8s(f, &s->msr);
3065    qemu_put_8s(f, &s->fcr);
3066    qemu_put_8s(f, &s->st00);
3067    qemu_put_8s(f, &s->st01);
3068
3069    qemu_put_8s(f, &s->dac_state);
3070    qemu_put_8s(f, &s->dac_sub_index);
3071    qemu_put_8s(f, &s->dac_read_index);
3072    qemu_put_8s(f, &s->dac_write_index);
3073    qemu_put_buffer(f, s->dac_cache, 3);
3074    qemu_put_buffer(f, s->palette, 768);
3075
3076    qemu_put_be32s(f, &s->bank_offset);
3077
3078    qemu_put_8s(f, &s->cirrus_hidden_dac_lockindex);
3079    qemu_put_8s(f, &s->cirrus_hidden_dac_data);
3080
3081    qemu_put_be32s(f, &s->hw_cursor_x);
3082    qemu_put_be32s(f, &s->hw_cursor_y);
3083    /* XXX: we do not save the bitblt state - we assume we do not save
3084       the state when the blitter is active */
3085
3086    vga_acc = (!!s->map_addr);
3087    qemu_put_8s(f, &vga_acc);
3088    qemu_put_be64s(f, (uint64_t*)&s->cirrus_lfb_addr);
3089    qemu_put_be64s(f, (uint64_t*)&s->cirrus_lfb_end);
3090    qemu_put_buffer(f, s->vram_ptr, VGA_RAM_SIZE); 
3091    if (vga_acc)
3092        cirrus_stop_acc(s);
3093}
3094
3095static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id)
3096{
3097    CirrusVGAState *s = opaque;
3098    uint8_t vga_acc = 0;
3099
3100    if (version_id != 1)
3101        return -EINVAL;
3102
3103    qemu_get_be32s(f, &s->latch);
3104    qemu_get_8s(f, &s->sr_index);
3105    qemu_get_buffer(f, s->sr, 256);
3106    qemu_get_8s(f, &s->gr_index);
3107    qemu_get_8s(f, &s->cirrus_shadow_gr0);
3108    qemu_get_8s(f, &s->cirrus_shadow_gr1);
3109    s->gr[0x00] = s->cirrus_shadow_gr0 & 0x0f;
3110    s->gr[0x01] = s->cirrus_shadow_gr1 & 0x0f;
3111    qemu_get_buffer(f, s->gr + 2, 254);
3112    qemu_get_8s(f, &s->ar_index);
3113    qemu_get_buffer(f, s->ar, 21);
3114    qemu_get_be32s(f, &s->ar_flip_flop);
3115    qemu_get_8s(f, &s->cr_index);
3116    qemu_get_buffer(f, s->cr, 256);
3117    qemu_get_8s(f, &s->msr);
3118    qemu_get_8s(f, &s->fcr);
3119    qemu_get_8s(f, &s->st00);
3120    qemu_get_8s(f, &s->st01);
3121
3122    qemu_get_8s(f, &s->dac_state);
3123    qemu_get_8s(f, &s->dac_sub_index);
3124    qemu_get_8s(f, &s->dac_read_index);
3125    qemu_get_8s(f, &s->dac_write_index);
3126    qemu_get_buffer(f, s->dac_cache, 3);
3127    qemu_get_buffer(f, s->palette, 768);
3128
3129    qemu_get_be32s(f, &s->bank_offset);
3130
3131    qemu_get_8s(f, &s->cirrus_hidden_dac_lockindex);
3132    qemu_get_8s(f, &s->cirrus_hidden_dac_data);
3133
3134    qemu_get_be32s(f, &s->hw_cursor_x);
3135    qemu_get_be32s(f, &s->hw_cursor_y);
3136
3137    qemu_get_8s(f, &vga_acc);
3138    qemu_get_be64s(f, (uint64_t*)&s->cirrus_lfb_addr);
3139    qemu_get_be64s(f, (uint64_t*)&s->cirrus_lfb_end);
3140    qemu_get_buffer(f, s->vram_ptr, VGA_RAM_SIZE); 
3141    if (vga_acc){
3142        cirrus_restart_acc(s);
3143    }
3144
3145    /* force refresh */
3146    s->graphic_mode = -1;
3147    cirrus_update_bank_ptr(s, 0);
3148    cirrus_update_bank_ptr(s, 1);
3149    return 0;
3150}
3151
3152/***************************************
3153 *
3154 *  initialize
3155 *
3156 ***************************************/
3157
3158static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
3159{
3160    int vga_io_memory, i;
3161    static int inited;
3162
3163    if (!inited) {
3164        inited = 1;
3165        for(i = 0;i < 256; i++)
3166            rop_to_index[i] = CIRRUS_ROP_NOP_INDEX; /* nop rop */
3167        rop_to_index[CIRRUS_ROP_0] = 0;
3168        rop_to_index[CIRRUS_ROP_SRC_AND_DST] = 1;
3169        rop_to_index[CIRRUS_ROP_NOP] = 2;
3170        rop_to_index[CIRRUS_ROP_SRC_AND_NOTDST] = 3;
3171        rop_to_index[CIRRUS_ROP_NOTDST] = 4;
3172        rop_to_index[CIRRUS_ROP_SRC] = 5;
3173        rop_to_index[CIRRUS_ROP_1] = 6;
3174        rop_to_index[CIRRUS_ROP_NOTSRC_AND_DST] = 7;
3175        rop_to_index[CIRRUS_ROP_SRC_XOR_DST] = 8;
3176        rop_to_index[CIRRUS_ROP_SRC_OR_DST] = 9;
3177        rop_to_index[CIRRUS_ROP_NOTSRC_OR_NOTDST] = 10;
3178        rop_to_index[CIRRUS_ROP_SRC_NOTXOR_DST] = 11;
3179        rop_to_index[CIRRUS_ROP_SRC_OR_NOTDST] = 12;
3180        rop_to_index[CIRRUS_ROP_NOTSRC] = 13;
3181        rop_to_index[CIRRUS_ROP_NOTSRC_OR_DST] = 14;
3182        rop_to_index[CIRRUS_ROP_NOTSRC_AND_NOTDST] = 15;
3183    }
3184
3185    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
3186
3187    register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
3188    register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
3189    register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
3190    register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
3191
3192    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
3193
3194    register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
3195    register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
3196    register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
3197    register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
3198
3199    vga_io_memory = cpu_register_io_memory(0, cirrus_vga_mem_read, 
3200                                           cirrus_vga_mem_write, s);
3201    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000, 
3202                                 vga_io_memory);
3203
3204    s->sr[0x06] = 0x0f;
3205    if (device_id == CIRRUS_ID_CLGD5446) {
3206        /* 4MB 64 bit memory config, always PCI */
3207        s->sr[0x1F] = 0x2d;             // MemClock
3208        s->gr[0x18] = 0x0f;             // fastest memory configuration
3209#if 1
3210        s->sr[0x0f] = 0x98;
3211        s->sr[0x17] = 0x20;
3212        s->sr[0x15] = 0x04; /* memory size, 3=2MB, 4=4MB */
3213        s->real_vram_size = 4096 * 1024;
3214#else
3215        s->sr[0x0f] = 0x18;
3216        s->sr[0x17] = 0x20;
3217        s->sr[0x15] = 0x03; /* memory size, 3=2MB, 4=4MB */
3218        s->real_vram_size = 2048 * 1024;
3219#endif
3220    } else {
3221        s->sr[0x1F] = 0x22;             // MemClock
3222        s->sr[0x0F] = CIRRUS_MEMSIZE_2M;
3223        if (is_pci) 
3224            s->sr[0x17] = CIRRUS_BUSTYPE_PCI;
3225        else
3226            s->sr[0x17] = CIRRUS_BUSTYPE_ISA;
3227        s->real_vram_size = 2048 * 1024;
3228        s->sr[0x15] = 0x03; /* memory size, 3=2MB, 4=4MB */
3229    }
3230    s->cr[0x27] = device_id;
3231
3232    /* Win2K seems to assume that the pattern buffer is at 0xff
3233       initially ! */
3234    memset(s->vram_ptr, 0xff, s->real_vram_size);
3235
3236    s->cirrus_hidden_dac_lockindex = 5;
3237    s->cirrus_hidden_dac_data = 0;
3238
3239    /* I/O handler for LFB */
3240    s->cirrus_linear_io_addr =
3241        cpu_register_io_memory(0, cirrus_linear_read, cirrus_linear_write,
3242                               s);
3243    s->cirrus_linear_write = cpu_get_io_memory_write(s->cirrus_linear_io_addr);
3244
3245    /* I/O handler for LFB */
3246    s->cirrus_linear_bitblt_io_addr =
3247        cpu_register_io_memory(0, cirrus_linear_bitblt_read, cirrus_linear_bitblt_write,
3248                               s);
3249
3250    /* I/O handler for memory-mapped I/O */
3251    s->cirrus_mmio_io_addr =
3252        cpu_register_io_memory(0, cirrus_mmio_read, cirrus_mmio_write, s);
3253
3254    /* XXX: s->vram_size must be a power of two */
3255    s->cirrus_addr_mask = s->real_vram_size - 1;
3256    s->linear_mmio_mask = s->real_vram_size - 256;
3257
3258    s->get_bpp = cirrus_get_bpp;
3259    s->get_offsets = cirrus_get_offsets;
3260    s->get_resolution = cirrus_get_resolution;
3261    s->cursor_invalidate = cirrus_cursor_invalidate;
3262    s->cursor_draw_line = cirrus_cursor_draw_line;
3263
3264    register_savevm("cirrus_vga", 0, 1, cirrus_vga_save, cirrus_vga_load, s);
3265}
3266
3267/***************************************
3268 *
3269 *  ISA bus support
3270 *
3271 ***************************************/
3272
3273void isa_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base, 
3274                         unsigned long vga_ram_offset, int vga_ram_size)
3275{
3276    CirrusVGAState *s;
3277
3278    s = qemu_mallocz(sizeof(CirrusVGAState));
3279   
3280    vga_common_init((VGAState *)s, 
3281                    ds, vga_ram_base, vga_ram_offset, vga_ram_size);
3282    cirrus_init_common(s, CIRRUS_ID_CLGD5430, 0);
3283    /* XXX ISA-LFB support */
3284}
3285
3286/***************************************
3287 *
3288 *  PCI bus support
3289 *
3290 ***************************************/
3291
3292static void cirrus_pci_lfb_map(PCIDevice *d, int region_num,
3293                               uint32_t addr, uint32_t size, int type)
3294{
3295    CirrusVGAState *s = &((PCICirrusVGAState *)d)->cirrus_vga;
3296
3297    /* XXX: add byte swapping apertures */
3298    cpu_register_physical_memory(addr, s->vram_size,
3299                                 s->cirrus_linear_io_addr);
3300    s->cirrus_lfb_addr = addr;
3301    s->cirrus_lfb_end = addr + VGA_RAM_SIZE;
3302
3303    if (s->map_addr && (s->cirrus_lfb_addr != s->map_addr) &&
3304        (s->cirrus_lfb_end != s->map_end))
3305        fprintf(logfile, "cirrus vga map change while on lfb mode\n");
3306
3307    cpu_register_physical_memory(addr + 0x1000000, 0x400000,
3308                                 s->cirrus_linear_bitblt_io_addr);
3309}
3310
3311static void cirrus_pci_mmio_map(PCIDevice *d, int region_num,
3312                                uint32_t addr, uint32_t size, int type)
3313{
3314    CirrusVGAState *s = &((PCICirrusVGAState *)d)->cirrus_vga;
3315
3316    cpu_register_physical_memory(addr, CIRRUS_PNPMMIO_SIZE,
3317                                 s->cirrus_mmio_io_addr);
3318}
3319
3320void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, 
3321                         unsigned long vga_ram_offset, int vga_ram_size)
3322{
3323    PCICirrusVGAState *d;
3324    uint8_t *pci_conf;
3325    CirrusVGAState *s;
3326    int device_id;
3327   
3328    device_id = CIRRUS_ID_CLGD5446;
3329
3330    /* setup PCI configuration registers */
3331    d = (PCICirrusVGAState *)pci_register_device(bus, "Cirrus VGA", 
3332                                                 sizeof(PCICirrusVGAState), 
3333                                                 -1, NULL, NULL);
3334    pci_conf = d->dev.config;
3335    pci_conf[0x00] = (uint8_t) (PCI_VENDOR_CIRRUS & 0xff);
3336    pci_conf[0x01] = (uint8_t) (PCI_VENDOR_CIRRUS >> 8);
3337    pci_conf[0x02] = (uint8_t) (device_id & 0xff);
3338    pci_conf[0x03] = (uint8_t) (device_id >> 8);
3339    pci_conf[0x04] = PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS;
3340    pci_conf[0x0a] = PCI_CLASS_SUB_VGA;
3341    pci_conf[0x0b] = PCI_CLASS_BASE_DISPLAY;
3342    pci_conf[0x0e] = PCI_CLASS_HEADERTYPE_00h;
3343    pci_conf[0x2c] = 0x53; /* subsystem vendor: XenSource */
3344    pci_conf[0x2d] = 0x58;
3345    pci_conf[0x2e] = 0x01; /* subsystem device */
3346    pci_conf[0x2f] = 0x00;
3347
3348    /* setup VGA */
3349    s = &d->cirrus_vga;
3350    vga_common_init((VGAState *)s, 
3351                    ds, vga_ram_base, vga_ram_offset, vga_ram_size);
3352    cirrus_init_common(s, device_id, 1);
3353
3354    register_savevm("cirrus_vga_pci", 0, 1, generic_pci_save, generic_pci_load, d);
3355
3356    /* setup memory space */
3357    /* memory #0 LFB */
3358    /* memory #1 memory-mapped I/O */
3359    /* XXX: s->vram_size must be a power of two */
3360    pci_register_io_region((PCIDevice *)d, 0, 0x2000000,
3361                           PCI_ADDRESS_SPACE_MEM_PREFETCH, cirrus_pci_lfb_map);
3362    if (device_id == CIRRUS_ID_CLGD5446) {
3363        pci_register_io_region((PCIDevice *)d, 1, CIRRUS_PNPMMIO_SIZE,
3364                               PCI_ADDRESS_SPACE_MEM, cirrus_pci_mmio_map);
3365    }
3366    /* XXX: ROM BIOS */
3367}
Note: See TracBrowser for help on using the repository browser.