Statistics
| Branch: | Revision:

root / hw / cirrus_vga.c @ 78e127ef

History | View | Annotate | Download (84.2 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 "vl.h"
30
#include "vga_int.h"
31

    
32
/*
33
 * TODO:
34
 *    - fix 24 bpp pattern fills (source is 32 bpp in that case)
35
 *    - add support for WRITEMASK (GR2F)
36
 *    - add support for scanline modulo in pattern fill
37
 *    - optimize linear mappings
38
 *    - optimize bitblt functions
39
 */
40

    
41
//#define DEBUG_CIRRUS
42
//#define DEBUG_BITBLT
43

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

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

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

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

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

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

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

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

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

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

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

    
135
#define CIRRUS_ROP_NOP_INDEX 2
136
#define CIRRUS_ROP_SRC_INDEX 5
137

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

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

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

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

    
215
#define CIRRUS_PNPMMIO_SIZE         0x1000
216

    
217

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

    
222
struct CirrusVGAState;
223
typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s,
224
                                     uint8_t * dst, const uint8_t * src,
225
                                     int dstpitch, int srcpitch,
226
                                     int bltwidth, int bltheight);
227
typedef void (*cirrus_fill_t)(struct CirrusVGAState *s,
228
                              uint8_t *dst, int dst_pitch, int width, int height);
229

    
230
typedef struct CirrusVGAState {
231
    VGA_STATE_COMMON
232

    
233
    int cirrus_linear_io_addr;
234
    int cirrus_linear_bitblt_io_addr;
235
    int cirrus_mmio_io_addr;
236
    uint32_t cirrus_addr_mask;
237
    uint32_t linear_mmio_mask;
238
    uint8_t cirrus_shadow_gr0;
239
    uint8_t cirrus_shadow_gr1;
240
    uint8_t cirrus_hidden_dac_lockindex;
241
    uint8_t cirrus_hidden_dac_data;
242
    uint32_t cirrus_bank_base[2];
243
    uint32_t cirrus_bank_limit[2];
244
    uint8_t cirrus_hidden_palette[48];
245
    uint32_t hw_cursor_x;
246
    uint32_t hw_cursor_y;
247
    int cirrus_blt_pixelwidth;
248
    int cirrus_blt_width;
249
    int cirrus_blt_height;
250
    int cirrus_blt_dstpitch;
251
    int cirrus_blt_srcpitch;
252
    uint32_t cirrus_blt_fgcol;
253
    uint32_t cirrus_blt_bgcol;
254
    uint32_t cirrus_blt_dstaddr;
255
    uint32_t cirrus_blt_srcaddr;
256
    uint8_t cirrus_blt_mode;
257
    uint8_t cirrus_blt_modeext;
258
    cirrus_bitblt_rop_t cirrus_rop;
259
#define CIRRUS_BLTBUFSIZE (2048 * 4) /* one line width */
260
    uint8_t cirrus_bltbuf[CIRRUS_BLTBUFSIZE];
261
    uint8_t *cirrus_srcptr;
262
    uint8_t *cirrus_srcptr_end;
263
    uint32_t cirrus_srccounter;
264
    uint8_t *cirrus_dstptr;
265
    uint8_t *cirrus_dstptr_end;
266
    uint32_t cirrus_dstcounter;
267
    /* hwcursor display state */
268
    int last_hw_cursor_size;
269
    int last_hw_cursor_x;
270
    int last_hw_cursor_y;
271
    int last_hw_cursor_y_start;
272
    int last_hw_cursor_y_end;
273
    int real_vram_size; /* XXX: suppress that */
274
} CirrusVGAState;
275

    
276
typedef struct PCICirrusVGAState {
277
    PCIDevice dev;
278
    CirrusVGAState cirrus_vga;
279
} PCICirrusVGAState;
280

    
281
static uint8_t rop_to_index[256];
282
    
283
/***************************************
284
 *
285
 *  prototypes.
286
 *
287
 ***************************************/
288

    
289

    
290
static void cirrus_bitblt_reset(CirrusVGAState * s);
291

    
292
/***************************************
293
 *
294
 *  raster operations
295
 *
296
 ***************************************/
297

    
298
static void cirrus_bitblt_rop_nop(CirrusVGAState *s,
299
                                  uint8_t *dst,const uint8_t *src,
300
                                  int dstpitch,int srcpitch,
301
                                  int bltwidth,int bltheight)
302
{
303
}
304

    
305
static void cirrus_bitblt_fill_nop(CirrusVGAState *s,
306
                                   uint8_t *dst,
307
                                   int dstpitch, int bltwidth,int bltheight)
308
{
309
}
310

    
311
#define ROP_NAME 0
312
#define ROP_OP(d, s) d = 0
313
#include "cirrus_vga_rop.h"
314

    
315
#define ROP_NAME src_and_dst
316
#define ROP_OP(d, s) d = (s) & (d)
317
#include "cirrus_vga_rop.h"
318

    
319
#define ROP_NAME src_and_notdst
320
#define ROP_OP(d, s) d = (s) & (~(d))
321
#include "cirrus_vga_rop.h"
322

    
323
#define ROP_NAME notdst
324
#define ROP_OP(d, s) d = ~(d)
325
#include "cirrus_vga_rop.h"
326

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

    
331
#define ROP_NAME 1
332
#define ROP_OP(d, s) d = ~0
333
#include "cirrus_vga_rop.h"
334

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

    
339
#define ROP_NAME src_xor_dst
340
#define ROP_OP(d, s) d = (s) ^ (d)
341
#include "cirrus_vga_rop.h"
342

    
343
#define ROP_NAME src_or_dst
344
#define ROP_OP(d, s) d = (s) | (d)
345
#include "cirrus_vga_rop.h"
346

    
347
#define ROP_NAME notsrc_or_notdst
348
#define ROP_OP(d, s) d = (~(s)) | (~(d))
349
#include "cirrus_vga_rop.h"
350

    
351
#define ROP_NAME src_notxor_dst
352
#define ROP_OP(d, s) d = ~((s) ^ (d))
353
#include "cirrus_vga_rop.h"
354

    
355
#define ROP_NAME src_or_notdst
356
#define ROP_OP(d, s) d = (s) | (~(d))
357
#include "cirrus_vga_rop.h"
358

    
359
#define ROP_NAME notsrc
360
#define ROP_OP(d, s) d = (~(s))
361
#include "cirrus_vga_rop.h"
362

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

    
367
#define ROP_NAME notsrc_and_notdst
368
#define ROP_OP(d, s) d = (~(s)) & (~(d))
369
#include "cirrus_vga_rop.h"
370

    
371
static const cirrus_bitblt_rop_t cirrus_fwd_rop[16] = {
372
    cirrus_bitblt_rop_fwd_0,
373
    cirrus_bitblt_rop_fwd_src_and_dst,
374
    cirrus_bitblt_rop_nop,
375
    cirrus_bitblt_rop_fwd_src_and_notdst,
376
    cirrus_bitblt_rop_fwd_notdst,
377
    cirrus_bitblt_rop_fwd_src,
378
    cirrus_bitblt_rop_fwd_1,
379
    cirrus_bitblt_rop_fwd_notsrc_and_dst,
380
    cirrus_bitblt_rop_fwd_src_xor_dst,
381
    cirrus_bitblt_rop_fwd_src_or_dst,
382
    cirrus_bitblt_rop_fwd_notsrc_or_notdst,
383
    cirrus_bitblt_rop_fwd_src_notxor_dst,
384
    cirrus_bitblt_rop_fwd_src_or_notdst,
385
    cirrus_bitblt_rop_fwd_notsrc,
386
    cirrus_bitblt_rop_fwd_notsrc_or_dst,
387
    cirrus_bitblt_rop_fwd_notsrc_and_notdst,
388
};
389

    
390
static const cirrus_bitblt_rop_t cirrus_bkwd_rop[16] = {
391
    cirrus_bitblt_rop_bkwd_0,
392
    cirrus_bitblt_rop_bkwd_src_and_dst,
393
    cirrus_bitblt_rop_nop,
394
    cirrus_bitblt_rop_bkwd_src_and_notdst,
395
    cirrus_bitblt_rop_bkwd_notdst,
396
    cirrus_bitblt_rop_bkwd_src,
397
    cirrus_bitblt_rop_bkwd_1,
398
    cirrus_bitblt_rop_bkwd_notsrc_and_dst,
399
    cirrus_bitblt_rop_bkwd_src_xor_dst,
400
    cirrus_bitblt_rop_bkwd_src_or_dst,
401
    cirrus_bitblt_rop_bkwd_notsrc_or_notdst,
402
    cirrus_bitblt_rop_bkwd_src_notxor_dst,
403
    cirrus_bitblt_rop_bkwd_src_or_notdst,
404
    cirrus_bitblt_rop_bkwd_notsrc,
405
    cirrus_bitblt_rop_bkwd_notsrc_or_dst,
406
    cirrus_bitblt_rop_bkwd_notsrc_and_notdst,
407
};
408
    
409
#define ROP2(name) {\
410
    name ## _8,\
411
    name ## _16,\
412
    name ## _24,\
413
    name ## _32,\
414
        }
415

    
416
#define ROP_NOP2(func) {\
417
    func,\
418
    func,\
419
    func,\
420
    func,\
421
        }
422

    
423
static const cirrus_bitblt_rop_t cirrus_colorexpand_transp[16][4] = {
424
    ROP2(cirrus_colorexpand_transp_0),
425
    ROP2(cirrus_colorexpand_transp_src_and_dst),
426
    ROP_NOP2(cirrus_bitblt_rop_nop),
427
    ROP2(cirrus_colorexpand_transp_src_and_notdst),
428
    ROP2(cirrus_colorexpand_transp_notdst),
429
    ROP2(cirrus_colorexpand_transp_src),
430
    ROP2(cirrus_colorexpand_transp_1),
431
    ROP2(cirrus_colorexpand_transp_notsrc_and_dst),
432
    ROP2(cirrus_colorexpand_transp_src_xor_dst),
433
    ROP2(cirrus_colorexpand_transp_src_or_dst),
434
    ROP2(cirrus_colorexpand_transp_notsrc_or_notdst),
435
    ROP2(cirrus_colorexpand_transp_src_notxor_dst),
436
    ROP2(cirrus_colorexpand_transp_src_or_notdst),
437
    ROP2(cirrus_colorexpand_transp_notsrc),
438
    ROP2(cirrus_colorexpand_transp_notsrc_or_dst),
439
    ROP2(cirrus_colorexpand_transp_notsrc_and_notdst),
440
};
441

    
442
static const cirrus_bitblt_rop_t cirrus_colorexpand_transp_inv[16][4] = {
443
    ROP2(cirrus_colorexpand_transp_inv_0),
444
    ROP2(cirrus_colorexpand_transp_inv_src_and_dst),
445
    ROP_NOP2(cirrus_bitblt_rop_nop),
446
    ROP2(cirrus_colorexpand_transp_inv_src_and_notdst),
447
    ROP2(cirrus_colorexpand_transp_inv_notdst),
448
    ROP2(cirrus_colorexpand_transp_inv_src),
449
    ROP2(cirrus_colorexpand_transp_inv_1),
450
    ROP2(cirrus_colorexpand_transp_inv_notsrc_and_dst),
451
    ROP2(cirrus_colorexpand_transp_inv_src_xor_dst),
452
    ROP2(cirrus_colorexpand_transp_inv_src_or_dst),
453
    ROP2(cirrus_colorexpand_transp_inv_notsrc_or_notdst),
454
    ROP2(cirrus_colorexpand_transp_inv_src_notxor_dst),
455
    ROP2(cirrus_colorexpand_transp_inv_src_or_notdst),
456
    ROP2(cirrus_colorexpand_transp_inv_notsrc),
457
    ROP2(cirrus_colorexpand_transp_inv_notsrc_or_dst),
458
    ROP2(cirrus_colorexpand_transp_inv_notsrc_and_notdst),
459
};
460

    
461
static const cirrus_bitblt_rop_t cirrus_colorexpand[16][4] = {
462
    ROP2(cirrus_colorexpand_0),
463
    ROP2(cirrus_colorexpand_src_and_dst),
464
    ROP_NOP2(cirrus_bitblt_rop_nop),
465
    ROP2(cirrus_colorexpand_src_and_notdst),
466
    ROP2(cirrus_colorexpand_notdst),
467
    ROP2(cirrus_colorexpand_src),
468
    ROP2(cirrus_colorexpand_1),
469
    ROP2(cirrus_colorexpand_notsrc_and_dst),
470
    ROP2(cirrus_colorexpand_src_xor_dst),
471
    ROP2(cirrus_colorexpand_src_or_dst),
472
    ROP2(cirrus_colorexpand_notsrc_or_notdst),
473
    ROP2(cirrus_colorexpand_src_notxor_dst),
474
    ROP2(cirrus_colorexpand_src_or_notdst),
475
    ROP2(cirrus_colorexpand_notsrc),
476
    ROP2(cirrus_colorexpand_notsrc_or_dst),
477
    ROP2(cirrus_colorexpand_notsrc_and_notdst),
478
};
479

    
480
static const cirrus_fill_t cirrus_fill[16][4] = {
481
    ROP2(cirrus_fill_0),
482
    ROP2(cirrus_fill_src_and_dst),
483
    ROP_NOP2(cirrus_bitblt_fill_nop),
484
    ROP2(cirrus_fill_src_and_notdst),
485
    ROP2(cirrus_fill_notdst),
486
    ROP2(cirrus_fill_src),
487
    ROP2(cirrus_fill_1),
488
    ROP2(cirrus_fill_notsrc_and_dst),
489
    ROP2(cirrus_fill_src_xor_dst),
490
    ROP2(cirrus_fill_src_or_dst),
491
    ROP2(cirrus_fill_notsrc_or_notdst),
492
    ROP2(cirrus_fill_src_notxor_dst),
493
    ROP2(cirrus_fill_src_or_notdst),
494
    ROP2(cirrus_fill_notsrc),
495
    ROP2(cirrus_fill_notsrc_or_dst),
496
    ROP2(cirrus_fill_notsrc_and_notdst),
497
};
498

    
499
static inline void cirrus_bitblt_fgcol(CirrusVGAState *s)
500
{
501
    unsigned int color;
502
    switch (s->cirrus_blt_pixelwidth) {
503
    case 1:
504
        s->cirrus_blt_fgcol = s->cirrus_shadow_gr1;
505
        break;
506
    case 2:
507
        color = s->cirrus_shadow_gr1 | (s->gr[0x11] << 8);
508
        s->cirrus_blt_fgcol = le16_to_cpu(color);
509
        break;
510
    case 3:
511
        s->cirrus_blt_fgcol = s->cirrus_shadow_gr1 | 
512
            (s->gr[0x11] << 8) | (s->gr[0x13] << 16);
513
        break;
514
    default:
515
    case 4:
516
        color = s->cirrus_shadow_gr1 | (s->gr[0x11] << 8) |
517
            (s->gr[0x13] << 16) | (s->gr[0x15] << 24);
518
        s->cirrus_blt_fgcol = le32_to_cpu(color);
519
        break;
520
    }
521
}
522

    
523
static inline void cirrus_bitblt_bgcol(CirrusVGAState *s)
524
{
525
    unsigned int color;
526
    switch (s->cirrus_blt_pixelwidth) {
527
    case 1:
528
        s->cirrus_blt_bgcol = s->cirrus_shadow_gr0;
529
        break;
530
    case 2:
531
        color = s->cirrus_shadow_gr0 | (s->gr[0x10] << 8);
532
        s->cirrus_blt_bgcol = le16_to_cpu(color);
533
        break;
534
    case 3:
535
        s->cirrus_blt_bgcol = s->cirrus_shadow_gr0 | 
536
            (s->gr[0x10] << 8) | (s->gr[0x12] << 16);
537
        break;
538
    default:
539
    case 4:
540
        color = s->cirrus_shadow_gr0 | (s->gr[0x10] << 8) |
541
            (s->gr[0x12] << 16) | (s->gr[0x14] << 24);
542
        s->cirrus_blt_bgcol = le32_to_cpu(color);
543
        break;
544
    }
545
}
546

    
547
static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin,
548
                                     int off_pitch, int bytesperline,
549
                                     int lines)
550
{
551
    int y;
552
    int off_cur;
553
    int off_cur_end;
554

    
555
    for (y = 0; y < lines; y++) {
556
        off_cur = off_begin;
557
        off_cur_end = off_cur + bytesperline;
558
        off_cur &= TARGET_PAGE_MASK;
559
        while (off_cur < off_cur_end) {
560
            cpu_physical_memory_set_dirty(s->vram_offset + off_cur);
561
            off_cur += TARGET_PAGE_SIZE;
562
        }
563
        off_begin += off_pitch;
564
    }
565
}
566

    
567
static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s,
568
                                            const uint8_t * src)
569
{
570
    uint8_t work_colorexp[256];
571
    uint8_t *dst;
572
    uint8_t *dstc;
573
    int x, y;
574
    int tilewidth, tileheight;
575
    int patternbytes = s->cirrus_blt_pixelwidth * 8;
576

    
577
    if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
578
        cirrus_bitblt_rop_t rop_func;
579
        cirrus_bitblt_fgcol(s);
580
        cirrus_bitblt_bgcol(s);
581
        rop_func = cirrus_colorexpand[CIRRUS_ROP_SRC_INDEX][s->cirrus_blt_pixelwidth - 1];
582
        rop_func(s, work_colorexp, src, patternbytes, 1, patternbytes, 8);
583
        src = work_colorexp;
584
        s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_COLOREXPAND;
585
    }
586
    if (s->cirrus_blt_mode & ~CIRRUS_BLTMODE_PATTERNCOPY) {
587
#ifdef DEBUG_BITBLT
588
        printf("cirrus: blt mode %02x (pattercopy) - unimplemented\n",
589
               s->cirrus_blt_mode);
590
#endif
591
        return 0;
592
    }
593
    
594
    dst = s->vram_ptr + s->cirrus_blt_dstaddr;
595
    for (y = 0; y < s->cirrus_blt_height; y += 8) {
596
        dstc = dst;
597
        tileheight = qemu_MIN(8, s->cirrus_blt_height - y);
598
        for (x = 0; x < s->cirrus_blt_width; x += patternbytes) {
599
            tilewidth = qemu_MIN(patternbytes, s->cirrus_blt_width - x);
600
            (*s->cirrus_rop) (s, dstc, src,
601
                              s->cirrus_blt_dstpitch, patternbytes,
602
                              tilewidth, tileheight);
603
            dstc += patternbytes;
604
        }
605
        dst += s->cirrus_blt_dstpitch * 8;
606
    }
607
    cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
608
                             s->cirrus_blt_dstpitch, s->cirrus_blt_width,
609
                             s->cirrus_blt_height);
610
    return 1;
611
}
612

    
613
/* fill */
614

    
615
static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop)
616
{
617
    cirrus_fill_t rop_func;
618

    
619
    rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
620
    rop_func(s, s->vram_ptr + s->cirrus_blt_dstaddr, 
621
             s->cirrus_blt_dstpitch,
622
             s->cirrus_blt_width, s->cirrus_blt_height);
623
    cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
624
                             s->cirrus_blt_dstpitch, s->cirrus_blt_width,
625
                             s->cirrus_blt_height);
626
    cirrus_bitblt_reset(s);
627
    return 1;
628
}
629

    
630
/***************************************
631
 *
632
 *  bitblt (video-to-video)
633
 *
634
 ***************************************/
635

    
636
static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
637
{
638
    return cirrus_bitblt_common_patterncopy(s,
639
                                            s->vram_ptr +
640
                                            s->cirrus_blt_srcaddr);
641
}
642

    
643
static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
644
{
645
    (*s->cirrus_rop) (s, s->vram_ptr + s->cirrus_blt_dstaddr,
646
                      s->vram_ptr + s->cirrus_blt_srcaddr,
647
                      s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
648
                      s->cirrus_blt_width, s->cirrus_blt_height);
649
    cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
650
                             s->cirrus_blt_dstpitch, s->cirrus_blt_width,
651
                             s->cirrus_blt_height);
652
    return 1;
653
}
654

    
655
/***************************************
656
 *
657
 *  bitblt (cpu-to-video)
658
 *
659
 ***************************************/
660

    
661
static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s)
662
{
663
    int copy_count;
664
    uint8_t *end_ptr;
665
    
666
    if (s->cirrus_srccounter > 0) {
667
        if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
668
            cirrus_bitblt_common_patterncopy(s, s->cirrus_bltbuf);
669
        the_end:
670
            s->cirrus_srccounter = 0;
671
            cirrus_bitblt_reset(s);
672
        } else {
673
            /* at least one scan line */
674
            do {
675
                (*s->cirrus_rop)(s, s->vram_ptr + s->cirrus_blt_dstaddr,
676
                                 s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1);
677
                cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0,
678
                                         s->cirrus_blt_width, 1);
679
                s->cirrus_blt_dstaddr += s->cirrus_blt_dstpitch;
680
                s->cirrus_srccounter -= s->cirrus_blt_srcpitch;
681
                if (s->cirrus_srccounter <= 0)
682
                    goto the_end;
683
                /* more bytes than needed can be transfered because of
684
                   word alignment, so we keep them for the next line */
685
                /* XXX: keep alignment to speed up transfer */
686
                end_ptr = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
687
                copy_count = s->cirrus_srcptr_end - end_ptr;
688
                memmove(s->cirrus_bltbuf, end_ptr, copy_count);
689
                s->cirrus_srcptr = s->cirrus_bltbuf + copy_count;
690
                s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
691
            } while (s->cirrus_srcptr >= s->cirrus_srcptr_end);
692
        }
693
    }
694
}
695

    
696
/***************************************
697
 *
698
 *  bitblt wrapper
699
 *
700
 ***************************************/
701

    
702
static void cirrus_bitblt_reset(CirrusVGAState * s)
703
{
704
    s->gr[0x31] &=
705
        ~(CIRRUS_BLT_START | CIRRUS_BLT_BUSY | CIRRUS_BLT_FIFOUSED);
706
    s->cirrus_srcptr = &s->cirrus_bltbuf[0];
707
    s->cirrus_srcptr_end = &s->cirrus_bltbuf[0];
708
    s->cirrus_srccounter = 0;
709
    s->cirrus_dstptr = &s->cirrus_bltbuf[0];
710
    s->cirrus_dstptr_end = &s->cirrus_bltbuf[0];
711
    s->cirrus_dstcounter = 0;
712
}
713

    
714
static int cirrus_bitblt_cputovideo(CirrusVGAState * s)
715
{
716
    int w;
717

    
718
    s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_MEMSYSSRC;
719
    s->cirrus_srcptr = &s->cirrus_bltbuf[0];
720
    s->cirrus_srcptr_end = &s->cirrus_bltbuf[0];
721

    
722
    if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
723
        if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
724
            s->cirrus_blt_srcpitch = 8;
725
        } else {
726
            s->cirrus_blt_srcpitch = 8 * 8 * s->cirrus_blt_pixelwidth;
727
        }
728
        s->cirrus_srccounter = s->cirrus_blt_srcpitch;
729
    } else {
730
        if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
731
            w = s->cirrus_blt_width / s->cirrus_blt_pixelwidth;
732
            if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY) 
733
                s->cirrus_blt_srcpitch = ((w + 31) >> 5);
734
            else
735
                s->cirrus_blt_srcpitch = ((w + 7) >> 3);
736
        } else {
737
            s->cirrus_blt_srcpitch = s->cirrus_blt_width;
738
        }
739
        s->cirrus_srccounter = s->cirrus_blt_srcpitch * s->cirrus_blt_height;
740
    }
741
    s->cirrus_srcptr = s->cirrus_bltbuf;
742
    s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
743
    return 1;
744
}
745

    
746
static int cirrus_bitblt_videotocpu(CirrusVGAState * s)
747
{
748
    /* XXX */
749
#ifdef DEBUG_BITBLT
750
    printf("cirrus: bitblt (video to cpu) is not implemented yet\n");
751
#endif
752
    return 0;
753
}
754

    
755
static int cirrus_bitblt_videotovideo(CirrusVGAState * s)
756
{
757
    int ret;
758

    
759
    if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
760
        ret = cirrus_bitblt_videotovideo_patterncopy(s);
761
    } else {
762
        ret = cirrus_bitblt_videotovideo_copy(s);
763
    }
764
    if (ret)
765
        cirrus_bitblt_reset(s);
766
    return ret;
767
}
768

    
769
static void cirrus_bitblt_start(CirrusVGAState * s)
770
{
771
    uint8_t blt_rop;
772

    
773
    s->gr[0x31] |= CIRRUS_BLT_BUSY;
774

    
775
    s->cirrus_blt_width = (s->gr[0x20] | (s->gr[0x21] << 8)) + 1;
776
    s->cirrus_blt_height = (s->gr[0x22] | (s->gr[0x23] << 8)) + 1;
777
    s->cirrus_blt_dstpitch = (s->gr[0x24] | (s->gr[0x25] << 8));
778
    s->cirrus_blt_srcpitch = (s->gr[0x26] | (s->gr[0x27] << 8));
779
    s->cirrus_blt_dstaddr =
780
        (s->gr[0x28] | (s->gr[0x29] << 8) | (s->gr[0x2a] << 16));
781
    s->cirrus_blt_srcaddr =
782
        (s->gr[0x2c] | (s->gr[0x2d] << 8) | (s->gr[0x2e] << 16));
783
    s->cirrus_blt_mode = s->gr[0x30];
784
    s->cirrus_blt_modeext = s->gr[0x33];
785
    blt_rop = s->gr[0x32];
786

    
787
#ifdef DEBUG_BITBLT
788
    printf("rop=0x%02x mode=0x%02x modeext=0x%02x w=%d h=%d dpitch=%d spicth=%d daddr=0x%08x saddr=0x%08x writemask=0x%02x\n",
789
           blt_rop, 
790
           s->cirrus_blt_mode,
791
           s->cirrus_blt_modeext,
792
           s->cirrus_blt_width,
793
           s->cirrus_blt_height,
794
           s->cirrus_blt_dstpitch,
795
           s->cirrus_blt_srcpitch,
796
           s->cirrus_blt_dstaddr,
797
           s->cirrus_blt_srcaddr,
798
           s->sr[0x2f]);
799
#endif
800

    
801
    switch (s->cirrus_blt_mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) {
802
    case CIRRUS_BLTMODE_PIXELWIDTH8:
803
        s->cirrus_blt_pixelwidth = 1;
804
        break;
805
    case CIRRUS_BLTMODE_PIXELWIDTH16:
806
        s->cirrus_blt_pixelwidth = 2;
807
        break;
808
    case CIRRUS_BLTMODE_PIXELWIDTH24:
809
        s->cirrus_blt_pixelwidth = 3;
810
        break;
811
    case CIRRUS_BLTMODE_PIXELWIDTH32:
812
        s->cirrus_blt_pixelwidth = 4;
813
        break;
814
    default:
815
#ifdef DEBUG_BITBLT
816
        printf("cirrus: bitblt - pixel width is unknown\n");
817
#endif
818
        goto bitblt_ignore;
819
    }
820
    s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_PIXELWIDTHMASK;
821

    
822
    if ((s->
823
         cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSSRC |
824
                            CIRRUS_BLTMODE_MEMSYSDEST))
825
        == (CIRRUS_BLTMODE_MEMSYSSRC | CIRRUS_BLTMODE_MEMSYSDEST)) {
826
#ifdef DEBUG_BITBLT
827
        printf("cirrus: bitblt - memory-to-memory copy is requested\n");
828
#endif
829
        goto bitblt_ignore;
830
    }
831

    
832
    if ((s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_SOLIDFILL) &&
833
        (s->cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSDEST | 
834
                               CIRRUS_BLTMODE_TRANSPARENTCOMP |
835
                               CIRRUS_BLTMODE_PATTERNCOPY | 
836
                               CIRRUS_BLTMODE_COLOREXPAND)) == 
837
         (CIRRUS_BLTMODE_PATTERNCOPY | CIRRUS_BLTMODE_COLOREXPAND)) {
838
        cirrus_bitblt_fgcol(s);
839
        cirrus_bitblt_solidfill(s, blt_rop);
840
    } else {
841
        if ((s->cirrus_blt_mode & (CIRRUS_BLTMODE_COLOREXPAND | 
842
                                   CIRRUS_BLTMODE_PATTERNCOPY)) == 
843
            CIRRUS_BLTMODE_COLOREXPAND) {
844

    
845
            if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) {
846
                if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
847
                    cirrus_bitblt_bgcol(s);
848
                    s->cirrus_rop = cirrus_colorexpand_transp_inv[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
849
                } else {
850
                    cirrus_bitblt_fgcol(s);
851
                    s->cirrus_rop = cirrus_colorexpand_transp[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
852
                }
853
            } else {
854
                cirrus_bitblt_fgcol(s);
855
                cirrus_bitblt_bgcol(s);
856
                s->cirrus_rop = cirrus_colorexpand[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
857
            }
858
        } else {
859
            if (s->cirrus_blt_mode & CIRRUS_BLTMODE_BACKWARDS) {
860
                s->cirrus_blt_dstpitch = -s->cirrus_blt_dstpitch;
861
                s->cirrus_blt_srcpitch = -s->cirrus_blt_srcpitch;
862
                s->cirrus_rop = cirrus_bkwd_rop[rop_to_index[blt_rop]];
863
            } else {
864
                s->cirrus_rop = cirrus_fwd_rop[rop_to_index[blt_rop]];
865
            }
866
        }
867
        
868
        // setup bitblt engine.
869
        if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSSRC) {
870
            if (!cirrus_bitblt_cputovideo(s))
871
                goto bitblt_ignore;
872
        } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST) {
873
            if (!cirrus_bitblt_videotocpu(s))
874
                goto bitblt_ignore;
875
        } else {
876
            if (!cirrus_bitblt_videotovideo(s))
877
                goto bitblt_ignore;
878
        }
879
    }
880
    return;
881
  bitblt_ignore:;
882
    cirrus_bitblt_reset(s);
883
}
884

    
885
static void cirrus_write_bitblt(CirrusVGAState * s, unsigned reg_value)
886
{
887
    unsigned old_value;
888

    
889
    old_value = s->gr[0x31];
890
    s->gr[0x31] = reg_value;
891

    
892
    if (((old_value & CIRRUS_BLT_RESET) != 0) &&
893
        ((reg_value & CIRRUS_BLT_RESET) == 0)) {
894
        cirrus_bitblt_reset(s);
895
    } else if (((old_value & CIRRUS_BLT_START) == 0) &&
896
               ((reg_value & CIRRUS_BLT_START) != 0)) {
897
        cirrus_bitblt_start(s);
898
    }
899
}
900

    
901

    
902
/***************************************
903
 *
904
 *  basic parameters
905
 *
906
 ***************************************/
907

    
908
static void cirrus_get_offsets(VGAState *s1, 
909
                                   uint32_t *pline_offset,
910
                                   uint32_t *pstart_addr)
911
{
912
    CirrusVGAState * s = (CirrusVGAState *)s1;
913
    uint32_t start_addr;
914
    uint32_t line_offset;
915

    
916
    line_offset = s->cr[0x13]
917
        | ((s->cr[0x1b] & 0x10) << 4);
918
    line_offset <<= 3;
919
    *pline_offset = line_offset;
920

    
921
    start_addr = (s->cr[0x0c] << 8)
922
        | s->cr[0x0d]
923
        | ((s->cr[0x1b] & 0x01) << 16)
924
        | ((s->cr[0x1b] & 0x0c) << 15)
925
        | ((s->cr[0x1d] & 0x80) << 12);
926
    *pstart_addr = start_addr;
927
}
928

    
929
static uint32_t cirrus_get_bpp16_depth(CirrusVGAState * s)
930
{
931
    uint32_t ret = 16;
932

    
933
    switch (s->cirrus_hidden_dac_data & 0xf) {
934
    case 0:
935
        ret = 15;
936
        break;                        /* Sierra HiColor */
937
    case 1:
938
        ret = 16;
939
        break;                        /* XGA HiColor */
940
    default:
941
#ifdef DEBUG_CIRRUS
942
        printf("cirrus: invalid DAC value %x in 16bpp\n",
943
               (s->cirrus_hidden_dac_data & 0xf));
944
#endif
945
        ret = 15;                /* XXX */
946
        break;
947
    }
948
    return ret;
949
}
950

    
951
static int cirrus_get_bpp(VGAState *s1)
952
{
953
    CirrusVGAState * s = (CirrusVGAState *)s1;
954
    uint32_t ret = 8;
955

    
956
    if ((s->sr[0x07] & 0x01) != 0) {
957
        /* Cirrus SVGA */
958
        switch (s->sr[0x07] & CIRRUS_SR7_BPP_MASK) {
959
        case CIRRUS_SR7_BPP_8:
960
            ret = 8;
961
            break;
962
        case CIRRUS_SR7_BPP_16_DOUBLEVCLK:
963
            ret = cirrus_get_bpp16_depth(s);
964
            break;
965
        case CIRRUS_SR7_BPP_24:
966
            ret = 24;
967
            break;
968
        case CIRRUS_SR7_BPP_16:
969
            ret = cirrus_get_bpp16_depth(s);
970
            break;
971
        case CIRRUS_SR7_BPP_32:
972
            ret = 32;
973
            break;
974
        default:
975
#ifdef DEBUG_CIRRUS
976
            printf("cirrus: unknown bpp - sr7=%x\n", s->sr[0x7]);
977
#endif
978
            ret = 8;
979
            break;
980
        }
981
    } else {
982
        /* VGA */
983
        ret = 0;
984
    }
985

    
986
    return ret;
987
}
988

    
989
static void cirrus_get_resolution(VGAState *s, int *pwidth, int *pheight)
990
{
991
    int width, height;
992
    
993
    width = (s->cr[0x01] + 1) * 8;
994
    height = s->cr[0x12] | 
995
        ((s->cr[0x07] & 0x02) << 7) | 
996
        ((s->cr[0x07] & 0x40) << 3);
997
    height = (height + 1);
998
    /* interlace support */
999
    if (s->cr[0x1a] & 0x01)
1000
        height = height * 2;
1001
    *pwidth = width;
1002
    *pheight = height;
1003
}
1004

    
1005
/***************************************
1006
 *
1007
 * bank memory
1008
 *
1009
 ***************************************/
1010

    
1011
static void cirrus_update_bank_ptr(CirrusVGAState * s, unsigned bank_index)
1012
{
1013
    unsigned offset;
1014
    unsigned limit;
1015

    
1016
    if ((s->gr[0x0b] & 0x01) != 0)        /* dual bank */
1017
        offset = s->gr[0x09 + bank_index];
1018
    else                        /* single bank */
1019
        offset = s->gr[0x09];
1020

    
1021
    if ((s->gr[0x0b] & 0x20) != 0)
1022
        offset <<= 14;
1023
    else
1024
        offset <<= 12;
1025

    
1026
    if (s->vram_size <= offset)
1027
        limit = 0;
1028
    else
1029
        limit = s->vram_size - offset;
1030

    
1031
    if (((s->gr[0x0b] & 0x01) == 0) && (bank_index != 0)) {
1032
        if (limit > 0x8000) {
1033
            offset += 0x8000;
1034
            limit -= 0x8000;
1035
        } else {
1036
            limit = 0;
1037
        }
1038
    }
1039

    
1040
    if (limit > 0) {
1041
        s->cirrus_bank_base[bank_index] = offset;
1042
        s->cirrus_bank_limit[bank_index] = limit;
1043
    } else {
1044
        s->cirrus_bank_base[bank_index] = 0;
1045
        s->cirrus_bank_limit[bank_index] = 0;
1046
    }
1047
}
1048

    
1049
/***************************************
1050
 *
1051
 *  I/O access between 0x3c4-0x3c5
1052
 *
1053
 ***************************************/
1054

    
1055
static int
1056
cirrus_hook_read_sr(CirrusVGAState * s, unsigned reg_index, int *reg_value)
1057
{
1058
    switch (reg_index) {
1059
    case 0x00:                        // Standard VGA
1060
    case 0x01:                        // Standard VGA
1061
    case 0x02:                        // Standard VGA
1062
    case 0x03:                        // Standard VGA
1063
    case 0x04:                        // Standard VGA
1064
        return CIRRUS_HOOK_NOT_HANDLED;
1065
    case 0x06:                        // Unlock Cirrus extensions
1066
        *reg_value = s->sr[reg_index];
1067
        break;
1068
    case 0x10:
1069
    case 0x30:
1070
    case 0x50:
1071
    case 0x70:                        // Graphics Cursor X
1072
    case 0x90:
1073
    case 0xb0:
1074
    case 0xd0:
1075
    case 0xf0:                        // Graphics Cursor X
1076
        *reg_value = s->sr[0x10];
1077
        break;
1078
    case 0x11:
1079
    case 0x31:
1080
    case 0x51:
1081
    case 0x71:                        // Graphics Cursor Y
1082
    case 0x91:
1083
    case 0xb1:
1084
    case 0xd1:
1085
    case 0xf1:                        // Graphics Cursor Y
1086
        *reg_value = s->sr[0x11];
1087
        break;
1088
    case 0x05:                        // ???
1089
    case 0x07:                        // Extended Sequencer Mode
1090
    case 0x08:                        // EEPROM Control
1091
    case 0x09:                        // Scratch Register 0
1092
    case 0x0a:                        // Scratch Register 1
1093
    case 0x0b:                        // VCLK 0
1094
    case 0x0c:                        // VCLK 1
1095
    case 0x0d:                        // VCLK 2
1096
    case 0x0e:                        // VCLK 3
1097
    case 0x0f:                        // DRAM Control
1098
    case 0x12:                        // Graphics Cursor Attribute
1099
    case 0x13:                        // Graphics Cursor Pattern Address
1100
    case 0x14:                        // Scratch Register 2
1101
    case 0x15:                        // Scratch Register 3
1102
    case 0x16:                        // Performance Tuning Register
1103
    case 0x17:                        // Configuration Readback and Extended Control
1104
    case 0x18:                        // Signature Generator Control
1105
    case 0x19:                        // Signal Generator Result
1106
    case 0x1a:                        // Signal Generator Result
1107
    case 0x1b:                        // VCLK 0 Denominator & Post
1108
    case 0x1c:                        // VCLK 1 Denominator & Post
1109
    case 0x1d:                        // VCLK 2 Denominator & Post
1110
    case 0x1e:                        // VCLK 3 Denominator & Post
1111
    case 0x1f:                        // BIOS Write Enable and MCLK select
1112
#ifdef DEBUG_CIRRUS
1113
        printf("cirrus: handled inport sr_index %02x\n", reg_index);
1114
#endif
1115
        *reg_value = s->sr[reg_index];
1116
        break;
1117
    default:
1118
#ifdef DEBUG_CIRRUS
1119
        printf("cirrus: inport sr_index %02x\n", reg_index);
1120
#endif
1121
        *reg_value = 0xff;
1122
        break;
1123
    }
1124

    
1125
    return CIRRUS_HOOK_HANDLED;
1126
}
1127

    
1128
static int
1129
cirrus_hook_write_sr(CirrusVGAState * s, unsigned reg_index, int reg_value)
1130
{
1131
    switch (reg_index) {
1132
    case 0x00:                        // Standard VGA
1133
    case 0x01:                        // Standard VGA
1134
    case 0x02:                        // Standard VGA
1135
    case 0x03:                        // Standard VGA
1136
    case 0x04:                        // Standard VGA
1137
        return CIRRUS_HOOK_NOT_HANDLED;
1138
    case 0x06:                        // Unlock Cirrus extensions
1139
        reg_value &= 0x17;
1140
        if (reg_value == 0x12) {
1141
            s->sr[reg_index] = 0x12;
1142
        } else {
1143
            s->sr[reg_index] = 0x0f;
1144
        }
1145
        break;
1146
    case 0x10:
1147
    case 0x30:
1148
    case 0x50:
1149
    case 0x70:                        // Graphics Cursor X
1150
    case 0x90:
1151
    case 0xb0:
1152
    case 0xd0:
1153
    case 0xf0:                        // Graphics Cursor X
1154
        s->sr[0x10] = reg_value;
1155
        s->hw_cursor_x = (reg_value << 3) | (reg_index >> 5);
1156
        break;
1157
    case 0x11:
1158
    case 0x31:
1159
    case 0x51:
1160
    case 0x71:                        // Graphics Cursor Y
1161
    case 0x91:
1162
    case 0xb1:
1163
    case 0xd1:
1164
    case 0xf1:                        // Graphics Cursor Y
1165
        s->sr[0x11] = reg_value;
1166
        s->hw_cursor_y = (reg_value << 3) | (reg_index >> 5);
1167
        break;
1168
    case 0x07:                        // Extended Sequencer Mode
1169
    case 0x08:                        // EEPROM Control
1170
    case 0x09:                        // Scratch Register 0
1171
    case 0x0a:                        // Scratch Register 1
1172
    case 0x0b:                        // VCLK 0
1173
    case 0x0c:                        // VCLK 1
1174
    case 0x0d:                        // VCLK 2
1175
    case 0x0e:                        // VCLK 3
1176
    case 0x0f:                        // DRAM Control
1177
    case 0x12:                        // Graphics Cursor Attribute
1178
    case 0x13:                        // Graphics Cursor Pattern Address
1179
    case 0x14:                        // Scratch Register 2
1180
    case 0x15:                        // Scratch Register 3
1181
    case 0x16:                        // Performance Tuning Register
1182
    case 0x17:                        // Configuration Readback and Extended Control
1183
    case 0x18:                        // Signature Generator Control
1184
    case 0x19:                        // Signature Generator Result
1185
    case 0x1a:                        // Signature Generator Result
1186
    case 0x1b:                        // VCLK 0 Denominator & Post
1187
    case 0x1c:                        // VCLK 1 Denominator & Post
1188
    case 0x1d:                        // VCLK 2 Denominator & Post
1189
    case 0x1e:                        // VCLK 3 Denominator & Post
1190
    case 0x1f:                        // BIOS Write Enable and MCLK select
1191
        s->sr[reg_index] = reg_value;
1192
#ifdef DEBUG_CIRRUS
1193
        printf("cirrus: handled outport sr_index %02x, sr_value %02x\n",
1194
               reg_index, reg_value);
1195
#endif
1196
        break;
1197
    default:
1198
#ifdef DEBUG_CIRRUS
1199
        printf("cirrus: outport sr_index %02x, sr_value %02x\n", reg_index,
1200
               reg_value);
1201
#endif
1202
        break;
1203
    }
1204

    
1205
    return CIRRUS_HOOK_HANDLED;
1206
}
1207

    
1208
/***************************************
1209
 *
1210
 *  I/O access at 0x3c6
1211
 *
1212
 ***************************************/
1213

    
1214
static void cirrus_read_hidden_dac(CirrusVGAState * s, int *reg_value)
1215
{
1216
    *reg_value = 0xff;
1217
    if (++s->cirrus_hidden_dac_lockindex == 5) {
1218
        *reg_value = s->cirrus_hidden_dac_data;
1219
        s->cirrus_hidden_dac_lockindex = 0;
1220
    }
1221
}
1222

    
1223
static void cirrus_write_hidden_dac(CirrusVGAState * s, int reg_value)
1224
{
1225
    if (s->cirrus_hidden_dac_lockindex == 4) {
1226
        s->cirrus_hidden_dac_data = reg_value;
1227
#if defined(DEBUG_CIRRUS)
1228
        printf("cirrus: outport hidden DAC, value %02x\n", reg_value);
1229
#endif
1230
    }
1231
    s->cirrus_hidden_dac_lockindex = 0;
1232
}
1233

    
1234
/***************************************
1235
 *
1236
 *  I/O access at 0x3c9
1237
 *
1238
 ***************************************/
1239

    
1240
static int cirrus_hook_read_palette(CirrusVGAState * s, int *reg_value)
1241
{
1242
    if (!(s->sr[0x12] & CIRRUS_CURSOR_HIDDENPEL))
1243
        return CIRRUS_HOOK_NOT_HANDLED;
1244
    *reg_value =
1245
        s->cirrus_hidden_palette[(s->dac_read_index & 0x0f) * 3 +
1246
                                 s->dac_sub_index];
1247
    if (++s->dac_sub_index == 3) {
1248
        s->dac_sub_index = 0;
1249
        s->dac_read_index++;
1250
    }
1251
    return CIRRUS_HOOK_HANDLED;
1252
}
1253

    
1254
static int cirrus_hook_write_palette(CirrusVGAState * s, int reg_value)
1255
{
1256
    if (!(s->sr[0x12] & CIRRUS_CURSOR_HIDDENPEL))
1257
        return CIRRUS_HOOK_NOT_HANDLED;
1258
    s->dac_cache[s->dac_sub_index] = reg_value;
1259
    if (++s->dac_sub_index == 3) {
1260
        memcpy(&s->cirrus_hidden_palette[(s->dac_write_index & 0x0f) * 3],
1261
               s->dac_cache, 3);
1262
        /* XXX update cursor */
1263
        s->dac_sub_index = 0;
1264
        s->dac_write_index++;
1265
    }
1266
    return CIRRUS_HOOK_HANDLED;
1267
}
1268

    
1269
/***************************************
1270
 *
1271
 *  I/O access between 0x3ce-0x3cf
1272
 *
1273
 ***************************************/
1274

    
1275
static int
1276
cirrus_hook_read_gr(CirrusVGAState * s, unsigned reg_index, int *reg_value)
1277
{
1278
    switch (reg_index) {
1279
    case 0x00: // Standard VGA, BGCOLOR 0x000000ff
1280
      *reg_value = s->cirrus_shadow_gr0;
1281
      return CIRRUS_HOOK_HANDLED;
1282
    case 0x01: // Standard VGA, FGCOLOR 0x000000ff
1283
      *reg_value = s->cirrus_shadow_gr1;
1284
      return CIRRUS_HOOK_HANDLED;
1285
    case 0x02:                        // Standard VGA
1286
    case 0x03:                        // Standard VGA
1287
    case 0x04:                        // Standard VGA
1288
    case 0x06:                        // Standard VGA
1289
    case 0x07:                        // Standard VGA
1290
    case 0x08:                        // Standard VGA
1291
        return CIRRUS_HOOK_NOT_HANDLED;
1292
    case 0x05:                        // Standard VGA, Cirrus extended mode
1293
    default:
1294
        break;
1295
    }
1296

    
1297
    if (reg_index < 0x3a) {
1298
        *reg_value = s->gr[reg_index];
1299
    } else {
1300
#ifdef DEBUG_CIRRUS
1301
        printf("cirrus: inport gr_index %02x\n", reg_index);
1302
#endif
1303
        *reg_value = 0xff;
1304
    }
1305

    
1306
    return CIRRUS_HOOK_HANDLED;
1307
}
1308

    
1309
static int
1310
cirrus_hook_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value)
1311
{
1312
#if defined(DEBUG_BITBLT) && 0
1313
    printf("gr%02x: %02x\n", reg_index, reg_value);
1314
#endif
1315
    switch (reg_index) {
1316
    case 0x00:                        // Standard VGA, BGCOLOR 0x000000ff
1317
        s->cirrus_shadow_gr0 = reg_value;
1318
        return CIRRUS_HOOK_NOT_HANDLED;
1319
    case 0x01:                        // Standard VGA, FGCOLOR 0x000000ff
1320
        s->cirrus_shadow_gr1 = reg_value;
1321
        return CIRRUS_HOOK_NOT_HANDLED;
1322
    case 0x02:                        // Standard VGA
1323
    case 0x03:                        // Standard VGA
1324
    case 0x04:                        // Standard VGA
1325
    case 0x06:                        // Standard VGA
1326
    case 0x07:                        // Standard VGA
1327
    case 0x08:                        // Standard VGA
1328
        return CIRRUS_HOOK_NOT_HANDLED;
1329
    case 0x05:                        // Standard VGA, Cirrus extended mode
1330
        s->gr[reg_index] = reg_value & 0x7f;
1331
        break;
1332
    case 0x09:                        // bank offset #0
1333
    case 0x0A:                        // bank offset #1
1334
    case 0x0B:
1335
        s->gr[reg_index] = reg_value;
1336
        cirrus_update_bank_ptr(s, 0);
1337
        cirrus_update_bank_ptr(s, 1);
1338
        break;
1339
    case 0x10:                        // BGCOLOR 0x0000ff00
1340
    case 0x11:                        // FGCOLOR 0x0000ff00
1341
    case 0x12:                        // BGCOLOR 0x00ff0000
1342
    case 0x13:                        // FGCOLOR 0x00ff0000
1343
    case 0x14:                        // BGCOLOR 0xff000000
1344
    case 0x15:                        // FGCOLOR 0xff000000
1345
    case 0x20:                        // BLT WIDTH 0x0000ff
1346
    case 0x22:                        // BLT HEIGHT 0x0000ff
1347
    case 0x24:                        // BLT DEST PITCH 0x0000ff
1348
    case 0x26:                        // BLT SRC PITCH 0x0000ff
1349
    case 0x28:                        // BLT DEST ADDR 0x0000ff
1350
    case 0x29:                        // BLT DEST ADDR 0x00ff00
1351
    case 0x2c:                        // BLT SRC ADDR 0x0000ff
1352
    case 0x2d:                        // BLT SRC ADDR 0x00ff00
1353
    case 0x2f:                  // BLT WRITEMASK
1354
    case 0x30:                        // BLT MODE
1355
    case 0x32:                        // RASTER OP
1356
    case 0x33:                        // BLT MODEEXT
1357
    case 0x34:                        // BLT TRANSPARENT COLOR 0x00ff
1358
    case 0x35:                        // BLT TRANSPARENT COLOR 0xff00
1359
    case 0x38:                        // BLT TRANSPARENT COLOR MASK 0x00ff
1360
    case 0x39:                        // BLT TRANSPARENT COLOR MASK 0xff00
1361
        s->gr[reg_index] = reg_value;
1362
        break;
1363
    case 0x21:                        // BLT WIDTH 0x001f00
1364
    case 0x23:                        // BLT HEIGHT 0x001f00
1365
    case 0x25:                        // BLT DEST PITCH 0x001f00
1366
    case 0x27:                        // BLT SRC PITCH 0x001f00
1367
        s->gr[reg_index] = reg_value & 0x1f;
1368
        break;
1369
    case 0x2a:                        // BLT DEST ADDR 0x3f0000
1370
        s->gr[reg_index] = reg_value & 0x3f;
1371
        /* if auto start mode, starts bit blt now */
1372
        if (s->gr[0x31] & CIRRUS_BLT_AUTOSTART) {
1373
            cirrus_bitblt_start(s);
1374
        }
1375
        break;
1376
    case 0x2e:                        // BLT SRC ADDR 0x3f0000
1377
        s->gr[reg_index] = reg_value & 0x3f;
1378
        break;
1379
    case 0x31:                        // BLT STATUS/START
1380
        cirrus_write_bitblt(s, reg_value);
1381
        break;
1382
    default:
1383
#ifdef DEBUG_CIRRUS
1384
        printf("cirrus: outport gr_index %02x, gr_value %02x\n", reg_index,
1385
               reg_value);
1386
#endif
1387
        break;
1388
    }
1389

    
1390
    return CIRRUS_HOOK_HANDLED;
1391
}
1392

    
1393
/***************************************
1394
 *
1395
 *  I/O access between 0x3d4-0x3d5
1396
 *
1397
 ***************************************/
1398

    
1399
static int
1400
cirrus_hook_read_cr(CirrusVGAState * s, unsigned reg_index, int *reg_value)
1401
{
1402
    switch (reg_index) {
1403
    case 0x00:                        // Standard VGA
1404
    case 0x01:                        // Standard VGA
1405
    case 0x02:                        // Standard VGA
1406
    case 0x03:                        // Standard VGA
1407
    case 0x04:                        // Standard VGA
1408
    case 0x05:                        // Standard VGA
1409
    case 0x06:                        // Standard VGA
1410
    case 0x07:                        // Standard VGA
1411
    case 0x08:                        // Standard VGA
1412
    case 0x09:                        // Standard VGA
1413
    case 0x0a:                        // Standard VGA
1414
    case 0x0b:                        // Standard VGA
1415
    case 0x0c:                        // Standard VGA
1416
    case 0x0d:                        // Standard VGA
1417
    case 0x0e:                        // Standard VGA
1418
    case 0x0f:                        // Standard VGA
1419
    case 0x10:                        // Standard VGA
1420
    case 0x11:                        // Standard VGA
1421
    case 0x12:                        // Standard VGA
1422
    case 0x13:                        // Standard VGA
1423
    case 0x14:                        // Standard VGA
1424
    case 0x15:                        // Standard VGA
1425
    case 0x16:                        // Standard VGA
1426
    case 0x17:                        // Standard VGA
1427
    case 0x18:                        // Standard VGA
1428
        return CIRRUS_HOOK_NOT_HANDLED;
1429
    case 0x19:                        // Interlace End
1430
    case 0x1a:                        // Miscellaneous Control
1431
    case 0x1b:                        // Extended Display Control
1432
    case 0x1c:                        // Sync Adjust and Genlock
1433
    case 0x1d:                        // Overlay Extended Control
1434
    case 0x22:                        // Graphics Data Latches Readback (R)
1435
    case 0x24:                        // Attribute Controller Toggle Readback (R)
1436
    case 0x25:                        // Part Status
1437
    case 0x27:                        // Part ID (R)
1438
        *reg_value = s->cr[reg_index];
1439
        break;
1440
    case 0x26:                        // Attribute Controller Index Readback (R)
1441
        *reg_value = s->ar_index & 0x3f;
1442
        break;
1443
    default:
1444
#ifdef DEBUG_CIRRUS
1445
        printf("cirrus: inport cr_index %02x\n", reg_index);
1446
        *reg_value = 0xff;
1447
#endif
1448
        break;
1449
    }
1450

    
1451
    return CIRRUS_HOOK_HANDLED;
1452
}
1453

    
1454
static int
1455
cirrus_hook_write_cr(CirrusVGAState * s, unsigned reg_index, int reg_value)
1456
{
1457
    switch (reg_index) {
1458
    case 0x00:                        // Standard VGA
1459
    case 0x01:                        // Standard VGA
1460
    case 0x02:                        // Standard VGA
1461
    case 0x03:                        // Standard VGA
1462
    case 0x04:                        // Standard VGA
1463
    case 0x05:                        // Standard VGA
1464
    case 0x06:                        // Standard VGA
1465
    case 0x07:                        // Standard VGA
1466
    case 0x08:                        // Standard VGA
1467
    case 0x09:                        // Standard VGA
1468
    case 0x0a:                        // Standard VGA
1469
    case 0x0b:                        // Standard VGA
1470
    case 0x0c:                        // Standard VGA
1471
    case 0x0d:                        // Standard VGA
1472
    case 0x0e:                        // Standard VGA
1473
    case 0x0f:                        // Standard VGA
1474
    case 0x10:                        // Standard VGA
1475
    case 0x11:                        // Standard VGA
1476
    case 0x12:                        // Standard VGA
1477
    case 0x13:                        // Standard VGA
1478
    case 0x14:                        // Standard VGA
1479
    case 0x15:                        // Standard VGA
1480
    case 0x16:                        // Standard VGA
1481
    case 0x17:                        // Standard VGA
1482
    case 0x18:                        // Standard VGA
1483
        return CIRRUS_HOOK_NOT_HANDLED;
1484
    case 0x19:                        // Interlace End
1485
    case 0x1a:                        // Miscellaneous Control
1486
    case 0x1b:                        // Extended Display Control
1487
    case 0x1c:                        // Sync Adjust and Genlock
1488
        s->cr[reg_index] = reg_value;
1489
#ifdef DEBUG_CIRRUS
1490
        printf("cirrus: handled outport cr_index %02x, cr_value %02x\n",
1491
               reg_index, reg_value);
1492
#endif
1493
        break;
1494
    case 0x22:                        // Graphics Data Latches Readback (R)
1495
    case 0x24:                        // Attribute Controller Toggle Readback (R)
1496
    case 0x26:                        // Attribute Controller Index Readback (R)
1497
    case 0x27:                        // Part ID (R)
1498
        break;
1499
    case 0x1d:                        // Overlay Extended Control
1500
    case 0x25:                        // Part Status
1501
    default:
1502
#ifdef DEBUG_CIRRUS
1503
        printf("cirrus: outport cr_index %02x, cr_value %02x\n", reg_index,
1504
               reg_value);
1505
#endif
1506
        break;
1507
    }
1508

    
1509
    return CIRRUS_HOOK_HANDLED;
1510
}
1511

    
1512
/***************************************
1513
 *
1514
 *  memory-mapped I/O (bitblt)
1515
 *
1516
 ***************************************/
1517

    
1518
static uint8_t cirrus_mmio_blt_read(CirrusVGAState * s, unsigned address)
1519
{
1520
    int value = 0xff;
1521

    
1522
    switch (address) {
1523
    case (CIRRUS_MMIO_BLTBGCOLOR + 0):
1524
        cirrus_hook_read_gr(s, 0x00, &value);
1525
        break;
1526
    case (CIRRUS_MMIO_BLTBGCOLOR + 1):
1527
        cirrus_hook_read_gr(s, 0x10, &value);
1528
        break;
1529
    case (CIRRUS_MMIO_BLTBGCOLOR + 2):
1530
        cirrus_hook_read_gr(s, 0x12, &value);
1531
        break;
1532
    case (CIRRUS_MMIO_BLTBGCOLOR + 3):
1533
        cirrus_hook_read_gr(s, 0x14, &value);
1534
        break;
1535
    case (CIRRUS_MMIO_BLTFGCOLOR + 0):
1536
        cirrus_hook_read_gr(s, 0x01, &value);
1537
        break;
1538
    case (CIRRUS_MMIO_BLTFGCOLOR + 1):
1539
        cirrus_hook_read_gr(s, 0x11, &value);
1540
        break;
1541
    case (CIRRUS_MMIO_BLTFGCOLOR + 2):
1542
        cirrus_hook_read_gr(s, 0x13, &value);
1543
        break;
1544
    case (CIRRUS_MMIO_BLTFGCOLOR + 3):
1545
        cirrus_hook_read_gr(s, 0x15, &value);
1546
        break;
1547
    case (CIRRUS_MMIO_BLTWIDTH + 0):
1548
        cirrus_hook_read_gr(s, 0x20, &value);
1549
        break;
1550
    case (CIRRUS_MMIO_BLTWIDTH + 1):
1551
        cirrus_hook_read_gr(s, 0x21, &value);
1552
        break;
1553
    case (CIRRUS_MMIO_BLTHEIGHT + 0):
1554
        cirrus_hook_read_gr(s, 0x22, &value);
1555
        break;
1556
    case (CIRRUS_MMIO_BLTHEIGHT + 1):
1557
        cirrus_hook_read_gr(s, 0x23, &value);
1558
        break;
1559
    case (CIRRUS_MMIO_BLTDESTPITCH + 0):
1560
        cirrus_hook_read_gr(s, 0x24, &value);
1561
        break;
1562
    case (CIRRUS_MMIO_BLTDESTPITCH + 1):
1563
        cirrus_hook_read_gr(s, 0x25, &value);
1564
        break;
1565
    case (CIRRUS_MMIO_BLTSRCPITCH + 0):
1566
        cirrus_hook_read_gr(s, 0x26, &value);
1567
        break;
1568
    case (CIRRUS_MMIO_BLTSRCPITCH + 1):
1569
        cirrus_hook_read_gr(s, 0x27, &value);
1570
        break;
1571
    case (CIRRUS_MMIO_BLTDESTADDR + 0):
1572
        cirrus_hook_read_gr(s, 0x28, &value);
1573
        break;
1574
    case (CIRRUS_MMIO_BLTDESTADDR + 1):
1575
        cirrus_hook_read_gr(s, 0x29, &value);
1576
        break;
1577
    case (CIRRUS_MMIO_BLTDESTADDR + 2):
1578
        cirrus_hook_read_gr(s, 0x2a, &value);
1579
        break;
1580
    case (CIRRUS_MMIO_BLTSRCADDR + 0):
1581
        cirrus_hook_read_gr(s, 0x2c, &value);
1582
        break;
1583
    case (CIRRUS_MMIO_BLTSRCADDR + 1):
1584
        cirrus_hook_read_gr(s, 0x2d, &value);
1585
        break;
1586
    case (CIRRUS_MMIO_BLTSRCADDR + 2):
1587
        cirrus_hook_read_gr(s, 0x2e, &value);
1588
        break;
1589
    case CIRRUS_MMIO_BLTWRITEMASK:
1590
        cirrus_hook_read_gr(s, 0x2f, &value);
1591
        break;
1592
    case CIRRUS_MMIO_BLTMODE:
1593
        cirrus_hook_read_gr(s, 0x30, &value);
1594
        break;
1595
    case CIRRUS_MMIO_BLTROP:
1596
        cirrus_hook_read_gr(s, 0x32, &value);
1597
        break;
1598
    case CIRRUS_MMIO_BLTMODEEXT:
1599
        cirrus_hook_read_gr(s, 0x33, &value);
1600
        break;
1601
    case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0):
1602
        cirrus_hook_read_gr(s, 0x34, &value);
1603
        break;
1604
    case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1):
1605
        cirrus_hook_read_gr(s, 0x35, &value);
1606
        break;
1607
    case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0):
1608
        cirrus_hook_read_gr(s, 0x38, &value);
1609
        break;
1610
    case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1):
1611
        cirrus_hook_read_gr(s, 0x39, &value);
1612
        break;
1613
    case CIRRUS_MMIO_BLTSTATUS:
1614
        cirrus_hook_read_gr(s, 0x31, &value);
1615
        break;
1616
    default:
1617
#ifdef DEBUG_CIRRUS
1618
        printf("cirrus: mmio read - address 0x%04x\n", address);
1619
#endif
1620
        break;
1621
    }
1622

    
1623
    return (uint8_t) value;
1624
}
1625

    
1626
static void cirrus_mmio_blt_write(CirrusVGAState * s, unsigned address,
1627
                                  uint8_t value)
1628
{
1629
    switch (address) {
1630
    case (CIRRUS_MMIO_BLTBGCOLOR + 0):
1631
        cirrus_hook_write_gr(s, 0x00, value);
1632
        break;
1633
    case (CIRRUS_MMIO_BLTBGCOLOR + 1):
1634
        cirrus_hook_write_gr(s, 0x10, value);
1635
        break;
1636
    case (CIRRUS_MMIO_BLTBGCOLOR + 2):
1637
        cirrus_hook_write_gr(s, 0x12, value);
1638
        break;
1639
    case (CIRRUS_MMIO_BLTBGCOLOR + 3):
1640
        cirrus_hook_write_gr(s, 0x14, value);
1641
        break;
1642
    case (CIRRUS_MMIO_BLTFGCOLOR + 0):
1643
        cirrus_hook_write_gr(s, 0x01, value);
1644
        break;
1645
    case (CIRRUS_MMIO_BLTFGCOLOR + 1):
1646
        cirrus_hook_write_gr(s, 0x11, value);
1647
        break;
1648
    case (CIRRUS_MMIO_BLTFGCOLOR + 2):
1649
        cirrus_hook_write_gr(s, 0x13, value);
1650
        break;
1651
    case (CIRRUS_MMIO_BLTFGCOLOR + 3):
1652
        cirrus_hook_write_gr(s, 0x15, value);
1653
        break;
1654
    case (CIRRUS_MMIO_BLTWIDTH + 0):
1655
        cirrus_hook_write_gr(s, 0x20, value);
1656
        break;
1657
    case (CIRRUS_MMIO_BLTWIDTH + 1):
1658
        cirrus_hook_write_gr(s, 0x21, value);
1659
        break;
1660
    case (CIRRUS_MMIO_BLTHEIGHT + 0):
1661
        cirrus_hook_write_gr(s, 0x22, value);
1662
        break;
1663
    case (CIRRUS_MMIO_BLTHEIGHT + 1):
1664
        cirrus_hook_write_gr(s, 0x23, value);
1665
        break;
1666
    case (CIRRUS_MMIO_BLTDESTPITCH + 0):
1667
        cirrus_hook_write_gr(s, 0x24, value);
1668
        break;
1669
    case (CIRRUS_MMIO_BLTDESTPITCH + 1):
1670
        cirrus_hook_write_gr(s, 0x25, value);
1671
        break;
1672
    case (CIRRUS_MMIO_BLTSRCPITCH + 0):
1673
        cirrus_hook_write_gr(s, 0x26, value);
1674
        break;
1675
    case (CIRRUS_MMIO_BLTSRCPITCH + 1):
1676
        cirrus_hook_write_gr(s, 0x27, value);
1677
        break;
1678
    case (CIRRUS_MMIO_BLTDESTADDR + 0):
1679
        cirrus_hook_write_gr(s, 0x28, value);
1680
        break;
1681
    case (CIRRUS_MMIO_BLTDESTADDR + 1):
1682
        cirrus_hook_write_gr(s, 0x29, value);
1683
        break;
1684
    case (CIRRUS_MMIO_BLTDESTADDR + 2):
1685
        cirrus_hook_write_gr(s, 0x2a, value);
1686
        break;
1687
    case (CIRRUS_MMIO_BLTDESTADDR + 3):
1688
        /* ignored */
1689
        break;
1690
    case (CIRRUS_MMIO_BLTSRCADDR + 0):
1691
        cirrus_hook_write_gr(s, 0x2c, value);
1692
        break;
1693
    case (CIRRUS_MMIO_BLTSRCADDR + 1):
1694
        cirrus_hook_write_gr(s, 0x2d, value);
1695
        break;
1696
    case (CIRRUS_MMIO_BLTSRCADDR + 2):
1697
        cirrus_hook_write_gr(s, 0x2e, value);
1698
        break;
1699
    case CIRRUS_MMIO_BLTWRITEMASK:
1700
        cirrus_hook_write_gr(s, 0x2f, value);
1701
        break;
1702
    case CIRRUS_MMIO_BLTMODE:
1703
        cirrus_hook_write_gr(s, 0x30, value);
1704
        break;
1705
    case CIRRUS_MMIO_BLTROP:
1706
        cirrus_hook_write_gr(s, 0x32, value);
1707
        break;
1708
    case CIRRUS_MMIO_BLTMODEEXT:
1709
        cirrus_hook_write_gr(s, 0x33, value);
1710
        break;
1711
    case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0):
1712
        cirrus_hook_write_gr(s, 0x34, value);
1713
        break;
1714
    case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1):
1715
        cirrus_hook_write_gr(s, 0x35, value);
1716
        break;
1717
    case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0):
1718
        cirrus_hook_write_gr(s, 0x38, value);
1719
        break;
1720
    case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1):
1721
        cirrus_hook_write_gr(s, 0x39, value);
1722
        break;
1723
    case CIRRUS_MMIO_BLTSTATUS:
1724
        cirrus_hook_write_gr(s, 0x31, value);
1725
        break;
1726
    default:
1727
#ifdef DEBUG_CIRRUS
1728
        printf("cirrus: mmio write - addr 0x%04x val 0x%02x (ignored)\n",
1729
               address, value);
1730
#endif
1731
        break;
1732
    }
1733
}
1734

    
1735
/***************************************
1736
 *
1737
 *  write mode 4/5
1738
 *
1739
 * assume TARGET_PAGE_SIZE >= 16
1740
 *
1741
 ***************************************/
1742

    
1743
static void cirrus_mem_writeb_mode4and5_8bpp(CirrusVGAState * s,
1744
                                             unsigned mode,
1745
                                             unsigned offset,
1746
                                             uint32_t mem_value)
1747
{
1748
    int x;
1749
    unsigned val = mem_value;
1750
    uint8_t *dst;
1751

    
1752
    dst = s->vram_ptr + offset;
1753
    for (x = 0; x < 8; x++) {
1754
        if (val & 0x80) {
1755
            *dst++ = s->cirrus_shadow_gr1;
1756
        } else if (mode == 5) {
1757
            *dst++ = s->cirrus_shadow_gr0;
1758
        }
1759
        val <<= 1;
1760
    }
1761
    cpu_physical_memory_set_dirty(s->vram_offset + offset);
1762
    cpu_physical_memory_set_dirty(s->vram_offset + offset + 7);
1763
}
1764

    
1765
static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,
1766
                                              unsigned mode,
1767
                                              unsigned offset,
1768
                                              uint32_t mem_value)
1769
{
1770
    int x;
1771
    unsigned val = mem_value;
1772
    uint8_t *dst;
1773

    
1774
    dst = s->vram_ptr + offset;
1775
    for (x = 0; x < 8; x++) {
1776
        if (val & 0x80) {
1777
            *dst++ = s->cirrus_shadow_gr1;
1778
            *dst++ = s->gr[0x11];
1779
        } else if (mode == 5) {
1780
            *dst++ = s->cirrus_shadow_gr0;
1781
            *dst++ = s->gr[0x10];
1782
        }
1783
        val <<= 1;
1784
    }
1785
    cpu_physical_memory_set_dirty(s->vram_offset + offset);
1786
    cpu_physical_memory_set_dirty(s->vram_offset + offset + 15);
1787
}
1788

    
1789
/***************************************
1790
 *
1791
 *  memory access between 0xa0000-0xbffff
1792
 *
1793
 ***************************************/
1794

    
1795
static uint32_t cirrus_vga_mem_readb(void *opaque, target_phys_addr_t addr)
1796
{
1797
    CirrusVGAState *s = opaque;
1798
    unsigned bank_index;
1799
    unsigned bank_offset;
1800
    uint32_t val;
1801

    
1802
    if ((s->sr[0x07] & 0x01) == 0) {
1803
        return vga_mem_readb(s, addr);
1804
    }
1805

    
1806
    addr &= 0x1ffff;
1807

    
1808
    if (addr < 0x10000) {
1809
        /* XXX handle bitblt */
1810
        /* video memory */
1811
        bank_index = addr >> 15;
1812
        bank_offset = addr & 0x7fff;
1813
        if (bank_offset < s->cirrus_bank_limit[bank_index]) {
1814
            bank_offset += s->cirrus_bank_base[bank_index];
1815
            if ((s->gr[0x0B] & 0x14) == 0x14) {
1816
                bank_offset <<= 4;
1817
            } else if (s->gr[0x0B] & 0x02) {
1818
                bank_offset <<= 3;
1819
            }
1820
            bank_offset &= s->cirrus_addr_mask;
1821
            val = *(s->vram_ptr + bank_offset);
1822
        } else
1823
            val = 0xff;
1824
    } else if (addr >= 0x18000 && addr < 0x18100) {
1825
        /* memory-mapped I/O */
1826
        val = 0xff;
1827
        if ((s->sr[0x17] & 0x44) == 0x04) {
1828
            val = cirrus_mmio_blt_read(s, addr & 0xff);
1829
        }
1830
    } else {
1831
        val = 0xff;
1832
#ifdef DEBUG_CIRRUS
1833
        printf("cirrus: mem_readb %06x\n", addr);
1834
#endif
1835
    }
1836
    return val;
1837
}
1838

    
1839
static uint32_t cirrus_vga_mem_readw(void *opaque, target_phys_addr_t addr)
1840
{
1841
    uint32_t v;
1842
#ifdef TARGET_WORDS_BIGENDIAN
1843
    v = cirrus_vga_mem_readb(opaque, addr) << 8;
1844
    v |= cirrus_vga_mem_readb(opaque, addr + 1);
1845
#else
1846
    v = cirrus_vga_mem_readb(opaque, addr);
1847
    v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
1848
#endif
1849
    return v;
1850
}
1851

    
1852
static uint32_t cirrus_vga_mem_readl(void *opaque, target_phys_addr_t addr)
1853
{
1854
    uint32_t v;
1855
#ifdef TARGET_WORDS_BIGENDIAN
1856
    v = cirrus_vga_mem_readb(opaque, addr) << 24;
1857
    v |= cirrus_vga_mem_readb(opaque, addr + 1) << 16;
1858
    v |= cirrus_vga_mem_readb(opaque, addr + 2) << 8;
1859
    v |= cirrus_vga_mem_readb(opaque, addr + 3);
1860
#else
1861
    v = cirrus_vga_mem_readb(opaque, addr);
1862
    v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
1863
    v |= cirrus_vga_mem_readb(opaque, addr + 2) << 16;
1864
    v |= cirrus_vga_mem_readb(opaque, addr + 3) << 24;
1865
#endif
1866
    return v;
1867
}
1868

    
1869
static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr, 
1870
                                  uint32_t mem_value)
1871
{
1872
    CirrusVGAState *s = opaque;
1873
    unsigned bank_index;
1874
    unsigned bank_offset;
1875
    unsigned mode;
1876

    
1877
    if ((s->sr[0x07] & 0x01) == 0) {
1878
        vga_mem_writeb(s, addr, mem_value);
1879
        return;
1880
    }
1881

    
1882
    addr &= 0x1ffff;
1883

    
1884
    if (addr < 0x10000) {
1885
        if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
1886
            /* bitblt */
1887
            *s->cirrus_srcptr++ = (uint8_t) mem_value;
1888
            if (s->cirrus_srcptr >= s->cirrus_srcptr_end) {
1889
                cirrus_bitblt_cputovideo_next(s);
1890
            }
1891
        } else {
1892
            /* video memory */
1893
            bank_index = addr >> 15;
1894
            bank_offset = addr & 0x7fff;
1895
            if (bank_offset < s->cirrus_bank_limit[bank_index]) {
1896
                bank_offset += s->cirrus_bank_base[bank_index];
1897
                if ((s->gr[0x0B] & 0x14) == 0x14) {
1898
                    bank_offset <<= 4;
1899
                } else if (s->gr[0x0B] & 0x02) {
1900
                    bank_offset <<= 3;
1901
                }
1902
                bank_offset &= s->cirrus_addr_mask;
1903
                mode = s->gr[0x05] & 0x7;
1904
                if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
1905
                    *(s->vram_ptr + bank_offset) = mem_value;
1906
                    cpu_physical_memory_set_dirty(s->vram_offset +
1907
                                                  bank_offset);
1908
                } else {
1909
                    if ((s->gr[0x0B] & 0x14) != 0x14) {
1910
                        cirrus_mem_writeb_mode4and5_8bpp(s, mode,
1911
                                                         bank_offset,
1912
                                                         mem_value);
1913
                    } else {
1914
                        cirrus_mem_writeb_mode4and5_16bpp(s, mode,
1915
                                                          bank_offset,
1916
                                                          mem_value);
1917
                    }
1918
                }
1919
            }
1920
        }
1921
    } else if (addr >= 0x18000 && addr < 0x18100) {
1922
        /* memory-mapped I/O */
1923
        if ((s->sr[0x17] & 0x44) == 0x04) {
1924
            cirrus_mmio_blt_write(s, addr & 0xff, mem_value);
1925
        }
1926
    } else {
1927
#ifdef DEBUG_CIRRUS
1928
        printf("cirrus: mem_writeb %06x value %02x\n", addr, mem_value);
1929
#endif
1930
    }
1931
}
1932

    
1933
static void cirrus_vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
1934
{
1935
#ifdef TARGET_WORDS_BIGENDIAN
1936
    cirrus_vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
1937
    cirrus_vga_mem_writeb(opaque, addr + 1, val & 0xff);
1938
#else
1939
    cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
1940
    cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
1941
#endif
1942
}
1943

    
1944
static void cirrus_vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
1945
{
1946
#ifdef TARGET_WORDS_BIGENDIAN
1947
    cirrus_vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
1948
    cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
1949
    cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
1950
    cirrus_vga_mem_writeb(opaque, addr + 3, val & 0xff);
1951
#else
1952
    cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
1953
    cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
1954
    cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
1955
    cirrus_vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
1956
#endif
1957
}
1958

    
1959
static CPUReadMemoryFunc *cirrus_vga_mem_read[3] = {
1960
    cirrus_vga_mem_readb,
1961
    cirrus_vga_mem_readw,
1962
    cirrus_vga_mem_readl,
1963
};
1964

    
1965
static CPUWriteMemoryFunc *cirrus_vga_mem_write[3] = {
1966
    cirrus_vga_mem_writeb,
1967
    cirrus_vga_mem_writew,
1968
    cirrus_vga_mem_writel,
1969
};
1970

    
1971
/***************************************
1972
 *
1973
 *  hardware cursor
1974
 *
1975
 ***************************************/
1976

    
1977
static inline void invalidate_cursor1(CirrusVGAState *s)
1978
{
1979
    if (s->last_hw_cursor_size) {
1980
        vga_invalidate_scanlines((VGAState *)s, 
1981
                                 s->last_hw_cursor_y + s->last_hw_cursor_y_start,
1982
                                 s->last_hw_cursor_y + s->last_hw_cursor_y_end);
1983
    }
1984
}
1985

    
1986
static inline void cirrus_cursor_compute_yrange(CirrusVGAState *s)
1987
{
1988
    const uint8_t *src;
1989
    uint32_t content;
1990
    int y, y_min, y_max;
1991

    
1992
    src = s->vram_ptr + s->real_vram_size - 16 * 1024;
1993
    if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) {
1994
        src += (s->sr[0x13] & 0x3c) * 256;
1995
        y_min = 64;
1996
        y_max = -1;
1997
        for(y = 0; y < 64; y++) {
1998
            content = ((uint32_t *)src)[0] |
1999
                ((uint32_t *)src)[1] |
2000
                ((uint32_t *)src)[2] |
2001
                ((uint32_t *)src)[3];
2002
            if (content) {
2003
                if (y < y_min)
2004
                    y_min = y;
2005
                if (y > y_max)
2006
                    y_max = y;
2007
            }
2008
            src += 16;
2009
        }
2010
    } else {
2011
        src += (s->sr[0x13] & 0x3f) * 256;
2012
        y_min = 32;
2013
        y_max = -1;
2014
        for(y = 0; y < 32; y++) {
2015
            content = ((uint32_t *)src)[0] |
2016
                ((uint32_t *)(src + 128))[0];
2017
            if (content) {
2018
                if (y < y_min)
2019
                    y_min = y;
2020
                if (y > y_max)
2021
                    y_max = y;
2022
            }
2023
            src += 4;
2024
        }
2025
    }
2026
    if (y_min > y_max) {
2027
        s->last_hw_cursor_y_start = 0;
2028
        s->last_hw_cursor_y_end = 0;
2029
    } else {
2030
        s->last_hw_cursor_y_start = y_min;
2031
        s->last_hw_cursor_y_end = y_max + 1;
2032
    }
2033
}
2034

    
2035
/* NOTE: we do not currently handle the cursor bitmap change, so we
2036
   update the cursor only if it moves. */
2037
static void cirrus_cursor_invalidate(VGAState *s1)
2038
{
2039
    CirrusVGAState *s = (CirrusVGAState *)s1;
2040
    int size;
2041

    
2042
    if (!s->sr[0x12] & CIRRUS_CURSOR_SHOW) {
2043
        size = 0;
2044
    } else {
2045
        if (s->sr[0x12] & CIRRUS_CURSOR_LARGE)
2046
            size = 64;
2047
        else
2048
            size = 32;
2049
    }
2050
    /* invalidate last cursor and new cursor if any change */
2051
    if (s->last_hw_cursor_size != size ||
2052
        s->last_hw_cursor_x != s->hw_cursor_x ||
2053
        s->last_hw_cursor_y != s->hw_cursor_y) {
2054

    
2055
        invalidate_cursor1(s);
2056
        
2057
        s->last_hw_cursor_size = size;
2058
        s->last_hw_cursor_x = s->hw_cursor_x;
2059
        s->last_hw_cursor_y = s->hw_cursor_y;
2060
        /* compute the real cursor min and max y */
2061
        cirrus_cursor_compute_yrange(s);
2062
        invalidate_cursor1(s);
2063
    }
2064
}
2065

    
2066
static void cirrus_cursor_draw_line(VGAState *s1, uint8_t *d1, int scr_y)
2067
{
2068
    CirrusVGAState *s = (CirrusVGAState *)s1;
2069
    int w, h, bpp, x1, x2, poffset;
2070
    unsigned int color0, color1;
2071
    const uint8_t *palette, *src;
2072
    uint32_t content;
2073
    
2074
    if (!(s->sr[0x12] & CIRRUS_CURSOR_SHOW)) 
2075
        return;
2076
    /* fast test to see if the cursor intersects with the scan line */
2077
    if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) {
2078
        h = 64;
2079
    } else {
2080
        h = 32;
2081
    }
2082
    if (scr_y < s->hw_cursor_y ||
2083
        scr_y >= (s->hw_cursor_y + h))
2084
        return;
2085
    
2086
    src = s->vram_ptr + s->real_vram_size - 16 * 1024;
2087
    if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) {
2088
        src += (s->sr[0x13] & 0x3c) * 256;
2089
        src += (scr_y - s->hw_cursor_y) * 16;
2090
        poffset = 8;
2091
        content = ((uint32_t *)src)[0] |
2092
            ((uint32_t *)src)[1] |
2093
            ((uint32_t *)src)[2] |
2094
            ((uint32_t *)src)[3];
2095
    } else {
2096
        src += (s->sr[0x13] & 0x3f) * 256;
2097
        src += (scr_y - s->hw_cursor_y) * 4;
2098
        poffset = 128;
2099
        content = ((uint32_t *)src)[0] |
2100
            ((uint32_t *)(src + 128))[0];
2101
    }
2102
    /* if nothing to draw, no need to continue */
2103
    if (!content)
2104
        return;
2105
    w = h;
2106

    
2107
    x1 = s->hw_cursor_x;
2108
    if (x1 >= s->last_scr_width)
2109
        return;
2110
    x2 = s->hw_cursor_x + w;
2111
    if (x2 > s->last_scr_width)
2112
        x2 = s->last_scr_width;
2113
    w = x2 - x1;
2114
    palette = s->cirrus_hidden_palette;
2115
    color0 = s->rgb_to_pixel(c6_to_8(palette[0x0 * 3]), 
2116
                             c6_to_8(palette[0x0 * 3 + 1]), 
2117
                             c6_to_8(palette[0x0 * 3 + 2]));
2118
    color1 = s->rgb_to_pixel(c6_to_8(palette[0xf * 3]), 
2119
                             c6_to_8(palette[0xf * 3 + 1]), 
2120
                             c6_to_8(palette[0xf * 3 + 2]));
2121
    bpp = ((s->ds->depth + 7) >> 3);
2122
    d1 += x1 * bpp;
2123
    switch(s->ds->depth) {
2124
    default:
2125
        break;
2126
    case 8:
2127
        vga_draw_cursor_line_8(d1, src, poffset, w, color0, color1, 0xff);
2128
        break;
2129
    case 15:
2130
        vga_draw_cursor_line_16(d1, src, poffset, w, color0, color1, 0x7fff);
2131
        break;
2132
    case 16:
2133
        vga_draw_cursor_line_16(d1, src, poffset, w, color0, color1, 0xffff);
2134
        break;
2135
    case 32:
2136
        vga_draw_cursor_line_32(d1, src, poffset, w, color0, color1, 0xffffff);
2137
        break;
2138
    }
2139
}
2140

    
2141
/***************************************
2142
 *
2143
 *  LFB memory access
2144
 *
2145
 ***************************************/
2146

    
2147
static uint32_t cirrus_linear_readb(void *opaque, target_phys_addr_t addr)
2148
{
2149
    CirrusVGAState *s = (CirrusVGAState *) opaque;
2150
    uint32_t ret;
2151

    
2152
    addr &= s->cirrus_addr_mask;
2153

    
2154
    if (((s->sr[0x17] & 0x44) == 0x44) && 
2155
        ((addr & s->linear_mmio_mask) == s->linear_mmio_mask)) {
2156
        /* memory-mapped I/O */
2157
        ret = cirrus_mmio_blt_read(s, addr & 0xff);
2158
    } else if (0) {
2159
        /* XXX handle bitblt */
2160
        ret = 0xff;
2161
    } else {
2162
        /* video memory */
2163
        if ((s->gr[0x0B] & 0x14) == 0x14) {
2164
            addr <<= 4;
2165
        } else if (s->gr[0x0B] & 0x02) {
2166
            addr <<= 3;
2167
        }
2168
        addr &= s->cirrus_addr_mask;
2169
        ret = *(s->vram_ptr + addr);
2170
    }
2171

    
2172
    return ret;
2173
}
2174

    
2175
static uint32_t cirrus_linear_readw(void *opaque, target_phys_addr_t addr)
2176
{
2177
    uint32_t v;
2178
#ifdef TARGET_WORDS_BIGENDIAN
2179
    v = cirrus_linear_readb(opaque, addr) << 8;
2180
    v |= cirrus_linear_readb(opaque, addr + 1);
2181
#else
2182
    v = cirrus_linear_readb(opaque, addr);
2183
    v |= cirrus_linear_readb(opaque, addr + 1) << 8;
2184
#endif
2185
    return v;
2186
}
2187

    
2188
static uint32_t cirrus_linear_readl(void *opaque, target_phys_addr_t addr)
2189
{
2190
    uint32_t v;
2191
#ifdef TARGET_WORDS_BIGENDIAN
2192
    v = cirrus_linear_readb(opaque, addr) << 24;
2193
    v |= cirrus_linear_readb(opaque, addr + 1) << 16;
2194
    v |= cirrus_linear_readb(opaque, addr + 2) << 8;
2195
    v |= cirrus_linear_readb(opaque, addr + 3);
2196
#else
2197
    v = cirrus_linear_readb(opaque, addr);
2198
    v |= cirrus_linear_readb(opaque, addr + 1) << 8;
2199
    v |= cirrus_linear_readb(opaque, addr + 2) << 16;
2200
    v |= cirrus_linear_readb(opaque, addr + 3) << 24;
2201
#endif
2202
    return v;
2203
}
2204

    
2205
static void cirrus_linear_writeb(void *opaque, target_phys_addr_t addr,
2206
                                 uint32_t val)
2207
{
2208
    CirrusVGAState *s = (CirrusVGAState *) opaque;
2209
    unsigned mode;
2210

    
2211
    addr &= s->cirrus_addr_mask;
2212
        
2213
    if (((s->sr[0x17] & 0x44) == 0x44) && 
2214
        ((addr & s->linear_mmio_mask) ==  s->linear_mmio_mask)) {
2215
        /* memory-mapped I/O */
2216
        cirrus_mmio_blt_write(s, addr & 0xff, val);
2217
    } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
2218
        /* bitblt */
2219
        *s->cirrus_srcptr++ = (uint8_t) val;
2220
        if (s->cirrus_srcptr >= s->cirrus_srcptr_end) {
2221
            cirrus_bitblt_cputovideo_next(s);
2222
        }
2223
    } else {
2224
        /* video memory */
2225
        if ((s->gr[0x0B] & 0x14) == 0x14) {
2226
            addr <<= 4;
2227
        } else if (s->gr[0x0B] & 0x02) {
2228
            addr <<= 3;
2229
        }
2230
        addr &= s->cirrus_addr_mask;
2231

    
2232
        mode = s->gr[0x05] & 0x7;
2233
        if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
2234
            *(s->vram_ptr + addr) = (uint8_t) val;
2235
            cpu_physical_memory_set_dirty(s->vram_offset + addr);
2236
        } else {
2237
            if ((s->gr[0x0B] & 0x14) != 0x14) {
2238
                cirrus_mem_writeb_mode4and5_8bpp(s, mode, addr, val);
2239
            } else {
2240
                cirrus_mem_writeb_mode4and5_16bpp(s, mode, addr, val);
2241
            }
2242
        }
2243
    }
2244
}
2245

    
2246
static void cirrus_linear_writew(void *opaque, target_phys_addr_t addr,
2247
                                 uint32_t val)
2248
{
2249
#ifdef TARGET_WORDS_BIGENDIAN
2250
    cirrus_linear_writeb(opaque, addr, (val >> 8) & 0xff);
2251
    cirrus_linear_writeb(opaque, addr + 1, val & 0xff);
2252
#else
2253
    cirrus_linear_writeb(opaque, addr, val & 0xff);
2254
    cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2255
#endif
2256
}
2257

    
2258
static void cirrus_linear_writel(void *opaque, target_phys_addr_t addr,
2259
                                 uint32_t val)
2260
{
2261
#ifdef TARGET_WORDS_BIGENDIAN
2262
    cirrus_linear_writeb(opaque, addr, (val >> 24) & 0xff);
2263
    cirrus_linear_writeb(opaque, addr + 1, (val >> 16) & 0xff);
2264
    cirrus_linear_writeb(opaque, addr + 2, (val >> 8) & 0xff);
2265
    cirrus_linear_writeb(opaque, addr + 3, val & 0xff);
2266
#else
2267
    cirrus_linear_writeb(opaque, addr, val & 0xff);
2268
    cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2269
    cirrus_linear_writeb(opaque, addr + 2, (val >> 16) & 0xff);
2270
    cirrus_linear_writeb(opaque, addr + 3, (val >> 24) & 0xff);
2271
#endif
2272
}
2273

    
2274

    
2275
static CPUReadMemoryFunc *cirrus_linear_read[3] = {
2276
    cirrus_linear_readb,
2277
    cirrus_linear_readw,
2278
    cirrus_linear_readl,
2279
};
2280

    
2281
static CPUWriteMemoryFunc *cirrus_linear_write[3] = {
2282
    cirrus_linear_writeb,
2283
    cirrus_linear_writew,
2284
    cirrus_linear_writel,
2285
};
2286

    
2287
/***************************************
2288
 *
2289
 *  system to screen memory access
2290
 *
2291
 ***************************************/
2292

    
2293

    
2294
static uint32_t cirrus_linear_bitblt_readb(void *opaque, target_phys_addr_t addr)
2295
{
2296
    uint32_t ret;
2297

    
2298
    /* XXX handle bitblt */
2299
    ret = 0xff;
2300
    return ret;
2301
}
2302

    
2303
static uint32_t cirrus_linear_bitblt_readw(void *opaque, target_phys_addr_t addr)
2304
{
2305
    uint32_t v;
2306
#ifdef TARGET_WORDS_BIGENDIAN
2307
    v = cirrus_linear_bitblt_readb(opaque, addr) << 8;
2308
    v |= cirrus_linear_bitblt_readb(opaque, addr + 1);
2309
#else
2310
    v = cirrus_linear_bitblt_readb(opaque, addr);
2311
    v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8;
2312
#endif
2313
    return v;
2314
}
2315

    
2316
static uint32_t cirrus_linear_bitblt_readl(void *opaque, target_phys_addr_t addr)
2317
{
2318
    uint32_t v;
2319
#ifdef TARGET_WORDS_BIGENDIAN
2320
    v = cirrus_linear_bitblt_readb(opaque, addr) << 24;
2321
    v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 16;
2322
    v |= cirrus_linear_bitblt_readb(opaque, addr + 2) << 8;
2323
    v |= cirrus_linear_bitblt_readb(opaque, addr + 3);
2324
#else
2325
    v = cirrus_linear_bitblt_readb(opaque, addr);
2326
    v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8;
2327
    v |= cirrus_linear_bitblt_readb(opaque, addr + 2) << 16;
2328
    v |= cirrus_linear_bitblt_readb(opaque, addr + 3) << 24;
2329
#endif
2330
    return v;
2331
}
2332

    
2333
static void cirrus_linear_bitblt_writeb(void *opaque, target_phys_addr_t addr,
2334
                                 uint32_t val)
2335
{
2336
    CirrusVGAState *s = (CirrusVGAState *) opaque;
2337

    
2338
    if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
2339
        /* bitblt */
2340
        *s->cirrus_srcptr++ = (uint8_t) val;
2341
        if (s->cirrus_srcptr >= s->cirrus_srcptr_end) {
2342
            cirrus_bitblt_cputovideo_next(s);
2343
        }
2344
    }
2345
}
2346

    
2347
static void cirrus_linear_bitblt_writew(void *opaque, target_phys_addr_t addr,
2348
                                 uint32_t val)
2349
{
2350
#ifdef TARGET_WORDS_BIGENDIAN
2351
    cirrus_linear_bitblt_writeb(opaque, addr, (val >> 8) & 0xff);
2352
    cirrus_linear_bitblt_writeb(opaque, addr + 1, val & 0xff);
2353
#else
2354
    cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff);
2355
    cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2356
#endif
2357
}
2358

    
2359
static void cirrus_linear_bitblt_writel(void *opaque, target_phys_addr_t addr,
2360
                                 uint32_t val)
2361
{
2362
#ifdef TARGET_WORDS_BIGENDIAN
2363
    cirrus_linear_bitblt_writeb(opaque, addr, (val >> 24) & 0xff);
2364
    cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 16) & 0xff);
2365
    cirrus_linear_bitblt_writeb(opaque, addr + 2, (val >> 8) & 0xff);
2366
    cirrus_linear_bitblt_writeb(opaque, addr + 3, val & 0xff);
2367
#else
2368
    cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff);
2369
    cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2370
    cirrus_linear_bitblt_writeb(opaque, addr + 2, (val >> 16) & 0xff);
2371
    cirrus_linear_bitblt_writeb(opaque, addr + 3, (val >> 24) & 0xff);
2372
#endif
2373
}
2374

    
2375

    
2376
static CPUReadMemoryFunc *cirrus_linear_bitblt_read[3] = {
2377
    cirrus_linear_bitblt_readb,
2378
    cirrus_linear_bitblt_readw,
2379
    cirrus_linear_bitblt_readl,
2380
};
2381

    
2382
static CPUWriteMemoryFunc *cirrus_linear_bitblt_write[3] = {
2383
    cirrus_linear_bitblt_writeb,
2384
    cirrus_linear_bitblt_writew,
2385
    cirrus_linear_bitblt_writel,
2386
};
2387

    
2388
/* I/O ports */
2389

    
2390
static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
2391
{
2392
    CirrusVGAState *s = opaque;
2393
    int val, index;
2394

    
2395
    /* check port range access depending on color/monochrome mode */
2396
    if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION))
2397
        || (addr >= 0x3d0 && addr <= 0x3df
2398
            && !(s->msr & MSR_COLOR_EMULATION))) {
2399
        val = 0xff;
2400
    } else {
2401
        switch (addr) {
2402
        case 0x3c0:
2403
            if (s->ar_flip_flop == 0) {
2404
                val = s->ar_index;
2405
            } else {
2406
                val = 0;
2407
            }
2408
            break;
2409
        case 0x3c1:
2410
            index = s->ar_index & 0x1f;
2411
            if (index < 21)
2412
                val = s->ar[index];
2413
            else
2414
                val = 0;
2415
            break;
2416
        case 0x3c2:
2417
            val = s->st00;
2418
            break;
2419
        case 0x3c4:
2420
            val = s->sr_index;
2421
            break;
2422
        case 0x3c5:
2423
            if (cirrus_hook_read_sr(s, s->sr_index, &val))
2424
                break;
2425
            val = s->sr[s->sr_index];
2426
#ifdef DEBUG_VGA_REG
2427
            printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
2428
#endif
2429
            break;
2430
        case 0x3c6:
2431
            cirrus_read_hidden_dac(s, &val);
2432
            break;
2433
        case 0x3c7:
2434
            val = s->dac_state;
2435
            break;
2436
        case 0x3c9:
2437
            if (cirrus_hook_read_palette(s, &val))
2438
                break;
2439
            val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
2440
            if (++s->dac_sub_index == 3) {
2441
                s->dac_sub_index = 0;
2442
                s->dac_read_index++;
2443
            }
2444
            break;
2445
        case 0x3ca:
2446
            val = s->fcr;
2447
            break;
2448
        case 0x3cc:
2449
            val = s->msr;
2450
            break;
2451
        case 0x3ce:
2452
            val = s->gr_index;
2453
            break;
2454
        case 0x3cf:
2455
            if (cirrus_hook_read_gr(s, s->gr_index, &val))
2456
                break;
2457
            val = s->gr[s->gr_index];
2458
#ifdef DEBUG_VGA_REG
2459
            printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
2460
#endif
2461
            break;
2462
        case 0x3b4:
2463
        case 0x3d4:
2464
            val = s->cr_index;
2465
            break;
2466
        case 0x3b5:
2467
        case 0x3d5:
2468
            if (cirrus_hook_read_cr(s, s->cr_index, &val))
2469
                break;
2470
            val = s->cr[s->cr_index];
2471
#ifdef DEBUG_VGA_REG
2472
            printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
2473
#endif
2474
            break;
2475
        case 0x3ba:
2476
        case 0x3da:
2477
            /* just toggle to fool polling */
2478
            s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;
2479
            val = s->st01;
2480
            s->ar_flip_flop = 0;
2481
            break;
2482
        default:
2483
            val = 0x00;
2484
            break;
2485
        }
2486
    }
2487
#if defined(DEBUG_VGA)
2488
    printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
2489
#endif
2490
    return val;
2491
}
2492

    
2493
static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
2494
{
2495
    CirrusVGAState *s = opaque;
2496
    int index;
2497

    
2498
    /* check port range access depending on color/monochrome mode */
2499
    if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION))
2500
        || (addr >= 0x3d0 && addr <= 0x3df
2501
            && !(s->msr & MSR_COLOR_EMULATION)))
2502
        return;
2503

    
2504
#ifdef DEBUG_VGA
2505
    printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
2506
#endif
2507

    
2508
    switch (addr) {
2509
    case 0x3c0:
2510
        if (s->ar_flip_flop == 0) {
2511
            val &= 0x3f;
2512
            s->ar_index = val;
2513
        } else {
2514
            index = s->ar_index & 0x1f;
2515
            switch (index) {
2516
            case 0x00 ... 0x0f:
2517
                s->ar[index] = val & 0x3f;
2518
                break;
2519
            case 0x10:
2520
                s->ar[index] = val & ~0x10;
2521
                break;
2522
            case 0x11:
2523
                s->ar[index] = val;
2524
                break;
2525
            case 0x12:
2526
                s->ar[index] = val & ~0xc0;
2527
                break;
2528
            case 0x13:
2529
                s->ar[index] = val & ~0xf0;
2530
                break;
2531
            case 0x14:
2532
                s->ar[index] = val & ~0xf0;
2533
                break;
2534
            default:
2535
                break;
2536
            }
2537
        }
2538
        s->ar_flip_flop ^= 1;
2539
        break;
2540
    case 0x3c2:
2541
        s->msr = val & ~0x10;
2542
        break;
2543
    case 0x3c4:
2544
        s->sr_index = val;
2545
        break;
2546
    case 0x3c5:
2547
        if (cirrus_hook_write_sr(s, s->sr_index, val))
2548
            break;
2549
#ifdef DEBUG_VGA_REG
2550
        printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
2551
#endif
2552
        s->sr[s->sr_index] = val & sr_mask[s->sr_index];
2553
        break;
2554
    case 0x3c6:
2555
        cirrus_write_hidden_dac(s, val);
2556
        break;
2557
    case 0x3c7:
2558
        s->dac_read_index = val;
2559
        s->dac_sub_index = 0;
2560
        s->dac_state = 3;
2561
        break;
2562
    case 0x3c8:
2563
        s->dac_write_index = val;
2564
        s->dac_sub_index = 0;
2565
        s->dac_state = 0;
2566
        break;
2567
    case 0x3c9:
2568
        if (cirrus_hook_write_palette(s, val))
2569
            break;
2570
        s->dac_cache[s->dac_sub_index] = val;
2571
        if (++s->dac_sub_index == 3) {
2572
            memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
2573
            s->dac_sub_index = 0;
2574
            s->dac_write_index++;
2575
        }
2576
        break;
2577
    case 0x3ce:
2578
        s->gr_index = val;
2579
        break;
2580
    case 0x3cf:
2581
        if (cirrus_hook_write_gr(s, s->gr_index, val))
2582
            break;
2583
#ifdef DEBUG_VGA_REG
2584
        printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
2585
#endif
2586
        s->gr[s->gr_index] = val & gr_mask[s->gr_index];
2587
        break;
2588
    case 0x3b4:
2589
    case 0x3d4:
2590
        s->cr_index = val;
2591
        break;
2592
    case 0x3b5:
2593
    case 0x3d5:
2594
        if (cirrus_hook_write_cr(s, s->cr_index, val))
2595
            break;
2596
#ifdef DEBUG_VGA_REG
2597
        printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
2598
#endif
2599
        /* handle CR0-7 protection */
2600
        if ((s->cr[11] & 0x80) && s->cr_index <= 7) {
2601
            /* can always write bit 4 of CR7 */
2602
            if (s->cr_index == 7)
2603
                s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
2604
            return;
2605
        }
2606
        switch (s->cr_index) {
2607
        case 0x01:                /* horizontal display end */
2608
        case 0x07:
2609
        case 0x09:
2610
        case 0x0c:
2611
        case 0x0d:
2612
        case 0x12:                /* veritcal display end */
2613
            s->cr[s->cr_index] = val;
2614
            break;
2615

    
2616
        default:
2617
            s->cr[s->cr_index] = val;
2618
            break;
2619
        }
2620
        break;
2621
    case 0x3ba:
2622
    case 0x3da:
2623
        s->fcr = val & 0x10;
2624
        break;
2625
    }
2626
}
2627

    
2628
/***************************************
2629
 *
2630
 *  memory-mapped I/O access
2631
 *
2632
 ***************************************/
2633

    
2634
static uint32_t cirrus_mmio_readb(void *opaque, target_phys_addr_t addr)
2635
{
2636
    CirrusVGAState *s = (CirrusVGAState *) opaque;
2637

    
2638
    addr &= CIRRUS_PNPMMIO_SIZE - 1;
2639

    
2640
    if (addr >= 0x100) {
2641
        return cirrus_mmio_blt_read(s, addr - 0x100);
2642
    } else {
2643
        return vga_ioport_read(s, addr + 0x3c0);
2644
    }
2645
}
2646

    
2647
static uint32_t cirrus_mmio_readw(void *opaque, target_phys_addr_t addr)
2648
{
2649
    uint32_t v;
2650
#ifdef TARGET_WORDS_BIGENDIAN
2651
    v = cirrus_mmio_readb(opaque, addr) << 8;
2652
    v |= cirrus_mmio_readb(opaque, addr + 1);
2653
#else
2654
    v = cirrus_mmio_readb(opaque, addr);
2655
    v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
2656
#endif
2657
    return v;
2658
}
2659

    
2660
static uint32_t cirrus_mmio_readl(void *opaque, target_phys_addr_t addr)
2661
{
2662
    uint32_t v;
2663
#ifdef TARGET_WORDS_BIGENDIAN
2664
    v = cirrus_mmio_readb(opaque, addr) << 24;
2665
    v |= cirrus_mmio_readb(opaque, addr + 1) << 16;
2666
    v |= cirrus_mmio_readb(opaque, addr + 2) << 8;
2667
    v |= cirrus_mmio_readb(opaque, addr + 3);
2668
#else
2669
    v = cirrus_mmio_readb(opaque, addr);
2670
    v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
2671
    v |= cirrus_mmio_readb(opaque, addr + 2) << 16;
2672
    v |= cirrus_mmio_readb(opaque, addr + 3) << 24;
2673
#endif
2674
    return v;
2675
}
2676

    
2677
static void cirrus_mmio_writeb(void *opaque, target_phys_addr_t addr,
2678
                               uint32_t val)
2679
{
2680
    CirrusVGAState *s = (CirrusVGAState *) opaque;
2681

    
2682
    addr &= CIRRUS_PNPMMIO_SIZE - 1;
2683

    
2684
    if (addr >= 0x100) {
2685
        cirrus_mmio_blt_write(s, addr - 0x100, val);
2686
    } else {
2687
        vga_ioport_write(s, addr + 0x3c0, val);
2688
    }
2689
}
2690

    
2691
static void cirrus_mmio_writew(void *opaque, target_phys_addr_t addr,
2692
                               uint32_t val)
2693
{
2694
#ifdef TARGET_WORDS_BIGENDIAN
2695
    cirrus_mmio_writeb(opaque, addr, (val >> 8) & 0xff);
2696
    cirrus_mmio_writeb(opaque, addr + 1, val & 0xff);
2697
#else
2698
    cirrus_mmio_writeb(opaque, addr, val & 0xff);
2699
    cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2700
#endif
2701
}
2702

    
2703
static void cirrus_mmio_writel(void *opaque, target_phys_addr_t addr,
2704
                               uint32_t val)
2705
{
2706
#ifdef TARGET_WORDS_BIGENDIAN
2707
    cirrus_mmio_writeb(opaque, addr, (val >> 24) & 0xff);
2708
    cirrus_mmio_writeb(opaque, addr + 1, (val >> 16) & 0xff);
2709
    cirrus_mmio_writeb(opaque, addr + 2, (val >> 8) & 0xff);
2710
    cirrus_mmio_writeb(opaque, addr + 3, val & 0xff);
2711
#else
2712
    cirrus_mmio_writeb(opaque, addr, val & 0xff);
2713
    cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2714
    cirrus_mmio_writeb(opaque, addr + 2, (val >> 16) & 0xff);
2715
    cirrus_mmio_writeb(opaque, addr + 3, (val >> 24) & 0xff);
2716
#endif
2717
}
2718

    
2719

    
2720
static CPUReadMemoryFunc *cirrus_mmio_read[3] = {
2721
    cirrus_mmio_readb,
2722
    cirrus_mmio_readw,
2723
    cirrus_mmio_readl,
2724
};
2725

    
2726
static CPUWriteMemoryFunc *cirrus_mmio_write[3] = {
2727
    cirrus_mmio_writeb,
2728
    cirrus_mmio_writew,
2729
    cirrus_mmio_writel,
2730
};
2731

    
2732
/***************************************
2733
 *
2734
 *  initialize
2735
 *
2736
 ***************************************/
2737

    
2738
static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
2739
{
2740
    int vga_io_memory, i;
2741
    static int inited;
2742

    
2743
    if (!inited) {
2744
        inited = 1;
2745
        for(i = 0;i < 256; i++)
2746
            rop_to_index[i] = CIRRUS_ROP_NOP_INDEX; /* nop rop */
2747
        rop_to_index[CIRRUS_ROP_0] = 0;
2748
        rop_to_index[CIRRUS_ROP_SRC_AND_DST] = 1;
2749
        rop_to_index[CIRRUS_ROP_NOP] = 2;
2750
        rop_to_index[CIRRUS_ROP_SRC_AND_NOTDST] = 3;
2751
        rop_to_index[CIRRUS_ROP_NOTDST] = 4;
2752
        rop_to_index[CIRRUS_ROP_SRC] = 5;
2753
        rop_to_index[CIRRUS_ROP_1] = 6;
2754
        rop_to_index[CIRRUS_ROP_NOTSRC_AND_DST] = 7;
2755
        rop_to_index[CIRRUS_ROP_SRC_XOR_DST] = 8;
2756
        rop_to_index[CIRRUS_ROP_SRC_OR_DST] = 9;
2757
        rop_to_index[CIRRUS_ROP_NOTSRC_OR_NOTDST] = 10;
2758
        rop_to_index[CIRRUS_ROP_SRC_NOTXOR_DST] = 11;
2759
        rop_to_index[CIRRUS_ROP_SRC_OR_NOTDST] = 12;
2760
        rop_to_index[CIRRUS_ROP_NOTSRC] = 13;
2761
        rop_to_index[CIRRUS_ROP_NOTSRC_OR_DST] = 14;
2762
        rop_to_index[CIRRUS_ROP_NOTSRC_AND_NOTDST] = 15;
2763
    }
2764

    
2765
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2766

    
2767
    register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
2768
    register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
2769
    register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
2770
    register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
2771

    
2772
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2773

    
2774
    register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
2775
    register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
2776
    register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
2777
    register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
2778

    
2779
    vga_io_memory = cpu_register_io_memory(0, cirrus_vga_mem_read, 
2780
                                           cirrus_vga_mem_write, s);
2781
    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000, 
2782
                                 vga_io_memory);
2783

    
2784
    s->sr[0x06] = 0x0f;
2785
    s->sr[0x1F] = 0x22;                // MemClock
2786
    if (device_id == CIRRUS_ID_CLGD5446) {
2787
        /* 4MB 64 bit memory config, always PCI */
2788
#if 1
2789
        s->sr[0x0f] = 0x98;
2790
        s->sr[0x17] = 0x20;
2791
        s->sr[0x15] = 0x04; /* memory size, 3=2MB, 4=4MB */
2792
        s->real_vram_size = 4096 * 1024;
2793
#else
2794
        s->sr[0x0f] = 0x18;
2795
        s->sr[0x17] = 0x20;
2796
        s->sr[0x15] = 0x03; /* memory size, 3=2MB, 4=4MB */
2797
        s->real_vram_size = 2048 * 1024;
2798
#endif
2799
    } else {
2800
        s->sr[0x0F] = CIRRUS_MEMSIZE_2M;
2801
        if (is_pci) 
2802
            s->sr[0x17] = CIRRUS_BUSTYPE_PCI;
2803
        else
2804
            s->sr[0x17] = CIRRUS_BUSTYPE_ISA;
2805
        s->real_vram_size = 2048 * 1024;
2806
        s->sr[0x15] = 0x03; /* memory size, 3=2MB, 4=4MB */
2807
    }
2808
    s->cr[0x27] = device_id;
2809

    
2810
    /* Win2K seems to assume that the pattern buffer is at 0xff
2811
       initially ! */
2812
    memset(s->vram_ptr, 0xff, s->real_vram_size);
2813

    
2814
    s->cirrus_hidden_dac_lockindex = 5;
2815
    s->cirrus_hidden_dac_data = 0;
2816

    
2817
    /* I/O handler for LFB */
2818
    s->cirrus_linear_io_addr =
2819
        cpu_register_io_memory(0, cirrus_linear_read, cirrus_linear_write,
2820
                               s);
2821
    /* I/O handler for LFB */
2822
    s->cirrus_linear_bitblt_io_addr =
2823
        cpu_register_io_memory(0, cirrus_linear_bitblt_read, cirrus_linear_bitblt_write,
2824
                               s);
2825

    
2826
    /* I/O handler for memory-mapped I/O */
2827
    s->cirrus_mmio_io_addr =
2828
        cpu_register_io_memory(0, cirrus_mmio_read, cirrus_mmio_write, s);
2829

    
2830
    /* XXX: s->vram_size must be a power of two */
2831
    s->cirrus_addr_mask = s->real_vram_size - 1;
2832
    s->linear_mmio_mask = s->real_vram_size - 256;
2833

    
2834
    s->get_bpp = cirrus_get_bpp;
2835
    s->get_offsets = cirrus_get_offsets;
2836
    s->get_resolution = cirrus_get_resolution;
2837
    s->cursor_invalidate = cirrus_cursor_invalidate;
2838
    s->cursor_draw_line = cirrus_cursor_draw_line;
2839
}
2840

    
2841
/***************************************
2842
 *
2843
 *  ISA bus support
2844
 *
2845
 ***************************************/
2846

    
2847
void isa_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base, 
2848
                         unsigned long vga_ram_offset, int vga_ram_size)
2849
{
2850
    CirrusVGAState *s;
2851

    
2852
    s = qemu_mallocz(sizeof(CirrusVGAState));
2853
    
2854
    vga_common_init((VGAState *)s, 
2855
                    ds, vga_ram_base, vga_ram_offset, vga_ram_size);
2856
    cirrus_init_common(s, CIRRUS_ID_CLGD5430, 0);
2857
    /* XXX ISA-LFB support */
2858
}
2859

    
2860
/***************************************
2861
 *
2862
 *  PCI bus support
2863
 *
2864
 ***************************************/
2865

    
2866
static void cirrus_pci_lfb_map(PCIDevice *d, int region_num,
2867
                               uint32_t addr, uint32_t size, int type)
2868
{
2869
    CirrusVGAState *s = &((PCICirrusVGAState *)d)->cirrus_vga;
2870

    
2871
    /* XXX: add byte swapping apertures */
2872
    cpu_register_physical_memory(addr, s->vram_size,
2873
                                 s->cirrus_linear_io_addr);
2874
    cpu_register_physical_memory(addr + 0x1000000, 0x400000,
2875
                                 s->cirrus_linear_bitblt_io_addr);
2876
}
2877

    
2878
static void cirrus_pci_mmio_map(PCIDevice *d, int region_num,
2879
                                uint32_t addr, uint32_t size, int type)
2880
{
2881
    CirrusVGAState *s = &((PCICirrusVGAState *)d)->cirrus_vga;
2882

    
2883
    cpu_register_physical_memory(addr, CIRRUS_PNPMMIO_SIZE,
2884
                                 s->cirrus_mmio_io_addr);
2885
}
2886

    
2887
void pci_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base, 
2888
                         unsigned long vga_ram_offset, int vga_ram_size)
2889
{
2890
    PCICirrusVGAState *d;
2891
    uint8_t *pci_conf;
2892
    CirrusVGAState *s;
2893
    int device_id;
2894
    
2895
    device_id = CIRRUS_ID_CLGD5446;
2896

    
2897
    /* setup PCI configuration registers */
2898
    d = (PCICirrusVGAState *)pci_register_device("Cirrus VGA", 
2899
                                                 sizeof(PCICirrusVGAState), 
2900
                                                 0, -1, NULL, NULL);
2901
    pci_conf = d->dev.config;
2902
    pci_conf[0x00] = (uint8_t) (PCI_VENDOR_CIRRUS & 0xff);
2903
    pci_conf[0x01] = (uint8_t) (PCI_VENDOR_CIRRUS >> 8);
2904
    pci_conf[0x02] = (uint8_t) (device_id & 0xff);
2905
    pci_conf[0x03] = (uint8_t) (device_id >> 8);
2906
    pci_conf[0x04] = PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS;
2907
    pci_conf[0x0a] = PCI_CLASS_SUB_VGA;
2908
    pci_conf[0x0b] = PCI_CLASS_BASE_DISPLAY;
2909
    pci_conf[0x0e] = PCI_CLASS_HEADERTYPE_00h;
2910

    
2911
    /* setup VGA */
2912
    s = &d->cirrus_vga;
2913
    vga_common_init((VGAState *)s, 
2914
                    ds, vga_ram_base, vga_ram_offset, vga_ram_size);
2915
    cirrus_init_common(s, device_id, 1);
2916

    
2917
    /* setup memory space */
2918
    /* memory #0 LFB */
2919
    /* memory #1 memory-mapped I/O */
2920
    /* XXX: s->vram_size must be a power of two */
2921
    pci_register_io_region((PCIDevice *)d, 0, 0x2000000,
2922
                           PCI_ADDRESS_SPACE_MEM_PREFETCH, cirrus_pci_lfb_map);
2923
    if (device_id == CIRRUS_ID_CLGD5446) {
2924
        pci_register_io_region((PCIDevice *)d, 1, CIRRUS_PNPMMIO_SIZE,
2925
                               PCI_ADDRESS_SPACE_MEM, cirrus_pci_mmio_map);
2926
    }
2927
    /* XXX: ROM BIOS */
2928
}