Statistics
| Branch: | Revision:

root / hw / cirrus_vga.c @ 7872c51c

History | View | Annotate | Download (99.8 kB)

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 "hw.h"
30
#include "pc.h"
31
#include "pci.h"
32
#include "console.h"
33
#include "vga_int.h"
34
#include "kvm.h"
35

    
36
/*
37
 * TODO:
38
 *    - destination write mask support not complete (bits 5..7)
39
 *    - optimize linear mappings
40
 *    - optimize bitblt functions
41
 */
42

    
43
//#define DEBUG_CIRRUS
44
//#define DEBUG_BITBLT
45

    
46
/***************************************
47
 *
48
 *  definitions
49
 *
50
 ***************************************/
51

    
52
#define qemu_MIN(a,b) ((a) < (b) ? (a) : (b))
53

    
54
// ID
55
#define CIRRUS_ID_CLGD5422  (0x23<<2)
56
#define CIRRUS_ID_CLGD5426  (0x24<<2)
57
#define CIRRUS_ID_CLGD5424  (0x25<<2)
58
#define CIRRUS_ID_CLGD5428  (0x26<<2)
59
#define CIRRUS_ID_CLGD5430  (0x28<<2)
60
#define CIRRUS_ID_CLGD5434  (0x2A<<2)
61
#define CIRRUS_ID_CLGD5436  (0x2B<<2)
62
#define CIRRUS_ID_CLGD5446  (0x2E<<2)
63

    
64
// sequencer 0x07
65
#define CIRRUS_SR7_BPP_VGA            0x00
66
#define CIRRUS_SR7_BPP_SVGA           0x01
67
#define CIRRUS_SR7_BPP_MASK           0x0e
68
#define CIRRUS_SR7_BPP_8              0x00
69
#define CIRRUS_SR7_BPP_16_DOUBLEVCLK  0x02
70
#define CIRRUS_SR7_BPP_24             0x04
71
#define CIRRUS_SR7_BPP_16             0x06
72
#define CIRRUS_SR7_BPP_32             0x08
73
#define CIRRUS_SR7_ISAADDR_MASK       0xe0
74

    
75
// sequencer 0x0f
76
#define CIRRUS_MEMSIZE_512k        0x08
77
#define CIRRUS_MEMSIZE_1M          0x10
78
#define CIRRUS_MEMSIZE_2M          0x18
79
#define CIRRUS_MEMFLAGS_BANKSWITCH 0x80        // bank switching is enabled.
80

    
81
// sequencer 0x12
82
#define CIRRUS_CURSOR_SHOW         0x01
83
#define CIRRUS_CURSOR_HIDDENPEL    0x02
84
#define CIRRUS_CURSOR_LARGE        0x04        // 64x64 if set, 32x32 if clear
85

    
86
// sequencer 0x17
87
#define CIRRUS_BUSTYPE_VLBFAST   0x10
88
#define CIRRUS_BUSTYPE_PCI       0x20
89
#define CIRRUS_BUSTYPE_VLBSLOW   0x30
90
#define CIRRUS_BUSTYPE_ISA       0x38
91
#define CIRRUS_MMIO_ENABLE       0x04
92
#define CIRRUS_MMIO_USE_PCIADDR  0x40        // 0xb8000 if cleared.
93
#define CIRRUS_MEMSIZEEXT_DOUBLE 0x80
94

    
95
// control 0x0b
96
#define CIRRUS_BANKING_DUAL             0x01
97
#define CIRRUS_BANKING_GRANULARITY_16K  0x20        // set:16k, clear:4k
98

    
99
// control 0x30
100
#define CIRRUS_BLTMODE_BACKWARDS        0x01
101
#define CIRRUS_BLTMODE_MEMSYSDEST       0x02
102
#define CIRRUS_BLTMODE_MEMSYSSRC        0x04
103
#define CIRRUS_BLTMODE_TRANSPARENTCOMP  0x08
104
#define CIRRUS_BLTMODE_PATTERNCOPY      0x40
105
#define CIRRUS_BLTMODE_COLOREXPAND      0x80
106
#define CIRRUS_BLTMODE_PIXELWIDTHMASK   0x30
107
#define CIRRUS_BLTMODE_PIXELWIDTH8      0x00
108
#define CIRRUS_BLTMODE_PIXELWIDTH16     0x10
109
#define CIRRUS_BLTMODE_PIXELWIDTH24     0x20
110
#define CIRRUS_BLTMODE_PIXELWIDTH32     0x30
111

    
112
// control 0x31
113
#define CIRRUS_BLT_BUSY                 0x01
114
#define CIRRUS_BLT_START                0x02
115
#define CIRRUS_BLT_RESET                0x04
116
#define CIRRUS_BLT_FIFOUSED             0x10
117
#define CIRRUS_BLT_AUTOSTART            0x80
118

    
119
// control 0x32
120
#define CIRRUS_ROP_0                    0x00
121
#define CIRRUS_ROP_SRC_AND_DST          0x05
122
#define CIRRUS_ROP_NOP                  0x06
123
#define CIRRUS_ROP_SRC_AND_NOTDST       0x09
124
#define CIRRUS_ROP_NOTDST               0x0b
125
#define CIRRUS_ROP_SRC                  0x0d
126
#define CIRRUS_ROP_1                    0x0e
127
#define CIRRUS_ROP_NOTSRC_AND_DST       0x50
128
#define CIRRUS_ROP_SRC_XOR_DST          0x59
129
#define CIRRUS_ROP_SRC_OR_DST           0x6d
130
#define CIRRUS_ROP_NOTSRC_OR_NOTDST     0x90
131
#define CIRRUS_ROP_SRC_NOTXOR_DST       0x95
132
#define CIRRUS_ROP_SRC_OR_NOTDST        0xad
133
#define CIRRUS_ROP_NOTSRC               0xd0
134
#define CIRRUS_ROP_NOTSRC_OR_DST        0xd6
135
#define CIRRUS_ROP_NOTSRC_AND_NOTDST    0xda
136

    
137
#define CIRRUS_ROP_NOP_INDEX 2
138
#define CIRRUS_ROP_SRC_INDEX 5
139

    
140
// control 0x33
141
#define CIRRUS_BLTMODEEXT_SOLIDFILL        0x04
142
#define CIRRUS_BLTMODEEXT_COLOREXPINV      0x02
143
#define CIRRUS_BLTMODEEXT_DWORDGRANULARITY 0x01
144

    
145
// memory-mapped IO
146
#define CIRRUS_MMIO_BLTBGCOLOR        0x00        // dword
147
#define CIRRUS_MMIO_BLTFGCOLOR        0x04        // dword
148
#define CIRRUS_MMIO_BLTWIDTH          0x08        // word
149
#define CIRRUS_MMIO_BLTHEIGHT         0x0a        // word
150
#define CIRRUS_MMIO_BLTDESTPITCH      0x0c        // word
151
#define CIRRUS_MMIO_BLTSRCPITCH       0x0e        // word
152
#define CIRRUS_MMIO_BLTDESTADDR       0x10        // dword
153
#define CIRRUS_MMIO_BLTSRCADDR        0x14        // dword
154
#define CIRRUS_MMIO_BLTWRITEMASK      0x17        // byte
155
#define CIRRUS_MMIO_BLTMODE           0x18        // byte
156
#define CIRRUS_MMIO_BLTROP            0x1a        // byte
157
#define CIRRUS_MMIO_BLTMODEEXT        0x1b        // byte
158
#define CIRRUS_MMIO_BLTTRANSPARENTCOLOR 0x1c        // word?
159
#define CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK 0x20        // word?
160
#define CIRRUS_MMIO_LINEARDRAW_START_X 0x24        // word
161
#define CIRRUS_MMIO_LINEARDRAW_START_Y 0x26        // word
162
#define CIRRUS_MMIO_LINEARDRAW_END_X  0x28        // word
163
#define CIRRUS_MMIO_LINEARDRAW_END_Y  0x2a        // word
164
#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_INC 0x2c        // byte
165
#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ROLLOVER 0x2d        // byte
166
#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_MASK 0x2e        // byte
167
#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ACCUM 0x2f        // byte
168
#define CIRRUS_MMIO_BRESENHAM_K1      0x30        // word
169
#define CIRRUS_MMIO_BRESENHAM_K3      0x32        // word
170
#define CIRRUS_MMIO_BRESENHAM_ERROR   0x34        // word
171
#define CIRRUS_MMIO_BRESENHAM_DELTA_MAJOR 0x36        // word
172
#define CIRRUS_MMIO_BRESENHAM_DIRECTION 0x38        // byte
173
#define CIRRUS_MMIO_LINEDRAW_MODE     0x39        // byte
174
#define CIRRUS_MMIO_BLTSTATUS         0x40        // byte
175

    
176
// PCI 0x00: vendor, 0x02: device
177
#define PCI_VENDOR_CIRRUS             0x1013
178
#define PCI_DEVICE_CLGD5462           0x00d0
179
#define PCI_DEVICE_CLGD5465           0x00d6
180

    
181
// PCI 0x04: command(word), 0x06(word): status
182
#define PCI_COMMAND_IOACCESS                0x0001
183
#define PCI_COMMAND_MEMACCESS               0x0002
184
#define PCI_COMMAND_BUSMASTER               0x0004
185
#define PCI_COMMAND_SPECIALCYCLE            0x0008
186
#define PCI_COMMAND_MEMWRITEINVALID         0x0010
187
#define PCI_COMMAND_PALETTESNOOPING         0x0020
188
#define PCI_COMMAND_PARITYDETECTION         0x0040
189
#define PCI_COMMAND_ADDRESSDATASTEPPING     0x0080
190
#define PCI_COMMAND_SERR                    0x0100
191
#define PCI_COMMAND_BACKTOBACKTRANS         0x0200
192
// PCI 0x08, 0xff000000 (0x09-0x0b:class,0x08:rev)
193
#define PCI_CLASS_BASE_DISPLAY        0x03
194
// PCI 0x08, 0x00ff0000
195
#define PCI_CLASS_SUB_VGA             0x00
196
// PCI 0x0c, 0x00ff0000 (0x0c:cacheline,0x0d:latency,0x0e:headertype,0x0f:Built-in self test)
197
#define PCI_CLASS_HEADERTYPE_00h  0x00
198
// 0x10-0x3f (headertype 00h)
199
// PCI 0x10,0x14,0x18,0x1c,0x20,0x24: base address mapping registers
200
//   0x10: MEMBASE, 0x14: IOBASE(hard-coded in XFree86 3.x)
201
#define PCI_MAP_MEM                 0x0
202
#define PCI_MAP_IO                  0x1
203
#define PCI_MAP_MEM_ADDR_MASK       (~0xf)
204
#define PCI_MAP_IO_ADDR_MASK        (~0x3)
205
#define PCI_MAP_MEMFLAGS_32BIT      0x0
206
#define PCI_MAP_MEMFLAGS_32BIT_1M   0x1
207
#define PCI_MAP_MEMFLAGS_64BIT      0x4
208
#define PCI_MAP_MEMFLAGS_CACHEABLE  0x8
209
// PCI 0x28: cardbus CIS pointer
210
// PCI 0x2c: subsystem vendor id, 0x2e: subsystem id
211
// PCI 0x30: expansion ROM base address
212
#define PCI_ROMBIOS_ENABLED         0x1
213
// PCI 0x34: 0xffffff00=reserved, 0x000000ff=capabilities pointer
214
// PCI 0x38: reserved
215
// PCI 0x3c: 0x3c=int-line, 0x3d=int-pin, 0x3e=min-gnt, 0x3f=maax-lat
216

    
217
#define CIRRUS_PNPMMIO_SIZE         0x1000
218

    
219

    
220
/* I/O and memory hook */
221
#define CIRRUS_HOOK_NOT_HANDLED 0
222
#define CIRRUS_HOOK_HANDLED 1
223

    
224
#define ABS(a) ((signed)(a) > 0 ? a : -a)
225

    
226
#define BLTUNSAFE(s) \
227
    ( \
228
        ( /* check dst is within bounds */ \
229
            (s)->cirrus_blt_height * ABS((s)->cirrus_blt_dstpitch) \
230
                + ((s)->cirrus_blt_dstaddr & (s)->cirrus_addr_mask) > \
231
                    (s)->vram_size \
232
        ) || \
233
        ( /* check src is within bounds */ \
234
            (s)->cirrus_blt_height * ABS((s)->cirrus_blt_srcpitch) \
235
                + ((s)->cirrus_blt_srcaddr & (s)->cirrus_addr_mask) > \
236
                    (s)->vram_size \
237
        ) \
238
    )
239

    
240
struct CirrusVGAState;
241
typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s,
242
                                     uint8_t * dst, const uint8_t * src,
243
                                     int dstpitch, int srcpitch,
244
                                     int bltwidth, int bltheight);
245
typedef void (*cirrus_fill_t)(struct CirrusVGAState *s,
246
                              uint8_t *dst, int dst_pitch, int width, int height);
247

    
248
typedef struct CirrusVGAState {
249
    VGA_STATE_COMMON
250

    
251
    int cirrus_linear_io_addr;
252
    int cirrus_linear_bitblt_io_addr;
253
    int cirrus_mmio_io_addr;
254
    uint32_t cirrus_addr_mask;
255
    uint32_t linear_mmio_mask;
256
    uint8_t cirrus_shadow_gr0;
257
    uint8_t cirrus_shadow_gr1;
258
    uint8_t cirrus_hidden_dac_lockindex;
259
    uint8_t cirrus_hidden_dac_data;
260
    uint32_t cirrus_bank_base[2];
261
    uint32_t cirrus_bank_limit[2];
262
    uint8_t cirrus_hidden_palette[48];
263
    uint32_t hw_cursor_x;
264
    uint32_t hw_cursor_y;
265
    int cirrus_blt_pixelwidth;
266
    int cirrus_blt_width;
267
    int cirrus_blt_height;
268
    int cirrus_blt_dstpitch;
269
    int cirrus_blt_srcpitch;
270
    uint32_t cirrus_blt_fgcol;
271
    uint32_t cirrus_blt_bgcol;
272
    uint32_t cirrus_blt_dstaddr;
273
    uint32_t cirrus_blt_srcaddr;
274
    uint8_t cirrus_blt_mode;
275
    uint8_t cirrus_blt_modeext;
276
    cirrus_bitblt_rop_t cirrus_rop;
277
#define CIRRUS_BLTBUFSIZE (2048 * 4) /* one line width */
278
    uint8_t cirrus_bltbuf[CIRRUS_BLTBUFSIZE];
279
    uint8_t *cirrus_srcptr;
280
    uint8_t *cirrus_srcptr_end;
281
    uint32_t cirrus_srccounter;
282
    /* hwcursor display state */
283
    int last_hw_cursor_size;
284
    int last_hw_cursor_x;
285
    int last_hw_cursor_y;
286
    int last_hw_cursor_y_start;
287
    int last_hw_cursor_y_end;
288
    int real_vram_size; /* XXX: suppress that */
289
    CPUWriteMemoryFunc **cirrus_linear_write;
290
} CirrusVGAState;
291

    
292
typedef struct PCICirrusVGAState {
293
    PCIDevice dev;
294
    CirrusVGAState cirrus_vga;
295
} PCICirrusVGAState;
296

    
297
static uint8_t rop_to_index[256];
298

    
299
/***************************************
300
 *
301
 *  prototypes.
302
 *
303
 ***************************************/
304

    
305

    
306
static void cirrus_bitblt_reset(CirrusVGAState *s);
307
static void cirrus_update_memory_access(CirrusVGAState *s);
308

    
309
/***************************************
310
 *
311
 *  raster operations
312
 *
313
 ***************************************/
314

    
315
static void cirrus_bitblt_rop_nop(CirrusVGAState *s,
316
                                  uint8_t *dst,const uint8_t *src,
317
                                  int dstpitch,int srcpitch,
318
                                  int bltwidth,int bltheight)
319
{
320
}
321

    
322
static void cirrus_bitblt_fill_nop(CirrusVGAState *s,
323
                                   uint8_t *dst,
324
                                   int dstpitch, int bltwidth,int bltheight)
325
{
326
}
327

    
328
#define ROP_NAME 0
329
#define ROP_OP(d, s) d = 0
330
#include "cirrus_vga_rop.h"
331

    
332
#define ROP_NAME src_and_dst
333
#define ROP_OP(d, s) d = (s) & (d)
334
#include "cirrus_vga_rop.h"
335

    
336
#define ROP_NAME src_and_notdst
337
#define ROP_OP(d, s) d = (s) & (~(d))
338
#include "cirrus_vga_rop.h"
339

    
340
#define ROP_NAME notdst
341
#define ROP_OP(d, s) d = ~(d)
342
#include "cirrus_vga_rop.h"
343

    
344
#define ROP_NAME src
345
#define ROP_OP(d, s) d = s
346
#include "cirrus_vga_rop.h"
347

    
348
#define ROP_NAME 1
349
#define ROP_OP(d, s) d = ~0
350
#include "cirrus_vga_rop.h"
351

    
352
#define ROP_NAME notsrc_and_dst
353
#define ROP_OP(d, s) d = (~(s)) & (d)
354
#include "cirrus_vga_rop.h"
355

    
356
#define ROP_NAME src_xor_dst
357
#define ROP_OP(d, s) d = (s) ^ (d)
358
#include "cirrus_vga_rop.h"
359

    
360
#define ROP_NAME src_or_dst
361
#define ROP_OP(d, s) d = (s) | (d)
362
#include "cirrus_vga_rop.h"
363

    
364
#define ROP_NAME notsrc_or_notdst
365
#define ROP_OP(d, s) d = (~(s)) | (~(d))
366
#include "cirrus_vga_rop.h"
367

    
368
#define ROP_NAME src_notxor_dst
369
#define ROP_OP(d, s) d = ~((s) ^ (d))
370
#include "cirrus_vga_rop.h"
371

    
372
#define ROP_NAME src_or_notdst
373
#define ROP_OP(d, s) d = (s) | (~(d))
374
#include "cirrus_vga_rop.h"
375

    
376
#define ROP_NAME notsrc
377
#define ROP_OP(d, s) d = (~(s))
378
#include "cirrus_vga_rop.h"
379

    
380
#define ROP_NAME notsrc_or_dst
381
#define ROP_OP(d, s) d = (~(s)) | (d)
382
#include "cirrus_vga_rop.h"
383

    
384
#define ROP_NAME notsrc_and_notdst
385
#define ROP_OP(d, s) d = (~(s)) & (~(d))
386
#include "cirrus_vga_rop.h"
387

    
388
static const cirrus_bitblt_rop_t cirrus_fwd_rop[16] = {
389
    cirrus_bitblt_rop_fwd_0,
390
    cirrus_bitblt_rop_fwd_src_and_dst,
391
    cirrus_bitblt_rop_nop,
392
    cirrus_bitblt_rop_fwd_src_and_notdst,
393
    cirrus_bitblt_rop_fwd_notdst,
394
    cirrus_bitblt_rop_fwd_src,
395
    cirrus_bitblt_rop_fwd_1,
396
    cirrus_bitblt_rop_fwd_notsrc_and_dst,
397
    cirrus_bitblt_rop_fwd_src_xor_dst,
398
    cirrus_bitblt_rop_fwd_src_or_dst,
399
    cirrus_bitblt_rop_fwd_notsrc_or_notdst,
400
    cirrus_bitblt_rop_fwd_src_notxor_dst,
401
    cirrus_bitblt_rop_fwd_src_or_notdst,
402
    cirrus_bitblt_rop_fwd_notsrc,
403
    cirrus_bitblt_rop_fwd_notsrc_or_dst,
404
    cirrus_bitblt_rop_fwd_notsrc_and_notdst,
405
};
406

    
407
static const cirrus_bitblt_rop_t cirrus_bkwd_rop[16] = {
408
    cirrus_bitblt_rop_bkwd_0,
409
    cirrus_bitblt_rop_bkwd_src_and_dst,
410
    cirrus_bitblt_rop_nop,
411
    cirrus_bitblt_rop_bkwd_src_and_notdst,
412
    cirrus_bitblt_rop_bkwd_notdst,
413
    cirrus_bitblt_rop_bkwd_src,
414
    cirrus_bitblt_rop_bkwd_1,
415
    cirrus_bitblt_rop_bkwd_notsrc_and_dst,
416
    cirrus_bitblt_rop_bkwd_src_xor_dst,
417
    cirrus_bitblt_rop_bkwd_src_or_dst,
418
    cirrus_bitblt_rop_bkwd_notsrc_or_notdst,
419
    cirrus_bitblt_rop_bkwd_src_notxor_dst,
420
    cirrus_bitblt_rop_bkwd_src_or_notdst,
421
    cirrus_bitblt_rop_bkwd_notsrc,
422
    cirrus_bitblt_rop_bkwd_notsrc_or_dst,
423
    cirrus_bitblt_rop_bkwd_notsrc_and_notdst,
424
};
425

    
426
#define TRANSP_ROP(name) {\
427
    name ## _8,\
428
    name ## _16,\
429
        }
430
#define TRANSP_NOP(func) {\
431
    func,\
432
    func,\
433
        }
434

    
435
static const cirrus_bitblt_rop_t cirrus_fwd_transp_rop[16][2] = {
436
    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_0),
437
    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_and_dst),
438
    TRANSP_NOP(cirrus_bitblt_rop_nop),
439
    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_and_notdst),
440
    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notdst),
441
    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src),
442
    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_1),
443
    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_and_dst),
444
    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_xor_dst),
445
    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_or_dst),
446
    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_or_notdst),
447
    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_notxor_dst),
448
    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_src_or_notdst),
449
    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc),
450
    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_or_dst),
451
    TRANSP_ROP(cirrus_bitblt_rop_fwd_transp_notsrc_and_notdst),
452
};
453

    
454
static const cirrus_bitblt_rop_t cirrus_bkwd_transp_rop[16][2] = {
455
    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_0),
456
    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_and_dst),
457
    TRANSP_NOP(cirrus_bitblt_rop_nop),
458
    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_and_notdst),
459
    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notdst),
460
    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src),
461
    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_1),
462
    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_and_dst),
463
    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_xor_dst),
464
    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_or_dst),
465
    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_or_notdst),
466
    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_notxor_dst),
467
    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_src_or_notdst),
468
    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc),
469
    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_or_dst),
470
    TRANSP_ROP(cirrus_bitblt_rop_bkwd_transp_notsrc_and_notdst),
471
};
472

    
473
#define ROP2(name) {\
474
    name ## _8,\
475
    name ## _16,\
476
    name ## _24,\
477
    name ## _32,\
478
        }
479

    
480
#define ROP_NOP2(func) {\
481
    func,\
482
    func,\
483
    func,\
484
    func,\
485
        }
486

    
487
static const cirrus_bitblt_rop_t cirrus_patternfill[16][4] = {
488
    ROP2(cirrus_patternfill_0),
489
    ROP2(cirrus_patternfill_src_and_dst),
490
    ROP_NOP2(cirrus_bitblt_rop_nop),
491
    ROP2(cirrus_patternfill_src_and_notdst),
492
    ROP2(cirrus_patternfill_notdst),
493
    ROP2(cirrus_patternfill_src),
494
    ROP2(cirrus_patternfill_1),
495
    ROP2(cirrus_patternfill_notsrc_and_dst),
496
    ROP2(cirrus_patternfill_src_xor_dst),
497
    ROP2(cirrus_patternfill_src_or_dst),
498
    ROP2(cirrus_patternfill_notsrc_or_notdst),
499
    ROP2(cirrus_patternfill_src_notxor_dst),
500
    ROP2(cirrus_patternfill_src_or_notdst),
501
    ROP2(cirrus_patternfill_notsrc),
502
    ROP2(cirrus_patternfill_notsrc_or_dst),
503
    ROP2(cirrus_patternfill_notsrc_and_notdst),
504
};
505

    
506
static const cirrus_bitblt_rop_t cirrus_colorexpand_transp[16][4] = {
507
    ROP2(cirrus_colorexpand_transp_0),
508
    ROP2(cirrus_colorexpand_transp_src_and_dst),
509
    ROP_NOP2(cirrus_bitblt_rop_nop),
510
    ROP2(cirrus_colorexpand_transp_src_and_notdst),
511
    ROP2(cirrus_colorexpand_transp_notdst),
512
    ROP2(cirrus_colorexpand_transp_src),
513
    ROP2(cirrus_colorexpand_transp_1),
514
    ROP2(cirrus_colorexpand_transp_notsrc_and_dst),
515
    ROP2(cirrus_colorexpand_transp_src_xor_dst),
516
    ROP2(cirrus_colorexpand_transp_src_or_dst),
517
    ROP2(cirrus_colorexpand_transp_notsrc_or_notdst),
518
    ROP2(cirrus_colorexpand_transp_src_notxor_dst),
519
    ROP2(cirrus_colorexpand_transp_src_or_notdst),
520
    ROP2(cirrus_colorexpand_transp_notsrc),
521
    ROP2(cirrus_colorexpand_transp_notsrc_or_dst),
522
    ROP2(cirrus_colorexpand_transp_notsrc_and_notdst),
523
};
524

    
525
static const cirrus_bitblt_rop_t cirrus_colorexpand[16][4] = {
526
    ROP2(cirrus_colorexpand_0),
527
    ROP2(cirrus_colorexpand_src_and_dst),
528
    ROP_NOP2(cirrus_bitblt_rop_nop),
529
    ROP2(cirrus_colorexpand_src_and_notdst),
530
    ROP2(cirrus_colorexpand_notdst),
531
    ROP2(cirrus_colorexpand_src),
532
    ROP2(cirrus_colorexpand_1),
533
    ROP2(cirrus_colorexpand_notsrc_and_dst),
534
    ROP2(cirrus_colorexpand_src_xor_dst),
535
    ROP2(cirrus_colorexpand_src_or_dst),
536
    ROP2(cirrus_colorexpand_notsrc_or_notdst),
537
    ROP2(cirrus_colorexpand_src_notxor_dst),
538
    ROP2(cirrus_colorexpand_src_or_notdst),
539
    ROP2(cirrus_colorexpand_notsrc),
540
    ROP2(cirrus_colorexpand_notsrc_or_dst),
541
    ROP2(cirrus_colorexpand_notsrc_and_notdst),
542
};
543

    
544
static const cirrus_bitblt_rop_t cirrus_colorexpand_pattern_transp[16][4] = {
545
    ROP2(cirrus_colorexpand_pattern_transp_0),
546
    ROP2(cirrus_colorexpand_pattern_transp_src_and_dst),
547
    ROP_NOP2(cirrus_bitblt_rop_nop),
548
    ROP2(cirrus_colorexpand_pattern_transp_src_and_notdst),
549
    ROP2(cirrus_colorexpand_pattern_transp_notdst),
550
    ROP2(cirrus_colorexpand_pattern_transp_src),
551
    ROP2(cirrus_colorexpand_pattern_transp_1),
552
    ROP2(cirrus_colorexpand_pattern_transp_notsrc_and_dst),
553
    ROP2(cirrus_colorexpand_pattern_transp_src_xor_dst),
554
    ROP2(cirrus_colorexpand_pattern_transp_src_or_dst),
555
    ROP2(cirrus_colorexpand_pattern_transp_notsrc_or_notdst),
556
    ROP2(cirrus_colorexpand_pattern_transp_src_notxor_dst),
557
    ROP2(cirrus_colorexpand_pattern_transp_src_or_notdst),
558
    ROP2(cirrus_colorexpand_pattern_transp_notsrc),
559
    ROP2(cirrus_colorexpand_pattern_transp_notsrc_or_dst),
560
    ROP2(cirrus_colorexpand_pattern_transp_notsrc_and_notdst),
561
};
562

    
563
static const cirrus_bitblt_rop_t cirrus_colorexpand_pattern[16][4] = {
564
    ROP2(cirrus_colorexpand_pattern_0),
565
    ROP2(cirrus_colorexpand_pattern_src_and_dst),
566
    ROP_NOP2(cirrus_bitblt_rop_nop),
567
    ROP2(cirrus_colorexpand_pattern_src_and_notdst),
568
    ROP2(cirrus_colorexpand_pattern_notdst),
569
    ROP2(cirrus_colorexpand_pattern_src),
570
    ROP2(cirrus_colorexpand_pattern_1),
571
    ROP2(cirrus_colorexpand_pattern_notsrc_and_dst),
572
    ROP2(cirrus_colorexpand_pattern_src_xor_dst),
573
    ROP2(cirrus_colorexpand_pattern_src_or_dst),
574
    ROP2(cirrus_colorexpand_pattern_notsrc_or_notdst),
575
    ROP2(cirrus_colorexpand_pattern_src_notxor_dst),
576
    ROP2(cirrus_colorexpand_pattern_src_or_notdst),
577
    ROP2(cirrus_colorexpand_pattern_notsrc),
578
    ROP2(cirrus_colorexpand_pattern_notsrc_or_dst),
579
    ROP2(cirrus_colorexpand_pattern_notsrc_and_notdst),
580
};
581

    
582
static const cirrus_fill_t cirrus_fill[16][4] = {
583
    ROP2(cirrus_fill_0),
584
    ROP2(cirrus_fill_src_and_dst),
585
    ROP_NOP2(cirrus_bitblt_fill_nop),
586
    ROP2(cirrus_fill_src_and_notdst),
587
    ROP2(cirrus_fill_notdst),
588
    ROP2(cirrus_fill_src),
589
    ROP2(cirrus_fill_1),
590
    ROP2(cirrus_fill_notsrc_and_dst),
591
    ROP2(cirrus_fill_src_xor_dst),
592
    ROP2(cirrus_fill_src_or_dst),
593
    ROP2(cirrus_fill_notsrc_or_notdst),
594
    ROP2(cirrus_fill_src_notxor_dst),
595
    ROP2(cirrus_fill_src_or_notdst),
596
    ROP2(cirrus_fill_notsrc),
597
    ROP2(cirrus_fill_notsrc_or_dst),
598
    ROP2(cirrus_fill_notsrc_and_notdst),
599
};
600

    
601
static inline void cirrus_bitblt_fgcol(CirrusVGAState *s)
602
{
603
    unsigned int color;
604
    switch (s->cirrus_blt_pixelwidth) {
605
    case 1:
606
        s->cirrus_blt_fgcol = s->cirrus_shadow_gr1;
607
        break;
608
    case 2:
609
        color = s->cirrus_shadow_gr1 | (s->gr[0x11] << 8);
610
        s->cirrus_blt_fgcol = le16_to_cpu(color);
611
        break;
612
    case 3:
613
        s->cirrus_blt_fgcol = s->cirrus_shadow_gr1 |
614
            (s->gr[0x11] << 8) | (s->gr[0x13] << 16);
615
        break;
616
    default:
617
    case 4:
618
        color = s->cirrus_shadow_gr1 | (s->gr[0x11] << 8) |
619
            (s->gr[0x13] << 16) | (s->gr[0x15] << 24);
620
        s->cirrus_blt_fgcol = le32_to_cpu(color);
621
        break;
622
    }
623
}
624

    
625
static inline void cirrus_bitblt_bgcol(CirrusVGAState *s)
626
{
627
    unsigned int color;
628
    switch (s->cirrus_blt_pixelwidth) {
629
    case 1:
630
        s->cirrus_blt_bgcol = s->cirrus_shadow_gr0;
631
        break;
632
    case 2:
633
        color = s->cirrus_shadow_gr0 | (s->gr[0x10] << 8);
634
        s->cirrus_blt_bgcol = le16_to_cpu(color);
635
        break;
636
    case 3:
637
        s->cirrus_blt_bgcol = s->cirrus_shadow_gr0 |
638
            (s->gr[0x10] << 8) | (s->gr[0x12] << 16);
639
        break;
640
    default:
641
    case 4:
642
        color = s->cirrus_shadow_gr0 | (s->gr[0x10] << 8) |
643
            (s->gr[0x12] << 16) | (s->gr[0x14] << 24);
644
        s->cirrus_blt_bgcol = le32_to_cpu(color);
645
        break;
646
    }
647
}
648

    
649
static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin,
650
                                     int off_pitch, int bytesperline,
651
                                     int lines)
652
{
653
    int y;
654
    int off_cur;
655
    int off_cur_end;
656

    
657
    for (y = 0; y < lines; y++) {
658
        off_cur = off_begin;
659
        off_cur_end = (off_cur + bytesperline) & s->cirrus_addr_mask;
660
        off_cur &= TARGET_PAGE_MASK;
661
        while (off_cur < off_cur_end) {
662
            cpu_physical_memory_set_dirty(s->vram_offset + off_cur);
663
            off_cur += TARGET_PAGE_SIZE;
664
        }
665
        off_begin += off_pitch;
666
    }
667
}
668

    
669
static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s,
670
                                            const uint8_t * src)
671
{
672
    uint8_t *dst;
673

    
674
    dst = s->vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask);
675

    
676
    if (BLTUNSAFE(s))
677
        return 0;
678

    
679
    (*s->cirrus_rop) (s, dst, src,
680
                      s->cirrus_blt_dstpitch, 0,
681
                      s->cirrus_blt_width, s->cirrus_blt_height);
682
    cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
683
                             s->cirrus_blt_dstpitch, s->cirrus_blt_width,
684
                             s->cirrus_blt_height);
685
    return 1;
686
}
687

    
688
/* fill */
689

    
690
static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop)
691
{
692
    cirrus_fill_t rop_func;
693

    
694
    if (BLTUNSAFE(s))
695
        return 0;
696
    rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
697
    rop_func(s, s->vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
698
             s->cirrus_blt_dstpitch,
699
             s->cirrus_blt_width, s->cirrus_blt_height);
700
    cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
701
                             s->cirrus_blt_dstpitch, s->cirrus_blt_width,
702
                             s->cirrus_blt_height);
703
    cirrus_bitblt_reset(s);
704
    return 1;
705
}
706

    
707
/***************************************
708
 *
709
 *  bitblt (video-to-video)
710
 *
711
 ***************************************/
712

    
713
static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
714
{
715
    return cirrus_bitblt_common_patterncopy(s,
716
                                            s->vram_ptr + ((s->cirrus_blt_srcaddr & ~7) &
717
                                            s->cirrus_addr_mask));
718
}
719

    
720
static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
721
{
722
    int sx, sy;
723
    int dx, dy;
724
    int width, height;
725
    int depth;
726
    int notify = 0;
727

    
728
    depth = s->get_bpp((VGAState *)s) / 8;
729
    s->get_resolution((VGAState *)s, &width, &height);
730

    
731
    /* extra x, y */
732
    sx = (src % (width * depth)) / depth;
733
    sy = (src / (width * depth));
734
    dx = (dst % (width *depth)) / depth;
735
    dy = (dst / (width * depth));
736

    
737
    /* normalize width */
738
    w /= depth;
739

    
740
    /* if we're doing a backward copy, we have to adjust
741
       our x/y to be the upper left corner (instead of the lower
742
       right corner) */
743
    if (s->cirrus_blt_dstpitch < 0) {
744
        sx -= (s->cirrus_blt_width / depth) - 1;
745
        dx -= (s->cirrus_blt_width / depth) - 1;
746
        sy -= s->cirrus_blt_height - 1;
747
        dy -= s->cirrus_blt_height - 1;
748
    }
749

    
750
    /* are we in the visible portion of memory? */
751
    if (sx >= 0 && sy >= 0 && dx >= 0 && dy >= 0 &&
752
        (sx + w) <= width && (sy + h) <= height &&
753
        (dx + w) <= width && (dy + h) <= height) {
754
        notify = 1;
755
    }
756

    
757
    /* make to sure only copy if it's a plain copy ROP */
758
    if (*s->cirrus_rop != cirrus_bitblt_rop_fwd_src &&
759
        *s->cirrus_rop != cirrus_bitblt_rop_bkwd_src)
760
        notify = 0;
761

    
762
    /* we have to flush all pending changes so that the copy
763
       is generated at the appropriate moment in time */
764
    if (notify)
765
        vga_hw_update();
766

    
767
    (*s->cirrus_rop) (s, s->vram_ptr +
768
                      (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
769
                      s->vram_ptr +
770
                      (s->cirrus_blt_srcaddr & s->cirrus_addr_mask),
771
                      s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
772
                      s->cirrus_blt_width, s->cirrus_blt_height);
773

    
774
    if (notify)
775
        qemu_console_copy(s->console,
776
                          sx, sy, dx, dy,
777
                          s->cirrus_blt_width / depth,
778
                          s->cirrus_blt_height);
779

    
780
    /* we don't have to notify the display that this portion has
781
       changed since qemu_console_copy implies this */
782

    
783
    if (!notify)
784
        cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
785
                                 s->cirrus_blt_dstpitch, s->cirrus_blt_width,
786
                                 s->cirrus_blt_height);
787
}
788

    
789
static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
790
{
791
    if (BLTUNSAFE(s))
792
        return 0;
793

    
794
    if (s->ds->dpy_copy) {
795
        cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->start_addr,
796
                       s->cirrus_blt_srcaddr - s->start_addr,
797
                       s->cirrus_blt_width, s->cirrus_blt_height);
798
    } else {
799
        (*s->cirrus_rop) (s, s->vram_ptr +
800
                (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
801
                          s->vram_ptr +
802
                (s->cirrus_blt_srcaddr & s->cirrus_addr_mask),
803
                          s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
804
                          s->cirrus_blt_width, s->cirrus_blt_height);
805

    
806
        cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
807
                                 s->cirrus_blt_dstpitch, s->cirrus_blt_width,
808
                                 s->cirrus_blt_height);
809
    }
810

    
811
    return 1;
812
}
813

    
814
/***************************************
815
 *
816
 *  bitblt (cpu-to-video)
817
 *
818
 ***************************************/
819

    
820
static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s)
821
{
822
    int copy_count;
823
    uint8_t *end_ptr;
824

    
825
    if (s->cirrus_srccounter > 0) {
826
        if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
827
            cirrus_bitblt_common_patterncopy(s, s->cirrus_bltbuf);
828
        the_end:
829
            s->cirrus_srccounter = 0;
830
            cirrus_bitblt_reset(s);
831
        } else {
832
            /* at least one scan line */
833
            do {
834
                (*s->cirrus_rop)(s, s->vram_ptr +
835
                                 (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
836
                                  s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1);
837
                cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0,
838
                                         s->cirrus_blt_width, 1);
839
                s->cirrus_blt_dstaddr += s->cirrus_blt_dstpitch;
840
                s->cirrus_srccounter -= s->cirrus_blt_srcpitch;
841
                if (s->cirrus_srccounter <= 0)
842
                    goto the_end;
843
                /* more bytes than needed can be transfered because of
844
                   word alignment, so we keep them for the next line */
845
                /* XXX: keep alignment to speed up transfer */
846
                end_ptr = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
847
                copy_count = s->cirrus_srcptr_end - end_ptr;
848
                memmove(s->cirrus_bltbuf, end_ptr, copy_count);
849
                s->cirrus_srcptr = s->cirrus_bltbuf + copy_count;
850
                s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
851
            } while (s->cirrus_srcptr >= s->cirrus_srcptr_end);
852
        }
853
    }
854
}
855

    
856
/***************************************
857
 *
858
 *  bitblt wrapper
859
 *
860
 ***************************************/
861

    
862
static void cirrus_bitblt_reset(CirrusVGAState * s)
863
{
864
    s->gr[0x31] &=
865
        ~(CIRRUS_BLT_START | CIRRUS_BLT_BUSY | CIRRUS_BLT_FIFOUSED);
866
    s->cirrus_srcptr = &s->cirrus_bltbuf[0];
867
    s->cirrus_srcptr_end = &s->cirrus_bltbuf[0];
868
    s->cirrus_srccounter = 0;
869
    cirrus_update_memory_access(s);
870
}
871

    
872
static int cirrus_bitblt_cputovideo(CirrusVGAState * s)
873
{
874
    int w;
875

    
876
    s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_MEMSYSSRC;
877
    s->cirrus_srcptr = &s->cirrus_bltbuf[0];
878
    s->cirrus_srcptr_end = &s->cirrus_bltbuf[0];
879

    
880
    if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
881
        if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
882
            s->cirrus_blt_srcpitch = 8;
883
        } else {
884
            /* XXX: check for 24 bpp */
885
            s->cirrus_blt_srcpitch = 8 * 8 * s->cirrus_blt_pixelwidth;
886
        }
887
        s->cirrus_srccounter = s->cirrus_blt_srcpitch;
888
    } else {
889
        if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
890
            w = s->cirrus_blt_width / s->cirrus_blt_pixelwidth;
891
            if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY)
892
                s->cirrus_blt_srcpitch = ((w + 31) >> 5);
893
            else
894
                s->cirrus_blt_srcpitch = ((w + 7) >> 3);
895
        } else {
896
            /* always align input size to 32 bits */
897
            s->cirrus_blt_srcpitch = (s->cirrus_blt_width + 3) & ~3;
898
        }
899
        s->cirrus_srccounter = s->cirrus_blt_srcpitch * s->cirrus_blt_height;
900
    }
901
    s->cirrus_srcptr = s->cirrus_bltbuf;
902
    s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
903
    cirrus_update_memory_access(s);
904
    return 1;
905
}
906

    
907
static int cirrus_bitblt_videotocpu(CirrusVGAState * s)
908
{
909
    /* XXX */
910
#ifdef DEBUG_BITBLT
911
    printf("cirrus: bitblt (video to cpu) is not implemented yet\n");
912
#endif
913
    return 0;
914
}
915

    
916
static int cirrus_bitblt_videotovideo(CirrusVGAState * s)
917
{
918
    int ret;
919

    
920
    if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
921
        ret = cirrus_bitblt_videotovideo_patterncopy(s);
922
    } else {
923
        ret = cirrus_bitblt_videotovideo_copy(s);
924
    }
925
    if (ret)
926
        cirrus_bitblt_reset(s);
927
    return ret;
928
}
929

    
930
static void cirrus_bitblt_start(CirrusVGAState * s)
931
{
932
    uint8_t blt_rop;
933

    
934
    s->gr[0x31] |= CIRRUS_BLT_BUSY;
935

    
936
    s->cirrus_blt_width = (s->gr[0x20] | (s->gr[0x21] << 8)) + 1;
937
    s->cirrus_blt_height = (s->gr[0x22] | (s->gr[0x23] << 8)) + 1;
938
    s->cirrus_blt_dstpitch = (s->gr[0x24] | (s->gr[0x25] << 8));
939
    s->cirrus_blt_srcpitch = (s->gr[0x26] | (s->gr[0x27] << 8));
940
    s->cirrus_blt_dstaddr =
941
        (s->gr[0x28] | (s->gr[0x29] << 8) | (s->gr[0x2a] << 16));
942
    s->cirrus_blt_srcaddr =
943
        (s->gr[0x2c] | (s->gr[0x2d] << 8) | (s->gr[0x2e] << 16));
944
    s->cirrus_blt_mode = s->gr[0x30];
945
    s->cirrus_blt_modeext = s->gr[0x33];
946
    blt_rop = s->gr[0x32];
947

    
948
#ifdef DEBUG_BITBLT
949
    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",
950
           blt_rop,
951
           s->cirrus_blt_mode,
952
           s->cirrus_blt_modeext,
953
           s->cirrus_blt_width,
954
           s->cirrus_blt_height,
955
           s->cirrus_blt_dstpitch,
956
           s->cirrus_blt_srcpitch,
957
           s->cirrus_blt_dstaddr,
958
           s->cirrus_blt_srcaddr,
959
           s->gr[0x2f]);
960
#endif
961

    
962
    switch (s->cirrus_blt_mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) {
963
    case CIRRUS_BLTMODE_PIXELWIDTH8:
964
        s->cirrus_blt_pixelwidth = 1;
965
        break;
966
    case CIRRUS_BLTMODE_PIXELWIDTH16:
967
        s->cirrus_blt_pixelwidth = 2;
968
        break;
969
    case CIRRUS_BLTMODE_PIXELWIDTH24:
970
        s->cirrus_blt_pixelwidth = 3;
971
        break;
972
    case CIRRUS_BLTMODE_PIXELWIDTH32:
973
        s->cirrus_blt_pixelwidth = 4;
974
        break;
975
    default:
976
#ifdef DEBUG_BITBLT
977
        printf("cirrus: bitblt - pixel width is unknown\n");
978
#endif
979
        goto bitblt_ignore;
980
    }
981
    s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_PIXELWIDTHMASK;
982

    
983
    if ((s->
984
         cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSSRC |
985
                            CIRRUS_BLTMODE_MEMSYSDEST))
986
        == (CIRRUS_BLTMODE_MEMSYSSRC | CIRRUS_BLTMODE_MEMSYSDEST)) {
987
#ifdef DEBUG_BITBLT
988
        printf("cirrus: bitblt - memory-to-memory copy is requested\n");
989
#endif
990
        goto bitblt_ignore;
991
    }
992

    
993
    if ((s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_SOLIDFILL) &&
994
        (s->cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSDEST |
995
                               CIRRUS_BLTMODE_TRANSPARENTCOMP |
996
                               CIRRUS_BLTMODE_PATTERNCOPY |
997
                               CIRRUS_BLTMODE_COLOREXPAND)) ==
998
         (CIRRUS_BLTMODE_PATTERNCOPY | CIRRUS_BLTMODE_COLOREXPAND)) {
999
        cirrus_bitblt_fgcol(s);
1000
        cirrus_bitblt_solidfill(s, blt_rop);
1001
    } else {
1002
        if ((s->cirrus_blt_mode & (CIRRUS_BLTMODE_COLOREXPAND |
1003
                                   CIRRUS_BLTMODE_PATTERNCOPY)) ==
1004
            CIRRUS_BLTMODE_COLOREXPAND) {
1005

    
1006
            if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) {
1007
                if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV)
1008
                    cirrus_bitblt_bgcol(s);
1009
                else
1010
                    cirrus_bitblt_fgcol(s);
1011
                s->cirrus_rop = cirrus_colorexpand_transp[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
1012
            } else {
1013
                cirrus_bitblt_fgcol(s);
1014
                cirrus_bitblt_bgcol(s);
1015
                s->cirrus_rop = cirrus_colorexpand[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
1016
            }
1017
        } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
1018
            if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
1019
                if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) {
1020
                    if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV)
1021
                        cirrus_bitblt_bgcol(s);
1022
                    else
1023
                        cirrus_bitblt_fgcol(s);
1024
                    s->cirrus_rop = cirrus_colorexpand_pattern_transp[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
1025
                } else {
1026
                    cirrus_bitblt_fgcol(s);
1027
                    cirrus_bitblt_bgcol(s);
1028
                    s->cirrus_rop = cirrus_colorexpand_pattern[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
1029
                }
1030
            } else {
1031
                s->cirrus_rop = cirrus_patternfill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
1032
            }
1033
        } else {
1034
            if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) {
1035
                if (s->cirrus_blt_pixelwidth > 2) {
1036
                    printf("src transparent without colorexpand must be 8bpp or 16bpp\n");
1037
                    goto bitblt_ignore;
1038
                }
1039
                if (s->cirrus_blt_mode & CIRRUS_BLTMODE_BACKWARDS) {
1040
                    s->cirrus_blt_dstpitch = -s->cirrus_blt_dstpitch;
1041
                    s->cirrus_blt_srcpitch = -s->cirrus_blt_srcpitch;
1042
                    s->cirrus_rop = cirrus_bkwd_transp_rop[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
1043
                } else {
1044
                    s->cirrus_rop = cirrus_fwd_transp_rop[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
1045
                }
1046
            } else {
1047
                if (s->cirrus_blt_mode & CIRRUS_BLTMODE_BACKWARDS) {
1048
                    s->cirrus_blt_dstpitch = -s->cirrus_blt_dstpitch;
1049
                    s->cirrus_blt_srcpitch = -s->cirrus_blt_srcpitch;
1050
                    s->cirrus_rop = cirrus_bkwd_rop[rop_to_index[blt_rop]];
1051
                } else {
1052
                    s->cirrus_rop = cirrus_fwd_rop[rop_to_index[blt_rop]];
1053
                }
1054
            }
1055
        }
1056
        // setup bitblt engine.
1057
        if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSSRC) {
1058
            if (!cirrus_bitblt_cputovideo(s))
1059
                goto bitblt_ignore;
1060
        } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST) {
1061
            if (!cirrus_bitblt_videotocpu(s))
1062
                goto bitblt_ignore;
1063
        } else {
1064
            if (!cirrus_bitblt_videotovideo(s))
1065
                goto bitblt_ignore;
1066
        }
1067
    }
1068
    return;
1069
  bitblt_ignore:;
1070
    cirrus_bitblt_reset(s);
1071
}
1072

    
1073
static void cirrus_write_bitblt(CirrusVGAState * s, unsigned reg_value)
1074
{
1075
    unsigned old_value;
1076

    
1077
    old_value = s->gr[0x31];
1078
    s->gr[0x31] = reg_value;
1079

    
1080
    if (((old_value & CIRRUS_BLT_RESET) != 0) &&
1081
        ((reg_value & CIRRUS_BLT_RESET) == 0)) {
1082
        cirrus_bitblt_reset(s);
1083
    } else if (((old_value & CIRRUS_BLT_START) == 0) &&
1084
               ((reg_value & CIRRUS_BLT_START) != 0)) {
1085
        cirrus_bitblt_start(s);
1086
    }
1087
}
1088

    
1089

    
1090
/***************************************
1091
 *
1092
 *  basic parameters
1093
 *
1094
 ***************************************/
1095

    
1096
static void cirrus_get_offsets(VGAState *s1,
1097
                               uint32_t *pline_offset,
1098
                               uint32_t *pstart_addr,
1099
                               uint32_t *pline_compare)
1100
{
1101
    CirrusVGAState * s = (CirrusVGAState *)s1;
1102
    uint32_t start_addr, line_offset, line_compare;
1103

    
1104
    line_offset = s->cr[0x13]
1105
        | ((s->cr[0x1b] & 0x10) << 4);
1106
    line_offset <<= 3;
1107
    *pline_offset = line_offset;
1108

    
1109
    start_addr = (s->cr[0x0c] << 8)
1110
        | s->cr[0x0d]
1111
        | ((s->cr[0x1b] & 0x01) << 16)
1112
        | ((s->cr[0x1b] & 0x0c) << 15)
1113
        | ((s->cr[0x1d] & 0x80) << 12);
1114
    *pstart_addr = start_addr;
1115

    
1116
    line_compare = s->cr[0x18] |
1117
        ((s->cr[0x07] & 0x10) << 4) |
1118
        ((s->cr[0x09] & 0x40) << 3);
1119
    *pline_compare = line_compare;
1120
}
1121

    
1122
static uint32_t cirrus_get_bpp16_depth(CirrusVGAState * s)
1123
{
1124
    uint32_t ret = 16;
1125

    
1126
    switch (s->cirrus_hidden_dac_data & 0xf) {
1127
    case 0:
1128
        ret = 15;
1129
        break;                        /* Sierra HiColor */
1130
    case 1:
1131
        ret = 16;
1132
        break;                        /* XGA HiColor */
1133
    default:
1134
#ifdef DEBUG_CIRRUS
1135
        printf("cirrus: invalid DAC value %x in 16bpp\n",
1136
               (s->cirrus_hidden_dac_data & 0xf));
1137
#endif
1138
        ret = 15;                /* XXX */
1139
        break;
1140
    }
1141
    return ret;
1142
}
1143

    
1144
static int cirrus_get_bpp(VGAState *s1)
1145
{
1146
    CirrusVGAState * s = (CirrusVGAState *)s1;
1147
    uint32_t ret = 8;
1148

    
1149
    if ((s->sr[0x07] & 0x01) != 0) {
1150
        /* Cirrus SVGA */
1151
        switch (s->sr[0x07] & CIRRUS_SR7_BPP_MASK) {
1152
        case CIRRUS_SR7_BPP_8:
1153
            ret = 8;
1154
            break;
1155
        case CIRRUS_SR7_BPP_16_DOUBLEVCLK:
1156
            ret = cirrus_get_bpp16_depth(s);
1157
            break;
1158
        case CIRRUS_SR7_BPP_24:
1159
            ret = 24;
1160
            break;
1161
        case CIRRUS_SR7_BPP_16:
1162
            ret = cirrus_get_bpp16_depth(s);
1163
            break;
1164
        case CIRRUS_SR7_BPP_32:
1165
            ret = 32;
1166
            break;
1167
        default:
1168
#ifdef DEBUG_CIRRUS
1169
            printf("cirrus: unknown bpp - sr7=%x\n", s->sr[0x7]);
1170
#endif
1171
            ret = 8;
1172
            break;
1173
        }
1174
    } else {
1175
        /* VGA */
1176
        ret = 0;
1177
    }
1178

    
1179
    return ret;
1180
}
1181

    
1182
static void cirrus_get_resolution(VGAState *s, int *pwidth, int *pheight)
1183
{
1184
    int width, height;
1185

    
1186
    width = (s->cr[0x01] + 1) * 8;
1187
    height = s->cr[0x12] |
1188
        ((s->cr[0x07] & 0x02) << 7) |
1189
        ((s->cr[0x07] & 0x40) << 3);
1190
    height = (height + 1);
1191
    /* interlace support */
1192
    if (s->cr[0x1a] & 0x01)
1193
        height = height * 2;
1194
    *pwidth = width;
1195
    *pheight = height;
1196
}
1197

    
1198
/***************************************
1199
 *
1200
 * bank memory
1201
 *
1202
 ***************************************/
1203

    
1204
static void cirrus_update_bank_ptr(CirrusVGAState * s, unsigned bank_index)
1205
{
1206
    unsigned offset;
1207
    unsigned limit;
1208

    
1209
    if ((s->gr[0x0b] & 0x01) != 0)        /* dual bank */
1210
        offset = s->gr[0x09 + bank_index];
1211
    else                        /* single bank */
1212
        offset = s->gr[0x09];
1213

    
1214
    if ((s->gr[0x0b] & 0x20) != 0)
1215
        offset <<= 14;
1216
    else
1217
        offset <<= 12;
1218

    
1219
    if (s->real_vram_size <= offset)
1220
        limit = 0;
1221
    else
1222
        limit = s->real_vram_size - offset;
1223

    
1224
    if (((s->gr[0x0b] & 0x01) == 0) && (bank_index != 0)) {
1225
        if (limit > 0x8000) {
1226
            offset += 0x8000;
1227
            limit -= 0x8000;
1228
        } else {
1229
            limit = 0;
1230
        }
1231
    }
1232

    
1233
    if (limit > 0) {
1234
        /* Thinking about changing bank base? First, drop the dirty bitmap information
1235
         * on the current location, otherwise we lose this pointer forever */
1236
        if (s->lfb_vram_mapped) {
1237
            target_phys_addr_t base_addr = isa_mem_base + 0xa0000 + bank_index * 0x8000;
1238
            cpu_physical_sync_dirty_bitmap(base_addr, base_addr + 0x8000);
1239
        }
1240
        s->cirrus_bank_base[bank_index] = offset;
1241
        s->cirrus_bank_limit[bank_index] = limit;
1242
    } else {
1243
        s->cirrus_bank_base[bank_index] = 0;
1244
        s->cirrus_bank_limit[bank_index] = 0;
1245
    }
1246
}
1247

    
1248
/***************************************
1249
 *
1250
 *  I/O access between 0x3c4-0x3c5
1251
 *
1252
 ***************************************/
1253

    
1254
static int
1255
cirrus_hook_read_sr(CirrusVGAState * s, unsigned reg_index, int *reg_value)
1256
{
1257
    switch (reg_index) {
1258
    case 0x00:                        // Standard VGA
1259
    case 0x01:                        // Standard VGA
1260
    case 0x02:                        // Standard VGA
1261
    case 0x03:                        // Standard VGA
1262
    case 0x04:                        // Standard VGA
1263
        return CIRRUS_HOOK_NOT_HANDLED;
1264
    case 0x06:                        // Unlock Cirrus extensions
1265
        *reg_value = s->sr[reg_index];
1266
        break;
1267
    case 0x10:
1268
    case 0x30:
1269
    case 0x50:
1270
    case 0x70:                        // Graphics Cursor X
1271
    case 0x90:
1272
    case 0xb0:
1273
    case 0xd0:
1274
    case 0xf0:                        // Graphics Cursor X
1275
        *reg_value = s->sr[0x10];
1276
        break;
1277
    case 0x11:
1278
    case 0x31:
1279
    case 0x51:
1280
    case 0x71:                        // Graphics Cursor Y
1281
    case 0x91:
1282
    case 0xb1:
1283
    case 0xd1:
1284
    case 0xf1:                        // Graphics Cursor Y
1285
        *reg_value = s->sr[0x11];
1286
        break;
1287
    case 0x05:                        // ???
1288
    case 0x07:                        // Extended Sequencer Mode
1289
    case 0x08:                        // EEPROM Control
1290
    case 0x09:                        // Scratch Register 0
1291
    case 0x0a:                        // Scratch Register 1
1292
    case 0x0b:                        // VCLK 0
1293
    case 0x0c:                        // VCLK 1
1294
    case 0x0d:                        // VCLK 2
1295
    case 0x0e:                        // VCLK 3
1296
    case 0x0f:                        // DRAM Control
1297
    case 0x12:                        // Graphics Cursor Attribute
1298
    case 0x13:                        // Graphics Cursor Pattern Address
1299
    case 0x14:                        // Scratch Register 2
1300
    case 0x15:                        // Scratch Register 3
1301
    case 0x16:                        // Performance Tuning Register
1302
    case 0x17:                        // Configuration Readback and Extended Control
1303
    case 0x18:                        // Signature Generator Control
1304
    case 0x19:                        // Signal Generator Result
1305
    case 0x1a:                        // Signal Generator Result
1306
    case 0x1b:                        // VCLK 0 Denominator & Post
1307
    case 0x1c:                        // VCLK 1 Denominator & Post
1308
    case 0x1d:                        // VCLK 2 Denominator & Post
1309
    case 0x1e:                        // VCLK 3 Denominator & Post
1310
    case 0x1f:                        // BIOS Write Enable and MCLK select
1311
#ifdef DEBUG_CIRRUS
1312
        printf("cirrus: handled inport sr_index %02x\n", reg_index);
1313
#endif
1314
        *reg_value = s->sr[reg_index];
1315
        break;
1316
    default:
1317
#ifdef DEBUG_CIRRUS
1318
        printf("cirrus: inport sr_index %02x\n", reg_index);
1319
#endif
1320
        *reg_value = 0xff;
1321
        break;
1322
    }
1323

    
1324
    return CIRRUS_HOOK_HANDLED;
1325
}
1326

    
1327
static int
1328
cirrus_hook_write_sr(CirrusVGAState * s, unsigned reg_index, int reg_value)
1329
{
1330
    switch (reg_index) {
1331
    case 0x00:                        // Standard VGA
1332
    case 0x01:                        // Standard VGA
1333
    case 0x02:                        // Standard VGA
1334
    case 0x03:                        // Standard VGA
1335
    case 0x04:                        // Standard VGA
1336
        return CIRRUS_HOOK_NOT_HANDLED;
1337
    case 0x06:                        // Unlock Cirrus extensions
1338
        reg_value &= 0x17;
1339
        if (reg_value == 0x12) {
1340
            s->sr[reg_index] = 0x12;
1341
        } else {
1342
            s->sr[reg_index] = 0x0f;
1343
        }
1344
        break;
1345
    case 0x10:
1346
    case 0x30:
1347
    case 0x50:
1348
    case 0x70:                        // Graphics Cursor X
1349
    case 0x90:
1350
    case 0xb0:
1351
    case 0xd0:
1352
    case 0xf0:                        // Graphics Cursor X
1353
        s->sr[0x10] = reg_value;
1354
        s->hw_cursor_x = (reg_value << 3) | (reg_index >> 5);
1355
        break;
1356
    case 0x11:
1357
    case 0x31:
1358
    case 0x51:
1359
    case 0x71:                        // Graphics Cursor Y
1360
    case 0x91:
1361
    case 0xb1:
1362
    case 0xd1:
1363
    case 0xf1:                        // Graphics Cursor Y
1364
        s->sr[0x11] = reg_value;
1365
        s->hw_cursor_y = (reg_value << 3) | (reg_index >> 5);
1366
        break;
1367
    case 0x07:                        // Extended Sequencer Mode
1368
    cirrus_update_memory_access(s);
1369
    case 0x08:                        // EEPROM Control
1370
    case 0x09:                        // Scratch Register 0
1371
    case 0x0a:                        // Scratch Register 1
1372
    case 0x0b:                        // VCLK 0
1373
    case 0x0c:                        // VCLK 1
1374
    case 0x0d:                        // VCLK 2
1375
    case 0x0e:                        // VCLK 3
1376
    case 0x0f:                        // DRAM Control
1377
    case 0x12:                        // Graphics Cursor Attribute
1378
    case 0x13:                        // Graphics Cursor Pattern Address
1379
    case 0x14:                        // Scratch Register 2
1380
    case 0x15:                        // Scratch Register 3
1381
    case 0x16:                        // Performance Tuning Register
1382
    case 0x18:                        // Signature Generator Control
1383
    case 0x19:                        // Signature Generator Result
1384
    case 0x1a:                        // Signature Generator Result
1385
    case 0x1b:                        // VCLK 0 Denominator & Post
1386
    case 0x1c:                        // VCLK 1 Denominator & Post
1387
    case 0x1d:                        // VCLK 2 Denominator & Post
1388
    case 0x1e:                        // VCLK 3 Denominator & Post
1389
    case 0x1f:                        // BIOS Write Enable and MCLK select
1390
        s->sr[reg_index] = reg_value;
1391
#ifdef DEBUG_CIRRUS
1392
        printf("cirrus: handled outport sr_index %02x, sr_value %02x\n",
1393
               reg_index, reg_value);
1394
#endif
1395
        break;
1396
    case 0x17:                        // Configuration Readback and Extended Control
1397
        s->sr[reg_index] = (s->sr[reg_index] & 0x38) | (reg_value & 0xc7);
1398
        cirrus_update_memory_access(s);
1399
        break;
1400
    default:
1401
#ifdef DEBUG_CIRRUS
1402
        printf("cirrus: outport sr_index %02x, sr_value %02x\n", reg_index,
1403
               reg_value);
1404
#endif
1405
        break;
1406
    }
1407

    
1408
    return CIRRUS_HOOK_HANDLED;
1409
}
1410

    
1411
/***************************************
1412
 *
1413
 *  I/O access at 0x3c6
1414
 *
1415
 ***************************************/
1416

    
1417
static void cirrus_read_hidden_dac(CirrusVGAState * s, int *reg_value)
1418
{
1419
    *reg_value = 0xff;
1420
    if (++s->cirrus_hidden_dac_lockindex == 5) {
1421
        *reg_value = s->cirrus_hidden_dac_data;
1422
        s->cirrus_hidden_dac_lockindex = 0;
1423
    }
1424
}
1425

    
1426
static void cirrus_write_hidden_dac(CirrusVGAState * s, int reg_value)
1427
{
1428
    if (s->cirrus_hidden_dac_lockindex == 4) {
1429
        s->cirrus_hidden_dac_data = reg_value;
1430
#if defined(DEBUG_CIRRUS)
1431
        printf("cirrus: outport hidden DAC, value %02x\n", reg_value);
1432
#endif
1433
    }
1434
    s->cirrus_hidden_dac_lockindex = 0;
1435
}
1436

    
1437
/***************************************
1438
 *
1439
 *  I/O access at 0x3c9
1440
 *
1441
 ***************************************/
1442

    
1443
static int cirrus_hook_read_palette(CirrusVGAState * s, int *reg_value)
1444
{
1445
    if (!(s->sr[0x12] & CIRRUS_CURSOR_HIDDENPEL))
1446
        return CIRRUS_HOOK_NOT_HANDLED;
1447
    *reg_value =
1448
        s->cirrus_hidden_palette[(s->dac_read_index & 0x0f) * 3 +
1449
                                 s->dac_sub_index];
1450
    if (++s->dac_sub_index == 3) {
1451
        s->dac_sub_index = 0;
1452
        s->dac_read_index++;
1453
    }
1454
    return CIRRUS_HOOK_HANDLED;
1455
}
1456

    
1457
static int cirrus_hook_write_palette(CirrusVGAState * s, int reg_value)
1458
{
1459
    if (!(s->sr[0x12] & CIRRUS_CURSOR_HIDDENPEL))
1460
        return CIRRUS_HOOK_NOT_HANDLED;
1461
    s->dac_cache[s->dac_sub_index] = reg_value;
1462
    if (++s->dac_sub_index == 3) {
1463
        memcpy(&s->cirrus_hidden_palette[(s->dac_write_index & 0x0f) * 3],
1464
               s->dac_cache, 3);
1465
        /* XXX update cursor */
1466
        s->dac_sub_index = 0;
1467
        s->dac_write_index++;
1468
    }
1469
    return CIRRUS_HOOK_HANDLED;
1470
}
1471

    
1472
/***************************************
1473
 *
1474
 *  I/O access between 0x3ce-0x3cf
1475
 *
1476
 ***************************************/
1477

    
1478
static int
1479
cirrus_hook_read_gr(CirrusVGAState * s, unsigned reg_index, int *reg_value)
1480
{
1481
    switch (reg_index) {
1482
    case 0x00: // Standard VGA, BGCOLOR 0x000000ff
1483
      *reg_value = s->cirrus_shadow_gr0;
1484
      return CIRRUS_HOOK_HANDLED;
1485
    case 0x01: // Standard VGA, FGCOLOR 0x000000ff
1486
      *reg_value = s->cirrus_shadow_gr1;
1487
      return CIRRUS_HOOK_HANDLED;
1488
    case 0x02:                        // Standard VGA
1489
    case 0x03:                        // Standard VGA
1490
    case 0x04:                        // Standard VGA
1491
    case 0x06:                        // Standard VGA
1492
    case 0x07:                        // Standard VGA
1493
    case 0x08:                        // Standard VGA
1494
        return CIRRUS_HOOK_NOT_HANDLED;
1495
    case 0x05:                        // Standard VGA, Cirrus extended mode
1496
    default:
1497
        break;
1498
    }
1499

    
1500
    if (reg_index < 0x3a) {
1501
        *reg_value = s->gr[reg_index];
1502
    } else {
1503
#ifdef DEBUG_CIRRUS
1504
        printf("cirrus: inport gr_index %02x\n", reg_index);
1505
#endif
1506
        *reg_value = 0xff;
1507
    }
1508

    
1509
    return CIRRUS_HOOK_HANDLED;
1510
}
1511

    
1512
static int
1513
cirrus_hook_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value)
1514
{
1515
#if defined(DEBUG_BITBLT) && 0
1516
    printf("gr%02x: %02x\n", reg_index, reg_value);
1517
#endif
1518
    switch (reg_index) {
1519
    case 0x00:                        // Standard VGA, BGCOLOR 0x000000ff
1520
        s->cirrus_shadow_gr0 = reg_value;
1521
        return CIRRUS_HOOK_NOT_HANDLED;
1522
    case 0x01:                        // Standard VGA, FGCOLOR 0x000000ff
1523
        s->cirrus_shadow_gr1 = reg_value;
1524
        return CIRRUS_HOOK_NOT_HANDLED;
1525
    case 0x02:                        // Standard VGA
1526
    case 0x03:                        // Standard VGA
1527
    case 0x04:                        // Standard VGA
1528
    case 0x06:                        // Standard VGA
1529
    case 0x07:                        // Standard VGA
1530
    case 0x08:                        // Standard VGA
1531
        return CIRRUS_HOOK_NOT_HANDLED;
1532
    case 0x05:                        // Standard VGA, Cirrus extended mode
1533
        s->gr[reg_index] = reg_value & 0x7f;
1534
        cirrus_update_memory_access(s);
1535
        break;
1536
    case 0x09:                        // bank offset #0
1537
    case 0x0A:                        // bank offset #1
1538
        s->gr[reg_index] = reg_value;
1539
        cirrus_update_bank_ptr(s, 0);
1540
        cirrus_update_bank_ptr(s, 1);
1541
        cirrus_update_memory_access(s);
1542
        break;
1543
    case 0x0B:
1544
        s->gr[reg_index] = reg_value;
1545
        cirrus_update_bank_ptr(s, 0);
1546
        cirrus_update_bank_ptr(s, 1);
1547
        cirrus_update_memory_access(s);
1548
        break;
1549
    case 0x10:                        // BGCOLOR 0x0000ff00
1550
    case 0x11:                        // FGCOLOR 0x0000ff00
1551
    case 0x12:                        // BGCOLOR 0x00ff0000
1552
    case 0x13:                        // FGCOLOR 0x00ff0000
1553
    case 0x14:                        // BGCOLOR 0xff000000
1554
    case 0x15:                        // FGCOLOR 0xff000000
1555
    case 0x20:                        // BLT WIDTH 0x0000ff
1556
    case 0x22:                        // BLT HEIGHT 0x0000ff
1557
    case 0x24:                        // BLT DEST PITCH 0x0000ff
1558
    case 0x26:                        // BLT SRC PITCH 0x0000ff
1559
    case 0x28:                        // BLT DEST ADDR 0x0000ff
1560
    case 0x29:                        // BLT DEST ADDR 0x00ff00
1561
    case 0x2c:                        // BLT SRC ADDR 0x0000ff
1562
    case 0x2d:                        // BLT SRC ADDR 0x00ff00
1563
    case 0x2f:                  // BLT WRITEMASK
1564
    case 0x30:                        // BLT MODE
1565
    case 0x32:                        // RASTER OP
1566
    case 0x33:                        // BLT MODEEXT
1567
    case 0x34:                        // BLT TRANSPARENT COLOR 0x00ff
1568
    case 0x35:                        // BLT TRANSPARENT COLOR 0xff00
1569
    case 0x38:                        // BLT TRANSPARENT COLOR MASK 0x00ff
1570
    case 0x39:                        // BLT TRANSPARENT COLOR MASK 0xff00
1571
        s->gr[reg_index] = reg_value;
1572
        break;
1573
    case 0x21:                        // BLT WIDTH 0x001f00
1574
    case 0x23:                        // BLT HEIGHT 0x001f00
1575
    case 0x25:                        // BLT DEST PITCH 0x001f00
1576
    case 0x27:                        // BLT SRC PITCH 0x001f00
1577
        s->gr[reg_index] = reg_value & 0x1f;
1578
        break;
1579
    case 0x2a:                        // BLT DEST ADDR 0x3f0000
1580
        s->gr[reg_index] = reg_value & 0x3f;
1581
        /* if auto start mode, starts bit blt now */
1582
        if (s->gr[0x31] & CIRRUS_BLT_AUTOSTART) {
1583
            cirrus_bitblt_start(s);
1584
        }
1585
        break;
1586
    case 0x2e:                        // BLT SRC ADDR 0x3f0000
1587
        s->gr[reg_index] = reg_value & 0x3f;
1588
        break;
1589
    case 0x31:                        // BLT STATUS/START
1590
        cirrus_write_bitblt(s, reg_value);
1591
        break;
1592
    default:
1593
#ifdef DEBUG_CIRRUS
1594
        printf("cirrus: outport gr_index %02x, gr_value %02x\n", reg_index,
1595
               reg_value);
1596
#endif
1597
        break;
1598
    }
1599

    
1600
    return CIRRUS_HOOK_HANDLED;
1601
}
1602

    
1603
/***************************************
1604
 *
1605
 *  I/O access between 0x3d4-0x3d5
1606
 *
1607
 ***************************************/
1608

    
1609
static int
1610
cirrus_hook_read_cr(CirrusVGAState * s, unsigned reg_index, int *reg_value)
1611
{
1612
    switch (reg_index) {
1613
    case 0x00:                        // Standard VGA
1614
    case 0x01:                        // Standard VGA
1615
    case 0x02:                        // Standard VGA
1616
    case 0x03:                        // Standard VGA
1617
    case 0x04:                        // Standard VGA
1618
    case 0x05:                        // Standard VGA
1619
    case 0x06:                        // Standard VGA
1620
    case 0x07:                        // Standard VGA
1621
    case 0x08:                        // Standard VGA
1622
    case 0x09:                        // Standard VGA
1623
    case 0x0a:                        // Standard VGA
1624
    case 0x0b:                        // Standard VGA
1625
    case 0x0c:                        // Standard VGA
1626
    case 0x0d:                        // Standard VGA
1627
    case 0x0e:                        // Standard VGA
1628
    case 0x0f:                        // Standard VGA
1629
    case 0x10:                        // Standard VGA
1630
    case 0x11:                        // Standard VGA
1631
    case 0x12:                        // Standard VGA
1632
    case 0x13:                        // Standard VGA
1633
    case 0x14:                        // Standard VGA
1634
    case 0x15:                        // Standard VGA
1635
    case 0x16:                        // Standard VGA
1636
    case 0x17:                        // Standard VGA
1637
    case 0x18:                        // Standard VGA
1638
        return CIRRUS_HOOK_NOT_HANDLED;
1639
    case 0x24:                        // Attribute Controller Toggle Readback (R)
1640
        *reg_value = (s->ar_flip_flop << 7);
1641
        break;
1642
    case 0x19:                        // Interlace End
1643
    case 0x1a:                        // Miscellaneous Control
1644
    case 0x1b:                        // Extended Display Control
1645
    case 0x1c:                        // Sync Adjust and Genlock
1646
    case 0x1d:                        // Overlay Extended Control
1647
    case 0x22:                        // Graphics Data Latches Readback (R)
1648
    case 0x25:                        // Part Status
1649
    case 0x27:                        // Part ID (R)
1650
        *reg_value = s->cr[reg_index];
1651
        break;
1652
    case 0x26:                        // Attribute Controller Index Readback (R)
1653
        *reg_value = s->ar_index & 0x3f;
1654
        break;
1655
    default:
1656
#ifdef DEBUG_CIRRUS
1657
        printf("cirrus: inport cr_index %02x\n", reg_index);
1658
        *reg_value = 0xff;
1659
#endif
1660
        break;
1661
    }
1662

    
1663
    return CIRRUS_HOOK_HANDLED;
1664
}
1665

    
1666
static int
1667
cirrus_hook_write_cr(CirrusVGAState * s, unsigned reg_index, int reg_value)
1668
{
1669
    switch (reg_index) {
1670
    case 0x00:                        // Standard VGA
1671
    case 0x01:                        // Standard VGA
1672
    case 0x02:                        // Standard VGA
1673
    case 0x03:                        // Standard VGA
1674
    case 0x04:                        // Standard VGA
1675
    case 0x05:                        // Standard VGA
1676
    case 0x06:                        // Standard VGA
1677
    case 0x07:                        // Standard VGA
1678
    case 0x08:                        // Standard VGA
1679
    case 0x09:                        // Standard VGA
1680
    case 0x0a:                        // Standard VGA
1681
    case 0x0b:                        // Standard VGA
1682
    case 0x0c:                        // Standard VGA
1683
    case 0x0d:                        // Standard VGA
1684
    case 0x0e:                        // Standard VGA
1685
    case 0x0f:                        // Standard VGA
1686
    case 0x10:                        // Standard VGA
1687
    case 0x11:                        // Standard VGA
1688
    case 0x12:                        // Standard VGA
1689
    case 0x13:                        // Standard VGA
1690
    case 0x14:                        // Standard VGA
1691
    case 0x15:                        // Standard VGA
1692
    case 0x16:                        // Standard VGA
1693
    case 0x17:                        // Standard VGA
1694
    case 0x18:                        // Standard VGA
1695
        return CIRRUS_HOOK_NOT_HANDLED;
1696
    case 0x19:                        // Interlace End
1697
    case 0x1a:                        // Miscellaneous Control
1698
    case 0x1b:                        // Extended Display Control
1699
    case 0x1c:                        // Sync Adjust and Genlock
1700
    case 0x1d:                        // Overlay Extended Control
1701
        s->cr[reg_index] = reg_value;
1702
#ifdef DEBUG_CIRRUS
1703
        printf("cirrus: handled outport cr_index %02x, cr_value %02x\n",
1704
               reg_index, reg_value);
1705
#endif
1706
        break;
1707
    case 0x22:                        // Graphics Data Latches Readback (R)
1708
    case 0x24:                        // Attribute Controller Toggle Readback (R)
1709
    case 0x26:                        // Attribute Controller Index Readback (R)
1710
    case 0x27:                        // Part ID (R)
1711
        break;
1712
    case 0x25:                        // Part Status
1713
    default:
1714
#ifdef DEBUG_CIRRUS
1715
        printf("cirrus: outport cr_index %02x, cr_value %02x\n", reg_index,
1716
               reg_value);
1717
#endif
1718
        break;
1719
    }
1720

    
1721
    return CIRRUS_HOOK_HANDLED;
1722
}
1723

    
1724
/***************************************
1725
 *
1726
 *  memory-mapped I/O (bitblt)
1727
 *
1728
 ***************************************/
1729

    
1730
static uint8_t cirrus_mmio_blt_read(CirrusVGAState * s, unsigned address)
1731
{
1732
    int value = 0xff;
1733

    
1734
    switch (address) {
1735
    case (CIRRUS_MMIO_BLTBGCOLOR + 0):
1736
        cirrus_hook_read_gr(s, 0x00, &value);
1737
        break;
1738
    case (CIRRUS_MMIO_BLTBGCOLOR + 1):
1739
        cirrus_hook_read_gr(s, 0x10, &value);
1740
        break;
1741
    case (CIRRUS_MMIO_BLTBGCOLOR + 2):
1742
        cirrus_hook_read_gr(s, 0x12, &value);
1743
        break;
1744
    case (CIRRUS_MMIO_BLTBGCOLOR + 3):
1745
        cirrus_hook_read_gr(s, 0x14, &value);
1746
        break;
1747
    case (CIRRUS_MMIO_BLTFGCOLOR + 0):
1748
        cirrus_hook_read_gr(s, 0x01, &value);
1749
        break;
1750
    case (CIRRUS_MMIO_BLTFGCOLOR + 1):
1751
        cirrus_hook_read_gr(s, 0x11, &value);
1752
        break;
1753
    case (CIRRUS_MMIO_BLTFGCOLOR + 2):
1754
        cirrus_hook_read_gr(s, 0x13, &value);
1755
        break;
1756
    case (CIRRUS_MMIO_BLTFGCOLOR + 3):
1757
        cirrus_hook_read_gr(s, 0x15, &value);
1758
        break;
1759
    case (CIRRUS_MMIO_BLTWIDTH + 0):
1760
        cirrus_hook_read_gr(s, 0x20, &value);
1761
        break;
1762
    case (CIRRUS_MMIO_BLTWIDTH + 1):
1763
        cirrus_hook_read_gr(s, 0x21, &value);
1764
        break;
1765
    case (CIRRUS_MMIO_BLTHEIGHT + 0):
1766
        cirrus_hook_read_gr(s, 0x22, &value);
1767
        break;
1768
    case (CIRRUS_MMIO_BLTHEIGHT + 1):
1769
        cirrus_hook_read_gr(s, 0x23, &value);
1770
        break;
1771
    case (CIRRUS_MMIO_BLTDESTPITCH + 0):
1772
        cirrus_hook_read_gr(s, 0x24, &value);
1773
        break;
1774
    case (CIRRUS_MMIO_BLTDESTPITCH + 1):
1775
        cirrus_hook_read_gr(s, 0x25, &value);
1776
        break;
1777
    case (CIRRUS_MMIO_BLTSRCPITCH + 0):
1778
        cirrus_hook_read_gr(s, 0x26, &value);
1779
        break;
1780
    case (CIRRUS_MMIO_BLTSRCPITCH + 1):
1781
        cirrus_hook_read_gr(s, 0x27, &value);
1782
        break;
1783
    case (CIRRUS_MMIO_BLTDESTADDR + 0):
1784
        cirrus_hook_read_gr(s, 0x28, &value);
1785
        break;
1786
    case (CIRRUS_MMIO_BLTDESTADDR + 1):
1787
        cirrus_hook_read_gr(s, 0x29, &value);
1788
        break;
1789
    case (CIRRUS_MMIO_BLTDESTADDR + 2):
1790
        cirrus_hook_read_gr(s, 0x2a, &value);
1791
        break;
1792
    case (CIRRUS_MMIO_BLTSRCADDR + 0):
1793
        cirrus_hook_read_gr(s, 0x2c, &value);
1794
        break;
1795
    case (CIRRUS_MMIO_BLTSRCADDR + 1):
1796
        cirrus_hook_read_gr(s, 0x2d, &value);
1797
        break;
1798
    case (CIRRUS_MMIO_BLTSRCADDR + 2):
1799
        cirrus_hook_read_gr(s, 0x2e, &value);
1800
        break;
1801
    case CIRRUS_MMIO_BLTWRITEMASK:
1802
        cirrus_hook_read_gr(s, 0x2f, &value);
1803
        break;
1804
    case CIRRUS_MMIO_BLTMODE:
1805
        cirrus_hook_read_gr(s, 0x30, &value);
1806
        break;
1807
    case CIRRUS_MMIO_BLTROP:
1808
        cirrus_hook_read_gr(s, 0x32, &value);
1809
        break;
1810
    case CIRRUS_MMIO_BLTMODEEXT:
1811
        cirrus_hook_read_gr(s, 0x33, &value);
1812
        break;
1813
    case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0):
1814
        cirrus_hook_read_gr(s, 0x34, &value);
1815
        break;
1816
    case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1):
1817
        cirrus_hook_read_gr(s, 0x35, &value);
1818
        break;
1819
    case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0):
1820
        cirrus_hook_read_gr(s, 0x38, &value);
1821
        break;
1822
    case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1):
1823
        cirrus_hook_read_gr(s, 0x39, &value);
1824
        break;
1825
    case CIRRUS_MMIO_BLTSTATUS:
1826
        cirrus_hook_read_gr(s, 0x31, &value);
1827
        break;
1828
    default:
1829
#ifdef DEBUG_CIRRUS
1830
        printf("cirrus: mmio read - address 0x%04x\n", address);
1831
#endif
1832
        break;
1833
    }
1834

    
1835
    return (uint8_t) value;
1836
}
1837

    
1838
static void cirrus_mmio_blt_write(CirrusVGAState * s, unsigned address,
1839
                                  uint8_t value)
1840
{
1841
    switch (address) {
1842
    case (CIRRUS_MMIO_BLTBGCOLOR + 0):
1843
        cirrus_hook_write_gr(s, 0x00, value);
1844
        break;
1845
    case (CIRRUS_MMIO_BLTBGCOLOR + 1):
1846
        cirrus_hook_write_gr(s, 0x10, value);
1847
        break;
1848
    case (CIRRUS_MMIO_BLTBGCOLOR + 2):
1849
        cirrus_hook_write_gr(s, 0x12, value);
1850
        break;
1851
    case (CIRRUS_MMIO_BLTBGCOLOR + 3):
1852
        cirrus_hook_write_gr(s, 0x14, value);
1853
        break;
1854
    case (CIRRUS_MMIO_BLTFGCOLOR + 0):
1855
        cirrus_hook_write_gr(s, 0x01, value);
1856
        break;
1857
    case (CIRRUS_MMIO_BLTFGCOLOR + 1):
1858
        cirrus_hook_write_gr(s, 0x11, value);
1859
        break;
1860
    case (CIRRUS_MMIO_BLTFGCOLOR + 2):
1861
        cirrus_hook_write_gr(s, 0x13, value);
1862
        break;
1863
    case (CIRRUS_MMIO_BLTFGCOLOR + 3):
1864
        cirrus_hook_write_gr(s, 0x15, value);
1865
        break;
1866
    case (CIRRUS_MMIO_BLTWIDTH + 0):
1867
        cirrus_hook_write_gr(s, 0x20, value);
1868
        break;
1869
    case (CIRRUS_MMIO_BLTWIDTH + 1):
1870
        cirrus_hook_write_gr(s, 0x21, value);
1871
        break;
1872
    case (CIRRUS_MMIO_BLTHEIGHT + 0):
1873
        cirrus_hook_write_gr(s, 0x22, value);
1874
        break;
1875
    case (CIRRUS_MMIO_BLTHEIGHT + 1):
1876
        cirrus_hook_write_gr(s, 0x23, value);
1877
        break;
1878
    case (CIRRUS_MMIO_BLTDESTPITCH + 0):
1879
        cirrus_hook_write_gr(s, 0x24, value);
1880
        break;
1881
    case (CIRRUS_MMIO_BLTDESTPITCH + 1):
1882
        cirrus_hook_write_gr(s, 0x25, value);
1883
        break;
1884
    case (CIRRUS_MMIO_BLTSRCPITCH + 0):
1885
        cirrus_hook_write_gr(s, 0x26, value);
1886
        break;
1887
    case (CIRRUS_MMIO_BLTSRCPITCH + 1):
1888
        cirrus_hook_write_gr(s, 0x27, value);
1889
        break;
1890
    case (CIRRUS_MMIO_BLTDESTADDR + 0):
1891
        cirrus_hook_write_gr(s, 0x28, value);
1892
        break;
1893
    case (CIRRUS_MMIO_BLTDESTADDR + 1):
1894
        cirrus_hook_write_gr(s, 0x29, value);
1895
        break;
1896
    case (CIRRUS_MMIO_BLTDESTADDR + 2):
1897
        cirrus_hook_write_gr(s, 0x2a, value);
1898
        break;
1899
    case (CIRRUS_MMIO_BLTDESTADDR + 3):
1900
        /* ignored */
1901
        break;
1902
    case (CIRRUS_MMIO_BLTSRCADDR + 0):
1903
        cirrus_hook_write_gr(s, 0x2c, value);
1904
        break;
1905
    case (CIRRUS_MMIO_BLTSRCADDR + 1):
1906
        cirrus_hook_write_gr(s, 0x2d, value);
1907
        break;
1908
    case (CIRRUS_MMIO_BLTSRCADDR + 2):
1909
        cirrus_hook_write_gr(s, 0x2e, value);
1910
        break;
1911
    case CIRRUS_MMIO_BLTWRITEMASK:
1912
        cirrus_hook_write_gr(s, 0x2f, value);
1913
        break;
1914
    case CIRRUS_MMIO_BLTMODE:
1915
        cirrus_hook_write_gr(s, 0x30, value);
1916
        break;
1917
    case CIRRUS_MMIO_BLTROP:
1918
        cirrus_hook_write_gr(s, 0x32, value);
1919
        break;
1920
    case CIRRUS_MMIO_BLTMODEEXT:
1921
        cirrus_hook_write_gr(s, 0x33, value);
1922
        break;
1923
    case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0):
1924
        cirrus_hook_write_gr(s, 0x34, value);
1925
        break;
1926
    case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1):
1927
        cirrus_hook_write_gr(s, 0x35, value);
1928
        break;
1929
    case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0):
1930
        cirrus_hook_write_gr(s, 0x38, value);
1931
        break;
1932
    case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1):
1933
        cirrus_hook_write_gr(s, 0x39, value);
1934
        break;
1935
    case CIRRUS_MMIO_BLTSTATUS:
1936
        cirrus_hook_write_gr(s, 0x31, value);
1937
        break;
1938
    default:
1939
#ifdef DEBUG_CIRRUS
1940
        printf("cirrus: mmio write - addr 0x%04x val 0x%02x (ignored)\n",
1941
               address, value);
1942
#endif
1943
        break;
1944
    }
1945
}
1946

    
1947
/***************************************
1948
 *
1949
 *  write mode 4/5
1950
 *
1951
 * assume TARGET_PAGE_SIZE >= 16
1952
 *
1953
 ***************************************/
1954

    
1955
static void cirrus_mem_writeb_mode4and5_8bpp(CirrusVGAState * s,
1956
                                             unsigned mode,
1957
                                             unsigned offset,
1958
                                             uint32_t mem_value)
1959
{
1960
    int x;
1961
    unsigned val = mem_value;
1962
    uint8_t *dst;
1963

    
1964
    dst = s->vram_ptr + (offset &= s->cirrus_addr_mask);
1965
    for (x = 0; x < 8; x++) {
1966
        if (val & 0x80) {
1967
            *dst = s->cirrus_shadow_gr1;
1968
        } else if (mode == 5) {
1969
            *dst = s->cirrus_shadow_gr0;
1970
        }
1971
        val <<= 1;
1972
        dst++;
1973
    }
1974
    cpu_physical_memory_set_dirty(s->vram_offset + offset);
1975
    cpu_physical_memory_set_dirty(s->vram_offset + offset + 7);
1976
}
1977

    
1978
static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,
1979
                                              unsigned mode,
1980
                                              unsigned offset,
1981
                                              uint32_t mem_value)
1982
{
1983
    int x;
1984
    unsigned val = mem_value;
1985
    uint8_t *dst;
1986

    
1987
    dst = s->vram_ptr + (offset &= s->cirrus_addr_mask);
1988
    for (x = 0; x < 8; x++) {
1989
        if (val & 0x80) {
1990
            *dst = s->cirrus_shadow_gr1;
1991
            *(dst + 1) = s->gr[0x11];
1992
        } else if (mode == 5) {
1993
            *dst = s->cirrus_shadow_gr0;
1994
            *(dst + 1) = s->gr[0x10];
1995
        }
1996
        val <<= 1;
1997
        dst += 2;
1998
    }
1999
    cpu_physical_memory_set_dirty(s->vram_offset + offset);
2000
    cpu_physical_memory_set_dirty(s->vram_offset + offset + 15);
2001
}
2002

    
2003
/***************************************
2004
 *
2005
 *  memory access between 0xa0000-0xbffff
2006
 *
2007
 ***************************************/
2008

    
2009
static uint32_t cirrus_vga_mem_readb(void *opaque, target_phys_addr_t addr)
2010
{
2011
    CirrusVGAState *s = opaque;
2012
    unsigned bank_index;
2013
    unsigned bank_offset;
2014
    uint32_t val;
2015

    
2016
    if ((s->sr[0x07] & 0x01) == 0) {
2017
        return vga_mem_readb(s, addr);
2018
    }
2019

    
2020
    addr &= 0x1ffff;
2021

    
2022
    if (addr < 0x10000) {
2023
        /* XXX handle bitblt */
2024
        /* video memory */
2025
        bank_index = addr >> 15;
2026
        bank_offset = addr & 0x7fff;
2027
        if (bank_offset < s->cirrus_bank_limit[bank_index]) {
2028
            bank_offset += s->cirrus_bank_base[bank_index];
2029
            if ((s->gr[0x0B] & 0x14) == 0x14) {
2030
                bank_offset <<= 4;
2031
            } else if (s->gr[0x0B] & 0x02) {
2032
                bank_offset <<= 3;
2033
            }
2034
            bank_offset &= s->cirrus_addr_mask;
2035
            val = *(s->vram_ptr + bank_offset);
2036
        } else
2037
            val = 0xff;
2038
    } else if (addr >= 0x18000 && addr < 0x18100) {
2039
        /* memory-mapped I/O */
2040
        val = 0xff;
2041
        if ((s->sr[0x17] & 0x44) == 0x04) {
2042
            val = cirrus_mmio_blt_read(s, addr & 0xff);
2043
        }
2044
    } else {
2045
        val = 0xff;
2046
#ifdef DEBUG_CIRRUS
2047
        printf("cirrus: mem_readb %06x\n", addr);
2048
#endif
2049
    }
2050
    return val;
2051
}
2052

    
2053
static uint32_t cirrus_vga_mem_readw(void *opaque, target_phys_addr_t addr)
2054
{
2055
    uint32_t v;
2056
#ifdef TARGET_WORDS_BIGENDIAN
2057
    v = cirrus_vga_mem_readb(opaque, addr) << 8;
2058
    v |= cirrus_vga_mem_readb(opaque, addr + 1);
2059
#else
2060
    v = cirrus_vga_mem_readb(opaque, addr);
2061
    v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
2062
#endif
2063
    return v;
2064
}
2065

    
2066
static uint32_t cirrus_vga_mem_readl(void *opaque, target_phys_addr_t addr)
2067
{
2068
    uint32_t v;
2069
#ifdef TARGET_WORDS_BIGENDIAN
2070
    v = cirrus_vga_mem_readb(opaque, addr) << 24;
2071
    v |= cirrus_vga_mem_readb(opaque, addr + 1) << 16;
2072
    v |= cirrus_vga_mem_readb(opaque, addr + 2) << 8;
2073
    v |= cirrus_vga_mem_readb(opaque, addr + 3);
2074
#else
2075
    v = cirrus_vga_mem_readb(opaque, addr);
2076
    v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
2077
    v |= cirrus_vga_mem_readb(opaque, addr + 2) << 16;
2078
    v |= cirrus_vga_mem_readb(opaque, addr + 3) << 24;
2079
#endif
2080
    return v;
2081
}
2082

    
2083
static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr,
2084
                                  uint32_t mem_value)
2085
{
2086
    CirrusVGAState *s = opaque;
2087
    unsigned bank_index;
2088
    unsigned bank_offset;
2089
    unsigned mode;
2090

    
2091
    if ((s->sr[0x07] & 0x01) == 0) {
2092
        vga_mem_writeb(s, addr, mem_value);
2093
        return;
2094
    }
2095

    
2096
    addr &= 0x1ffff;
2097

    
2098
    if (addr < 0x10000) {
2099
        if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
2100
            /* bitblt */
2101
            *s->cirrus_srcptr++ = (uint8_t) mem_value;
2102
            if (s->cirrus_srcptr >= s->cirrus_srcptr_end) {
2103
                cirrus_bitblt_cputovideo_next(s);
2104
            }
2105
        } else {
2106
            /* video memory */
2107
            bank_index = addr >> 15;
2108
            bank_offset = addr & 0x7fff;
2109
            if (bank_offset < s->cirrus_bank_limit[bank_index]) {
2110
                bank_offset += s->cirrus_bank_base[bank_index];
2111
                if ((s->gr[0x0B] & 0x14) == 0x14) {
2112
                    bank_offset <<= 4;
2113
                } else if (s->gr[0x0B] & 0x02) {
2114
                    bank_offset <<= 3;
2115
                }
2116
                bank_offset &= s->cirrus_addr_mask;
2117
                mode = s->gr[0x05] & 0x7;
2118
                if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
2119
                    *(s->vram_ptr + bank_offset) = mem_value;
2120
                    cpu_physical_memory_set_dirty(s->vram_offset +
2121
                                                  bank_offset);
2122
                } else {
2123
                    if ((s->gr[0x0B] & 0x14) != 0x14) {
2124
                        cirrus_mem_writeb_mode4and5_8bpp(s, mode,
2125
                                                         bank_offset,
2126
                                                         mem_value);
2127
                    } else {
2128
                        cirrus_mem_writeb_mode4and5_16bpp(s, mode,
2129
                                                          bank_offset,
2130
                                                          mem_value);
2131
                    }
2132
                }
2133
            }
2134
        }
2135
    } else if (addr >= 0x18000 && addr < 0x18100) {
2136
        /* memory-mapped I/O */
2137
        if ((s->sr[0x17] & 0x44) == 0x04) {
2138
            cirrus_mmio_blt_write(s, addr & 0xff, mem_value);
2139
        }
2140
    } else {
2141
#ifdef DEBUG_CIRRUS
2142
        printf("cirrus: mem_writeb %06x value %02x\n", addr, mem_value);
2143
#endif
2144
    }
2145
}
2146

    
2147
static void cirrus_vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
2148
{
2149
#ifdef TARGET_WORDS_BIGENDIAN
2150
    cirrus_vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
2151
    cirrus_vga_mem_writeb(opaque, addr + 1, val & 0xff);
2152
#else
2153
    cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
2154
    cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2155
#endif
2156
}
2157

    
2158
static void cirrus_vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
2159
{
2160
#ifdef TARGET_WORDS_BIGENDIAN
2161
    cirrus_vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
2162
    cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
2163
    cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
2164
    cirrus_vga_mem_writeb(opaque, addr + 3, val & 0xff);
2165
#else
2166
    cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
2167
    cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2168
    cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
2169
    cirrus_vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
2170
#endif
2171
}
2172

    
2173
static CPUReadMemoryFunc *cirrus_vga_mem_read[3] = {
2174
    cirrus_vga_mem_readb,
2175
    cirrus_vga_mem_readw,
2176
    cirrus_vga_mem_readl,
2177
};
2178

    
2179
static CPUWriteMemoryFunc *cirrus_vga_mem_write[3] = {
2180
    cirrus_vga_mem_writeb,
2181
    cirrus_vga_mem_writew,
2182
    cirrus_vga_mem_writel,
2183
};
2184

    
2185
/***************************************
2186
 *
2187
 *  hardware cursor
2188
 *
2189
 ***************************************/
2190

    
2191
static inline void invalidate_cursor1(CirrusVGAState *s)
2192
{
2193
    if (s->last_hw_cursor_size) {
2194
        vga_invalidate_scanlines((VGAState *)s,
2195
                                 s->last_hw_cursor_y + s->last_hw_cursor_y_start,
2196
                                 s->last_hw_cursor_y + s->last_hw_cursor_y_end);
2197
    }
2198
}
2199

    
2200
static inline void cirrus_cursor_compute_yrange(CirrusVGAState *s)
2201
{
2202
    const uint8_t *src;
2203
    uint32_t content;
2204
    int y, y_min, y_max;
2205

    
2206
    src = s->vram_ptr + s->real_vram_size - 16 * 1024;
2207
    if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) {
2208
        src += (s->sr[0x13] & 0x3c) * 256;
2209
        y_min = 64;
2210
        y_max = -1;
2211
        for(y = 0; y < 64; y++) {
2212
            content = ((uint32_t *)src)[0] |
2213
                ((uint32_t *)src)[1] |
2214
                ((uint32_t *)src)[2] |
2215
                ((uint32_t *)src)[3];
2216
            if (content) {
2217
                if (y < y_min)
2218
                    y_min = y;
2219
                if (y > y_max)
2220
                    y_max = y;
2221
            }
2222
            src += 16;
2223
        }
2224
    } else {
2225
        src += (s->sr[0x13] & 0x3f) * 256;
2226
        y_min = 32;
2227
        y_max = -1;
2228
        for(y = 0; y < 32; y++) {
2229
            content = ((uint32_t *)src)[0] |
2230
                ((uint32_t *)(src + 128))[0];
2231
            if (content) {
2232
                if (y < y_min)
2233
                    y_min = y;
2234
                if (y > y_max)
2235
                    y_max = y;
2236
            }
2237
            src += 4;
2238
        }
2239
    }
2240
    if (y_min > y_max) {
2241
        s->last_hw_cursor_y_start = 0;
2242
        s->last_hw_cursor_y_end = 0;
2243
    } else {
2244
        s->last_hw_cursor_y_start = y_min;
2245
        s->last_hw_cursor_y_end = y_max + 1;
2246
    }
2247
}
2248

    
2249
/* NOTE: we do not currently handle the cursor bitmap change, so we
2250
   update the cursor only if it moves. */
2251
static void cirrus_cursor_invalidate(VGAState *s1)
2252
{
2253
    CirrusVGAState *s = (CirrusVGAState *)s1;
2254
    int size;
2255

    
2256
    if (!s->sr[0x12] & CIRRUS_CURSOR_SHOW) {
2257
        size = 0;
2258
    } else {
2259
        if (s->sr[0x12] & CIRRUS_CURSOR_LARGE)
2260
            size = 64;
2261
        else
2262
            size = 32;
2263
    }
2264
    /* invalidate last cursor and new cursor if any change */
2265
    if (s->last_hw_cursor_size != size ||
2266
        s->last_hw_cursor_x != s->hw_cursor_x ||
2267
        s->last_hw_cursor_y != s->hw_cursor_y) {
2268

    
2269
        invalidate_cursor1(s);
2270

    
2271
        s->last_hw_cursor_size = size;
2272
        s->last_hw_cursor_x = s->hw_cursor_x;
2273
        s->last_hw_cursor_y = s->hw_cursor_y;
2274
        /* compute the real cursor min and max y */
2275
        cirrus_cursor_compute_yrange(s);
2276
        invalidate_cursor1(s);
2277
    }
2278
}
2279

    
2280
static void cirrus_cursor_draw_line(VGAState *s1, uint8_t *d1, int scr_y)
2281
{
2282
    CirrusVGAState *s = (CirrusVGAState *)s1;
2283
    int w, h, bpp, x1, x2, poffset;
2284
    unsigned int color0, color1;
2285
    const uint8_t *palette, *src;
2286
    uint32_t content;
2287

    
2288
    if (!(s->sr[0x12] & CIRRUS_CURSOR_SHOW))
2289
        return;
2290
    /* fast test to see if the cursor intersects with the scan line */
2291
    if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) {
2292
        h = 64;
2293
    } else {
2294
        h = 32;
2295
    }
2296
    if (scr_y < s->hw_cursor_y ||
2297
        scr_y >= (s->hw_cursor_y + h))
2298
        return;
2299

    
2300
    src = s->vram_ptr + s->real_vram_size - 16 * 1024;
2301
    if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) {
2302
        src += (s->sr[0x13] & 0x3c) * 256;
2303
        src += (scr_y - s->hw_cursor_y) * 16;
2304
        poffset = 8;
2305
        content = ((uint32_t *)src)[0] |
2306
            ((uint32_t *)src)[1] |
2307
            ((uint32_t *)src)[2] |
2308
            ((uint32_t *)src)[3];
2309
    } else {
2310
        src += (s->sr[0x13] & 0x3f) * 256;
2311
        src += (scr_y - s->hw_cursor_y) * 4;
2312
        poffset = 128;
2313
        content = ((uint32_t *)src)[0] |
2314
            ((uint32_t *)(src + 128))[0];
2315
    }
2316
    /* if nothing to draw, no need to continue */
2317
    if (!content)
2318
        return;
2319
    w = h;
2320

    
2321
    x1 = s->hw_cursor_x;
2322
    if (x1 >= s->last_scr_width)
2323
        return;
2324
    x2 = s->hw_cursor_x + w;
2325
    if (x2 > s->last_scr_width)
2326
        x2 = s->last_scr_width;
2327
    w = x2 - x1;
2328
    palette = s->cirrus_hidden_palette;
2329
    color0 = s->rgb_to_pixel(c6_to_8(palette[0x0 * 3]),
2330
                             c6_to_8(palette[0x0 * 3 + 1]),
2331
                             c6_to_8(palette[0x0 * 3 + 2]));
2332
    color1 = s->rgb_to_pixel(c6_to_8(palette[0xf * 3]),
2333
                             c6_to_8(palette[0xf * 3 + 1]),
2334
                             c6_to_8(palette[0xf * 3 + 2]));
2335
    bpp = ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
2336
    d1 += x1 * bpp;
2337
    switch(ds_get_bits_per_pixel(s->ds)) {
2338
    default:
2339
        break;
2340
    case 8:
2341
        vga_draw_cursor_line_8(d1, src, poffset, w, color0, color1, 0xff);
2342
        break;
2343
    case 15:
2344
        vga_draw_cursor_line_16(d1, src, poffset, w, color0, color1, 0x7fff);
2345
        break;
2346
    case 16:
2347
        vga_draw_cursor_line_16(d1, src, poffset, w, color0, color1, 0xffff);
2348
        break;
2349
    case 32:
2350
        vga_draw_cursor_line_32(d1, src, poffset, w, color0, color1, 0xffffff);
2351
        break;
2352
    }
2353
}
2354

    
2355
/***************************************
2356
 *
2357
 *  LFB memory access
2358
 *
2359
 ***************************************/
2360

    
2361
static uint32_t cirrus_linear_readb(void *opaque, target_phys_addr_t addr)
2362
{
2363
    CirrusVGAState *s = (CirrusVGAState *) opaque;
2364
    uint32_t ret;
2365

    
2366
    addr &= s->cirrus_addr_mask;
2367

    
2368
    if (((s->sr[0x17] & 0x44) == 0x44) &&
2369
        ((addr & s->linear_mmio_mask) == s->linear_mmio_mask)) {
2370
        /* memory-mapped I/O */
2371
        ret = cirrus_mmio_blt_read(s, addr & 0xff);
2372
    } else if (0) {
2373
        /* XXX handle bitblt */
2374
        ret = 0xff;
2375
    } else {
2376
        /* video memory */
2377
        if ((s->gr[0x0B] & 0x14) == 0x14) {
2378
            addr <<= 4;
2379
        } else if (s->gr[0x0B] & 0x02) {
2380
            addr <<= 3;
2381
        }
2382
        addr &= s->cirrus_addr_mask;
2383
        ret = *(s->vram_ptr + addr);
2384
    }
2385

    
2386
    return ret;
2387
}
2388

    
2389
static uint32_t cirrus_linear_readw(void *opaque, target_phys_addr_t addr)
2390
{
2391
    uint32_t v;
2392
#ifdef TARGET_WORDS_BIGENDIAN
2393
    v = cirrus_linear_readb(opaque, addr) << 8;
2394
    v |= cirrus_linear_readb(opaque, addr + 1);
2395
#else
2396
    v = cirrus_linear_readb(opaque, addr);
2397
    v |= cirrus_linear_readb(opaque, addr + 1) << 8;
2398
#endif
2399
    return v;
2400
}
2401

    
2402
static uint32_t cirrus_linear_readl(void *opaque, target_phys_addr_t addr)
2403
{
2404
    uint32_t v;
2405
#ifdef TARGET_WORDS_BIGENDIAN
2406
    v = cirrus_linear_readb(opaque, addr) << 24;
2407
    v |= cirrus_linear_readb(opaque, addr + 1) << 16;
2408
    v |= cirrus_linear_readb(opaque, addr + 2) << 8;
2409
    v |= cirrus_linear_readb(opaque, addr + 3);
2410
#else
2411
    v = cirrus_linear_readb(opaque, addr);
2412
    v |= cirrus_linear_readb(opaque, addr + 1) << 8;
2413
    v |= cirrus_linear_readb(opaque, addr + 2) << 16;
2414
    v |= cirrus_linear_readb(opaque, addr + 3) << 24;
2415
#endif
2416
    return v;
2417
}
2418

    
2419
static void cirrus_linear_writeb(void *opaque, target_phys_addr_t addr,
2420
                                 uint32_t val)
2421
{
2422
    CirrusVGAState *s = (CirrusVGAState *) opaque;
2423
    unsigned mode;
2424

    
2425
    addr &= s->cirrus_addr_mask;
2426

    
2427
    if (((s->sr[0x17] & 0x44) == 0x44) &&
2428
        ((addr & s->linear_mmio_mask) ==  s->linear_mmio_mask)) {
2429
        /* memory-mapped I/O */
2430
        cirrus_mmio_blt_write(s, addr & 0xff, val);
2431
    } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
2432
        /* bitblt */
2433
        *s->cirrus_srcptr++ = (uint8_t) val;
2434
        if (s->cirrus_srcptr >= s->cirrus_srcptr_end) {
2435
            cirrus_bitblt_cputovideo_next(s);
2436
        }
2437
    } else {
2438
        /* video memory */
2439
        if ((s->gr[0x0B] & 0x14) == 0x14) {
2440
            addr <<= 4;
2441
        } else if (s->gr[0x0B] & 0x02) {
2442
            addr <<= 3;
2443
        }
2444
        addr &= s->cirrus_addr_mask;
2445

    
2446
        mode = s->gr[0x05] & 0x7;
2447
        if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
2448
            *(s->vram_ptr + addr) = (uint8_t) val;
2449
            cpu_physical_memory_set_dirty(s->vram_offset + addr);
2450
        } else {
2451
            if ((s->gr[0x0B] & 0x14) != 0x14) {
2452
                cirrus_mem_writeb_mode4and5_8bpp(s, mode, addr, val);
2453
            } else {
2454
                cirrus_mem_writeb_mode4and5_16bpp(s, mode, addr, val);
2455
            }
2456
        }
2457
    }
2458
}
2459

    
2460
static void cirrus_linear_writew(void *opaque, target_phys_addr_t addr,
2461
                                 uint32_t val)
2462
{
2463
#ifdef TARGET_WORDS_BIGENDIAN
2464
    cirrus_linear_writeb(opaque, addr, (val >> 8) & 0xff);
2465
    cirrus_linear_writeb(opaque, addr + 1, val & 0xff);
2466
#else
2467
    cirrus_linear_writeb(opaque, addr, val & 0xff);
2468
    cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2469
#endif
2470
}
2471

    
2472
static void cirrus_linear_writel(void *opaque, target_phys_addr_t addr,
2473
                                 uint32_t val)
2474
{
2475
#ifdef TARGET_WORDS_BIGENDIAN
2476
    cirrus_linear_writeb(opaque, addr, (val >> 24) & 0xff);
2477
    cirrus_linear_writeb(opaque, addr + 1, (val >> 16) & 0xff);
2478
    cirrus_linear_writeb(opaque, addr + 2, (val >> 8) & 0xff);
2479
    cirrus_linear_writeb(opaque, addr + 3, val & 0xff);
2480
#else
2481
    cirrus_linear_writeb(opaque, addr, val & 0xff);
2482
    cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2483
    cirrus_linear_writeb(opaque, addr + 2, (val >> 16) & 0xff);
2484
    cirrus_linear_writeb(opaque, addr + 3, (val >> 24) & 0xff);
2485
#endif
2486
}
2487

    
2488

    
2489
static CPUReadMemoryFunc *cirrus_linear_read[3] = {
2490
    cirrus_linear_readb,
2491
    cirrus_linear_readw,
2492
    cirrus_linear_readl,
2493
};
2494

    
2495
static CPUWriteMemoryFunc *cirrus_linear_write[3] = {
2496
    cirrus_linear_writeb,
2497
    cirrus_linear_writew,
2498
    cirrus_linear_writel,
2499
};
2500

    
2501
static void cirrus_linear_mem_writeb(void *opaque, target_phys_addr_t addr,
2502
                                     uint32_t val)
2503
{
2504
    CirrusVGAState *s = (CirrusVGAState *) opaque;
2505

    
2506
    addr &= s->cirrus_addr_mask;
2507
    *(s->vram_ptr + addr) = val;
2508
    cpu_physical_memory_set_dirty(s->vram_offset + addr);
2509
}
2510

    
2511
static void cirrus_linear_mem_writew(void *opaque, target_phys_addr_t addr,
2512
                                     uint32_t val)
2513
{
2514
    CirrusVGAState *s = (CirrusVGAState *) opaque;
2515

    
2516
    addr &= s->cirrus_addr_mask;
2517
    cpu_to_le16w((uint16_t *)(s->vram_ptr + addr), val);
2518
    cpu_physical_memory_set_dirty(s->vram_offset + addr);
2519
}
2520

    
2521
static void cirrus_linear_mem_writel(void *opaque, target_phys_addr_t addr,
2522
                                     uint32_t val)
2523
{
2524
    CirrusVGAState *s = (CirrusVGAState *) opaque;
2525

    
2526
    addr &= s->cirrus_addr_mask;
2527
    cpu_to_le32w((uint32_t *)(s->vram_ptr + addr), val);
2528
    cpu_physical_memory_set_dirty(s->vram_offset + addr);
2529
}
2530

    
2531
/***************************************
2532
 *
2533
 *  system to screen memory access
2534
 *
2535
 ***************************************/
2536

    
2537

    
2538
static uint32_t cirrus_linear_bitblt_readb(void *opaque, target_phys_addr_t addr)
2539
{
2540
    uint32_t ret;
2541

    
2542
    /* XXX handle bitblt */
2543
    ret = 0xff;
2544
    return ret;
2545
}
2546

    
2547
static uint32_t cirrus_linear_bitblt_readw(void *opaque, target_phys_addr_t addr)
2548
{
2549
    uint32_t v;
2550
#ifdef TARGET_WORDS_BIGENDIAN
2551
    v = cirrus_linear_bitblt_readb(opaque, addr) << 8;
2552
    v |= cirrus_linear_bitblt_readb(opaque, addr + 1);
2553
#else
2554
    v = cirrus_linear_bitblt_readb(opaque, addr);
2555
    v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8;
2556
#endif
2557
    return v;
2558
}
2559

    
2560
static uint32_t cirrus_linear_bitblt_readl(void *opaque, target_phys_addr_t addr)
2561
{
2562
    uint32_t v;
2563
#ifdef TARGET_WORDS_BIGENDIAN
2564
    v = cirrus_linear_bitblt_readb(opaque, addr) << 24;
2565
    v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 16;
2566
    v |= cirrus_linear_bitblt_readb(opaque, addr + 2) << 8;
2567
    v |= cirrus_linear_bitblt_readb(opaque, addr + 3);
2568
#else
2569
    v = cirrus_linear_bitblt_readb(opaque, addr);
2570
    v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8;
2571
    v |= cirrus_linear_bitblt_readb(opaque, addr + 2) << 16;
2572
    v |= cirrus_linear_bitblt_readb(opaque, addr + 3) << 24;
2573
#endif
2574
    return v;
2575
}
2576

    
2577
static void cirrus_linear_bitblt_writeb(void *opaque, target_phys_addr_t addr,
2578
                                 uint32_t val)
2579
{
2580
    CirrusVGAState *s = (CirrusVGAState *) opaque;
2581

    
2582
    if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
2583
        /* bitblt */
2584
        *s->cirrus_srcptr++ = (uint8_t) val;
2585
        if (s->cirrus_srcptr >= s->cirrus_srcptr_end) {
2586
            cirrus_bitblt_cputovideo_next(s);
2587
        }
2588
    }
2589
}
2590

    
2591
static void cirrus_linear_bitblt_writew(void *opaque, target_phys_addr_t addr,
2592
                                 uint32_t val)
2593
{
2594
#ifdef TARGET_WORDS_BIGENDIAN
2595
    cirrus_linear_bitblt_writeb(opaque, addr, (val >> 8) & 0xff);
2596
    cirrus_linear_bitblt_writeb(opaque, addr + 1, val & 0xff);
2597
#else
2598
    cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff);
2599
    cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2600
#endif
2601
}
2602

    
2603
static void cirrus_linear_bitblt_writel(void *opaque, target_phys_addr_t addr,
2604
                                 uint32_t val)
2605
{
2606
#ifdef TARGET_WORDS_BIGENDIAN
2607
    cirrus_linear_bitblt_writeb(opaque, addr, (val >> 24) & 0xff);
2608
    cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 16) & 0xff);
2609
    cirrus_linear_bitblt_writeb(opaque, addr + 2, (val >> 8) & 0xff);
2610
    cirrus_linear_bitblt_writeb(opaque, addr + 3, val & 0xff);
2611
#else
2612
    cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff);
2613
    cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2614
    cirrus_linear_bitblt_writeb(opaque, addr + 2, (val >> 16) & 0xff);
2615
    cirrus_linear_bitblt_writeb(opaque, addr + 3, (val >> 24) & 0xff);
2616
#endif
2617
}
2618

    
2619

    
2620
static CPUReadMemoryFunc *cirrus_linear_bitblt_read[3] = {
2621
    cirrus_linear_bitblt_readb,
2622
    cirrus_linear_bitblt_readw,
2623
    cirrus_linear_bitblt_readl,
2624
};
2625

    
2626
static CPUWriteMemoryFunc *cirrus_linear_bitblt_write[3] = {
2627
    cirrus_linear_bitblt_writeb,
2628
    cirrus_linear_bitblt_writew,
2629
    cirrus_linear_bitblt_writel,
2630
};
2631

    
2632
static void map_linear_vram(CirrusVGAState *s)
2633
{
2634

    
2635
    if (!s->map_addr && s->lfb_addr && s->lfb_end) {
2636
        s->map_addr = s->lfb_addr;
2637
        s->map_end = s->lfb_end;
2638
        cpu_register_physical_memory(s->map_addr, s->map_end - s->map_addr, s->vram_offset);
2639
        vga_dirty_log_start((VGAState *)s);
2640
    }
2641

    
2642
    if (!s->map_addr)
2643
        return;
2644

    
2645
    s->lfb_vram_mapped = 0;
2646

    
2647
    if (!(s->cirrus_srcptr != s->cirrus_srcptr_end)
2648
        && !((s->sr[0x07] & 0x01) == 0)
2649
        && !((s->gr[0x0B] & 0x14) == 0x14)
2650
        && !(s->gr[0x0B] & 0x02)) {
2651

    
2652
        cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x8000,
2653
                                    (s->vram_offset + s->cirrus_bank_base[0]) | IO_MEM_RAM);
2654
        cpu_register_physical_memory(isa_mem_base + 0xa8000, 0x8000,
2655
                                    (s->vram_offset + s->cirrus_bank_base[1]) | IO_MEM_RAM);
2656

    
2657
        s->lfb_vram_mapped = 1;
2658
        vga_dirty_log_start((VGAState *)s);
2659
    }
2660
    else {
2661
        cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x8000, s->vga_io_memory);
2662
        cpu_register_physical_memory(isa_mem_base + 0xa8000, 0x8000, s->vga_io_memory);
2663
    }
2664

    
2665
}
2666

    
2667
static void unmap_linear_vram(CirrusVGAState *s)
2668
{
2669
    if (s->map_addr && s->lfb_addr && s->lfb_end) {
2670
        vga_dirty_log_stop((VGAState *)s);
2671
        s->map_addr = s->map_end = 0;
2672
    }
2673

    
2674
    cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x20000,
2675
                                 s->vga_io_memory);
2676
}
2677

    
2678
/* Compute the memory access functions */
2679
static void cirrus_update_memory_access(CirrusVGAState *s)
2680
{
2681
    unsigned mode;
2682

    
2683
    if ((s->sr[0x17] & 0x44) == 0x44) {
2684
        goto generic_io;
2685
    } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
2686
        goto generic_io;
2687
    } else {
2688
        if ((s->gr[0x0B] & 0x14) == 0x14) {
2689
            goto generic_io;
2690
        } else if (s->gr[0x0B] & 0x02) {
2691
            goto generic_io;
2692
        }
2693

    
2694
        mode = s->gr[0x05] & 0x7;
2695
        if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
2696
            map_linear_vram(s);
2697
            s->cirrus_linear_write[0] = cirrus_linear_mem_writeb;
2698
            s->cirrus_linear_write[1] = cirrus_linear_mem_writew;
2699
            s->cirrus_linear_write[2] = cirrus_linear_mem_writel;
2700
        } else {
2701
        generic_io:
2702
            unmap_linear_vram(s);
2703
            s->cirrus_linear_write[0] = cirrus_linear_writeb;
2704
            s->cirrus_linear_write[1] = cirrus_linear_writew;
2705
            s->cirrus_linear_write[2] = cirrus_linear_writel;
2706
        }
2707
    }
2708
}
2709

    
2710

    
2711
/* I/O ports */
2712

    
2713
static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
2714
{
2715
    CirrusVGAState *s = opaque;
2716
    int val, index;
2717

    
2718
    /* check port range access depending on color/monochrome mode */
2719
    if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION))
2720
        || (addr >= 0x3d0 && addr <= 0x3df
2721
            && !(s->msr & MSR_COLOR_EMULATION))) {
2722
        val = 0xff;
2723
    } else {
2724
        switch (addr) {
2725
        case 0x3c0:
2726
            if (s->ar_flip_flop == 0) {
2727
                val = s->ar_index;
2728
            } else {
2729
                val = 0;
2730
            }
2731
            break;
2732
        case 0x3c1:
2733
            index = s->ar_index & 0x1f;
2734
            if (index < 21)
2735
                val = s->ar[index];
2736
            else
2737
                val = 0;
2738
            break;
2739
        case 0x3c2:
2740
            val = s->st00;
2741
            break;
2742
        case 0x3c4:
2743
            val = s->sr_index;
2744
            break;
2745
        case 0x3c5:
2746
            if (cirrus_hook_read_sr(s, s->sr_index, &val))
2747
                break;
2748
            val = s->sr[s->sr_index];
2749
#ifdef DEBUG_VGA_REG
2750
            printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
2751
#endif
2752
            break;
2753
        case 0x3c6:
2754
            cirrus_read_hidden_dac(s, &val);
2755
            break;
2756
        case 0x3c7:
2757
            val = s->dac_state;
2758
            break;
2759
        case 0x3c8:
2760
            val = s->dac_write_index;
2761
            s->cirrus_hidden_dac_lockindex = 0;
2762
            break;
2763
        case 0x3c9:
2764
            if (cirrus_hook_read_palette(s, &val))
2765
                break;
2766
            val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
2767
            if (++s->dac_sub_index == 3) {
2768
                s->dac_sub_index = 0;
2769
                s->dac_read_index++;
2770
            }
2771
            break;
2772
        case 0x3ca:
2773
            val = s->fcr;
2774
            break;
2775
        case 0x3cc:
2776
            val = s->msr;
2777
            break;
2778
        case 0x3ce:
2779
            val = s->gr_index;
2780
            break;
2781
        case 0x3cf:
2782
            if (cirrus_hook_read_gr(s, s->gr_index, &val))
2783
                break;
2784
            val = s->gr[s->gr_index];
2785
#ifdef DEBUG_VGA_REG
2786
            printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
2787
#endif
2788
            break;
2789
        case 0x3b4:
2790
        case 0x3d4:
2791
            val = s->cr_index;
2792
            break;
2793
        case 0x3b5:
2794
        case 0x3d5:
2795
            if (cirrus_hook_read_cr(s, s->cr_index, &val))
2796
                break;
2797
            val = s->cr[s->cr_index];
2798
#ifdef DEBUG_VGA_REG
2799
            printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
2800
#endif
2801
            break;
2802
        case 0x3ba:
2803
        case 0x3da:
2804
            /* just toggle to fool polling */
2805
            val = s->st01 = s->retrace((VGAState *) s);
2806
            s->ar_flip_flop = 0;
2807
            break;
2808
        default:
2809
            val = 0x00;
2810
            break;
2811
        }
2812
    }
2813
#if defined(DEBUG_VGA)
2814
    printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
2815
#endif
2816
    return val;
2817
}
2818

    
2819
static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
2820
{
2821
    CirrusVGAState *s = opaque;
2822
    int index;
2823

    
2824
    /* check port range access depending on color/monochrome mode */
2825
    if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION))
2826
        || (addr >= 0x3d0 && addr <= 0x3df
2827
            && !(s->msr & MSR_COLOR_EMULATION)))
2828
        return;
2829

    
2830
#ifdef DEBUG_VGA
2831
    printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
2832
#endif
2833

    
2834
    switch (addr) {
2835
    case 0x3c0:
2836
        if (s->ar_flip_flop == 0) {
2837
            val &= 0x3f;
2838
            s->ar_index = val;
2839
        } else {
2840
            index = s->ar_index & 0x1f;
2841
            switch (index) {
2842
            case 0x00 ... 0x0f:
2843
                s->ar[index] = val & 0x3f;
2844
                break;
2845
            case 0x10:
2846
                s->ar[index] = val & ~0x10;
2847
                break;
2848
            case 0x11:
2849
                s->ar[index] = val;
2850
                break;
2851
            case 0x12:
2852
                s->ar[index] = val & ~0xc0;
2853
                break;
2854
            case 0x13:
2855
                s->ar[index] = val & ~0xf0;
2856
                break;
2857
            case 0x14:
2858
                s->ar[index] = val & ~0xf0;
2859
                break;
2860
            default:
2861
                break;
2862
            }
2863
        }
2864
        s->ar_flip_flop ^= 1;
2865
        break;
2866
    case 0x3c2:
2867
        s->msr = val & ~0x10;
2868
        s->update_retrace_info((VGAState *) s);
2869
        break;
2870
    case 0x3c4:
2871
        s->sr_index = val;
2872
        break;
2873
    case 0x3c5:
2874
        if (cirrus_hook_write_sr(s, s->sr_index, val))
2875
            break;
2876
#ifdef DEBUG_VGA_REG
2877
        printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
2878
#endif
2879
        s->sr[s->sr_index] = val & sr_mask[s->sr_index];
2880
        if (s->sr_index == 1) s->update_retrace_info((VGAState *) s);
2881
        break;
2882
    case 0x3c6:
2883
        cirrus_write_hidden_dac(s, val);
2884
        break;
2885
    case 0x3c7:
2886
        s->dac_read_index = val;
2887
        s->dac_sub_index = 0;
2888
        s->dac_state = 3;
2889
        break;
2890
    case 0x3c8:
2891
        s->dac_write_index = val;
2892
        s->dac_sub_index = 0;
2893
        s->dac_state = 0;
2894
        break;
2895
    case 0x3c9:
2896
        if (cirrus_hook_write_palette(s, val))
2897
            break;
2898
        s->dac_cache[s->dac_sub_index] = val;
2899
        if (++s->dac_sub_index == 3) {
2900
            memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
2901
            s->dac_sub_index = 0;
2902
            s->dac_write_index++;
2903
        }
2904
        break;
2905
    case 0x3ce:
2906
        s->gr_index = val;
2907
        break;
2908
    case 0x3cf:
2909
        if (cirrus_hook_write_gr(s, s->gr_index, val))
2910
            break;
2911
#ifdef DEBUG_VGA_REG
2912
        printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
2913
#endif
2914
        s->gr[s->gr_index] = val & gr_mask[s->gr_index];
2915
        break;
2916
    case 0x3b4:
2917
    case 0x3d4:
2918
        s->cr_index = val;
2919
        break;
2920
    case 0x3b5:
2921
    case 0x3d5:
2922
        if (cirrus_hook_write_cr(s, s->cr_index, val))
2923
            break;
2924
#ifdef DEBUG_VGA_REG
2925
        printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
2926
#endif
2927
        /* handle CR0-7 protection */
2928
        if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {
2929
            /* can always write bit 4 of CR7 */
2930
            if (s->cr_index == 7)
2931
                s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
2932
            return;
2933
        }
2934
        switch (s->cr_index) {
2935
        case 0x01:                /* horizontal display end */
2936
        case 0x07:
2937
        case 0x09:
2938
        case 0x0c:
2939
        case 0x0d:
2940
        case 0x12:                /* vertical display end */
2941
            s->cr[s->cr_index] = val;
2942
            break;
2943

    
2944
        default:
2945
            s->cr[s->cr_index] = val;
2946
            break;
2947
        }
2948

    
2949
        switch(s->cr_index) {
2950
        case 0x00:
2951
        case 0x04:
2952
        case 0x05:
2953
        case 0x06:
2954
        case 0x07:
2955
        case 0x11:
2956
        case 0x17:
2957
            s->update_retrace_info((VGAState *) s);
2958
            break;
2959
        }
2960
        break;
2961
    case 0x3ba:
2962
    case 0x3da:
2963
        s->fcr = val & 0x10;
2964
        break;
2965
    }
2966
}
2967

    
2968
/***************************************
2969
 *
2970
 *  memory-mapped I/O access
2971
 *
2972
 ***************************************/
2973

    
2974
static uint32_t cirrus_mmio_readb(void *opaque, target_phys_addr_t addr)
2975
{
2976
    CirrusVGAState *s = (CirrusVGAState *) opaque;
2977

    
2978
    addr &= CIRRUS_PNPMMIO_SIZE - 1;
2979

    
2980
    if (addr >= 0x100) {
2981
        return cirrus_mmio_blt_read(s, addr - 0x100);
2982
    } else {
2983
        return vga_ioport_read(s, addr + 0x3c0);
2984
    }
2985
}
2986

    
2987
static uint32_t cirrus_mmio_readw(void *opaque, target_phys_addr_t addr)
2988
{
2989
    uint32_t v;
2990
#ifdef TARGET_WORDS_BIGENDIAN
2991
    v = cirrus_mmio_readb(opaque, addr) << 8;
2992
    v |= cirrus_mmio_readb(opaque, addr + 1);
2993
#else
2994
    v = cirrus_mmio_readb(opaque, addr);
2995
    v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
2996
#endif
2997
    return v;
2998
}
2999

    
3000
static uint32_t cirrus_mmio_readl(void *opaque, target_phys_addr_t addr)
3001
{
3002
    uint32_t v;
3003
#ifdef TARGET_WORDS_BIGENDIAN
3004
    v = cirrus_mmio_readb(opaque, addr) << 24;
3005
    v |= cirrus_mmio_readb(opaque, addr + 1) << 16;
3006
    v |= cirrus_mmio_readb(opaque, addr + 2) << 8;
3007
    v |= cirrus_mmio_readb(opaque, addr + 3);
3008
#else
3009
    v = cirrus_mmio_readb(opaque, addr);
3010
    v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
3011
    v |= cirrus_mmio_readb(opaque, addr + 2) << 16;
3012
    v |= cirrus_mmio_readb(opaque, addr + 3) << 24;
3013
#endif
3014
    return v;
3015
}
3016

    
3017
static void cirrus_mmio_writeb(void *opaque, target_phys_addr_t addr,
3018
                               uint32_t val)
3019
{
3020
    CirrusVGAState *s = (CirrusVGAState *) opaque;
3021

    
3022
    addr &= CIRRUS_PNPMMIO_SIZE - 1;
3023

    
3024
    if (addr >= 0x100) {
3025
        cirrus_mmio_blt_write(s, addr - 0x100, val);
3026
    } else {
3027
        vga_ioport_write(s, addr + 0x3c0, val);
3028
    }
3029
}
3030

    
3031
static void cirrus_mmio_writew(void *opaque, target_phys_addr_t addr,
3032
                               uint32_t val)
3033
{
3034
#ifdef TARGET_WORDS_BIGENDIAN
3035
    cirrus_mmio_writeb(opaque, addr, (val >> 8) & 0xff);
3036
    cirrus_mmio_writeb(opaque, addr + 1, val & 0xff);
3037
#else
3038
    cirrus_mmio_writeb(opaque, addr, val & 0xff);
3039
    cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
3040
#endif
3041
}
3042

    
3043
static void cirrus_mmio_writel(void *opaque, target_phys_addr_t addr,
3044
                               uint32_t val)
3045
{
3046
#ifdef TARGET_WORDS_BIGENDIAN
3047
    cirrus_mmio_writeb(opaque, addr, (val >> 24) & 0xff);
3048
    cirrus_mmio_writeb(opaque, addr + 1, (val >> 16) & 0xff);
3049
    cirrus_mmio_writeb(opaque, addr + 2, (val >> 8) & 0xff);
3050
    cirrus_mmio_writeb(opaque, addr + 3, val & 0xff);
3051
#else
3052
    cirrus_mmio_writeb(opaque, addr, val & 0xff);
3053
    cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
3054
    cirrus_mmio_writeb(opaque, addr + 2, (val >> 16) & 0xff);
3055
    cirrus_mmio_writeb(opaque, addr + 3, (val >> 24) & 0xff);
3056
#endif
3057
}
3058

    
3059

    
3060
static CPUReadMemoryFunc *cirrus_mmio_read[3] = {
3061
    cirrus_mmio_readb,
3062
    cirrus_mmio_readw,
3063
    cirrus_mmio_readl,
3064
};
3065

    
3066
static CPUWriteMemoryFunc *cirrus_mmio_write[3] = {
3067
    cirrus_mmio_writeb,
3068
    cirrus_mmio_writew,
3069
    cirrus_mmio_writel,
3070
};
3071

    
3072
/* load/save state */
3073

    
3074
static void cirrus_vga_save(QEMUFile *f, void *opaque)
3075
{
3076
    CirrusVGAState *s = opaque;
3077

    
3078
    if (s->pci_dev)
3079
        pci_device_save(s->pci_dev, f);
3080

    
3081
    qemu_put_be32s(f, &s->latch);
3082
    qemu_put_8s(f, &s->sr_index);
3083
    qemu_put_buffer(f, s->sr, 256);
3084
    qemu_put_8s(f, &s->gr_index);
3085
    qemu_put_8s(f, &s->cirrus_shadow_gr0);
3086
    qemu_put_8s(f, &s->cirrus_shadow_gr1);
3087
    qemu_put_buffer(f, s->gr + 2, 254);
3088
    qemu_put_8s(f, &s->ar_index);
3089
    qemu_put_buffer(f, s->ar, 21);
3090
    qemu_put_be32(f, s->ar_flip_flop);
3091
    qemu_put_8s(f, &s->cr_index);
3092
    qemu_put_buffer(f, s->cr, 256);
3093
    qemu_put_8s(f, &s->msr);
3094
    qemu_put_8s(f, &s->fcr);
3095
    qemu_put_8s(f, &s->st00);
3096
    qemu_put_8s(f, &s->st01);
3097

    
3098
    qemu_put_8s(f, &s->dac_state);
3099
    qemu_put_8s(f, &s->dac_sub_index);
3100
    qemu_put_8s(f, &s->dac_read_index);
3101
    qemu_put_8s(f, &s->dac_write_index);
3102
    qemu_put_buffer(f, s->dac_cache, 3);
3103
    qemu_put_buffer(f, s->palette, 768);
3104

    
3105
    qemu_put_be32(f, s->bank_offset);
3106

    
3107
    qemu_put_8s(f, &s->cirrus_hidden_dac_lockindex);
3108
    qemu_put_8s(f, &s->cirrus_hidden_dac_data);
3109

    
3110
    qemu_put_be32s(f, &s->hw_cursor_x);
3111
    qemu_put_be32s(f, &s->hw_cursor_y);
3112
    /* XXX: we do not save the bitblt state - we assume we do not save
3113
       the state when the blitter is active */
3114
}
3115

    
3116
static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id)
3117
{
3118
    CirrusVGAState *s = opaque;
3119
    int ret;
3120

    
3121
    if (version_id > 2)
3122
        return -EINVAL;
3123

    
3124
    if (s->pci_dev && version_id >= 2) {
3125
        ret = pci_device_load(s->pci_dev, f);
3126
        if (ret < 0)
3127
            return ret;
3128
    }
3129

    
3130
    qemu_get_be32s(f, &s->latch);
3131
    qemu_get_8s(f, &s->sr_index);
3132
    qemu_get_buffer(f, s->sr, 256);
3133
    qemu_get_8s(f, &s->gr_index);
3134
    qemu_get_8s(f, &s->cirrus_shadow_gr0);
3135
    qemu_get_8s(f, &s->cirrus_shadow_gr1);
3136
    s->gr[0x00] = s->cirrus_shadow_gr0 & 0x0f;
3137
    s->gr[0x01] = s->cirrus_shadow_gr1 & 0x0f;
3138
    qemu_get_buffer(f, s->gr + 2, 254);
3139
    qemu_get_8s(f, &s->ar_index);
3140
    qemu_get_buffer(f, s->ar, 21);
3141
    s->ar_flip_flop=qemu_get_be32(f);
3142
    qemu_get_8s(f, &s->cr_index);
3143
    qemu_get_buffer(f, s->cr, 256);
3144
    qemu_get_8s(f, &s->msr);
3145
    qemu_get_8s(f, &s->fcr);
3146
    qemu_get_8s(f, &s->st00);
3147
    qemu_get_8s(f, &s->st01);
3148

    
3149
    qemu_get_8s(f, &s->dac_state);
3150
    qemu_get_8s(f, &s->dac_sub_index);
3151
    qemu_get_8s(f, &s->dac_read_index);
3152
    qemu_get_8s(f, &s->dac_write_index);
3153
    qemu_get_buffer(f, s->dac_cache, 3);
3154
    qemu_get_buffer(f, s->palette, 768);
3155

    
3156
    s->bank_offset=qemu_get_be32(f);
3157

    
3158
    qemu_get_8s(f, &s->cirrus_hidden_dac_lockindex);
3159
    qemu_get_8s(f, &s->cirrus_hidden_dac_data);
3160

    
3161
    qemu_get_be32s(f, &s->hw_cursor_x);
3162
    qemu_get_be32s(f, &s->hw_cursor_y);
3163

    
3164
    cirrus_update_memory_access(s);
3165
    /* force refresh */
3166
    s->graphic_mode = -1;
3167
    cirrus_update_bank_ptr(s, 0);
3168
    cirrus_update_bank_ptr(s, 1);
3169
    return 0;
3170
}
3171

    
3172
/***************************************
3173
 *
3174
 *  initialize
3175
 *
3176
 ***************************************/
3177

    
3178
static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
3179
{
3180
    int i;
3181
    static int inited;
3182

    
3183
    if (!inited) {
3184
        inited = 1;
3185
        for(i = 0;i < 256; i++)
3186
            rop_to_index[i] = CIRRUS_ROP_NOP_INDEX; /* nop rop */
3187
        rop_to_index[CIRRUS_ROP_0] = 0;
3188
        rop_to_index[CIRRUS_ROP_SRC_AND_DST] = 1;
3189
        rop_to_index[CIRRUS_ROP_NOP] = 2;
3190
        rop_to_index[CIRRUS_ROP_SRC_AND_NOTDST] = 3;
3191
        rop_to_index[CIRRUS_ROP_NOTDST] = 4;
3192
        rop_to_index[CIRRUS_ROP_SRC] = 5;
3193
        rop_to_index[CIRRUS_ROP_1] = 6;
3194
        rop_to_index[CIRRUS_ROP_NOTSRC_AND_DST] = 7;
3195
        rop_to_index[CIRRUS_ROP_SRC_XOR_DST] = 8;
3196
        rop_to_index[CIRRUS_ROP_SRC_OR_DST] = 9;
3197
        rop_to_index[CIRRUS_ROP_NOTSRC_OR_NOTDST] = 10;
3198
        rop_to_index[CIRRUS_ROP_SRC_NOTXOR_DST] = 11;
3199
        rop_to_index[CIRRUS_ROP_SRC_OR_NOTDST] = 12;
3200
        rop_to_index[CIRRUS_ROP_NOTSRC] = 13;
3201
        rop_to_index[CIRRUS_ROP_NOTSRC_OR_DST] = 14;
3202
        rop_to_index[CIRRUS_ROP_NOTSRC_AND_NOTDST] = 15;
3203
    }
3204

    
3205
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
3206

    
3207
    register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
3208
    register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
3209
    register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
3210
    register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
3211

    
3212
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
3213

    
3214
    register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
3215
    register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
3216
    register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
3217
    register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
3218

    
3219
    s->vga_io_memory = cpu_register_io_memory(0, cirrus_vga_mem_read,
3220
                                           cirrus_vga_mem_write, s);
3221
    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
3222
                                 s->vga_io_memory);
3223
    qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
3224

    
3225
    s->sr[0x06] = 0x0f;
3226
    if (device_id == CIRRUS_ID_CLGD5446) {
3227
        /* 4MB 64 bit memory config, always PCI */
3228
        s->sr[0x1F] = 0x2d;                // MemClock
3229
        s->gr[0x18] = 0x0f;             // fastest memory configuration
3230
#if 1
3231
        s->sr[0x0f] = 0x98;
3232
        s->sr[0x17] = 0x20;
3233
        s->sr[0x15] = 0x04; /* memory size, 3=2MB, 4=4MB */
3234
        s->real_vram_size = 4096 * 1024;
3235
#else
3236
        s->sr[0x0f] = 0x18;
3237
        s->sr[0x17] = 0x20;
3238
        s->sr[0x15] = 0x03; /* memory size, 3=2MB, 4=4MB */
3239
        s->real_vram_size = 2048 * 1024;
3240
#endif
3241
    } else {
3242
        s->sr[0x1F] = 0x22;                // MemClock
3243
        s->sr[0x0F] = CIRRUS_MEMSIZE_2M;
3244
        if (is_pci)
3245
            s->sr[0x17] = CIRRUS_BUSTYPE_PCI;
3246
        else
3247
            s->sr[0x17] = CIRRUS_BUSTYPE_ISA;
3248
        s->real_vram_size = 2048 * 1024;
3249
        s->sr[0x15] = 0x03; /* memory size, 3=2MB, 4=4MB */
3250
    }
3251
    s->cr[0x27] = device_id;
3252

    
3253
    /* Win2K seems to assume that the pattern buffer is at 0xff
3254
       initially ! */
3255
    memset(s->vram_ptr, 0xff, s->real_vram_size);
3256

    
3257
    s->cirrus_hidden_dac_lockindex = 5;
3258
    s->cirrus_hidden_dac_data = 0;
3259

    
3260
    /* I/O handler for LFB */
3261
    s->cirrus_linear_io_addr =
3262
        cpu_register_io_memory(0, cirrus_linear_read, cirrus_linear_write,
3263
                               s);
3264
    s->cirrus_linear_write = cpu_get_io_memory_write(s->cirrus_linear_io_addr);
3265

    
3266
    /* I/O handler for LFB */
3267
    s->cirrus_linear_bitblt_io_addr =
3268
        cpu_register_io_memory(0, cirrus_linear_bitblt_read, cirrus_linear_bitblt_write,
3269
                               s);
3270

    
3271
    /* I/O handler for memory-mapped I/O */
3272
    s->cirrus_mmio_io_addr =
3273
        cpu_register_io_memory(0, cirrus_mmio_read, cirrus_mmio_write, s);
3274

    
3275
    /* XXX: s->vram_size must be a power of two */
3276
    s->cirrus_addr_mask = s->real_vram_size - 1;
3277
    s->linear_mmio_mask = s->real_vram_size - 256;
3278

    
3279
    s->get_bpp = cirrus_get_bpp;
3280
    s->get_offsets = cirrus_get_offsets;
3281
    s->get_resolution = cirrus_get_resolution;
3282
    s->cursor_invalidate = cirrus_cursor_invalidate;
3283
    s->cursor_draw_line = cirrus_cursor_draw_line;
3284

    
3285
    register_savevm("cirrus_vga", 0, 2, cirrus_vga_save, cirrus_vga_load, s);
3286
}
3287

    
3288
/***************************************
3289
 *
3290
 *  ISA bus support
3291
 *
3292
 ***************************************/
3293

    
3294
void isa_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
3295
                         ram_addr_t vga_ram_offset, int vga_ram_size)
3296
{
3297
    CirrusVGAState *s;
3298

    
3299
    s = qemu_mallocz(sizeof(CirrusVGAState));
3300

    
3301
    vga_common_init((VGAState *)s,
3302
                    ds, vga_ram_base, vga_ram_offset, vga_ram_size);
3303
    cirrus_init_common(s, CIRRUS_ID_CLGD5430, 0);
3304
    s->console = graphic_console_init(s->ds, s->update, s->invalidate,
3305
                                      s->screen_dump, s->text_update, s);
3306
    /* XXX ISA-LFB support */
3307
}
3308

    
3309
/***************************************
3310
 *
3311
 *  PCI bus support
3312
 *
3313
 ***************************************/
3314

    
3315
static void cirrus_pci_lfb_map(PCIDevice *d, int region_num,
3316
                               uint32_t addr, uint32_t size, int type)
3317
{
3318
    CirrusVGAState *s = &((PCICirrusVGAState *)d)->cirrus_vga;
3319

    
3320
    /* XXX: add byte swapping apertures */
3321
    cpu_register_physical_memory(addr, s->vram_size,
3322
                                 s->cirrus_linear_io_addr);
3323
    cpu_register_physical_memory(addr + 0x1000000, 0x400000,
3324
                                 s->cirrus_linear_bitblt_io_addr);
3325

    
3326
    s->map_addr = s->map_end = 0;
3327
    s->lfb_addr = addr & TARGET_PAGE_MASK;
3328
    s->lfb_end = ((addr + VGA_RAM_SIZE) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK;
3329
    /* account for overflow */
3330
    if (s->lfb_end < addr + VGA_RAM_SIZE)
3331
        s->lfb_end = addr + VGA_RAM_SIZE;
3332
}
3333

    
3334
static void cirrus_pci_mmio_map(PCIDevice *d, int region_num,
3335
                                uint32_t addr, uint32_t size, int type)
3336
{
3337
    CirrusVGAState *s = &((PCICirrusVGAState *)d)->cirrus_vga;
3338

    
3339
    cpu_register_physical_memory(addr, CIRRUS_PNPMMIO_SIZE,
3340
                                 s->cirrus_mmio_io_addr);
3341
}
3342

    
3343
void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
3344
                         ram_addr_t vga_ram_offset, int vga_ram_size)
3345
{
3346
    PCICirrusVGAState *d;
3347
    uint8_t *pci_conf;
3348
    CirrusVGAState *s;
3349
    int device_id;
3350

    
3351
    device_id = CIRRUS_ID_CLGD5446;
3352

    
3353
    /* setup PCI configuration registers */
3354
    d = (PCICirrusVGAState *)pci_register_device(bus, "Cirrus VGA",
3355
                                                 sizeof(PCICirrusVGAState),
3356
                                                 -1, NULL, NULL);
3357
    pci_conf = d->dev.config;
3358
    pci_conf[0x00] = (uint8_t) (PCI_VENDOR_CIRRUS & 0xff);
3359
    pci_conf[0x01] = (uint8_t) (PCI_VENDOR_CIRRUS >> 8);
3360
    pci_conf[0x02] = (uint8_t) (device_id & 0xff);
3361
    pci_conf[0x03] = (uint8_t) (device_id >> 8);
3362
    pci_conf[0x04] = PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS;
3363
    pci_conf[0x0a] = PCI_CLASS_SUB_VGA;
3364
    pci_conf[0x0b] = PCI_CLASS_BASE_DISPLAY;
3365
    pci_conf[0x0e] = PCI_CLASS_HEADERTYPE_00h;
3366

    
3367
    /* setup VGA */
3368
    s = &d->cirrus_vga;
3369
    vga_common_init((VGAState *)s,
3370
                    ds, vga_ram_base, vga_ram_offset, vga_ram_size);
3371
    cirrus_init_common(s, device_id, 1);
3372

    
3373
    s->console = graphic_console_init(s->ds, s->update, s->invalidate,
3374
                                      s->screen_dump, s->text_update, s);
3375

    
3376
    s->pci_dev = (PCIDevice *)d;
3377

    
3378
    /* setup memory space */
3379
    /* memory #0 LFB */
3380
    /* memory #1 memory-mapped I/O */
3381
    /* XXX: s->vram_size must be a power of two */
3382
    pci_register_io_region((PCIDevice *)d, 0, 0x2000000,
3383
                           PCI_ADDRESS_SPACE_MEM_PREFETCH, cirrus_pci_lfb_map);
3384
    if (device_id == CIRRUS_ID_CLGD5446) {
3385
        pci_register_io_region((PCIDevice *)d, 1, CIRRUS_PNPMMIO_SIZE,
3386
                               PCI_ADDRESS_SPACE_MEM, cirrus_pci_mmio_map);
3387
    }
3388
    /* XXX: ROM BIOS */
3389
}