Statistics
| Branch: | Revision:

root / hw / cirrus_vga.c @ c60e08d9

History | View | Annotate | Download (97 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

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

    
42
//#define DEBUG_CIRRUS
43
//#define DEBUG_BITBLT
44

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

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

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

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

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

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

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

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

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

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

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

    
136
#define CIRRUS_ROP_NOP_INDEX 2
137
#define CIRRUS_ROP_SRC_INDEX 5
138

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

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

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

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

    
216
#define CIRRUS_PNPMMIO_SIZE         0x1000
217

    
218

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

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

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

    
245
typedef struct CirrusVGAState {
246
    VGA_STATE_COMMON
247

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

    
289
typedef struct PCICirrusVGAState {
290
    PCIDevice dev;
291
    CirrusVGAState cirrus_vga;
292
} PCICirrusVGAState;
293

    
294
static uint8_t rop_to_index[256];
295

    
296
/***************************************
297
 *
298
 *  prototypes.
299
 *
300
 ***************************************/
301

    
302

    
303
static void cirrus_bitblt_reset(CirrusVGAState *s);
304
static void cirrus_update_memory_access(CirrusVGAState *s);
305

    
306
/***************************************
307
 *
308
 *  raster operations
309
 *
310
 ***************************************/
311

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

    
319
static void cirrus_bitblt_fill_nop(CirrusVGAState *s,
320
                                   uint8_t *dst,
321
                                   int dstpitch, int bltwidth,int bltheight)
322
{
323
}
324

    
325
#define ROP_NAME 0
326
#define ROP_OP(d, s) d = 0
327
#include "cirrus_vga_rop.h"
328

    
329
#define ROP_NAME src_and_dst
330
#define ROP_OP(d, s) d = (s) & (d)
331
#include "cirrus_vga_rop.h"
332

    
333
#define ROP_NAME src_and_notdst
334
#define ROP_OP(d, s) d = (s) & (~(d))
335
#include "cirrus_vga_rop.h"
336

    
337
#define ROP_NAME notdst
338
#define ROP_OP(d, s) d = ~(d)
339
#include "cirrus_vga_rop.h"
340

    
341
#define ROP_NAME src
342
#define ROP_OP(d, s) d = s
343
#include "cirrus_vga_rop.h"
344

    
345
#define ROP_NAME 1
346
#define ROP_OP(d, s) d = ~0
347
#include "cirrus_vga_rop.h"
348

    
349
#define ROP_NAME notsrc_and_dst
350
#define ROP_OP(d, s) d = (~(s)) & (d)
351
#include "cirrus_vga_rop.h"
352

    
353
#define ROP_NAME src_xor_dst
354
#define ROP_OP(d, s) d = (s) ^ (d)
355
#include "cirrus_vga_rop.h"
356

    
357
#define ROP_NAME src_or_dst
358
#define ROP_OP(d, s) d = (s) | (d)
359
#include "cirrus_vga_rop.h"
360

    
361
#define ROP_NAME notsrc_or_notdst
362
#define ROP_OP(d, s) d = (~(s)) | (~(d))
363
#include "cirrus_vga_rop.h"
364

    
365
#define ROP_NAME src_notxor_dst
366
#define ROP_OP(d, s) d = ~((s) ^ (d))
367
#include "cirrus_vga_rop.h"
368

    
369
#define ROP_NAME src_or_notdst
370
#define ROP_OP(d, s) d = (s) | (~(d))
371
#include "cirrus_vga_rop.h"
372

    
373
#define ROP_NAME notsrc
374
#define ROP_OP(d, s) d = (~(s))
375
#include "cirrus_vga_rop.h"
376

    
377
#define ROP_NAME notsrc_or_dst
378
#define ROP_OP(d, s) d = (~(s)) | (d)
379
#include "cirrus_vga_rop.h"
380

    
381
#define ROP_NAME notsrc_and_notdst
382
#define ROP_OP(d, s) d = (~(s)) & (~(d))
383
#include "cirrus_vga_rop.h"
384

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

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

    
423
#define TRANSP_ROP(name) {\
424
    name ## _8,\
425
    name ## _16,\
426
        }
427
#define TRANSP_NOP(func) {\
428
    func,\
429
    func,\
430
        }
431

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

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

    
470
#define ROP2(name) {\
471
    name ## _8,\
472
    name ## _16,\
473
    name ## _24,\
474
    name ## _32,\
475
        }
476

    
477
#define ROP_NOP2(func) {\
478
    func,\
479
    func,\
480
    func,\
481
    func,\
482
        }
483

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

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

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

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

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

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

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

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

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

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

    
666
static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s,
667
                                            const uint8_t * src)
668
{
669
    uint8_t *dst;
670

    
671
    dst = s->vram_ptr + (s->cirrus_blt_dstaddr & s->cirrus_addr_mask);
672

    
673
    if (BLTUNSAFE(s))
674
        return 0;
675

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

    
685
/* fill */
686

    
687
static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop)
688
{
689
    cirrus_fill_t rop_func;
690

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

    
704
/***************************************
705
 *
706
 *  bitblt (video-to-video)
707
 *
708
 ***************************************/
709

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

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

    
725
    depth = s->get_bpp((VGAState *)s) / 8;
726
    s->get_resolution((VGAState *)s, &width, &height);
727

    
728
    /* extra x, y */
729
    sx = (src % (width * depth)) / depth;
730
    sy = (src / (width * depth));
731
    dx = (dst % (width *depth)) / depth;
732
    dy = (dst / (width * depth));
733

    
734
    /* normalize width */
735
    w /= depth;
736

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

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

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

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

    
764
    (*s->cirrus_rop) (s, s->vram_ptr +
765
                      (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
766
                      s->vram_ptr +
767
                      (s->cirrus_blt_srcaddr & s->cirrus_addr_mask),
768
                      s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
769
                      s->cirrus_blt_width, s->cirrus_blt_height);
770

    
771
    if (notify)
772
        s->ds->dpy_copy(s->ds,
773
                        sx, sy, dx, dy,
774
                        s->cirrus_blt_width / depth,
775
                        s->cirrus_blt_height);
776

    
777
    /* we don't have to notify the display that this portion has
778
       changed since dpy_copy implies this */
779

    
780
    if (!notify)
781
        cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
782
                                 s->cirrus_blt_dstpitch, s->cirrus_blt_width,
783
                                 s->cirrus_blt_height);
784
}
785

    
786
static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
787
{
788
    if (s->ds->dpy_copy) {
789
        cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->start_addr,
790
                       s->cirrus_blt_srcaddr - s->start_addr,
791
                       s->cirrus_blt_width, s->cirrus_blt_height);
792
    } else {
793

    
794
    if (BLTUNSAFE(s))
795
        return 0;
796

    
797
        (*s->cirrus_rop) (s, s->vram_ptr +
798
                (s->cirrus_blt_dstaddr & s->cirrus_addr_mask),
799
                          s->vram_ptr +
800
                (s->cirrus_blt_srcaddr & s->cirrus_addr_mask),
801
                          s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
802
                          s->cirrus_blt_width, s->cirrus_blt_height);
803

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

    
809
    return 1;
810
}
811

    
812
/***************************************
813
 *
814
 *  bitblt (cpu-to-video)
815
 *
816
 ***************************************/
817

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

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

    
854
/***************************************
855
 *
856
 *  bitblt wrapper
857
 *
858
 ***************************************/
859

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

    
870
static int cirrus_bitblt_cputovideo(CirrusVGAState * s)
871
{
872
    int w;
873

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

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

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

    
914
static int cirrus_bitblt_videotovideo(CirrusVGAState * s)
915
{
916
    int ret;
917

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

    
928
static void cirrus_bitblt_start(CirrusVGAState * s)
929
{
930
    uint8_t blt_rop;
931

    
932
    s->gr[0x31] |= CIRRUS_BLT_BUSY;
933

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

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

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

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

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

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

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

    
1075
    old_value = s->gr[0x31];
1076
    s->gr[0x31] = reg_value;
1077

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

    
1087

    
1088
/***************************************
1089
 *
1090
 *  basic parameters
1091
 *
1092
 ***************************************/
1093

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

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

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

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

    
1120
static uint32_t cirrus_get_bpp16_depth(CirrusVGAState * s)
1121
{
1122
    uint32_t ret = 16;
1123

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

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

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

    
1177
    return ret;
1178
}
1179

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

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

    
1196
/***************************************
1197
 *
1198
 * bank memory
1199
 *
1200
 ***************************************/
1201

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

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

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

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

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

    
1231
    if (limit > 0) {
1232
        s->cirrus_bank_base[bank_index] = offset;
1233
        s->cirrus_bank_limit[bank_index] = limit;
1234
    } else {
1235
        s->cirrus_bank_base[bank_index] = 0;
1236
        s->cirrus_bank_limit[bank_index] = 0;
1237
    }
1238
}
1239

    
1240
/***************************************
1241
 *
1242
 *  I/O access between 0x3c4-0x3c5
1243
 *
1244
 ***************************************/
1245

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

    
1316
    return CIRRUS_HOOK_HANDLED;
1317
}
1318

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

    
1399
    return CIRRUS_HOOK_HANDLED;
1400
}
1401

    
1402
/***************************************
1403
 *
1404
 *  I/O access at 0x3c6
1405
 *
1406
 ***************************************/
1407

    
1408
static void cirrus_read_hidden_dac(CirrusVGAState * s, int *reg_value)
1409
{
1410
    *reg_value = 0xff;
1411
    if (++s->cirrus_hidden_dac_lockindex == 5) {
1412
        *reg_value = s->cirrus_hidden_dac_data;
1413
        s->cirrus_hidden_dac_lockindex = 0;
1414
    }
1415
}
1416

    
1417
static void cirrus_write_hidden_dac(CirrusVGAState * s, int reg_value)
1418
{
1419
    if (s->cirrus_hidden_dac_lockindex == 4) {
1420
        s->cirrus_hidden_dac_data = reg_value;
1421
#if defined(DEBUG_CIRRUS)
1422
        printf("cirrus: outport hidden DAC, value %02x\n", reg_value);
1423
#endif
1424
    }
1425
    s->cirrus_hidden_dac_lockindex = 0;
1426
}
1427

    
1428
/***************************************
1429
 *
1430
 *  I/O access at 0x3c9
1431
 *
1432
 ***************************************/
1433

    
1434
static int cirrus_hook_read_palette(CirrusVGAState * s, int *reg_value)
1435
{
1436
    if (!(s->sr[0x12] & CIRRUS_CURSOR_HIDDENPEL))
1437
        return CIRRUS_HOOK_NOT_HANDLED;
1438
    *reg_value =
1439
        s->cirrus_hidden_palette[(s->dac_read_index & 0x0f) * 3 +
1440
                                 s->dac_sub_index];
1441
    if (++s->dac_sub_index == 3) {
1442
        s->dac_sub_index = 0;
1443
        s->dac_read_index++;
1444
    }
1445
    return CIRRUS_HOOK_HANDLED;
1446
}
1447

    
1448
static int cirrus_hook_write_palette(CirrusVGAState * s, int reg_value)
1449
{
1450
    if (!(s->sr[0x12] & CIRRUS_CURSOR_HIDDENPEL))
1451
        return CIRRUS_HOOK_NOT_HANDLED;
1452
    s->dac_cache[s->dac_sub_index] = reg_value;
1453
    if (++s->dac_sub_index == 3) {
1454
        memcpy(&s->cirrus_hidden_palette[(s->dac_write_index & 0x0f) * 3],
1455
               s->dac_cache, 3);
1456
        /* XXX update cursor */
1457
        s->dac_sub_index = 0;
1458
        s->dac_write_index++;
1459
    }
1460
    return CIRRUS_HOOK_HANDLED;
1461
}
1462

    
1463
/***************************************
1464
 *
1465
 *  I/O access between 0x3ce-0x3cf
1466
 *
1467
 ***************************************/
1468

    
1469
static int
1470
cirrus_hook_read_gr(CirrusVGAState * s, unsigned reg_index, int *reg_value)
1471
{
1472
    switch (reg_index) {
1473
    case 0x00: // Standard VGA, BGCOLOR 0x000000ff
1474
      *reg_value = s->cirrus_shadow_gr0;
1475
      return CIRRUS_HOOK_HANDLED;
1476
    case 0x01: // Standard VGA, FGCOLOR 0x000000ff
1477
      *reg_value = s->cirrus_shadow_gr1;
1478
      return CIRRUS_HOOK_HANDLED;
1479
    case 0x02:                        // Standard VGA
1480
    case 0x03:                        // Standard VGA
1481
    case 0x04:                        // Standard VGA
1482
    case 0x06:                        // Standard VGA
1483
    case 0x07:                        // Standard VGA
1484
    case 0x08:                        // Standard VGA
1485
        return CIRRUS_HOOK_NOT_HANDLED;
1486
    case 0x05:                        // Standard VGA, Cirrus extended mode
1487
    default:
1488
        break;
1489
    }
1490

    
1491
    if (reg_index < 0x3a) {
1492
        *reg_value = s->gr[reg_index];
1493
    } else {
1494
#ifdef DEBUG_CIRRUS
1495
        printf("cirrus: inport gr_index %02x\n", reg_index);
1496
#endif
1497
        *reg_value = 0xff;
1498
    }
1499

    
1500
    return CIRRUS_HOOK_HANDLED;
1501
}
1502

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

    
1590
    return CIRRUS_HOOK_HANDLED;
1591
}
1592

    
1593
/***************************************
1594
 *
1595
 *  I/O access between 0x3d4-0x3d5
1596
 *
1597
 ***************************************/
1598

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

    
1653
    return CIRRUS_HOOK_HANDLED;
1654
}
1655

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

    
1711
    return CIRRUS_HOOK_HANDLED;
1712
}
1713

    
1714
/***************************************
1715
 *
1716
 *  memory-mapped I/O (bitblt)
1717
 *
1718
 ***************************************/
1719

    
1720
static uint8_t cirrus_mmio_blt_read(CirrusVGAState * s, unsigned address)
1721
{
1722
    int value = 0xff;
1723

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

    
1825
    return (uint8_t) value;
1826
}
1827

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

    
1937
/***************************************
1938
 *
1939
 *  write mode 4/5
1940
 *
1941
 * assume TARGET_PAGE_SIZE >= 16
1942
 *
1943
 ***************************************/
1944

    
1945
static void cirrus_mem_writeb_mode4and5_8bpp(CirrusVGAState * s,
1946
                                             unsigned mode,
1947
                                             unsigned offset,
1948
                                             uint32_t mem_value)
1949
{
1950
    int x;
1951
    unsigned val = mem_value;
1952
    uint8_t *dst;
1953

    
1954
    dst = s->vram_ptr + (offset &= s->cirrus_addr_mask);
1955
    for (x = 0; x < 8; x++) {
1956
        if (val & 0x80) {
1957
            *dst = s->cirrus_shadow_gr1;
1958
        } else if (mode == 5) {
1959
            *dst = s->cirrus_shadow_gr0;
1960
        }
1961
        val <<= 1;
1962
        dst++;
1963
    }
1964
    cpu_physical_memory_set_dirty(s->vram_offset + offset);
1965
    cpu_physical_memory_set_dirty(s->vram_offset + offset + 7);
1966
}
1967

    
1968
static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,
1969
                                              unsigned mode,
1970
                                              unsigned offset,
1971
                                              uint32_t mem_value)
1972
{
1973
    int x;
1974
    unsigned val = mem_value;
1975
    uint8_t *dst;
1976

    
1977
    dst = s->vram_ptr + (offset &= s->cirrus_addr_mask);
1978
    for (x = 0; x < 8; x++) {
1979
        if (val & 0x80) {
1980
            *dst = s->cirrus_shadow_gr1;
1981
            *(dst + 1) = s->gr[0x11];
1982
        } else if (mode == 5) {
1983
            *dst = s->cirrus_shadow_gr0;
1984
            *(dst + 1) = s->gr[0x10];
1985
        }
1986
        val <<= 1;
1987
        dst += 2;
1988
    }
1989
    cpu_physical_memory_set_dirty(s->vram_offset + offset);
1990
    cpu_physical_memory_set_dirty(s->vram_offset + offset + 15);
1991
}
1992

    
1993
/***************************************
1994
 *
1995
 *  memory access between 0xa0000-0xbffff
1996
 *
1997
 ***************************************/
1998

    
1999
static uint32_t cirrus_vga_mem_readb(void *opaque, target_phys_addr_t addr)
2000
{
2001
    CirrusVGAState *s = opaque;
2002
    unsigned bank_index;
2003
    unsigned bank_offset;
2004
    uint32_t val;
2005

    
2006
    if ((s->sr[0x07] & 0x01) == 0) {
2007
        return vga_mem_readb(s, addr);
2008
    }
2009

    
2010
    addr &= 0x1ffff;
2011

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

    
2043
static uint32_t cirrus_vga_mem_readw(void *opaque, target_phys_addr_t addr)
2044
{
2045
    uint32_t v;
2046
#ifdef TARGET_WORDS_BIGENDIAN
2047
    v = cirrus_vga_mem_readb(opaque, addr) << 8;
2048
    v |= cirrus_vga_mem_readb(opaque, addr + 1);
2049
#else
2050
    v = cirrus_vga_mem_readb(opaque, addr);
2051
    v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
2052
#endif
2053
    return v;
2054
}
2055

    
2056
static uint32_t cirrus_vga_mem_readl(void *opaque, target_phys_addr_t addr)
2057
{
2058
    uint32_t v;
2059
#ifdef TARGET_WORDS_BIGENDIAN
2060
    v = cirrus_vga_mem_readb(opaque, addr) << 24;
2061
    v |= cirrus_vga_mem_readb(opaque, addr + 1) << 16;
2062
    v |= cirrus_vga_mem_readb(opaque, addr + 2) << 8;
2063
    v |= cirrus_vga_mem_readb(opaque, addr + 3);
2064
#else
2065
    v = cirrus_vga_mem_readb(opaque, addr);
2066
    v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
2067
    v |= cirrus_vga_mem_readb(opaque, addr + 2) << 16;
2068
    v |= cirrus_vga_mem_readb(opaque, addr + 3) << 24;
2069
#endif
2070
    return v;
2071
}
2072

    
2073
static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr,
2074
                                  uint32_t mem_value)
2075
{
2076
    CirrusVGAState *s = opaque;
2077
    unsigned bank_index;
2078
    unsigned bank_offset;
2079
    unsigned mode;
2080

    
2081
    if ((s->sr[0x07] & 0x01) == 0) {
2082
        vga_mem_writeb(s, addr, mem_value);
2083
        return;
2084
    }
2085

    
2086
    addr &= 0x1ffff;
2087

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

    
2137
static void cirrus_vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
2138
{
2139
#ifdef TARGET_WORDS_BIGENDIAN
2140
    cirrus_vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
2141
    cirrus_vga_mem_writeb(opaque, addr + 1, val & 0xff);
2142
#else
2143
    cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
2144
    cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2145
#endif
2146
}
2147

    
2148
static void cirrus_vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
2149
{
2150
#ifdef TARGET_WORDS_BIGENDIAN
2151
    cirrus_vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
2152
    cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
2153
    cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
2154
    cirrus_vga_mem_writeb(opaque, addr + 3, val & 0xff);
2155
#else
2156
    cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
2157
    cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2158
    cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
2159
    cirrus_vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
2160
#endif
2161
}
2162

    
2163
static CPUReadMemoryFunc *cirrus_vga_mem_read[3] = {
2164
    cirrus_vga_mem_readb,
2165
    cirrus_vga_mem_readw,
2166
    cirrus_vga_mem_readl,
2167
};
2168

    
2169
static CPUWriteMemoryFunc *cirrus_vga_mem_write[3] = {
2170
    cirrus_vga_mem_writeb,
2171
    cirrus_vga_mem_writew,
2172
    cirrus_vga_mem_writel,
2173
};
2174

    
2175
/***************************************
2176
 *
2177
 *  hardware cursor
2178
 *
2179
 ***************************************/
2180

    
2181
static inline void invalidate_cursor1(CirrusVGAState *s)
2182
{
2183
    if (s->last_hw_cursor_size) {
2184
        vga_invalidate_scanlines((VGAState *)s,
2185
                                 s->last_hw_cursor_y + s->last_hw_cursor_y_start,
2186
                                 s->last_hw_cursor_y + s->last_hw_cursor_y_end);
2187
    }
2188
}
2189

    
2190
static inline void cirrus_cursor_compute_yrange(CirrusVGAState *s)
2191
{
2192
    const uint8_t *src;
2193
    uint32_t content;
2194
    int y, y_min, y_max;
2195

    
2196
    src = s->vram_ptr + s->real_vram_size - 16 * 1024;
2197
    if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) {
2198
        src += (s->sr[0x13] & 0x3c) * 256;
2199
        y_min = 64;
2200
        y_max = -1;
2201
        for(y = 0; y < 64; y++) {
2202
            content = ((uint32_t *)src)[0] |
2203
                ((uint32_t *)src)[1] |
2204
                ((uint32_t *)src)[2] |
2205
                ((uint32_t *)src)[3];
2206
            if (content) {
2207
                if (y < y_min)
2208
                    y_min = y;
2209
                if (y > y_max)
2210
                    y_max = y;
2211
            }
2212
            src += 16;
2213
        }
2214
    } else {
2215
        src += (s->sr[0x13] & 0x3f) * 256;
2216
        y_min = 32;
2217
        y_max = -1;
2218
        for(y = 0; y < 32; y++) {
2219
            content = ((uint32_t *)src)[0] |
2220
                ((uint32_t *)(src + 128))[0];
2221
            if (content) {
2222
                if (y < y_min)
2223
                    y_min = y;
2224
                if (y > y_max)
2225
                    y_max = y;
2226
            }
2227
            src += 4;
2228
        }
2229
    }
2230
    if (y_min > y_max) {
2231
        s->last_hw_cursor_y_start = 0;
2232
        s->last_hw_cursor_y_end = 0;
2233
    } else {
2234
        s->last_hw_cursor_y_start = y_min;
2235
        s->last_hw_cursor_y_end = y_max + 1;
2236
    }
2237
}
2238

    
2239
/* NOTE: we do not currently handle the cursor bitmap change, so we
2240
   update the cursor only if it moves. */
2241
static void cirrus_cursor_invalidate(VGAState *s1)
2242
{
2243
    CirrusVGAState *s = (CirrusVGAState *)s1;
2244
    int size;
2245

    
2246
    if (!s->sr[0x12] & CIRRUS_CURSOR_SHOW) {
2247
        size = 0;
2248
    } else {
2249
        if (s->sr[0x12] & CIRRUS_CURSOR_LARGE)
2250
            size = 64;
2251
        else
2252
            size = 32;
2253
    }
2254
    /* invalidate last cursor and new cursor if any change */
2255
    if (s->last_hw_cursor_size != size ||
2256
        s->last_hw_cursor_x != s->hw_cursor_x ||
2257
        s->last_hw_cursor_y != s->hw_cursor_y) {
2258

    
2259
        invalidate_cursor1(s);
2260

    
2261
        s->last_hw_cursor_size = size;
2262
        s->last_hw_cursor_x = s->hw_cursor_x;
2263
        s->last_hw_cursor_y = s->hw_cursor_y;
2264
        /* compute the real cursor min and max y */
2265
        cirrus_cursor_compute_yrange(s);
2266
        invalidate_cursor1(s);
2267
    }
2268
}
2269

    
2270
static void cirrus_cursor_draw_line(VGAState *s1, uint8_t *d1, int scr_y)
2271
{
2272
    CirrusVGAState *s = (CirrusVGAState *)s1;
2273
    int w, h, bpp, x1, x2, poffset;
2274
    unsigned int color0, color1;
2275
    const uint8_t *palette, *src;
2276
    uint32_t content;
2277

    
2278
    if (!(s->sr[0x12] & CIRRUS_CURSOR_SHOW))
2279
        return;
2280
    /* fast test to see if the cursor intersects with the scan line */
2281
    if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) {
2282
        h = 64;
2283
    } else {
2284
        h = 32;
2285
    }
2286
    if (scr_y < s->hw_cursor_y ||
2287
        scr_y >= (s->hw_cursor_y + h))
2288
        return;
2289

    
2290
    src = s->vram_ptr + s->real_vram_size - 16 * 1024;
2291
    if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) {
2292
        src += (s->sr[0x13] & 0x3c) * 256;
2293
        src += (scr_y - s->hw_cursor_y) * 16;
2294
        poffset = 8;
2295
        content = ((uint32_t *)src)[0] |
2296
            ((uint32_t *)src)[1] |
2297
            ((uint32_t *)src)[2] |
2298
            ((uint32_t *)src)[3];
2299
    } else {
2300
        src += (s->sr[0x13] & 0x3f) * 256;
2301
        src += (scr_y - s->hw_cursor_y) * 4;
2302
        poffset = 128;
2303
        content = ((uint32_t *)src)[0] |
2304
            ((uint32_t *)(src + 128))[0];
2305
    }
2306
    /* if nothing to draw, no need to continue */
2307
    if (!content)
2308
        return;
2309
    w = h;
2310

    
2311
    x1 = s->hw_cursor_x;
2312
    if (x1 >= s->last_scr_width)
2313
        return;
2314
    x2 = s->hw_cursor_x + w;
2315
    if (x2 > s->last_scr_width)
2316
        x2 = s->last_scr_width;
2317
    w = x2 - x1;
2318
    palette = s->cirrus_hidden_palette;
2319
    color0 = s->rgb_to_pixel(c6_to_8(palette[0x0 * 3]),
2320
                             c6_to_8(palette[0x0 * 3 + 1]),
2321
                             c6_to_8(palette[0x0 * 3 + 2]));
2322
    color1 = s->rgb_to_pixel(c6_to_8(palette[0xf * 3]),
2323
                             c6_to_8(palette[0xf * 3 + 1]),
2324
                             c6_to_8(palette[0xf * 3 + 2]));
2325
    bpp = ((s->ds->depth + 7) >> 3);
2326
    d1 += x1 * bpp;
2327
    switch(s->ds->depth) {
2328
    default:
2329
        break;
2330
    case 8:
2331
        vga_draw_cursor_line_8(d1, src, poffset, w, color0, color1, 0xff);
2332
        break;
2333
    case 15:
2334
        vga_draw_cursor_line_16(d1, src, poffset, w, color0, color1, 0x7fff);
2335
        break;
2336
    case 16:
2337
        vga_draw_cursor_line_16(d1, src, poffset, w, color0, color1, 0xffff);
2338
        break;
2339
    case 32:
2340
        vga_draw_cursor_line_32(d1, src, poffset, w, color0, color1, 0xffffff);
2341
        break;
2342
    }
2343
}
2344

    
2345
/***************************************
2346
 *
2347
 *  LFB memory access
2348
 *
2349
 ***************************************/
2350

    
2351
static uint32_t cirrus_linear_readb(void *opaque, target_phys_addr_t addr)
2352
{
2353
    CirrusVGAState *s = (CirrusVGAState *) opaque;
2354
    uint32_t ret;
2355

    
2356
    addr &= s->cirrus_addr_mask;
2357

    
2358
    if (((s->sr[0x17] & 0x44) == 0x44) &&
2359
        ((addr & s->linear_mmio_mask) == s->linear_mmio_mask)) {
2360
        /* memory-mapped I/O */
2361
        ret = cirrus_mmio_blt_read(s, addr & 0xff);
2362
    } else if (0) {
2363
        /* XXX handle bitblt */
2364
        ret = 0xff;
2365
    } else {
2366
        /* video memory */
2367
        if ((s->gr[0x0B] & 0x14) == 0x14) {
2368
            addr <<= 4;
2369
        } else if (s->gr[0x0B] & 0x02) {
2370
            addr <<= 3;
2371
        }
2372
        addr &= s->cirrus_addr_mask;
2373
        ret = *(s->vram_ptr + addr);
2374
    }
2375

    
2376
    return ret;
2377
}
2378

    
2379
static uint32_t cirrus_linear_readw(void *opaque, target_phys_addr_t addr)
2380
{
2381
    uint32_t v;
2382
#ifdef TARGET_WORDS_BIGENDIAN
2383
    v = cirrus_linear_readb(opaque, addr) << 8;
2384
    v |= cirrus_linear_readb(opaque, addr + 1);
2385
#else
2386
    v = cirrus_linear_readb(opaque, addr);
2387
    v |= cirrus_linear_readb(opaque, addr + 1) << 8;
2388
#endif
2389
    return v;
2390
}
2391

    
2392
static uint32_t cirrus_linear_readl(void *opaque, target_phys_addr_t addr)
2393
{
2394
    uint32_t v;
2395
#ifdef TARGET_WORDS_BIGENDIAN
2396
    v = cirrus_linear_readb(opaque, addr) << 24;
2397
    v |= cirrus_linear_readb(opaque, addr + 1) << 16;
2398
    v |= cirrus_linear_readb(opaque, addr + 2) << 8;
2399
    v |= cirrus_linear_readb(opaque, addr + 3);
2400
#else
2401
    v = cirrus_linear_readb(opaque, addr);
2402
    v |= cirrus_linear_readb(opaque, addr + 1) << 8;
2403
    v |= cirrus_linear_readb(opaque, addr + 2) << 16;
2404
    v |= cirrus_linear_readb(opaque, addr + 3) << 24;
2405
#endif
2406
    return v;
2407
}
2408

    
2409
static void cirrus_linear_writeb(void *opaque, target_phys_addr_t addr,
2410
                                 uint32_t val)
2411
{
2412
    CirrusVGAState *s = (CirrusVGAState *) opaque;
2413
    unsigned mode;
2414

    
2415
    addr &= s->cirrus_addr_mask;
2416

    
2417
    if (((s->sr[0x17] & 0x44) == 0x44) &&
2418
        ((addr & s->linear_mmio_mask) ==  s->linear_mmio_mask)) {
2419
        /* memory-mapped I/O */
2420
        cirrus_mmio_blt_write(s, addr & 0xff, val);
2421
    } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
2422
        /* bitblt */
2423
        *s->cirrus_srcptr++ = (uint8_t) val;
2424
        if (s->cirrus_srcptr >= s->cirrus_srcptr_end) {
2425
            cirrus_bitblt_cputovideo_next(s);
2426
        }
2427
    } else {
2428
        /* video memory */
2429
        if ((s->gr[0x0B] & 0x14) == 0x14) {
2430
            addr <<= 4;
2431
        } else if (s->gr[0x0B] & 0x02) {
2432
            addr <<= 3;
2433
        }
2434
        addr &= s->cirrus_addr_mask;
2435

    
2436
        mode = s->gr[0x05] & 0x7;
2437
        if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
2438
            *(s->vram_ptr + addr) = (uint8_t) val;
2439
            cpu_physical_memory_set_dirty(s->vram_offset + addr);
2440
        } else {
2441
            if ((s->gr[0x0B] & 0x14) != 0x14) {
2442
                cirrus_mem_writeb_mode4and5_8bpp(s, mode, addr, val);
2443
            } else {
2444
                cirrus_mem_writeb_mode4and5_16bpp(s, mode, addr, val);
2445
            }
2446
        }
2447
    }
2448
}
2449

    
2450
static void cirrus_linear_writew(void *opaque, target_phys_addr_t addr,
2451
                                 uint32_t val)
2452
{
2453
#ifdef TARGET_WORDS_BIGENDIAN
2454
    cirrus_linear_writeb(opaque, addr, (val >> 8) & 0xff);
2455
    cirrus_linear_writeb(opaque, addr + 1, val & 0xff);
2456
#else
2457
    cirrus_linear_writeb(opaque, addr, val & 0xff);
2458
    cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2459
#endif
2460
}
2461

    
2462
static void cirrus_linear_writel(void *opaque, target_phys_addr_t addr,
2463
                                 uint32_t val)
2464
{
2465
#ifdef TARGET_WORDS_BIGENDIAN
2466
    cirrus_linear_writeb(opaque, addr, (val >> 24) & 0xff);
2467
    cirrus_linear_writeb(opaque, addr + 1, (val >> 16) & 0xff);
2468
    cirrus_linear_writeb(opaque, addr + 2, (val >> 8) & 0xff);
2469
    cirrus_linear_writeb(opaque, addr + 3, val & 0xff);
2470
#else
2471
    cirrus_linear_writeb(opaque, addr, val & 0xff);
2472
    cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2473
    cirrus_linear_writeb(opaque, addr + 2, (val >> 16) & 0xff);
2474
    cirrus_linear_writeb(opaque, addr + 3, (val >> 24) & 0xff);
2475
#endif
2476
}
2477

    
2478

    
2479
static CPUReadMemoryFunc *cirrus_linear_read[3] = {
2480
    cirrus_linear_readb,
2481
    cirrus_linear_readw,
2482
    cirrus_linear_readl,
2483
};
2484

    
2485
static CPUWriteMemoryFunc *cirrus_linear_write[3] = {
2486
    cirrus_linear_writeb,
2487
    cirrus_linear_writew,
2488
    cirrus_linear_writel,
2489
};
2490

    
2491
static void cirrus_linear_mem_writeb(void *opaque, target_phys_addr_t addr,
2492
                                     uint32_t val)
2493
{
2494
    CirrusVGAState *s = (CirrusVGAState *) opaque;
2495

    
2496
    addr &= s->cirrus_addr_mask;
2497
    *(s->vram_ptr + addr) = val;
2498
    cpu_physical_memory_set_dirty(s->vram_offset + addr);
2499
}
2500

    
2501
static void cirrus_linear_mem_writew(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
    cpu_to_le16w((uint16_t *)(s->vram_ptr + addr), val);
2508
    cpu_physical_memory_set_dirty(s->vram_offset + addr);
2509
}
2510

    
2511
static void cirrus_linear_mem_writel(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_le32w((uint32_t *)(s->vram_ptr + addr), val);
2518
    cpu_physical_memory_set_dirty(s->vram_offset + addr);
2519
}
2520

    
2521
/***************************************
2522
 *
2523
 *  system to screen memory access
2524
 *
2525
 ***************************************/
2526

    
2527

    
2528
static uint32_t cirrus_linear_bitblt_readb(void *opaque, target_phys_addr_t addr)
2529
{
2530
    uint32_t ret;
2531

    
2532
    /* XXX handle bitblt */
2533
    ret = 0xff;
2534
    return ret;
2535
}
2536

    
2537
static uint32_t cirrus_linear_bitblt_readw(void *opaque, target_phys_addr_t addr)
2538
{
2539
    uint32_t v;
2540
#ifdef TARGET_WORDS_BIGENDIAN
2541
    v = cirrus_linear_bitblt_readb(opaque, addr) << 8;
2542
    v |= cirrus_linear_bitblt_readb(opaque, addr + 1);
2543
#else
2544
    v = cirrus_linear_bitblt_readb(opaque, addr);
2545
    v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8;
2546
#endif
2547
    return v;
2548
}
2549

    
2550
static uint32_t cirrus_linear_bitblt_readl(void *opaque, target_phys_addr_t addr)
2551
{
2552
    uint32_t v;
2553
#ifdef TARGET_WORDS_BIGENDIAN
2554
    v = cirrus_linear_bitblt_readb(opaque, addr) << 24;
2555
    v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 16;
2556
    v |= cirrus_linear_bitblt_readb(opaque, addr + 2) << 8;
2557
    v |= cirrus_linear_bitblt_readb(opaque, addr + 3);
2558
#else
2559
    v = cirrus_linear_bitblt_readb(opaque, addr);
2560
    v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8;
2561
    v |= cirrus_linear_bitblt_readb(opaque, addr + 2) << 16;
2562
    v |= cirrus_linear_bitblt_readb(opaque, addr + 3) << 24;
2563
#endif
2564
    return v;
2565
}
2566

    
2567
static void cirrus_linear_bitblt_writeb(void *opaque, target_phys_addr_t addr,
2568
                                 uint32_t val)
2569
{
2570
    CirrusVGAState *s = (CirrusVGAState *) opaque;
2571

    
2572
    if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
2573
        /* bitblt */
2574
        *s->cirrus_srcptr++ = (uint8_t) val;
2575
        if (s->cirrus_srcptr >= s->cirrus_srcptr_end) {
2576
            cirrus_bitblt_cputovideo_next(s);
2577
        }
2578
    }
2579
}
2580

    
2581
static void cirrus_linear_bitblt_writew(void *opaque, target_phys_addr_t addr,
2582
                                 uint32_t val)
2583
{
2584
#ifdef TARGET_WORDS_BIGENDIAN
2585
    cirrus_linear_bitblt_writeb(opaque, addr, (val >> 8) & 0xff);
2586
    cirrus_linear_bitblt_writeb(opaque, addr + 1, val & 0xff);
2587
#else
2588
    cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff);
2589
    cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2590
#endif
2591
}
2592

    
2593
static void cirrus_linear_bitblt_writel(void *opaque, target_phys_addr_t addr,
2594
                                 uint32_t val)
2595
{
2596
#ifdef TARGET_WORDS_BIGENDIAN
2597
    cirrus_linear_bitblt_writeb(opaque, addr, (val >> 24) & 0xff);
2598
    cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 16) & 0xff);
2599
    cirrus_linear_bitblt_writeb(opaque, addr + 2, (val >> 8) & 0xff);
2600
    cirrus_linear_bitblt_writeb(opaque, addr + 3, val & 0xff);
2601
#else
2602
    cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff);
2603
    cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2604
    cirrus_linear_bitblt_writeb(opaque, addr + 2, (val >> 16) & 0xff);
2605
    cirrus_linear_bitblt_writeb(opaque, addr + 3, (val >> 24) & 0xff);
2606
#endif
2607
}
2608

    
2609

    
2610
static CPUReadMemoryFunc *cirrus_linear_bitblt_read[3] = {
2611
    cirrus_linear_bitblt_readb,
2612
    cirrus_linear_bitblt_readw,
2613
    cirrus_linear_bitblt_readl,
2614
};
2615

    
2616
static CPUWriteMemoryFunc *cirrus_linear_bitblt_write[3] = {
2617
    cirrus_linear_bitblt_writeb,
2618
    cirrus_linear_bitblt_writew,
2619
    cirrus_linear_bitblt_writel,
2620
};
2621

    
2622
/* Compute the memory access functions */
2623
static void cirrus_update_memory_access(CirrusVGAState *s)
2624
{
2625
    unsigned mode;
2626

    
2627
    if ((s->sr[0x17] & 0x44) == 0x44) {
2628
        goto generic_io;
2629
    } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
2630
        goto generic_io;
2631
    } else {
2632
        if ((s->gr[0x0B] & 0x14) == 0x14) {
2633
            goto generic_io;
2634
        } else if (s->gr[0x0B] & 0x02) {
2635
            goto generic_io;
2636
        }
2637

    
2638
        mode = s->gr[0x05] & 0x7;
2639
        if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
2640
            s->cirrus_linear_write[0] = cirrus_linear_mem_writeb;
2641
            s->cirrus_linear_write[1] = cirrus_linear_mem_writew;
2642
            s->cirrus_linear_write[2] = cirrus_linear_mem_writel;
2643
        } else {
2644
        generic_io:
2645
            s->cirrus_linear_write[0] = cirrus_linear_writeb;
2646
            s->cirrus_linear_write[1] = cirrus_linear_writew;
2647
            s->cirrus_linear_write[2] = cirrus_linear_writel;
2648
        }
2649
    }
2650
}
2651

    
2652

    
2653
/* I/O ports */
2654

    
2655
static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
2656
{
2657
    CirrusVGAState *s = opaque;
2658
    int val, index;
2659

    
2660
    /* check port range access depending on color/monochrome mode */
2661
    if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION))
2662
        || (addr >= 0x3d0 && addr <= 0x3df
2663
            && !(s->msr & MSR_COLOR_EMULATION))) {
2664
        val = 0xff;
2665
    } else {
2666
        switch (addr) {
2667
        case 0x3c0:
2668
            if (s->ar_flip_flop == 0) {
2669
                val = s->ar_index;
2670
            } else {
2671
                val = 0;
2672
            }
2673
            break;
2674
        case 0x3c1:
2675
            index = s->ar_index & 0x1f;
2676
            if (index < 21)
2677
                val = s->ar[index];
2678
            else
2679
                val = 0;
2680
            break;
2681
        case 0x3c2:
2682
            val = s->st00;
2683
            break;
2684
        case 0x3c4:
2685
            val = s->sr_index;
2686
            break;
2687
        case 0x3c5:
2688
            if (cirrus_hook_read_sr(s, s->sr_index, &val))
2689
                break;
2690
            val = s->sr[s->sr_index];
2691
#ifdef DEBUG_VGA_REG
2692
            printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
2693
#endif
2694
            break;
2695
        case 0x3c6:
2696
            cirrus_read_hidden_dac(s, &val);
2697
            break;
2698
        case 0x3c7:
2699
            val = s->dac_state;
2700
            break;
2701
        case 0x3c8:
2702
            val = s->dac_write_index;
2703
            s->cirrus_hidden_dac_lockindex = 0;
2704
            break;
2705
        case 0x3c9:
2706
            if (cirrus_hook_read_palette(s, &val))
2707
                break;
2708
            val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
2709
            if (++s->dac_sub_index == 3) {
2710
                s->dac_sub_index = 0;
2711
                s->dac_read_index++;
2712
            }
2713
            break;
2714
        case 0x3ca:
2715
            val = s->fcr;
2716
            break;
2717
        case 0x3cc:
2718
            val = s->msr;
2719
            break;
2720
        case 0x3ce:
2721
            val = s->gr_index;
2722
            break;
2723
        case 0x3cf:
2724
            if (cirrus_hook_read_gr(s, s->gr_index, &val))
2725
                break;
2726
            val = s->gr[s->gr_index];
2727
#ifdef DEBUG_VGA_REG
2728
            printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
2729
#endif
2730
            break;
2731
        case 0x3b4:
2732
        case 0x3d4:
2733
            val = s->cr_index;
2734
            break;
2735
        case 0x3b5:
2736
        case 0x3d5:
2737
            if (cirrus_hook_read_cr(s, s->cr_index, &val))
2738
                break;
2739
            val = s->cr[s->cr_index];
2740
#ifdef DEBUG_VGA_REG
2741
            printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
2742
#endif
2743
            break;
2744
        case 0x3ba:
2745
        case 0x3da:
2746
            /* just toggle to fool polling */
2747
            s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;
2748
            val = s->st01;
2749
            s->ar_flip_flop = 0;
2750
            break;
2751
        default:
2752
            val = 0x00;
2753
            break;
2754
        }
2755
    }
2756
#if defined(DEBUG_VGA)
2757
    printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
2758
#endif
2759
    return val;
2760
}
2761

    
2762
static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
2763
{
2764
    CirrusVGAState *s = opaque;
2765
    int index;
2766

    
2767
    /* check port range access depending on color/monochrome mode */
2768
    if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION))
2769
        || (addr >= 0x3d0 && addr <= 0x3df
2770
            && !(s->msr & MSR_COLOR_EMULATION)))
2771
        return;
2772

    
2773
#ifdef DEBUG_VGA
2774
    printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
2775
#endif
2776

    
2777
    switch (addr) {
2778
    case 0x3c0:
2779
        if (s->ar_flip_flop == 0) {
2780
            val &= 0x3f;
2781
            s->ar_index = val;
2782
        } else {
2783
            index = s->ar_index & 0x1f;
2784
            switch (index) {
2785
            case 0x00 ... 0x0f:
2786
                s->ar[index] = val & 0x3f;
2787
                break;
2788
            case 0x10:
2789
                s->ar[index] = val & ~0x10;
2790
                break;
2791
            case 0x11:
2792
                s->ar[index] = val;
2793
                break;
2794
            case 0x12:
2795
                s->ar[index] = val & ~0xc0;
2796
                break;
2797
            case 0x13:
2798
                s->ar[index] = val & ~0xf0;
2799
                break;
2800
            case 0x14:
2801
                s->ar[index] = val & ~0xf0;
2802
                break;
2803
            default:
2804
                break;
2805
            }
2806
        }
2807
        s->ar_flip_flop ^= 1;
2808
        break;
2809
    case 0x3c2:
2810
        s->msr = val & ~0x10;
2811
        break;
2812
    case 0x3c4:
2813
        s->sr_index = val;
2814
        break;
2815
    case 0x3c5:
2816
        if (cirrus_hook_write_sr(s, s->sr_index, val))
2817
            break;
2818
#ifdef DEBUG_VGA_REG
2819
        printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
2820
#endif
2821
        s->sr[s->sr_index] = val & sr_mask[s->sr_index];
2822
        break;
2823
    case 0x3c6:
2824
        cirrus_write_hidden_dac(s, val);
2825
        break;
2826
    case 0x3c7:
2827
        s->dac_read_index = val;
2828
        s->dac_sub_index = 0;
2829
        s->dac_state = 3;
2830
        break;
2831
    case 0x3c8:
2832
        s->dac_write_index = val;
2833
        s->dac_sub_index = 0;
2834
        s->dac_state = 0;
2835
        break;
2836
    case 0x3c9:
2837
        if (cirrus_hook_write_palette(s, val))
2838
            break;
2839
        s->dac_cache[s->dac_sub_index] = val;
2840
        if (++s->dac_sub_index == 3) {
2841
            memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
2842
            s->dac_sub_index = 0;
2843
            s->dac_write_index++;
2844
        }
2845
        break;
2846
    case 0x3ce:
2847
        s->gr_index = val;
2848
        break;
2849
    case 0x3cf:
2850
        if (cirrus_hook_write_gr(s, s->gr_index, val))
2851
            break;
2852
#ifdef DEBUG_VGA_REG
2853
        printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
2854
#endif
2855
        s->gr[s->gr_index] = val & gr_mask[s->gr_index];
2856
        break;
2857
    case 0x3b4:
2858
    case 0x3d4:
2859
        s->cr_index = val;
2860
        break;
2861
    case 0x3b5:
2862
    case 0x3d5:
2863
        if (cirrus_hook_write_cr(s, s->cr_index, val))
2864
            break;
2865
#ifdef DEBUG_VGA_REG
2866
        printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
2867
#endif
2868
        /* handle CR0-7 protection */
2869
        if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {
2870
            /* can always write bit 4 of CR7 */
2871
            if (s->cr_index == 7)
2872
                s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
2873
            return;
2874
        }
2875
        switch (s->cr_index) {
2876
        case 0x01:                /* horizontal display end */
2877
        case 0x07:
2878
        case 0x09:
2879
        case 0x0c:
2880
        case 0x0d:
2881
        case 0x12:                /* vertical display end */
2882
            s->cr[s->cr_index] = val;
2883
            break;
2884

    
2885
        default:
2886
            s->cr[s->cr_index] = val;
2887
            break;
2888
        }
2889
        break;
2890
    case 0x3ba:
2891
    case 0x3da:
2892
        s->fcr = val & 0x10;
2893
        break;
2894
    }
2895
}
2896

    
2897
/***************************************
2898
 *
2899
 *  memory-mapped I/O access
2900
 *
2901
 ***************************************/
2902

    
2903
static uint32_t cirrus_mmio_readb(void *opaque, target_phys_addr_t addr)
2904
{
2905
    CirrusVGAState *s = (CirrusVGAState *) opaque;
2906

    
2907
    addr &= CIRRUS_PNPMMIO_SIZE - 1;
2908

    
2909
    if (addr >= 0x100) {
2910
        return cirrus_mmio_blt_read(s, addr - 0x100);
2911
    } else {
2912
        return vga_ioport_read(s, addr + 0x3c0);
2913
    }
2914
}
2915

    
2916
static uint32_t cirrus_mmio_readw(void *opaque, target_phys_addr_t addr)
2917
{
2918
    uint32_t v;
2919
#ifdef TARGET_WORDS_BIGENDIAN
2920
    v = cirrus_mmio_readb(opaque, addr) << 8;
2921
    v |= cirrus_mmio_readb(opaque, addr + 1);
2922
#else
2923
    v = cirrus_mmio_readb(opaque, addr);
2924
    v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
2925
#endif
2926
    return v;
2927
}
2928

    
2929
static uint32_t cirrus_mmio_readl(void *opaque, target_phys_addr_t addr)
2930
{
2931
    uint32_t v;
2932
#ifdef TARGET_WORDS_BIGENDIAN
2933
    v = cirrus_mmio_readb(opaque, addr) << 24;
2934
    v |= cirrus_mmio_readb(opaque, addr + 1) << 16;
2935
    v |= cirrus_mmio_readb(opaque, addr + 2) << 8;
2936
    v |= cirrus_mmio_readb(opaque, addr + 3);
2937
#else
2938
    v = cirrus_mmio_readb(opaque, addr);
2939
    v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
2940
    v |= cirrus_mmio_readb(opaque, addr + 2) << 16;
2941
    v |= cirrus_mmio_readb(opaque, addr + 3) << 24;
2942
#endif
2943
    return v;
2944
}
2945

    
2946
static void cirrus_mmio_writeb(void *opaque, target_phys_addr_t addr,
2947
                               uint32_t val)
2948
{
2949
    CirrusVGAState *s = (CirrusVGAState *) opaque;
2950

    
2951
    addr &= CIRRUS_PNPMMIO_SIZE - 1;
2952

    
2953
    if (addr >= 0x100) {
2954
        cirrus_mmio_blt_write(s, addr - 0x100, val);
2955
    } else {
2956
        vga_ioport_write(s, addr + 0x3c0, val);
2957
    }
2958
}
2959

    
2960
static void cirrus_mmio_writew(void *opaque, target_phys_addr_t addr,
2961
                               uint32_t val)
2962
{
2963
#ifdef TARGET_WORDS_BIGENDIAN
2964
    cirrus_mmio_writeb(opaque, addr, (val >> 8) & 0xff);
2965
    cirrus_mmio_writeb(opaque, addr + 1, val & 0xff);
2966
#else
2967
    cirrus_mmio_writeb(opaque, addr, val & 0xff);
2968
    cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2969
#endif
2970
}
2971

    
2972
static void cirrus_mmio_writel(void *opaque, target_phys_addr_t addr,
2973
                               uint32_t val)
2974
{
2975
#ifdef TARGET_WORDS_BIGENDIAN
2976
    cirrus_mmio_writeb(opaque, addr, (val >> 24) & 0xff);
2977
    cirrus_mmio_writeb(opaque, addr + 1, (val >> 16) & 0xff);
2978
    cirrus_mmio_writeb(opaque, addr + 2, (val >> 8) & 0xff);
2979
    cirrus_mmio_writeb(opaque, addr + 3, val & 0xff);
2980
#else
2981
    cirrus_mmio_writeb(opaque, addr, val & 0xff);
2982
    cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2983
    cirrus_mmio_writeb(opaque, addr + 2, (val >> 16) & 0xff);
2984
    cirrus_mmio_writeb(opaque, addr + 3, (val >> 24) & 0xff);
2985
#endif
2986
}
2987

    
2988

    
2989
static CPUReadMemoryFunc *cirrus_mmio_read[3] = {
2990
    cirrus_mmio_readb,
2991
    cirrus_mmio_readw,
2992
    cirrus_mmio_readl,
2993
};
2994

    
2995
static CPUWriteMemoryFunc *cirrus_mmio_write[3] = {
2996
    cirrus_mmio_writeb,
2997
    cirrus_mmio_writew,
2998
    cirrus_mmio_writel,
2999
};
3000

    
3001
/* load/save state */
3002

    
3003
static void cirrus_vga_save(QEMUFile *f, void *opaque)
3004
{
3005
    CirrusVGAState *s = opaque;
3006

    
3007
    if (s->pci_dev)
3008
        pci_device_save(s->pci_dev, f);
3009

    
3010
    qemu_put_be32s(f, &s->latch);
3011
    qemu_put_8s(f, &s->sr_index);
3012
    qemu_put_buffer(f, s->sr, 256);
3013
    qemu_put_8s(f, &s->gr_index);
3014
    qemu_put_8s(f, &s->cirrus_shadow_gr0);
3015
    qemu_put_8s(f, &s->cirrus_shadow_gr1);
3016
    qemu_put_buffer(f, s->gr + 2, 254);
3017
    qemu_put_8s(f, &s->ar_index);
3018
    qemu_put_buffer(f, s->ar, 21);
3019
    qemu_put_be32(f, s->ar_flip_flop);
3020
    qemu_put_8s(f, &s->cr_index);
3021
    qemu_put_buffer(f, s->cr, 256);
3022
    qemu_put_8s(f, &s->msr);
3023
    qemu_put_8s(f, &s->fcr);
3024
    qemu_put_8s(f, &s->st00);
3025
    qemu_put_8s(f, &s->st01);
3026

    
3027
    qemu_put_8s(f, &s->dac_state);
3028
    qemu_put_8s(f, &s->dac_sub_index);
3029
    qemu_put_8s(f, &s->dac_read_index);
3030
    qemu_put_8s(f, &s->dac_write_index);
3031
    qemu_put_buffer(f, s->dac_cache, 3);
3032
    qemu_put_buffer(f, s->palette, 768);
3033

    
3034
    qemu_put_be32(f, s->bank_offset);
3035

    
3036
    qemu_put_8s(f, &s->cirrus_hidden_dac_lockindex);
3037
    qemu_put_8s(f, &s->cirrus_hidden_dac_data);
3038

    
3039
    qemu_put_be32s(f, &s->hw_cursor_x);
3040
    qemu_put_be32s(f, &s->hw_cursor_y);
3041
    /* XXX: we do not save the bitblt state - we assume we do not save
3042
       the state when the blitter is active */
3043
}
3044

    
3045
static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id)
3046
{
3047
    CirrusVGAState *s = opaque;
3048
    int ret;
3049

    
3050
    if (version_id > 2)
3051
        return -EINVAL;
3052

    
3053
    if (s->pci_dev && version_id >= 2) {
3054
        ret = pci_device_load(s->pci_dev, f);
3055
        if (ret < 0)
3056
            return ret;
3057
    }
3058

    
3059
    qemu_get_be32s(f, &s->latch);
3060
    qemu_get_8s(f, &s->sr_index);
3061
    qemu_get_buffer(f, s->sr, 256);
3062
    qemu_get_8s(f, &s->gr_index);
3063
    qemu_get_8s(f, &s->cirrus_shadow_gr0);
3064
    qemu_get_8s(f, &s->cirrus_shadow_gr1);
3065
    s->gr[0x00] = s->cirrus_shadow_gr0 & 0x0f;
3066
    s->gr[0x01] = s->cirrus_shadow_gr1 & 0x0f;
3067
    qemu_get_buffer(f, s->gr + 2, 254);
3068
    qemu_get_8s(f, &s->ar_index);
3069
    qemu_get_buffer(f, s->ar, 21);
3070
    s->ar_flip_flop=qemu_get_be32(f);
3071
    qemu_get_8s(f, &s->cr_index);
3072
    qemu_get_buffer(f, s->cr, 256);
3073
    qemu_get_8s(f, &s->msr);
3074
    qemu_get_8s(f, &s->fcr);
3075
    qemu_get_8s(f, &s->st00);
3076
    qemu_get_8s(f, &s->st01);
3077

    
3078
    qemu_get_8s(f, &s->dac_state);
3079
    qemu_get_8s(f, &s->dac_sub_index);
3080
    qemu_get_8s(f, &s->dac_read_index);
3081
    qemu_get_8s(f, &s->dac_write_index);
3082
    qemu_get_buffer(f, s->dac_cache, 3);
3083
    qemu_get_buffer(f, s->palette, 768);
3084

    
3085
    s->bank_offset=qemu_get_be32(f);
3086

    
3087
    qemu_get_8s(f, &s->cirrus_hidden_dac_lockindex);
3088
    qemu_get_8s(f, &s->cirrus_hidden_dac_data);
3089

    
3090
    qemu_get_be32s(f, &s->hw_cursor_x);
3091
    qemu_get_be32s(f, &s->hw_cursor_y);
3092

    
3093
    /* force refresh */
3094
    s->graphic_mode = -1;
3095
    cirrus_update_bank_ptr(s, 0);
3096
    cirrus_update_bank_ptr(s, 1);
3097
    return 0;
3098
}
3099

    
3100
/***************************************
3101
 *
3102
 *  initialize
3103
 *
3104
 ***************************************/
3105

    
3106
static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
3107
{
3108
    int vga_io_memory, i;
3109
    static int inited;
3110

    
3111
    if (!inited) {
3112
        inited = 1;
3113
        for(i = 0;i < 256; i++)
3114
            rop_to_index[i] = CIRRUS_ROP_NOP_INDEX; /* nop rop */
3115
        rop_to_index[CIRRUS_ROP_0] = 0;
3116
        rop_to_index[CIRRUS_ROP_SRC_AND_DST] = 1;
3117
        rop_to_index[CIRRUS_ROP_NOP] = 2;
3118
        rop_to_index[CIRRUS_ROP_SRC_AND_NOTDST] = 3;
3119
        rop_to_index[CIRRUS_ROP_NOTDST] = 4;
3120
        rop_to_index[CIRRUS_ROP_SRC] = 5;
3121
        rop_to_index[CIRRUS_ROP_1] = 6;
3122
        rop_to_index[CIRRUS_ROP_NOTSRC_AND_DST] = 7;
3123
        rop_to_index[CIRRUS_ROP_SRC_XOR_DST] = 8;
3124
        rop_to_index[CIRRUS_ROP_SRC_OR_DST] = 9;
3125
        rop_to_index[CIRRUS_ROP_NOTSRC_OR_NOTDST] = 10;
3126
        rop_to_index[CIRRUS_ROP_SRC_NOTXOR_DST] = 11;
3127
        rop_to_index[CIRRUS_ROP_SRC_OR_NOTDST] = 12;
3128
        rop_to_index[CIRRUS_ROP_NOTSRC] = 13;
3129
        rop_to_index[CIRRUS_ROP_NOTSRC_OR_DST] = 14;
3130
        rop_to_index[CIRRUS_ROP_NOTSRC_AND_NOTDST] = 15;
3131
    }
3132

    
3133
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
3134

    
3135
    register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
3136
    register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
3137
    register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
3138
    register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
3139

    
3140
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
3141

    
3142
    register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
3143
    register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
3144
    register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
3145
    register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
3146

    
3147
    vga_io_memory = cpu_register_io_memory(0, cirrus_vga_mem_read,
3148
                                           cirrus_vga_mem_write, s);
3149
    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
3150
                                 vga_io_memory);
3151

    
3152
    s->sr[0x06] = 0x0f;
3153
    if (device_id == CIRRUS_ID_CLGD5446) {
3154
        /* 4MB 64 bit memory config, always PCI */
3155
        s->sr[0x1F] = 0x2d;                // MemClock
3156
        s->gr[0x18] = 0x0f;             // fastest memory configuration
3157
#if 1
3158
        s->sr[0x0f] = 0x98;
3159
        s->sr[0x17] = 0x20;
3160
        s->sr[0x15] = 0x04; /* memory size, 3=2MB, 4=4MB */
3161
        s->real_vram_size = 4096 * 1024;
3162
#else
3163
        s->sr[0x0f] = 0x18;
3164
        s->sr[0x17] = 0x20;
3165
        s->sr[0x15] = 0x03; /* memory size, 3=2MB, 4=4MB */
3166
        s->real_vram_size = 2048 * 1024;
3167
#endif
3168
    } else {
3169
        s->sr[0x1F] = 0x22;                // MemClock
3170
        s->sr[0x0F] = CIRRUS_MEMSIZE_2M;
3171
        if (is_pci)
3172
            s->sr[0x17] = CIRRUS_BUSTYPE_PCI;
3173
        else
3174
            s->sr[0x17] = CIRRUS_BUSTYPE_ISA;
3175
        s->real_vram_size = 2048 * 1024;
3176
        s->sr[0x15] = 0x03; /* memory size, 3=2MB, 4=4MB */
3177
    }
3178
    s->cr[0x27] = device_id;
3179

    
3180
    /* Win2K seems to assume that the pattern buffer is at 0xff
3181
       initially ! */
3182
    memset(s->vram_ptr, 0xff, s->real_vram_size);
3183

    
3184
    s->cirrus_hidden_dac_lockindex = 5;
3185
    s->cirrus_hidden_dac_data = 0;
3186

    
3187
    /* I/O handler for LFB */
3188
    s->cirrus_linear_io_addr =
3189
        cpu_register_io_memory(0, cirrus_linear_read, cirrus_linear_write,
3190
                               s);
3191
    s->cirrus_linear_write = cpu_get_io_memory_write(s->cirrus_linear_io_addr);
3192

    
3193
    /* I/O handler for LFB */
3194
    s->cirrus_linear_bitblt_io_addr =
3195
        cpu_register_io_memory(0, cirrus_linear_bitblt_read, cirrus_linear_bitblt_write,
3196
                               s);
3197

    
3198
    /* I/O handler for memory-mapped I/O */
3199
    s->cirrus_mmio_io_addr =
3200
        cpu_register_io_memory(0, cirrus_mmio_read, cirrus_mmio_write, s);
3201

    
3202
    /* XXX: s->vram_size must be a power of two */
3203
    s->cirrus_addr_mask = s->real_vram_size - 1;
3204
    s->linear_mmio_mask = s->real_vram_size - 256;
3205

    
3206
    s->get_bpp = cirrus_get_bpp;
3207
    s->get_offsets = cirrus_get_offsets;
3208
    s->get_resolution = cirrus_get_resolution;
3209
    s->cursor_invalidate = cirrus_cursor_invalidate;
3210
    s->cursor_draw_line = cirrus_cursor_draw_line;
3211

    
3212
    register_savevm("cirrus_vga", 0, 2, cirrus_vga_save, cirrus_vga_load, s);
3213
}
3214

    
3215
/***************************************
3216
 *
3217
 *  ISA bus support
3218
 *
3219
 ***************************************/
3220

    
3221
void isa_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
3222
                         unsigned long vga_ram_offset, int vga_ram_size)
3223
{
3224
    CirrusVGAState *s;
3225

    
3226
    s = qemu_mallocz(sizeof(CirrusVGAState));
3227

    
3228
    vga_common_init((VGAState *)s,
3229
                    ds, vga_ram_base, vga_ram_offset, vga_ram_size);
3230
    cirrus_init_common(s, CIRRUS_ID_CLGD5430, 0);
3231
    /* XXX ISA-LFB support */
3232
}
3233

    
3234
/***************************************
3235
 *
3236
 *  PCI bus support
3237
 *
3238
 ***************************************/
3239

    
3240
static void cirrus_pci_lfb_map(PCIDevice *d, int region_num,
3241
                               uint32_t addr, uint32_t size, int type)
3242
{
3243
    CirrusVGAState *s = &((PCICirrusVGAState *)d)->cirrus_vga;
3244

    
3245
    /* XXX: add byte swapping apertures */
3246
    cpu_register_physical_memory(addr, s->vram_size,
3247
                                 s->cirrus_linear_io_addr);
3248
    cpu_register_physical_memory(addr + 0x1000000, 0x400000,
3249
                                 s->cirrus_linear_bitblt_io_addr);
3250
}
3251

    
3252
static void cirrus_pci_mmio_map(PCIDevice *d, int region_num,
3253
                                uint32_t addr, uint32_t size, int type)
3254
{
3255
    CirrusVGAState *s = &((PCICirrusVGAState *)d)->cirrus_vga;
3256

    
3257
    cpu_register_physical_memory(addr, CIRRUS_PNPMMIO_SIZE,
3258
                                 s->cirrus_mmio_io_addr);
3259
}
3260

    
3261
void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
3262
                         unsigned long vga_ram_offset, int vga_ram_size)
3263
{
3264
    PCICirrusVGAState *d;
3265
    uint8_t *pci_conf;
3266
    CirrusVGAState *s;
3267
    int device_id;
3268

    
3269
    device_id = CIRRUS_ID_CLGD5446;
3270

    
3271
    /* setup PCI configuration registers */
3272
    d = (PCICirrusVGAState *)pci_register_device(bus, "Cirrus VGA",
3273
                                                 sizeof(PCICirrusVGAState),
3274
                                                 -1, NULL, NULL);
3275
    pci_conf = d->dev.config;
3276
    pci_conf[0x00] = (uint8_t) (PCI_VENDOR_CIRRUS & 0xff);
3277
    pci_conf[0x01] = (uint8_t) (PCI_VENDOR_CIRRUS >> 8);
3278
    pci_conf[0x02] = (uint8_t) (device_id & 0xff);
3279
    pci_conf[0x03] = (uint8_t) (device_id >> 8);
3280
    pci_conf[0x04] = PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS;
3281
    pci_conf[0x0a] = PCI_CLASS_SUB_VGA;
3282
    pci_conf[0x0b] = PCI_CLASS_BASE_DISPLAY;
3283
    pci_conf[0x0e] = PCI_CLASS_HEADERTYPE_00h;
3284

    
3285
    /* setup VGA */
3286
    s = &d->cirrus_vga;
3287
    vga_common_init((VGAState *)s,
3288
                    ds, vga_ram_base, vga_ram_offset, vga_ram_size);
3289
    cirrus_init_common(s, device_id, 1);
3290

    
3291
    s->console = graphic_console_init(s->ds, s->update, s->invalidate,
3292
                                      s->screen_dump, s->text_update, s);
3293

    
3294
    s->pci_dev = (PCIDevice *)d;
3295

    
3296
    /* setup memory space */
3297
    /* memory #0 LFB */
3298
    /* memory #1 memory-mapped I/O */
3299
    /* XXX: s->vram_size must be a power of two */
3300
    pci_register_io_region((PCIDevice *)d, 0, 0x2000000,
3301
                           PCI_ADDRESS_SPACE_MEM_PREFETCH, cirrus_pci_lfb_map);
3302
    if (device_id == CIRRUS_ID_CLGD5446) {
3303
        pci_register_io_region((PCIDevice *)d, 1, CIRRUS_PNPMMIO_SIZE,
3304
                               PCI_ADDRESS_SPACE_MEM, cirrus_pci_mmio_map);
3305
    }
3306
    /* XXX: ROM BIOS */
3307
}