Statistics
| Branch: | Revision:

root / hw / cirrus_vga.c @ aeb3c85f

History | View | Annotate | Download (73.7 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
//#define DEBUG_CIRRUS
33

    
34
/***************************************
35
 *
36
 *  definitions
37
 *
38
 ***************************************/
39

    
40
#define qemu_MIN(a,b) ((a) < (b) ? (a) : (b))
41

    
42
// ID
43
#define CIRRUS_ID_CLGD5422  (0x23<<2)
44
#define CIRRUS_ID_CLGD5426  (0x24<<2)
45
#define CIRRUS_ID_CLGD5424  (0x25<<2)
46
#define CIRRUS_ID_CLGD5428  (0x26<<2)
47
#define CIRRUS_ID_CLGD5430  (0x28<<2)
48
#define CIRRUS_ID_CLGD5434  (0x2A<<2)
49
#define CIRRUS_ID_CLGD5446  (0x2E<<2)
50

    
51
// sequencer 0x07
52
#define CIRRUS_SR7_BPP_VGA            0x00
53
#define CIRRUS_SR7_BPP_SVGA           0x01
54
#define CIRRUS_SR7_BPP_MASK           0x0e
55
#define CIRRUS_SR7_BPP_8              0x00
56
#define CIRRUS_SR7_BPP_16_DOUBLEVCLK  0x02
57
#define CIRRUS_SR7_BPP_24             0x04
58
#define CIRRUS_SR7_BPP_16             0x06
59
#define CIRRUS_SR7_BPP_32             0x08
60
#define CIRRUS_SR7_ISAADDR_MASK       0xe0
61

    
62
// sequencer 0x0f
63
#define CIRRUS_MEMSIZE_512k        0x08
64
#define CIRRUS_MEMSIZE_1M          0x10
65
#define CIRRUS_MEMSIZE_2M          0x18
66
#define CIRRUS_MEMFLAGS_BANKSWITCH 0x80        // bank switching is enabled.
67

    
68
// sequencer 0x12
69
#define CIRRUS_CURSOR_SHOW         0x01
70
#define CIRRUS_CURSOR_HIDDENPEL    0x02
71
#define CIRRUS_CURSOR_LARGE        0x04        // 64x64 if set, 32x32 if clear
72

    
73
// sequencer 0x17
74
#define CIRRUS_BUSTYPE_VLBFAST   0x10
75
#define CIRRUS_BUSTYPE_PCI       0x20
76
#define CIRRUS_BUSTYPE_VLBSLOW   0x30
77
#define CIRRUS_BUSTYPE_ISA       0x38
78
#define CIRRUS_MMIO_ENABLE       0x04
79
#define CIRRUS_MMIO_USE_PCIADDR  0x40        // 0xb8000 if cleared.
80
#define CIRRUS_MEMSIZEEXT_DOUBLE 0x80
81

    
82
// control 0x0b
83
#define CIRRUS_BANKING_DUAL             0x01
84
#define CIRRUS_BANKING_GRANULARITY_16K  0x20        // set:16k, clear:4k
85

    
86
// control 0x30
87
#define CIRRUS_BLTMODE_BACKWARDS        0x01
88
#define CIRRUS_BLTMODE_MEMSYSDEST       0x02
89
#define CIRRUS_BLTMODE_MEMSYSSRC        0x04
90
#define CIRRUS_BLTMODE_TRANSPARENTCOMP  0x08
91
#define CIRRUS_BLTMODE_PATTERNCOPY      0x40
92
#define CIRRUS_BLTMODE_COLOREXPAND      0x80
93
#define CIRRUS_BLTMODE_PIXELWIDTHMASK   0x30
94
#define CIRRUS_BLTMODE_PIXELWIDTH8      0x00
95
#define CIRRUS_BLTMODE_PIXELWIDTH16     0x10
96
#define CIRRUS_BLTMODE_PIXELWIDTH24     0x20
97
#define CIRRUS_BLTMODE_PIXELWIDTH32     0x30
98

    
99
// control 0x31
100
#define CIRRUS_BLT_BUSY                 0x01
101
#define CIRRUS_BLT_START                0x02
102
#define CIRRUS_BLT_RESET                0x04
103
#define CIRRUS_BLT_FIFOUSED             0x10
104

    
105
// control 0x32
106
#define CIRRUS_ROP_0                    0x00
107
#define CIRRUS_ROP_SRC_AND_DST          0x05
108
#define CIRRUS_ROP_NOP                  0x06
109
#define CIRRUS_ROP_SRC_AND_NOTDST       0x09
110
#define CIRRUS_ROP_NOTDST               0x0b
111
#define CIRRUS_ROP_SRC                  0x0d
112
#define CIRRUS_ROP_1                    0x0e
113
#define CIRRUS_ROP_NOTSRC_AND_DST       0x50
114
#define CIRRUS_ROP_SRC_XOR_DST          0x59
115
#define CIRRUS_ROP_SRC_OR_DST           0x6d
116
#define CIRRUS_ROP_NOTSRC_OR_NOTDST     0x90
117
#define CIRRUS_ROP_SRC_NOTXOR_DST       0x95
118
#define CIRRUS_ROP_SRC_OR_NOTDST        0xad
119
#define CIRRUS_ROP_NOTSRC               0xd0
120
#define CIRRUS_ROP_NOTSRC_OR_DST        0xd6
121
#define CIRRUS_ROP_NOTSRC_AND_NOTDST    0xda
122

    
123
// memory-mapped IO
124
#define CIRRUS_MMIO_BLTBGCOLOR        0x00        // dword
125
#define CIRRUS_MMIO_BLTFGCOLOR        0x04        // dword
126
#define CIRRUS_MMIO_BLTWIDTH          0x08        // word
127
#define CIRRUS_MMIO_BLTHEIGHT         0x0a        // word
128
#define CIRRUS_MMIO_BLTDESTPITCH      0x0c        // word
129
#define CIRRUS_MMIO_BLTSRCPITCH       0x0e        // word
130
#define CIRRUS_MMIO_BLTDESTADDR       0x10        // dword
131
#define CIRRUS_MMIO_BLTSRCADDR        0x14        // dword
132
#define CIRRUS_MMIO_BLTWRITEMASK      0x17        // byte
133
#define CIRRUS_MMIO_BLTMODE           0x18        // byte
134
#define CIRRUS_MMIO_BLTROP            0x1a        // byte
135
#define CIRRUS_MMIO_BLTMODEEXT        0x1b        // byte
136
#define CIRRUS_MMIO_BLTTRANSPARENTCOLOR 0x1c        // word?
137
#define CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK 0x20        // word?
138
#define CIRRUS_MMIO_LINEARDRAW_START_X 0x24        // word
139
#define CIRRUS_MMIO_LINEARDRAW_START_Y 0x26        // word
140
#define CIRRUS_MMIO_LINEARDRAW_END_X  0x28        // word
141
#define CIRRUS_MMIO_LINEARDRAW_END_Y  0x2a        // word
142
#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_INC 0x2c        // byte
143
#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ROLLOVER 0x2d        // byte
144
#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_MASK 0x2e        // byte
145
#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ACCUM 0x2f        // byte
146
#define CIRRUS_MMIO_BRESENHAM_K1      0x30        // word
147
#define CIRRUS_MMIO_BRESENHAM_K3      0x32        // word
148
#define CIRRUS_MMIO_BRESENHAM_ERROR   0x34        // word
149
#define CIRRUS_MMIO_BRESENHAM_DELTA_MAJOR 0x36        // word
150
#define CIRRUS_MMIO_BRESENHAM_DIRECTION 0x38        // byte
151
#define CIRRUS_MMIO_LINEDRAW_MODE     0x39        // byte
152
#define CIRRUS_MMIO_BLTSTATUS         0x40        // byte
153

    
154
// PCI 0x00: vendor, 0x02: device
155
#define PCI_VENDOR_CIRRUS             0x1013
156
#define PCI_DEVICE_CLGD5430           0x00a0        // CLGD5430 or CLGD5440
157
#define PCI_DEVICE_CLGD5434           0x00a8
158
#define PCI_DEVICE_CLGD5436           0x00ac
159
#define PCI_DEVICE_CLGD5446           0x00b8
160
#define PCI_DEVICE_CLGD5462           0x00d0
161
#define PCI_DEVICE_CLGD5465           0x00d6
162
// PCI 0x04: command(word), 0x06(word): status
163
#define PCI_COMMAND_IOACCESS                0x0001
164
#define PCI_COMMAND_MEMACCESS               0x0002
165
#define PCI_COMMAND_BUSMASTER               0x0004
166
#define PCI_COMMAND_SPECIALCYCLE            0x0008
167
#define PCI_COMMAND_MEMWRITEINVALID         0x0010
168
#define PCI_COMMAND_PALETTESNOOPING         0x0020
169
#define PCI_COMMAND_PARITYDETECTION         0x0040
170
#define PCI_COMMAND_ADDRESSDATASTEPPING     0x0080
171
#define PCI_COMMAND_SERR                    0x0100
172
#define PCI_COMMAND_BACKTOBACKTRANS         0x0200
173
// PCI 0x08, 0xff000000 (0x09-0x0b:class,0x08:rev)
174
#define PCI_CLASS_BASE_DISPLAY        0x03
175
// PCI 0x08, 0x00ff0000
176
#define PCI_CLASS_SUB_VGA             0x00
177
// PCI 0x0c, 0x00ff0000 (0x0c:cacheline,0x0d:latency,0x0e:headertype,0x0f:Built-in self test)
178
#define PCI_CLASS_HEADERTYPE_00h  0x00
179
// 0x10-0x3f (headertype 00h)
180
// PCI 0x10,0x14,0x18,0x1c,0x20,0x24: base address mapping registers
181
//   0x10: MEMBASE, 0x14: IOBASE(hard-coded in XFree86 3.x)
182
#define PCI_MAP_MEM                 0x0
183
#define PCI_MAP_IO                  0x1
184
#define PCI_MAP_MEM_ADDR_MASK       (~0xf)
185
#define PCI_MAP_IO_ADDR_MASK        (~0x3)
186
#define PCI_MAP_MEMFLAGS_32BIT      0x0
187
#define PCI_MAP_MEMFLAGS_32BIT_1M   0x1
188
#define PCI_MAP_MEMFLAGS_64BIT      0x4
189
#define PCI_MAP_MEMFLAGS_CACHEABLE  0x8
190
// PCI 0x28: cardbus CIS pointer
191
// PCI 0x2c: subsystem vendor id, 0x2e: subsystem id
192
// PCI 0x30: expansion ROM base address
193
#define PCI_ROMBIOS_ENABLED         0x1
194
// PCI 0x34: 0xffffff00=reserved, 0x000000ff=capabilities pointer
195
// PCI 0x38: reserved
196
// PCI 0x3c: 0x3c=int-line, 0x3d=int-pin, 0x3e=min-gnt, 0x3f=maax-lat
197

    
198
#define CIRRUS_PNPMMIO_SIZE         0x800
199

    
200

    
201
/* I/O and memory hook */
202
#define CIRRUS_HOOK_NOT_HANDLED 0
203
#define CIRRUS_HOOK_HANDLED 1
204

    
205
typedef void (*cirrus_bitblt_rop_t) (uint8_t * dst, const uint8_t * src,
206
                                     int dstpitch, int srcpitch,
207
                                     int bltwidth, int bltheight);
208

    
209
typedef void (*cirrus_bitblt_handler_t) (void *opaque);
210

    
211
typedef struct CirrusVGAState {
212
    VGA_STATE_COMMON
213

    
214
    int cirrus_linear_io_addr;
215
    int cirrus_mmio_io_addr;
216
    uint32_t cirrus_addr_mask;
217
    uint8_t cirrus_shadow_gr0;
218
    uint8_t cirrus_shadow_gr1;
219
    uint8_t cirrus_hidden_dac_lockindex;
220
    uint8_t cirrus_hidden_dac_data;
221
    uint32_t cirrus_bank_base[2];
222
    uint32_t cirrus_bank_limit[2];
223
    uint8_t cirrus_hidden_palette[48];
224
    uint32_t cirrus_hw_cursor_x;
225
    uint32_t cirrus_hw_cursor_y;
226
    int cirrus_blt_pixelwidth;
227
    int cirrus_blt_width;
228
    int cirrus_blt_height;
229
    int cirrus_blt_dstpitch;
230
    int cirrus_blt_srcpitch;
231
    uint32_t cirrus_blt_dstaddr;
232
    uint32_t cirrus_blt_srcaddr;
233
    uint8_t cirrus_blt_mode;
234
    cirrus_bitblt_rop_t cirrus_rop;
235
#define CIRRUS_BLTBUFSIZE 256
236
    uint8_t cirrus_bltbuf[CIRRUS_BLTBUFSIZE];
237
    uint8_t *cirrus_srcptr;
238
    uint8_t *cirrus_srcptr_end;
239
    uint32_t cirrus_srccounter;
240
    uint8_t *cirrus_dstptr;
241
    uint8_t *cirrus_dstptr_end;
242
    uint32_t cirrus_dstcounter;
243
    cirrus_bitblt_handler_t cirrus_blt_handler;
244
    int cirrus_blt_horz_counter;
245
} CirrusVGAState;
246

    
247
typedef struct PCICirrusVGAState {
248
    PCIDevice dev;
249
    CirrusVGAState cirrus_vga;
250
} PCICirrusVGAState;
251

    
252
/***************************************
253
 *
254
 *  prototypes.
255
 *
256
 ***************************************/
257

    
258

    
259
static void cirrus_bitblt_reset(CirrusVGAState * s);
260

    
261
/***************************************
262
 *
263
 *  raster operations
264
 *
265
 ***************************************/
266

    
267
#define IMPLEMENT_FORWARD_BITBLT(name,opline) \
268
  static void \
269
  cirrus_bitblt_rop_fwd_##name( \
270
    uint8_t *dst,const uint8_t *src, \
271
    int dstpitch,int srcpitch, \
272
    int bltwidth,int bltheight) \
273
  { \
274
    int x,y; \
275
    dstpitch -= bltwidth; \
276
    srcpitch -= bltwidth; \
277
    for (y = 0; y < bltheight; y++) { \
278
      for (x = 0; x < bltwidth; x++) { \
279
        opline; \
280
        dst++; \
281
        src++; \
282
        } \
283
      dst += dstpitch; \
284
      src += srcpitch; \
285
      } \
286
    }
287

    
288
#define IMPLEMENT_BACKWARD_BITBLT(name,opline) \
289
  static void \
290
  cirrus_bitblt_rop_bkwd_##name( \
291
    uint8_t *dst,const uint8_t *src, \
292
    int dstpitch,int srcpitch, \
293
    int bltwidth,int bltheight) \
294
  { \
295
    int x,y; \
296
    dstpitch += bltwidth; \
297
    srcpitch += bltwidth; \
298
    for (y = 0; y < bltheight; y++) { \
299
      for (x = 0; x < bltwidth; x++) { \
300
        opline; \
301
        dst--; \
302
        src--; \
303
      } \
304
      dst += dstpitch; \
305
      src += srcpitch; \
306
    } \
307
  }
308

    
309
IMPLEMENT_FORWARD_BITBLT(0, *dst = 0)
310
    IMPLEMENT_FORWARD_BITBLT(src_and_dst, *dst = (*src) & (*dst))
311
    IMPLEMENT_FORWARD_BITBLT(nop, (void) 0)
312
    IMPLEMENT_FORWARD_BITBLT(src_and_notdst, *dst = (*src) & (~(*dst)))
313
    IMPLEMENT_FORWARD_BITBLT(notdst, *dst = ~(*dst))
314
    IMPLEMENT_FORWARD_BITBLT(src, *dst = *src)
315
    IMPLEMENT_FORWARD_BITBLT(1, *dst = 0xff)
316
    IMPLEMENT_FORWARD_BITBLT(notsrc_and_dst, *dst = (~(*src)) & (*dst))
317
    IMPLEMENT_FORWARD_BITBLT(src_xor_dst, *dst = (*src) ^ (*dst))
318
    IMPLEMENT_FORWARD_BITBLT(src_or_dst, *dst = (*src) | (*dst))
319
    IMPLEMENT_FORWARD_BITBLT(notsrc_or_notdst, *dst = (~(*src)) | (~(*dst)))
320
    IMPLEMENT_FORWARD_BITBLT(src_notxor_dst, *dst = ~((*src) ^ (*dst)))
321
    IMPLEMENT_FORWARD_BITBLT(src_or_notdst, *dst = (*src) | (~(*dst)))
322
    IMPLEMENT_FORWARD_BITBLT(notsrc, *dst = (~(*src)))
323
    IMPLEMENT_FORWARD_BITBLT(notsrc_or_dst, *dst = (~(*src)) | (*dst))
324
    IMPLEMENT_FORWARD_BITBLT(notsrc_and_notdst, *dst = (~(*src)) & (~(*dst)))
325

    
326
    IMPLEMENT_BACKWARD_BITBLT(0, *dst = 0)
327
    IMPLEMENT_BACKWARD_BITBLT(src_and_dst, *dst = (*src) & (*dst))
328
    IMPLEMENT_BACKWARD_BITBLT(nop, (void) 0)
329
    IMPLEMENT_BACKWARD_BITBLT(src_and_notdst, *dst = (*src) & (~(*dst)))
330
    IMPLEMENT_BACKWARD_BITBLT(notdst, *dst = ~(*dst))
331
    IMPLEMENT_BACKWARD_BITBLT(src, *dst = *src)
332
    IMPLEMENT_BACKWARD_BITBLT(1, *dst = 0xff)
333
    IMPLEMENT_BACKWARD_BITBLT(notsrc_and_dst, *dst = (~(*src)) & (*dst))
334
    IMPLEMENT_BACKWARD_BITBLT(src_xor_dst, *dst = (*src) ^ (*dst))
335
    IMPLEMENT_BACKWARD_BITBLT(src_or_dst, *dst = (*src) | (*dst))
336
    IMPLEMENT_BACKWARD_BITBLT(notsrc_or_notdst, *dst = (~(*src)) | (~(*dst)))
337
    IMPLEMENT_BACKWARD_BITBLT(src_notxor_dst, *dst = ~((*src) ^ (*dst)))
338
    IMPLEMENT_BACKWARD_BITBLT(src_or_notdst, *dst = (*src) | (~(*dst)))
339
    IMPLEMENT_BACKWARD_BITBLT(notsrc, *dst = (~(*src)))
340
    IMPLEMENT_BACKWARD_BITBLT(notsrc_or_dst, *dst = (~(*src)) | (*dst))
341
    IMPLEMENT_BACKWARD_BITBLT(notsrc_and_notdst, *dst = (~(*src)) & (~(*dst)))
342

    
343
static cirrus_bitblt_rop_t cirrus_get_fwd_rop_handler(uint8_t rop)
344
{
345
    cirrus_bitblt_rop_t rop_handler = cirrus_bitblt_rop_fwd_nop;
346

    
347
    switch (rop) {
348
    case CIRRUS_ROP_0:
349
        rop_handler = cirrus_bitblt_rop_fwd_0;
350
        break;
351
    case CIRRUS_ROP_SRC_AND_DST:
352
        rop_handler = cirrus_bitblt_rop_fwd_src_and_dst;
353
        break;
354
    case CIRRUS_ROP_NOP:
355
        rop_handler = cirrus_bitblt_rop_fwd_nop;
356
        break;
357
    case CIRRUS_ROP_SRC_AND_NOTDST:
358
        rop_handler = cirrus_bitblt_rop_fwd_src_and_notdst;
359
        break;
360
    case CIRRUS_ROP_NOTDST:
361
        rop_handler = cirrus_bitblt_rop_fwd_notdst;
362
        break;
363
    case CIRRUS_ROP_SRC:
364
        rop_handler = cirrus_bitblt_rop_fwd_src;
365
        break;
366
    case CIRRUS_ROP_1:
367
        rop_handler = cirrus_bitblt_rop_fwd_1;
368
        break;
369
    case CIRRUS_ROP_NOTSRC_AND_DST:
370
        rop_handler = cirrus_bitblt_rop_fwd_notsrc_and_dst;
371
        break;
372
    case CIRRUS_ROP_SRC_XOR_DST:
373
        rop_handler = cirrus_bitblt_rop_fwd_src_xor_dst;
374
        break;
375
    case CIRRUS_ROP_SRC_OR_DST:
376
        rop_handler = cirrus_bitblt_rop_fwd_src_or_dst;
377
        break;
378
    case CIRRUS_ROP_NOTSRC_OR_NOTDST:
379
        rop_handler = cirrus_bitblt_rop_fwd_notsrc_or_notdst;
380
        break;
381
    case CIRRUS_ROP_SRC_NOTXOR_DST:
382
        rop_handler = cirrus_bitblt_rop_fwd_src_notxor_dst;
383
        break;
384
    case CIRRUS_ROP_SRC_OR_NOTDST:
385
        rop_handler = cirrus_bitblt_rop_fwd_src_or_notdst;
386
        break;
387
    case CIRRUS_ROP_NOTSRC:
388
        rop_handler = cirrus_bitblt_rop_fwd_notsrc;
389
        break;
390
    case CIRRUS_ROP_NOTSRC_OR_DST:
391
        rop_handler = cirrus_bitblt_rop_fwd_notsrc_or_dst;
392
        break;
393
    case CIRRUS_ROP_NOTSRC_AND_NOTDST:
394
        rop_handler = cirrus_bitblt_rop_fwd_notsrc_and_notdst;
395
        break;
396
    default:
397
#ifdef DEBUG_CIRRUS
398
        printf("unknown ROP %02x\n", rop);
399
#endif
400
        break;
401
    }
402

    
403
    return rop_handler;
404
}
405

    
406
static cirrus_bitblt_rop_t cirrus_get_bkwd_rop_handler(uint8_t rop)
407
{
408
    cirrus_bitblt_rop_t rop_handler = cirrus_bitblt_rop_bkwd_nop;
409

    
410
    switch (rop) {
411
    case CIRRUS_ROP_0:
412
        rop_handler = cirrus_bitblt_rop_bkwd_0;
413
        break;
414
    case CIRRUS_ROP_SRC_AND_DST:
415
        rop_handler = cirrus_bitblt_rop_bkwd_src_and_dst;
416
        break;
417
    case CIRRUS_ROP_NOP:
418
        rop_handler = cirrus_bitblt_rop_bkwd_nop;
419
        break;
420
    case CIRRUS_ROP_SRC_AND_NOTDST:
421
        rop_handler = cirrus_bitblt_rop_bkwd_src_and_notdst;
422
        break;
423
    case CIRRUS_ROP_NOTDST:
424
        rop_handler = cirrus_bitblt_rop_bkwd_notdst;
425
        break;
426
    case CIRRUS_ROP_SRC:
427
        rop_handler = cirrus_bitblt_rop_bkwd_src;
428
        break;
429
    case CIRRUS_ROP_1:
430
        rop_handler = cirrus_bitblt_rop_bkwd_1;
431
        break;
432
    case CIRRUS_ROP_NOTSRC_AND_DST:
433
        rop_handler = cirrus_bitblt_rop_bkwd_notsrc_and_dst;
434
        break;
435
    case CIRRUS_ROP_SRC_XOR_DST:
436
        rop_handler = cirrus_bitblt_rop_bkwd_src_xor_dst;
437
        break;
438
    case CIRRUS_ROP_SRC_OR_DST:
439
        rop_handler = cirrus_bitblt_rop_bkwd_src_or_dst;
440
        break;
441
    case CIRRUS_ROP_NOTSRC_OR_NOTDST:
442
        rop_handler = cirrus_bitblt_rop_bkwd_notsrc_or_notdst;
443
        break;
444
    case CIRRUS_ROP_SRC_NOTXOR_DST:
445
        rop_handler = cirrus_bitblt_rop_bkwd_src_notxor_dst;
446
        break;
447
    case CIRRUS_ROP_SRC_OR_NOTDST:
448
        rop_handler = cirrus_bitblt_rop_bkwd_src_or_notdst;
449
        break;
450
    case CIRRUS_ROP_NOTSRC:
451
        rop_handler = cirrus_bitblt_rop_bkwd_notsrc;
452
        break;
453
    case CIRRUS_ROP_NOTSRC_OR_DST:
454
        rop_handler = cirrus_bitblt_rop_bkwd_notsrc_or_dst;
455
        break;
456
    case CIRRUS_ROP_NOTSRC_AND_NOTDST:
457
        rop_handler = cirrus_bitblt_rop_bkwd_notsrc_and_notdst;
458
        break;
459
    default:
460
#ifdef DEBUG_CIRRUS
461
        printf("unknown ROP %02x\n", rop);
462
#endif
463
        break;
464
    }
465

    
466
    return rop_handler;
467
}
468

    
469
/***************************************
470
 *
471
 *  color expansion
472
 *
473
 ***************************************/
474

    
475
static void
476
cirrus_colorexpand_8(CirrusVGAState * s, uint8_t * dst,
477
                     const uint8_t * src, int count)
478
{
479
    int x;
480
    uint8_t colors[2];
481
    unsigned bits;
482
    unsigned bitmask;
483
    int srcskipleft = 0;
484

    
485
    colors[0] = s->cirrus_shadow_gr0;
486
    colors[1] = s->cirrus_shadow_gr1;
487

    
488
    bitmask = 0x80 >> srcskipleft;
489
    bits = *src++;
490
    for (x = 0; x < count; x++) {
491
        if ((bitmask & 0xff) == 0) {
492
            bitmask = 0x80;
493
            bits = *src++;
494
        }
495
        *dst++ = colors[!!(bits & bitmask)];
496
        bitmask >>= 1;
497
    }
498
}
499

    
500
static void
501
cirrus_colorexpand_16(CirrusVGAState * s, uint8_t * dst,
502
                      const uint8_t * src, int count)
503
{
504
    int x;
505
    uint8_t colors[2][2];
506
    unsigned bits;
507
    unsigned bitmask;
508
    unsigned index;
509
    int srcskipleft = 0;
510

    
511
    colors[0][0] = s->cirrus_shadow_gr0;
512
    colors[0][1] = s->gr[0x10];
513
    colors[1][0] = s->cirrus_shadow_gr1;
514
    colors[1][1] = s->gr[0x11];
515

    
516
    bitmask = 0x80 >> srcskipleft;
517
    bits = *src++;
518
    for (x = 0; x < count; x++) {
519
        if ((bitmask & 0xff) == 0) {
520
            bitmask = 0x80;
521
            bits = *src++;
522
        }
523
        index = !!(bits & bitmask);
524
        *dst++ = colors[index][0];
525
        *dst++ = colors[index][1];
526
        bitmask >>= 1;
527
    }
528
}
529

    
530
static void
531
cirrus_colorexpand_24(CirrusVGAState * s, uint8_t * dst,
532
                      const uint8_t * src, int count)
533
{
534
    int x;
535
    uint8_t colors[2][3];
536
    unsigned bits;
537
    unsigned bitmask;
538
    unsigned index;
539
    int srcskipleft = 0;
540

    
541
    colors[0][0] = s->cirrus_shadow_gr0;
542
    colors[0][1] = s->gr[0x10];
543
    colors[0][2] = s->gr[0x12];
544
    colors[1][0] = s->cirrus_shadow_gr1;
545
    colors[1][1] = s->gr[0x11];
546
    colors[1][2] = s->gr[0x13];
547

    
548
    bitmask = 0x80 << srcskipleft;
549
    bits = *src++;
550
    for (x = 0; x < count; x++) {
551
        if ((bitmask & 0xff) == 0) {
552
            bitmask = 0x80;
553
            bits = *src++;
554
        }
555
        index = !!(bits & bitmask);
556
        *dst++ = colors[index][0];
557
        *dst++ = colors[index][1];
558
        *dst++ = colors[index][2];
559
        bitmask >>= 1;
560
    }
561
}
562

    
563
static void
564
cirrus_colorexpand_32(CirrusVGAState * s, uint8_t * dst,
565
                      const uint8_t * src, int count)
566
{
567
    int x;
568
    uint8_t colors[2][4];
569
    unsigned bits;
570
    unsigned bitmask;
571
    unsigned index;
572
    int srcskipleft = 0;
573

    
574
    colors[0][0] = s->cirrus_shadow_gr0;
575
    colors[0][1] = s->gr[0x10];
576
    colors[0][2] = s->gr[0x12];
577
    colors[0][3] = s->gr[0x14];
578
    colors[1][0] = s->cirrus_shadow_gr1;
579
    colors[1][1] = s->gr[0x11];
580
    colors[1][2] = s->gr[0x13];
581
    colors[1][3] = s->gr[0x15];
582

    
583
    bitmask = 0x80 << srcskipleft;
584
    bits = *src++;
585
    for (x = 0; x < count; x++) {
586
        if ((bitmask & 0xff) == 0) {
587
            bitmask = 0x80;
588
            bits = *src++;
589
        }
590
        index = !!(bits & bitmask);
591
        *dst++ = colors[index][0];
592
        *dst++ = colors[index][1];
593
        *dst++ = colors[index][2];
594
        *dst++ = colors[index][3];
595
        bitmask >>= 1;
596
    }
597
}
598

    
599
static void
600
cirrus_colorexpand(CirrusVGAState * s, uint8_t * dst, const uint8_t * src,
601
                   int count)
602
{
603
    switch (s->cirrus_blt_pixelwidth) {
604
    case 1:
605
        cirrus_colorexpand_8(s, dst, src, count);
606
        break;
607
    case 2:
608
        cirrus_colorexpand_16(s, dst, src, count);
609
        break;
610
    case 3:
611
        cirrus_colorexpand_24(s, dst, src, count);
612
        break;
613
    case 4:
614
        cirrus_colorexpand_32(s, dst, src, count);
615
        break;
616
    default:
617
#ifdef DEBUG_CIRRUS
618
        printf("cirrus: COLOREXPAND pixelwidth %d - unimplemented\n",
619
               s->cirrus_blt_pixelwidth);
620
#endif
621
        break;
622
    }
623
}
624

    
625
static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin,
626
                                     int off_pitch, int bytesperline,
627
                                     int lines)
628
{
629
    int y;
630
    int off_cur;
631
    int off_cur_end;
632

    
633
    for (y = 0; y < lines; y++) {
634
        off_cur = off_begin;
635
        off_cur_end = off_cur + bytesperline;
636
        off_cur &= TARGET_PAGE_MASK;
637
        while (off_cur < off_cur_end) {
638
            cpu_physical_memory_set_dirty(s->vram_offset + off_cur);
639
            off_cur += TARGET_PAGE_SIZE;
640
        }
641
        off_begin += off_pitch;
642
    }
643
}
644

    
645

    
646

    
647
static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s,
648
                                            const uint8_t * src)
649
{
650
    uint8_t work_colorexp[256];
651
    uint8_t *dst;
652
    uint8_t *dstc;
653
    int x, y;
654
    int tilewidth, tileheight;
655
    int patternbytes = s->cirrus_blt_pixelwidth * 8;
656

    
657
    if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
658
        cirrus_colorexpand(s, work_colorexp, src, 8 * 8);
659
        src = work_colorexp;
660
        s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_COLOREXPAND;
661
    }
662
    if (s->cirrus_blt_mode & ~CIRRUS_BLTMODE_PATTERNCOPY) {
663
#ifdef DEBUG_CIRRUS
664
        printf("cirrus: blt mode %02x (pattercopy) - unimplemented\n",
665
               s->cirrus_blt_mode);
666
#endif
667
        return 0;
668
    }
669

    
670
    dst = s->vram_ptr + s->cirrus_blt_dstaddr;
671
    for (y = 0; y < s->cirrus_blt_height; y += 8) {
672
        dstc = dst;
673
        tileheight = qemu_MIN(8, s->cirrus_blt_height - y);
674
        for (x = 0; x < s->cirrus_blt_width; x += patternbytes) {
675
            tilewidth = qemu_MIN(patternbytes, s->cirrus_blt_width - x);
676
            (*s->cirrus_rop) (dstc, src,
677
                              s->cirrus_blt_dstpitch, patternbytes,
678
                              tilewidth, tileheight);
679
            dstc += patternbytes;
680
        }
681
        dst += s->cirrus_blt_dstpitch * 8;
682
    }
683
    cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
684
                             s->cirrus_blt_dstpitch, s->cirrus_blt_width,
685
                             s->cirrus_blt_height);
686
    return 1;
687
}
688

    
689
/***************************************
690
 *
691
 *  bitblt (video-to-video)
692
 *
693
 ***************************************/
694

    
695
static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
696
{
697
    return cirrus_bitblt_common_patterncopy(s,
698
                                            s->vram_ptr +
699
                                            s->cirrus_blt_srcaddr);
700
}
701

    
702
static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
703
{
704
    if ((s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) != 0) {
705
#ifdef DEBUG_CIRRUS
706
        printf("cirrus: CIRRUS_BLTMODE_COLOREXPAND - unimplemented\n");
707
#endif
708
        return 0;
709
    }
710
    if ((s->cirrus_blt_mode & (~CIRRUS_BLTMODE_BACKWARDS)) != 0) {
711
#ifdef DEBUG_CIRRUS
712
        printf("cirrus: blt mode %02x - unimplemented\n",
713
               s->cirrus_blt_mode);
714
#endif
715
        return 0;
716
    }
717

    
718
    (*s->cirrus_rop) (s->vram_ptr + s->cirrus_blt_dstaddr,
719
                      s->vram_ptr + s->cirrus_blt_srcaddr,
720
                      s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
721
                      s->cirrus_blt_width, s->cirrus_blt_height);
722
    cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
723
                             s->cirrus_blt_dstpitch, s->cirrus_blt_width,
724
                             s->cirrus_blt_height);
725
    return 1;
726
}
727

    
728
/***************************************
729
 *
730
 *  bitblt (cpu-to-video)
731
 *
732
 ***************************************/
733

    
734
static void cirrus_bitblt_cputovideo_patterncopy(void *opaque)
735
{
736
    CirrusVGAState *s = (CirrusVGAState *) opaque;
737
    int data_count;
738

    
739
    data_count = s->cirrus_srcptr - &s->cirrus_bltbuf[0];
740

    
741
    if (data_count > 0) {
742
        if (data_count != s->cirrus_srccounter) {
743
#ifdef DEBUG_CIRRUS
744
            printf("cirrus: internal error\n");
745
#endif
746
        } else {
747
            cirrus_bitblt_common_patterncopy(s, &s->cirrus_bltbuf[0]);
748
        }
749
        cirrus_bitblt_reset(s);
750
    }
751
}
752

    
753
static void cirrus_bitblt_cputovideo_copy(void *opaque)
754
{
755
    CirrusVGAState *s = (CirrusVGAState *) opaque;
756
    int data_count;
757
    int data_avail;
758
    uint8_t work_colorexp[256];
759
    uint8_t *src_ptr = NULL;
760
    int src_avail = 0;
761
    int src_processing;
762
    int src_linepad = 0;
763

    
764
    if (s->cirrus_blt_height <= 0) {
765
        s->cirrus_srcptr = s->cirrus_srcptr_end;
766
        return;
767
    }
768

    
769
    s->cirrus_srcptr = &s->cirrus_bltbuf[0];
770
    while (1) {
771
        /* get BLT source. */
772
        if (src_avail <= 0) {
773
            data_count = s->cirrus_srcptr_end - s->cirrus_srcptr;
774
            if (data_count <= 0)
775
                break;
776

    
777
            if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
778
                if (s->cirrus_blt_mode & ~CIRRUS_BLTMODE_COLOREXPAND) {
779
#ifdef DEBUG_CIRRUS
780
                    printf("cirrus: unsupported\n");
781
#endif
782
                    cirrus_bitblt_reset(s);
783
                    return;
784
                }
785
                data_avail = qemu_MIN(data_count, 256 / 32);
786
                cirrus_colorexpand(s, work_colorexp, s->cirrus_srcptr,
787
                                   data_avail * 8);
788
                src_ptr = &work_colorexp[0];
789
                src_avail = data_avail * 8 * s->cirrus_blt_pixelwidth;
790
                s->cirrus_srcptr += data_avail;
791
                src_linepad =
792
                    ((s->cirrus_blt_width + 7) / 8) * 8 -
793
                    s->cirrus_blt_width;
794
                src_linepad *= s->cirrus_blt_pixelwidth;
795
            } else {
796
                if (s->cirrus_blt_mode != 0) {
797
#ifdef DEBUG_CIRRUS
798
                    printf("cirrus: unsupported\n");
799
#endif
800
                    cirrus_bitblt_reset(s);
801
                    return;
802
                }
803
                src_ptr = s->cirrus_srcptr;
804
                src_avail =
805
                    data_count / s->cirrus_blt_pixelwidth *
806
                    s->cirrus_blt_pixelwidth;
807
                s->cirrus_srcptr += src_avail;
808
            }
809
            if (src_avail <= 0)
810
                break;
811
        }
812

    
813
        /* 1-line BLT */
814
        src_processing =
815
            s->cirrus_blt_srcpitch - s->cirrus_blt_horz_counter;
816
        src_processing = qemu_MIN(src_avail, src_processing);
817
        (*s->cirrus_rop) (s->vram_ptr + s->cirrus_blt_dstaddr,
818
                          src_ptr, 0, 0, src_processing, 1);
819
        cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0,
820
                                 src_processing, 1);
821

    
822
        s->cirrus_blt_dstaddr += src_processing;
823
        src_ptr += src_processing;
824
        src_avail -= src_processing;
825
        s->cirrus_blt_horz_counter += src_processing;
826
        if (s->cirrus_blt_horz_counter >= s->cirrus_blt_srcpitch) {
827
            src_ptr += src_linepad;
828
            src_avail -= src_linepad;
829
            s->cirrus_blt_dstaddr +=
830
                s->cirrus_blt_dstpitch - s->cirrus_blt_srcpitch;
831
            s->cirrus_blt_horz_counter = 0;
832
            s->cirrus_blt_height--;
833
            if (s->cirrus_blt_height <= 0) {
834
                s->cirrus_srcptr = s->cirrus_srcptr_end;
835
                return;
836
            }
837
        }
838
    }
839
}
840

    
841
static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s)
842
{
843
    int copy_count;
844
    int avail_count;
845

    
846
    s->cirrus_blt_handler(s);
847

    
848
    if (s->cirrus_srccounter > 0) {
849
        s->cirrus_srccounter -= s->cirrus_srcptr - &s->cirrus_bltbuf[0];
850
        copy_count = s->cirrus_srcptr_end - s->cirrus_srcptr;
851
        memmove(&s->cirrus_bltbuf[0], s->cirrus_srcptr, copy_count);
852
        avail_count = qemu_MIN(CIRRUS_BLTBUFSIZE, s->cirrus_srccounter);
853
        s->cirrus_srcptr = &s->cirrus_bltbuf[0];
854
        s->cirrus_srcptr_end = s->cirrus_srcptr + avail_count;
855
        if (s->cirrus_srccounter <= 0) {
856
            cirrus_bitblt_reset(s);
857
        }
858
    }
859
}
860

    
861
/***************************************
862
 *
863
 *  bitblt wrapper
864
 *
865
 ***************************************/
866

    
867
static void cirrus_bitblt_reset(CirrusVGAState * s)
868
{
869
    s->gr[0x31] &=
870
        ~(CIRRUS_BLT_START | CIRRUS_BLT_BUSY | CIRRUS_BLT_FIFOUSED);
871
    s->cirrus_srcptr = &s->cirrus_bltbuf[0];
872
    s->cirrus_srcptr_end = &s->cirrus_bltbuf[0];
873
    s->cirrus_srccounter = 0;
874
    s->cirrus_dstptr = &s->cirrus_bltbuf[0];
875
    s->cirrus_dstptr_end = &s->cirrus_bltbuf[0];
876
    s->cirrus_dstcounter = 0;
877
    s->cirrus_blt_handler = NULL;
878
}
879

    
880
static int cirrus_bitblt_cputovideo(CirrusVGAState * s)
881
{
882
    s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_MEMSYSSRC;
883
    s->cirrus_srcptr = &s->cirrus_bltbuf[0];
884
    s->cirrus_srcptr_end = &s->cirrus_bltbuf[0];
885

    
886
    if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
887
        if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
888
            s->cirrus_srccounter = 8;
889
        } else {
890
            s->cirrus_srccounter = 8 * 8 * s->cirrus_blt_pixelwidth;
891
        }
892
        s->cirrus_blt_srcpitch = 0;
893
        s->cirrus_blt_handler = cirrus_bitblt_cputovideo_patterncopy;
894
    } else {
895
        if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
896
            s->cirrus_srccounter =
897
                ((s->cirrus_blt_width + 7) / 8) * s->cirrus_blt_height;
898
            s->cirrus_blt_srcpitch =
899
                s->cirrus_blt_width * s->cirrus_blt_pixelwidth;
900
        } else {
901
            s->cirrus_srccounter =
902
                s->cirrus_blt_width * s->cirrus_blt_height;
903
            s->cirrus_blt_srcpitch = s->cirrus_blt_width;
904
        }
905
        /* 4-byte alignment */
906
        s->cirrus_srccounter = (s->cirrus_srccounter + 3) & (~3);
907

    
908
        s->cirrus_blt_handler = cirrus_bitblt_cputovideo_copy;
909
        s->cirrus_blt_horz_counter = 0;
910
    }
911

    
912
    cirrus_bitblt_cputovideo_next(s);
913
    return 1;
914
}
915

    
916
static int cirrus_bitblt_videotocpu(CirrusVGAState * s)
917
{
918
    /* XXX */
919
#ifdef DEBUG_CIRRUS
920
    printf("cirrus: bitblt (video to cpu) is not implemented yet\n");
921
#endif
922
    return 0;
923
}
924

    
925
static int cirrus_bitblt_videotovideo(CirrusVGAState * s)
926
{
927
    int ret;
928

    
929
    if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
930
        ret = cirrus_bitblt_videotovideo_patterncopy(s);
931
    } else {
932
        ret = cirrus_bitblt_videotovideo_copy(s);
933
    }
934

    
935
    if (ret)
936
        cirrus_bitblt_reset(s);
937
    return ret;
938
}
939

    
940
static void cirrus_bitblt_start(CirrusVGAState * s)
941
{
942
    uint8_t blt_rop;
943

    
944
    s->cirrus_blt_width = (s->gr[0x20] | (s->gr[0x21] << 8)) + 1;
945
    s->cirrus_blt_height = (s->gr[0x22] | (s->gr[0x23] << 8)) + 1;
946
    s->cirrus_blt_dstpitch = (s->gr[0x24] | (s->gr[0x25] << 8));
947
    s->cirrus_blt_srcpitch = (s->gr[0x26] | (s->gr[0x27] << 8));
948
    s->cirrus_blt_dstaddr =
949
        (s->gr[0x28] | (s->gr[0x29] << 8) | (s->gr[0x2a] << 16));
950
    s->cirrus_blt_srcaddr =
951
        (s->gr[0x2c] | (s->gr[0x2d] << 8) | (s->gr[0x2e] << 16));
952
    s->cirrus_blt_mode = s->gr[0x30];
953
    blt_rop = s->gr[0x32];
954

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

    
976
    if ((s->
977
         cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSSRC |
978
                            CIRRUS_BLTMODE_MEMSYSDEST))
979
        == (CIRRUS_BLTMODE_MEMSYSSRC | CIRRUS_BLTMODE_MEMSYSDEST)) {
980
#ifdef DEBUG_CIRRUS
981
        printf("cirrus: bitblt - memory-to-memory copy is requested\n");
982
#endif
983
        goto bitblt_ignore;
984
    }
985

    
986
    if (s->cirrus_blt_mode & CIRRUS_BLTMODE_BACKWARDS) {
987
        s->cirrus_blt_dstpitch = -s->cirrus_blt_dstpitch;
988
        s->cirrus_blt_srcpitch = -s->cirrus_blt_srcpitch;
989
        s->cirrus_rop = cirrus_get_bkwd_rop_handler(blt_rop);
990
    } else {
991
        s->cirrus_rop = cirrus_get_fwd_rop_handler(blt_rop);
992
    }
993

    
994
    // setup bitblt engine.
995
    if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSSRC) {
996
        if (!cirrus_bitblt_cputovideo(s))
997
            goto bitblt_ignore;
998
    } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST) {
999
        if (!cirrus_bitblt_videotocpu(s))
1000
            goto bitblt_ignore;
1001
    } else {
1002
        if (!cirrus_bitblt_videotovideo(s))
1003
            goto bitblt_ignore;
1004
    }
1005

    
1006
    return;
1007
  bitblt_ignore:;
1008
    cirrus_bitblt_reset(s);
1009
}
1010

    
1011
static void cirrus_write_bitblt(CirrusVGAState * s, unsigned reg_value)
1012
{
1013
    unsigned old_value;
1014

    
1015
    old_value = s->gr[0x31];
1016
    s->gr[0x31] = reg_value;
1017

    
1018
    if (((old_value & CIRRUS_BLT_RESET) != 0) &&
1019
        ((reg_value & CIRRUS_BLT_RESET) == 0)) {
1020
        cirrus_bitblt_reset(s);
1021
    } else if (((old_value & CIRRUS_BLT_START) == 0) &&
1022
               ((reg_value & CIRRUS_BLT_START) != 0)) {
1023
        s->gr[0x31] |= CIRRUS_BLT_BUSY;
1024
        cirrus_bitblt_start(s);
1025
    }
1026
}
1027

    
1028

    
1029
/***************************************
1030
 *
1031
 *  basic parameters
1032
 *
1033
 ***************************************/
1034

    
1035
static void cirrus_get_offsets(VGAState *s1, 
1036
                                   uint32_t *pline_offset,
1037
                                   uint32_t *pstart_addr)
1038
{
1039
    CirrusVGAState * s = (CirrusVGAState *)s1;
1040
    uint32_t start_addr;
1041
    uint32_t line_offset;
1042

    
1043
    line_offset = s->cr[0x13]
1044
        | ((s->cr[0x1b] & 0x10) << 4);
1045
    line_offset <<= 3;
1046
    *pline_offset = line_offset;
1047

    
1048
    start_addr = (s->cr[0x0c] << 8)
1049
        | s->cr[0x0d]
1050
        | ((s->cr[0x1b] & 0x01) << 16)
1051
        | ((s->cr[0x1b] & 0x0c) << 15)
1052
        | ((s->cr[0x1d] & 0x80) << 12);
1053
    *pstart_addr = start_addr;
1054
}
1055

    
1056
static uint32_t cirrus_get_bpp16_depth(CirrusVGAState * s)
1057
{
1058
    uint32_t ret = 16;
1059

    
1060
    switch (s->cirrus_hidden_dac_data & 0xf) {
1061
    case 0:
1062
        ret = 15;
1063
        break;                        /* Sierra HiColor */
1064
    case 1:
1065
        ret = 16;
1066
        break;                        /* XGA HiColor */
1067
    default:
1068
#ifdef DEBUG_CIRRUS
1069
        printf("cirrus: invalid DAC value %x in 16bpp\n",
1070
               (s->cirrus_hidden_dac_data & 0xf));
1071
#endif
1072
        ret = 15;                /* XXX */
1073
        break;
1074
    }
1075
    return ret;
1076
}
1077

    
1078
static int cirrus_get_bpp(VGAState *s1)
1079
{
1080
    CirrusVGAState * s = (CirrusVGAState *)s1;
1081
    uint32_t ret = 8;
1082

    
1083
    if ((s->sr[0x07] & 0x01) != 0) {
1084
        /* Cirrus SVGA */
1085
        switch (s->sr[0x07] & CIRRUS_SR7_BPP_MASK) {
1086
        case CIRRUS_SR7_BPP_8:
1087
            ret = 8;
1088
            break;
1089
        case CIRRUS_SR7_BPP_16_DOUBLEVCLK:
1090
            ret = cirrus_get_bpp16_depth(s);
1091
            break;
1092
        case CIRRUS_SR7_BPP_24:
1093
            ret = 24;
1094
            break;
1095
        case CIRRUS_SR7_BPP_16:
1096
            ret = cirrus_get_bpp16_depth(s);
1097
            break;
1098
        case CIRRUS_SR7_BPP_32:
1099
            ret = 32;
1100
            break;
1101
        default:
1102
#ifdef DEBUG_CIRRUS
1103
            printf("cirrus: unknown bpp - sr7=%x\n", s->sr[0x7]);
1104
#endif
1105
            ret = 8;
1106
            break;
1107
        }
1108
    } else {
1109
        /* VGA */
1110
        ret = 0;
1111
    }
1112

    
1113
    return ret;
1114
}
1115

    
1116
/***************************************
1117
 *
1118
 * bank memory
1119
 *
1120
 ***************************************/
1121

    
1122
static void cirrus_update_bank_ptr(CirrusVGAState * s, unsigned bank_index)
1123
{
1124
    unsigned offset;
1125
    unsigned limit;
1126

    
1127
    if ((s->gr[0x0b] & 0x01) != 0)        /* dual bank */
1128
        offset = s->gr[0x09 + bank_index];
1129
    else                        /* single bank */
1130
        offset = s->gr[0x09];
1131

    
1132
    if ((s->gr[0x0b] & 0x20) != 0)
1133
        offset <<= 14;
1134
    else
1135
        offset <<= 12;
1136

    
1137
    if (s->vram_size <= offset)
1138
        limit = 0;
1139
    else
1140
        limit = s->vram_size - offset;
1141

    
1142
    if (((s->gr[0x0b] & 0x01) == 0) && (bank_index != 0)) {
1143
        if (limit > 0x8000) {
1144
            offset += 0x8000;
1145
            limit -= 0x8000;
1146
        } else {
1147
            limit = 0;
1148
        }
1149
    }
1150

    
1151
    if (limit > 0) {
1152
        s->cirrus_bank_base[bank_index] = offset;
1153
        s->cirrus_bank_limit[bank_index] = limit;
1154
    } else {
1155
        s->cirrus_bank_base[bank_index] = 0;
1156
        s->cirrus_bank_limit[bank_index] = 0;
1157
    }
1158
}
1159

    
1160
/***************************************
1161
 *
1162
 *  I/O access between 0x3c4-0x3c5
1163
 *
1164
 ***************************************/
1165

    
1166
static int
1167
cirrus_hook_read_sr(CirrusVGAState * s, unsigned reg_index, int *reg_value)
1168
{
1169
    switch (reg_index) {
1170
    case 0x00:                        // Standard VGA
1171
    case 0x01:                        // Standard VGA
1172
    case 0x02:                        // Standard VGA
1173
    case 0x03:                        // Standard VGA
1174
    case 0x04:                        // Standard VGA
1175
        return CIRRUS_HOOK_NOT_HANDLED;
1176
    case 0x06:                        // Unlock Cirrus extensions
1177
        *reg_value = s->sr[reg_index];
1178
        break;
1179
    case 0x10:
1180
    case 0x30:
1181
    case 0x50:
1182
    case 0x70:                        // Graphics Cursor X
1183
    case 0x90:
1184
    case 0xb0:
1185
    case 0xd0:
1186
    case 0xf0:                        // Graphics Cursor X
1187
        *reg_value = s->sr[0x10];
1188
        break;
1189
    case 0x11:
1190
    case 0x31:
1191
    case 0x51:
1192
    case 0x71:                        // Graphics Cursor Y
1193
    case 0x91:
1194
    case 0xb1:
1195
    case 0xd1:
1196
        *reg_value = s->sr[0x11];
1197
        break;
1198
    case 0x05:                        // ???
1199
    case 0x07:                        // Extended Sequencer Mode
1200
    case 0x08:                        // EEPROM Control
1201
    case 0x09:                        // Scratch Register 0
1202
    case 0x0a:                        // Scratch Register 1
1203
    case 0x0b:                        // VCLK 0
1204
    case 0x0c:                        // VCLK 1
1205
    case 0x0d:                        // VCLK 2
1206
    case 0x0e:                        // VCLK 3
1207
    case 0x0f:                        // DRAM Control
1208
    case 0xf1:                        // Graphics Cursor Y
1209
    case 0x12:                        // Graphics Cursor Attribute
1210
    case 0x13:                        // Graphics Cursor Pattern Address
1211
    case 0x14:                        // Scratch Register 2
1212
    case 0x15:                        // Scratch Register 3
1213
    case 0x16:                        // Performance Tuning Register
1214
    case 0x17:                        // Configuration Readback and Extended Control
1215
    case 0x18:                        // Signature Generator Control
1216
    case 0x19:                        // Signal Generator Result
1217
    case 0x1a:                        // Signal Generator Result
1218
    case 0x1b:                        // VCLK 0 Denominator & Post
1219
    case 0x1c:                        // VCLK 1 Denominator & Post
1220
    case 0x1d:                        // VCLK 2 Denominator & Post
1221
    case 0x1e:                        // VCLK 3 Denominator & Post
1222
    case 0x1f:                        // BIOS Write Enable and MCLK select
1223
#ifdef DEBUG_CIRRUS
1224
        printf("cirrus: handled inport sr_index %02x\n", reg_index);
1225
#endif
1226
        *reg_value = s->sr[reg_index];
1227
        break;
1228
    default:
1229
#ifdef DEBUG_CIRRUS
1230
        printf("cirrus: inport sr_index %02x\n", reg_index);
1231
#endif
1232
        *reg_value = 0xff;
1233
        break;
1234
    }
1235

    
1236
    return CIRRUS_HOOK_HANDLED;
1237
}
1238

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

    
1316
    return CIRRUS_HOOK_HANDLED;
1317
}
1318

    
1319
/***************************************
1320
 *
1321
 *  I/O access at 0x3c6
1322
 *
1323
 ***************************************/
1324

    
1325
static void cirrus_read_hidden_dac(CirrusVGAState * s, int *reg_value)
1326
{
1327
    *reg_value = 0xff;
1328
    if (s->cirrus_hidden_dac_lockindex < 5) {
1329
        if (s->cirrus_hidden_dac_lockindex == 4) {
1330
            *reg_value = s->cirrus_hidden_dac_data;
1331
        }
1332
        s->cirrus_hidden_dac_lockindex++;
1333
    }
1334
}
1335

    
1336
static void cirrus_write_hidden_dac(CirrusVGAState * s, int reg_value)
1337
{
1338
    if (s->cirrus_hidden_dac_lockindex == 4) {
1339
        s->cirrus_hidden_dac_data = reg_value;
1340
#ifdef DEBUG_CIRRUS
1341
        printf("cirrus: outport hidden DAC, value %02x\n", reg_value);
1342
#endif
1343
    }
1344
    s->cirrus_hidden_dac_lockindex = 0;
1345
}
1346

    
1347
/***************************************
1348
 *
1349
 *  I/O access at 0x3c9
1350
 *
1351
 ***************************************/
1352

    
1353
static int cirrus_hook_read_palette(CirrusVGAState * s, int *reg_value)
1354
{
1355
    if (!(s->sr[0x12] & CIRRUS_CURSOR_HIDDENPEL))
1356
        return CIRRUS_HOOK_NOT_HANDLED;
1357
    if (s->dac_read_index < 0x10) {
1358
        *reg_value =
1359
            s->cirrus_hidden_palette[s->dac_read_index * 3 +
1360
                                     s->dac_sub_index];
1361
    } else {
1362
        *reg_value = 0xff;        /* XXX */
1363
    }
1364
    if (++s->dac_sub_index == 3) {
1365
        s->dac_sub_index = 0;
1366
        s->dac_read_index++;
1367
    }
1368
    return CIRRUS_HOOK_HANDLED;
1369
}
1370

    
1371
static int cirrus_hook_write_palette(CirrusVGAState * s, int reg_value)
1372
{
1373
    if (!(s->sr[0x12] & CIRRUS_CURSOR_HIDDENPEL))
1374
        return CIRRUS_HOOK_NOT_HANDLED;
1375
    s->dac_cache[s->dac_sub_index] = reg_value;
1376
    if (++s->dac_sub_index == 3) {
1377
        if (s->dac_read_index < 0x10) {
1378
            memcpy(&s->cirrus_hidden_palette[s->dac_write_index * 3],
1379
                   s->dac_cache, 3);
1380
            /* XXX update cursor */
1381
        }
1382
        s->dac_sub_index = 0;
1383
        s->dac_write_index++;
1384
    }
1385
    return CIRRUS_HOOK_HANDLED;
1386
}
1387

    
1388
/***************************************
1389
 *
1390
 *  I/O access between 0x3ce-0x3cf
1391
 *
1392
 ***************************************/
1393

    
1394
static int
1395
cirrus_hook_read_gr(CirrusVGAState * s, unsigned reg_index, int *reg_value)
1396
{
1397
    switch (reg_index) {
1398
    case 0x00: // Standard VGA, BGCOLOR 0x000000ff
1399
      *reg_value = s->cirrus_shadow_gr0;
1400
      return CIRRUS_HOOK_HANDLED;
1401
    case 0x01: // Standard VGA, FGCOLOR 0x000000ff
1402
      *reg_value = s->cirrus_shadow_gr1;
1403
      return CIRRUS_HOOK_HANDLED;
1404
    case 0x02:                        // Standard VGA
1405
    case 0x03:                        // Standard VGA
1406
    case 0x04:                        // Standard VGA
1407
    case 0x06:                        // Standard VGA
1408
    case 0x07:                        // Standard VGA
1409
    case 0x08:                        // Standard VGA
1410
        return CIRRUS_HOOK_NOT_HANDLED;
1411
    case 0x05:                        // Standard VGA, Cirrus extended mode
1412
    default:
1413
        break;
1414
    }
1415

    
1416
    if (reg_index < 0x3a) {
1417
        *reg_value = s->gr[reg_index];
1418
    } else {
1419
#ifdef DEBUG_CIRRUS
1420
        printf("cirrus: inport gr_index %02x\n", reg_index);
1421
#endif
1422
        *reg_value = 0xff;
1423
    }
1424

    
1425
    return CIRRUS_HOOK_HANDLED;
1426
}
1427

    
1428
static int
1429
cirrus_hook_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value)
1430
{
1431
    switch (reg_index) {
1432
    case 0x00:                        // Standard VGA, BGCOLOR 0x000000ff
1433
        s->cirrus_shadow_gr0 = reg_value;
1434
        return CIRRUS_HOOK_NOT_HANDLED;
1435
    case 0x01:                        // Standard VGA, FGCOLOR 0x000000ff
1436
        s->cirrus_shadow_gr1 = reg_value;
1437
        return CIRRUS_HOOK_NOT_HANDLED;
1438
    case 0x02:                        // Standard VGA
1439
    case 0x03:                        // Standard VGA
1440
    case 0x04:                        // Standard VGA
1441
    case 0x06:                        // Standard VGA
1442
    case 0x07:                        // Standard VGA
1443
    case 0x08:                        // Standard VGA
1444
        return CIRRUS_HOOK_NOT_HANDLED;
1445
    case 0x05:                        // Standard VGA, Cirrus extended mode
1446
        s->gr[reg_index] = reg_value & 0x7f;
1447
        break;
1448
    case 0x09:                        // bank offset #0
1449
    case 0x0A:                        // bank offset #1
1450
    case 0x0B:
1451
        s->gr[reg_index] = reg_value;
1452
        cirrus_update_bank_ptr(s, 0);
1453
        cirrus_update_bank_ptr(s, 1);
1454
        break;
1455
    case 0x10:                        // BGCOLOR 0x0000ff00
1456
    case 0x11:                        // FGCOLOR 0x0000ff00
1457
    case 0x12:                        // BGCOLOR 0x00ff0000
1458
    case 0x13:                        // FGCOLOR 0x00ff0000
1459
    case 0x14:                        // BGCOLOR 0xff000000
1460
    case 0x15:                        // FGCOLOR 0xff000000
1461
    case 0x20:                        // BLT WIDTH 0x0000ff
1462
    case 0x22:                        // BLT HEIGHT 0x0000ff
1463
    case 0x24:                        // BLT DEST PITCH 0x0000ff
1464
    case 0x26:                        // BLT SRC PITCH 0x0000ff
1465
    case 0x28:                        // BLT DEST ADDR 0x0000ff
1466
    case 0x29:                        // BLT DEST ADDR 0x00ff00
1467
    case 0x2c:                        // BLT SRC ADDR 0x0000ff
1468
    case 0x2d:                        // BLT SRC ADDR 0x00ff00
1469
    case 0x30:                        // BLT MODE
1470
    case 0x32:                        // RASTER OP
1471
    case 0x34:                        // BLT TRANSPARENT COLOR 0x00ff
1472
    case 0x35:                        // BLT TRANSPARENT COLOR 0xff00
1473
    case 0x38:                        // BLT TRANSPARENT COLOR MASK 0x00ff
1474
    case 0x39:                        // BLT TRANSPARENT COLOR MASK 0xff00
1475
        s->gr[reg_index] = reg_value;
1476
        break;
1477
    case 0x21:                        // BLT WIDTH 0x001f00
1478
    case 0x23:                        // BLT HEIGHT 0x001f00
1479
    case 0x25:                        // BLT DEST PITCH 0x001f00
1480
    case 0x27:                        // BLT SRC PITCH 0x001f00
1481
        s->gr[reg_index] = reg_value & 0x1f;
1482
        break;
1483
    case 0x2a:                        // BLT DEST ADDR 0x3f0000
1484
    case 0x2e:                        // BLT SRC ADDR 0x3f0000
1485
        s->gr[reg_index] = reg_value & 0x3f;
1486
        break;
1487
    case 0x31:                        // BLT STATUS/START
1488
        cirrus_write_bitblt(s, reg_value);
1489
        break;
1490
    default:
1491
#ifdef DEBUG_CIRRUS
1492
        printf("cirrus: outport gr_index %02x, gr_value %02x\n", reg_index,
1493
               reg_value);
1494
#endif
1495
        break;
1496
    }
1497

    
1498
    return CIRRUS_HOOK_HANDLED;
1499
}
1500

    
1501
/***************************************
1502
 *
1503
 *  I/O access between 0x3d4-0x3d5
1504
 *
1505
 ***************************************/
1506

    
1507
static int
1508
cirrus_hook_read_cr(CirrusVGAState * s, unsigned reg_index, int *reg_value)
1509
{
1510
    switch (reg_index) {
1511
    case 0x00:                        // Standard VGA
1512
    case 0x01:                        // Standard VGA
1513
    case 0x02:                        // Standard VGA
1514
    case 0x03:                        // Standard VGA
1515
    case 0x04:                        // Standard VGA
1516
    case 0x05:                        // Standard VGA
1517
    case 0x06:                        // Standard VGA
1518
    case 0x07:                        // Standard VGA
1519
    case 0x08:                        // Standard VGA
1520
    case 0x09:                        // Standard VGA
1521
    case 0x0a:                        // Standard VGA
1522
    case 0x0b:                        // Standard VGA
1523
    case 0x0c:                        // Standard VGA
1524
    case 0x0d:                        // Standard VGA
1525
    case 0x0e:                        // Standard VGA
1526
    case 0x0f:                        // Standard VGA
1527
    case 0x10:                        // Standard VGA
1528
    case 0x11:                        // Standard VGA
1529
    case 0x12:                        // Standard VGA
1530
    case 0x13:                        // Standard VGA
1531
    case 0x14:                        // Standard VGA
1532
    case 0x15:                        // Standard VGA
1533
    case 0x16:                        // Standard VGA
1534
    case 0x17:                        // Standard VGA
1535
    case 0x18:                        // Standard VGA
1536
        return CIRRUS_HOOK_NOT_HANDLED;
1537
    case 0x19:                        // Interlace End
1538
    case 0x1a:                        // Miscellaneous Control
1539
    case 0x1b:                        // Extended Display Control
1540
    case 0x1c:                        // Sync Adjust and Genlock
1541
    case 0x1d:                        // Overlay Extended Control
1542
    case 0x22:                        // Graphics Data Latches Readback (R)
1543
    case 0x24:                        // Attribute Controller Toggle Readback (R)
1544
    case 0x25:                        // Part Status
1545
    case 0x27:                        // Part ID (R)
1546
        *reg_value = s->cr[reg_index];
1547
        break;
1548
    case 0x26:                        // Attribute Controller Index Readback (R)
1549
        *reg_value = s->ar_index & 0x3f;
1550
        break;
1551
    default:
1552
#ifdef DEBUG_CIRRUS
1553
        printf("cirrus: inport cr_index %02x\n", reg_index);
1554
        *reg_value = 0xff;
1555
#endif
1556
        break;
1557
    }
1558

    
1559
    return CIRRUS_HOOK_HANDLED;
1560
}
1561

    
1562
static int
1563
cirrus_hook_write_cr(CirrusVGAState * s, unsigned reg_index, int reg_value)
1564
{
1565
    switch (reg_index) {
1566
    case 0x00:                        // Standard VGA
1567
    case 0x01:                        // Standard VGA
1568
    case 0x02:                        // Standard VGA
1569
    case 0x03:                        // Standard VGA
1570
    case 0x04:                        // Standard VGA
1571
    case 0x05:                        // Standard VGA
1572
    case 0x06:                        // Standard VGA
1573
    case 0x07:                        // Standard VGA
1574
    case 0x08:                        // Standard VGA
1575
    case 0x09:                        // Standard VGA
1576
    case 0x0a:                        // Standard VGA
1577
    case 0x0b:                        // Standard VGA
1578
    case 0x0c:                        // Standard VGA
1579
    case 0x0d:                        // Standard VGA
1580
    case 0x0e:                        // Standard VGA
1581
    case 0x0f:                        // Standard VGA
1582
    case 0x10:                        // Standard VGA
1583
    case 0x11:                        // Standard VGA
1584
    case 0x12:                        // Standard VGA
1585
    case 0x13:                        // Standard VGA
1586
    case 0x14:                        // Standard VGA
1587
    case 0x15:                        // Standard VGA
1588
    case 0x16:                        // Standard VGA
1589
    case 0x17:                        // Standard VGA
1590
    case 0x18:                        // Standard VGA
1591
        return CIRRUS_HOOK_NOT_HANDLED;
1592
    case 0x19:                        // Interlace End
1593
    case 0x1a:                        // Miscellaneous Control
1594
    case 0x1b:                        // Extended Display Control
1595
    case 0x1c:                        // Sync Adjust and Genlock
1596
        s->cr[reg_index] = reg_value;
1597
#ifdef DEBUG_CIRRUS
1598
        printf("cirrus: handled outport cr_index %02x, cr_value %02x\n",
1599
               reg_index, reg_value);
1600
#endif
1601
        break;
1602
    case 0x22:                        // Graphics Data Latches Readback (R)
1603
    case 0x24:                        // Attribute Controller Toggle Readback (R)
1604
    case 0x26:                        // Attribute Controller Index Readback (R)
1605
    case 0x27:                        // Part ID (R)
1606
        break;
1607
    case 0x1d:                        // Overlay Extended Control
1608
    case 0x25:                        // Part Status
1609
    default:
1610
#ifdef DEBUG_CIRRUS
1611
        printf("cirrus: outport cr_index %02x, cr_value %02x\n", reg_index,
1612
               reg_value);
1613
#endif
1614
        break;
1615
    }
1616

    
1617
    return CIRRUS_HOOK_HANDLED;
1618
}
1619

    
1620
/***************************************
1621
 *
1622
 *  memory-mapped I/O (bitblt)
1623
 *
1624
 ***************************************/
1625

    
1626
static uint8_t cirrus_mmio_blt_read(CirrusVGAState * s, unsigned address)
1627
{
1628
    int value = 0xff;
1629

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

    
1728
    return (uint8_t) value;
1729
}
1730

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

    
1837
/***************************************
1838
 *
1839
 *  write mode 4/5
1840
 *
1841
 * assume TARGET_PAGE_SIZE >= 16
1842
 *
1843
 ***************************************/
1844

    
1845
static void cirrus_mem_writeb_mode4and5_8bpp(CirrusVGAState * s,
1846
                                             unsigned mode,
1847
                                             unsigned offset,
1848
                                             uint32_t mem_value)
1849
{
1850
    int x;
1851
    unsigned val = mem_value;
1852
    uint8_t *dst;
1853

    
1854
    dst = s->vram_ptr + offset;
1855
    for (x = 0; x < 8; x++) {
1856
        if (val & 0x80) {
1857
            *dst++ = s->cirrus_shadow_gr1;
1858
        } else if (mode == 5) {
1859
            *dst++ = s->cirrus_shadow_gr0;
1860
        }
1861
        val <<= 1;
1862
    }
1863
    cpu_physical_memory_set_dirty(s->vram_offset + offset);
1864
    cpu_physical_memory_set_dirty(s->vram_offset + offset + 7);
1865
}
1866

    
1867
static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,
1868
                                              unsigned mode,
1869
                                              unsigned offset,
1870
                                              uint32_t mem_value)
1871
{
1872
    int x;
1873
    unsigned val = mem_value;
1874
    uint8_t *dst;
1875

    
1876
    dst = s->vram_ptr + offset;
1877
    for (x = 0; x < 8; x++) {
1878
        if (val & 0x80) {
1879
            *dst++ = s->cirrus_shadow_gr1;
1880
            *dst++ = s->gr[0x11];
1881
        } else if (mode == 5) {
1882
            *dst++ = s->cirrus_shadow_gr0;
1883
            *dst++ = s->gr[0x10];
1884
        }
1885
        val <<= 1;
1886
    }
1887
    cpu_physical_memory_set_dirty(s->vram_offset + offset);
1888
    cpu_physical_memory_set_dirty(s->vram_offset + offset + 15);
1889
}
1890

    
1891
/***************************************
1892
 *
1893
 *  memory access between 0xa0000-0xbffff
1894
 *
1895
 ***************************************/
1896

    
1897
static uint32_t cirrus_vga_mem_readb(void *opaque, target_phys_addr_t addr)
1898
{
1899
    CirrusVGAState *s = opaque;
1900
    unsigned bank_index;
1901
    unsigned bank_offset;
1902
    uint32_t val;
1903

    
1904
    if ((s->sr[0x07] & 0x01) == 0) {
1905
        return vga_mem_readb(s, addr);
1906
    }
1907

    
1908
    addr &= 0x1ffff;
1909

    
1910
    if (addr < 0x10000) {
1911
        /* XXX handle bitblt */
1912
        /* video memory */
1913
        bank_index = addr >> 15;
1914
        bank_offset = addr & 0x7fff;
1915
        if (bank_offset < s->cirrus_bank_limit[bank_index]) {
1916
            bank_offset += s->cirrus_bank_base[bank_index];
1917
            if ((s->gr[0x0B] & 0x14) == 0x14) {
1918
                bank_offset <<= 4;
1919
            } else if (s->gr[0x0B] & 0x02) {
1920
                bank_offset <<= 3;
1921
            }
1922
            bank_offset &= s->cirrus_addr_mask;
1923
            val = *(s->vram_ptr + bank_offset);
1924
        } else
1925
            val = 0xff;
1926
    } else if (addr >= 0x18000 && addr < 0x18100) {
1927
        /* memory-mapped I/O */
1928
        val = 0xff;
1929
        if ((s->sr[0x17] & 0x44) == 0x04) {
1930
            val = cirrus_mmio_blt_read(s, addr & 0xff);
1931
        }
1932
    } else {
1933
        val = 0xff;
1934
#ifdef DEBUG_CIRRUS
1935
        printf("cirrus: mem_readb %06x\n", addr);
1936
#endif
1937
    }
1938
    return val;
1939
}
1940

    
1941
static uint32_t cirrus_vga_mem_readw(void *opaque, target_phys_addr_t addr)
1942
{
1943
    uint32_t v;
1944
#ifdef TARGET_WORDS_BIGENDIAN
1945
    v = cirrus_vga_mem_readb(opaque, addr) << 8;
1946
    v |= cirrus_vga_mem_readb(opaque, addr + 1);
1947
#else
1948
    v = cirrus_vga_mem_readb(opaque, addr);
1949
    v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
1950
#endif
1951
    return v;
1952
}
1953

    
1954
static uint32_t cirrus_vga_mem_readl(void *opaque, target_phys_addr_t addr)
1955
{
1956
    uint32_t v;
1957
#ifdef TARGET_WORDS_BIGENDIAN
1958
    v = cirrus_vga_mem_readb(opaque, addr) << 24;
1959
    v |= cirrus_vga_mem_readb(opaque, addr + 1) << 16;
1960
    v |= cirrus_vga_mem_readb(opaque, addr + 2) << 8;
1961
    v |= cirrus_vga_mem_readb(opaque, addr + 3);
1962
#else
1963
    v = cirrus_vga_mem_readb(opaque, addr);
1964
    v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
1965
    v |= cirrus_vga_mem_readb(opaque, addr + 2) << 16;
1966
    v |= cirrus_vga_mem_readb(opaque, addr + 3) << 24;
1967
#endif
1968
    return v;
1969
}
1970

    
1971
static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr, 
1972
                                  uint32_t mem_value)
1973
{
1974
    CirrusVGAState *s = opaque;
1975
    unsigned bank_index;
1976
    unsigned bank_offset;
1977
    unsigned mode;
1978

    
1979
    if ((s->sr[0x07] & 0x01) == 0) {
1980
        vga_mem_writeb(s, addr, mem_value);
1981
        return;
1982
    }
1983

    
1984
    addr &= 0x1ffff;
1985

    
1986
    if (addr < 0x10000) {
1987
        if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
1988
            /* bitblt */
1989
            *s->cirrus_srcptr++ = (uint8_t) mem_value;
1990
            if (s->cirrus_srcptr == s->cirrus_srcptr_end) {
1991
                cirrus_bitblt_cputovideo_next(s);
1992
            }
1993
        } else {
1994
            /* video memory */
1995
            bank_index = addr >> 15;
1996
            bank_offset = addr & 0x7fff;
1997
            if (bank_offset < s->cirrus_bank_limit[bank_index]) {
1998
                bank_offset += s->cirrus_bank_base[bank_index];
1999
                if ((s->gr[0x0B] & 0x14) == 0x14) {
2000
                    bank_offset <<= 4;
2001
                } else if (s->gr[0x0B] & 0x02) {
2002
                    bank_offset <<= 3;
2003
                }
2004
                bank_offset &= s->cirrus_addr_mask;
2005
                mode = s->gr[0x05] & 0x7;
2006
                if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
2007
                    *(s->vram_ptr + bank_offset) = mem_value;
2008
                    cpu_physical_memory_set_dirty(s->vram_offset +
2009
                                                  bank_offset);
2010
                } else {
2011
                    if ((s->gr[0x0B] & 0x14) != 0x14) {
2012
                        cirrus_mem_writeb_mode4and5_8bpp(s, mode,
2013
                                                         bank_offset,
2014
                                                         mem_value);
2015
                    } else {
2016
                        cirrus_mem_writeb_mode4and5_16bpp(s, mode,
2017
                                                          bank_offset,
2018
                                                          mem_value);
2019
                    }
2020
                }
2021
            }
2022
        }
2023
    } else if (addr >= 0x18000 && addr < 0x18100) {
2024
        /* memory-mapped I/O */
2025
        if ((s->sr[0x17] & 0x44) == 0x04) {
2026
            cirrus_mmio_blt_write(s, addr & 0xff, mem_value);
2027
        }
2028
    } else {
2029
#ifdef DEBUG_CIRRUS
2030
        printf("cirrus: mem_writeb %06x value %02x\n", addr, mem_value);
2031
#endif
2032
    }
2033
}
2034

    
2035
static void cirrus_vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
2036
{
2037
#ifdef TARGET_WORDS_BIGENDIAN
2038
    cirrus_vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
2039
    cirrus_vga_mem_writeb(opaque, addr + 1, val & 0xff);
2040
#else
2041
    cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
2042
    cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2043
#endif
2044
}
2045

    
2046
static void cirrus_vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
2047
{
2048
#ifdef TARGET_WORDS_BIGENDIAN
2049
    cirrus_vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
2050
    cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
2051
    cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
2052
    cirrus_vga_mem_writeb(opaque, addr + 3, val & 0xff);
2053
#else
2054
    cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
2055
    cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2056
    cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
2057
    cirrus_vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
2058
#endif
2059
}
2060

    
2061
static CPUReadMemoryFunc *cirrus_vga_mem_read[3] = {
2062
    cirrus_vga_mem_readb,
2063
    cirrus_vga_mem_readw,
2064
    cirrus_vga_mem_readl,
2065
};
2066

    
2067
static CPUWriteMemoryFunc *cirrus_vga_mem_write[3] = {
2068
    cirrus_vga_mem_writeb,
2069
    cirrus_vga_mem_writew,
2070
    cirrus_vga_mem_writel,
2071
};
2072

    
2073
/***************************************
2074
 *
2075
 *  LFB memory access
2076
 *
2077
 ***************************************/
2078

    
2079
static uint32_t cirrus_linear_readb(void *opaque, target_phys_addr_t addr)
2080
{
2081
    CirrusVGAState *s = (CirrusVGAState *) opaque;
2082
    uint32_t ret;
2083

    
2084
    /* XXX: s->vram_size must be a power of two */
2085
    addr &= s->cirrus_addr_mask;
2086

    
2087
    if (((s->sr[0x17] & 0x44) == 0x44) && ((addr & 0x1fff00) == 0x1fff00)) {
2088
        /* memory-mapped I/O */
2089
        ret = cirrus_mmio_blt_read(s, addr & 0xff);
2090
    } else if (0) {
2091
        /* XXX handle bitblt */
2092
        ret = 0xff;
2093
    } else {
2094
        /* video memory */
2095
        if ((s->gr[0x0B] & 0x14) == 0x14) {
2096
            addr <<= 4;
2097
        } else if (s->gr[0x0B] & 0x02) {
2098
            addr <<= 3;
2099
        }
2100
        addr &= s->cirrus_addr_mask;
2101
        ret = *(s->vram_ptr + addr);
2102
    }
2103

    
2104
    return ret;
2105
}
2106

    
2107
static uint32_t cirrus_linear_readw(void *opaque, target_phys_addr_t addr)
2108
{
2109
    uint32_t v;
2110
#ifdef TARGET_WORDS_BIGENDIAN
2111
    v = cirrus_linear_readb(opaque, addr) << 8;
2112
    v |= cirrus_linear_readb(opaque, addr + 1);
2113
#else
2114
    v = cirrus_linear_readb(opaque, addr);
2115
    v |= cirrus_linear_readb(opaque, addr + 1) << 8;
2116
#endif
2117
    return v;
2118
}
2119

    
2120
static uint32_t cirrus_linear_readl(void *opaque, target_phys_addr_t addr)
2121
{
2122
    uint32_t v;
2123
#ifdef TARGET_WORDS_BIGENDIAN
2124
    v = cirrus_linear_readb(opaque, addr) << 24;
2125
    v |= cirrus_linear_readb(opaque, addr + 1) << 16;
2126
    v |= cirrus_linear_readb(opaque, addr + 2) << 8;
2127
    v |= cirrus_linear_readb(opaque, addr + 3);
2128
#else
2129
    v = cirrus_linear_readb(opaque, addr);
2130
    v |= cirrus_linear_readb(opaque, addr + 1) << 8;
2131
    v |= cirrus_linear_readb(opaque, addr + 2) << 16;
2132
    v |= cirrus_linear_readb(opaque, addr + 3) << 24;
2133
#endif
2134
    return v;
2135
}
2136

    
2137
static void cirrus_linear_writeb(void *opaque, target_phys_addr_t addr,
2138
                                 uint32_t val)
2139
{
2140
    CirrusVGAState *s = (CirrusVGAState *) opaque;
2141
    unsigned mode;
2142

    
2143
    addr &= s->cirrus_addr_mask;
2144

    
2145
    if (((s->sr[0x17] & 0x44) == 0x44) && ((addr & 0x1fff00) == 0x1fff00)) {
2146
        /* memory-mapped I/O */
2147
        cirrus_mmio_blt_write(s, addr & 0xff, val);
2148
    } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
2149
        /* bitblt */
2150
        *s->cirrus_srcptr++ = (uint8_t) val;
2151
        if (s->cirrus_srcptr == s->cirrus_srcptr_end) {
2152
            cirrus_bitblt_cputovideo_next(s);
2153
        }
2154
    } else {
2155
        /* video memory */
2156
        if ((s->gr[0x0B] & 0x14) == 0x14) {
2157
            addr <<= 4;
2158
        } else if (s->gr[0x0B] & 0x02) {
2159
            addr <<= 3;
2160
        }
2161
        addr &= s->cirrus_addr_mask;
2162

    
2163
        mode = s->gr[0x05] & 0x7;
2164
        if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
2165
            *(s->vram_ptr + addr) = (uint8_t) val;
2166
            cpu_physical_memory_set_dirty(s->vram_offset + addr);
2167
        } else {
2168
            if ((s->gr[0x0B] & 0x14) != 0x14) {
2169
                cirrus_mem_writeb_mode4and5_8bpp(s, mode, addr, val);
2170
            } else {
2171
                cirrus_mem_writeb_mode4and5_16bpp(s, mode, addr, val);
2172
            }
2173
        }
2174
    }
2175
}
2176

    
2177
static void cirrus_linear_writew(void *opaque, target_phys_addr_t addr,
2178
                                 uint32_t val)
2179
{
2180
#ifdef TARGET_WORDS_BIGENDIAN
2181
    cirrus_linear_writeb(opaque, addr, (val >> 8) & 0xff);
2182
    cirrus_linear_writeb(opaque, addr + 1, val & 0xff);
2183
#else
2184
    cirrus_linear_writeb(opaque, addr, val & 0xff);
2185
    cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2186
#endif
2187
}
2188

    
2189
static void cirrus_linear_writel(void *opaque, target_phys_addr_t addr,
2190
                                 uint32_t val)
2191
{
2192
#ifdef TARGET_WORDS_BIGENDIAN
2193
    cirrus_linear_writeb(opaque, addr, (val >> 24) & 0xff);
2194
    cirrus_linear_writeb(opaque, addr + 1, (val >> 16) & 0xff);
2195
    cirrus_linear_writeb(opaque, addr + 2, (val >> 8) & 0xff);
2196
    cirrus_linear_writeb(opaque, addr + 3, val & 0xff);
2197
#else
2198
    cirrus_linear_writeb(opaque, addr, val & 0xff);
2199
    cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2200
    cirrus_linear_writeb(opaque, addr + 2, (val >> 16) & 0xff);
2201
    cirrus_linear_writeb(opaque, addr + 3, (val >> 24) & 0xff);
2202
#endif
2203
}
2204

    
2205

    
2206
static CPUReadMemoryFunc *cirrus_linear_read[3] = {
2207
    cirrus_linear_readb,
2208
    cirrus_linear_readw,
2209
    cirrus_linear_readl,
2210
};
2211

    
2212
static CPUWriteMemoryFunc *cirrus_linear_write[3] = {
2213
    cirrus_linear_writeb,
2214
    cirrus_linear_writew,
2215
    cirrus_linear_writel,
2216
};
2217

    
2218
/* I/O ports */
2219

    
2220
static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
2221
{
2222
    CirrusVGAState *s = opaque;
2223
    int val, index;
2224

    
2225
    /* check port range access depending on color/monochrome mode */
2226
    if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION))
2227
        || (addr >= 0x3d0 && addr <= 0x3df
2228
            && !(s->msr & MSR_COLOR_EMULATION))) {
2229
        val = 0xff;
2230
    } else {
2231
        switch (addr) {
2232
        case 0x3c0:
2233
            if (s->ar_flip_flop == 0) {
2234
                val = s->ar_index;
2235
            } else {
2236
                val = 0;
2237
            }
2238
            break;
2239
        case 0x3c1:
2240
            index = s->ar_index & 0x1f;
2241
            if (index < 21)
2242
                val = s->ar[index];
2243
            else
2244
                val = 0;
2245
            break;
2246
        case 0x3c2:
2247
            val = s->st00;
2248
            break;
2249
        case 0x3c4:
2250
            val = s->sr_index;
2251
            break;
2252
        case 0x3c5:
2253
            if (cirrus_hook_read_sr(s, s->sr_index, &val))
2254
                break;
2255
            val = s->sr[s->sr_index];
2256
#ifdef DEBUG_VGA_REG
2257
            printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
2258
#endif
2259
            break;
2260
        case 0x3c6:
2261
            cirrus_read_hidden_dac(s, &val);
2262
            break;
2263
        case 0x3c7:
2264
            val = s->dac_state;
2265
            break;
2266
        case 0x3c9:
2267
            if (cirrus_hook_read_palette(s, &val))
2268
                break;
2269
            val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
2270
            if (++s->dac_sub_index == 3) {
2271
                s->dac_sub_index = 0;
2272
                s->dac_read_index++;
2273
            }
2274
            break;
2275
        case 0x3ca:
2276
            val = s->fcr;
2277
            break;
2278
        case 0x3cc:
2279
            val = s->msr;
2280
            break;
2281
        case 0x3ce:
2282
            val = s->gr_index;
2283
            break;
2284
        case 0x3cf:
2285
            if (cirrus_hook_read_gr(s, s->gr_index, &val))
2286
                break;
2287
            val = s->gr[s->gr_index];
2288
#ifdef DEBUG_VGA_REG
2289
            printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
2290
#endif
2291
            break;
2292
        case 0x3b4:
2293
        case 0x3d4:
2294
            val = s->cr_index;
2295
            break;
2296
        case 0x3b5:
2297
        case 0x3d5:
2298
            if (cirrus_hook_read_cr(s, s->cr_index, &val))
2299
                break;
2300
            val = s->cr[s->cr_index];
2301
#ifdef DEBUG_VGA_REG
2302
            printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
2303
#endif
2304
            break;
2305
        case 0x3ba:
2306
        case 0x3da:
2307
            /* just toggle to fool polling */
2308
            s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;
2309
            val = s->st01;
2310
            s->ar_flip_flop = 0;
2311
            break;
2312
        default:
2313
            val = 0x00;
2314
            break;
2315
        }
2316
    }
2317
#if defined(DEBUG_VGA)
2318
    printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
2319
#endif
2320
    return val;
2321
}
2322

    
2323
static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
2324
{
2325
    CirrusVGAState *s = opaque;
2326
    int index;
2327

    
2328
    /* check port range access depending on color/monochrome mode */
2329
    if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION))
2330
        || (addr >= 0x3d0 && addr <= 0x3df
2331
            && !(s->msr & MSR_COLOR_EMULATION)))
2332
        return;
2333

    
2334
#ifdef DEBUG_VGA
2335
    printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
2336
#endif
2337

    
2338
    switch (addr) {
2339
    case 0x3c0:
2340
        if (s->ar_flip_flop == 0) {
2341
            val &= 0x3f;
2342
            s->ar_index = val;
2343
        } else {
2344
            index = s->ar_index & 0x1f;
2345
            switch (index) {
2346
            case 0x00 ... 0x0f:
2347
                s->ar[index] = val & 0x3f;
2348
                break;
2349
            case 0x10:
2350
                s->ar[index] = val & ~0x10;
2351
                break;
2352
            case 0x11:
2353
                s->ar[index] = val;
2354
                break;
2355
            case 0x12:
2356
                s->ar[index] = val & ~0xc0;
2357
                break;
2358
            case 0x13:
2359
                s->ar[index] = val & ~0xf0;
2360
                break;
2361
            case 0x14:
2362
                s->ar[index] = val & ~0xf0;
2363
                break;
2364
            default:
2365
                break;
2366
            }
2367
        }
2368
        s->ar_flip_flop ^= 1;
2369
        break;
2370
    case 0x3c2:
2371
        s->msr = val & ~0x10;
2372
        break;
2373
    case 0x3c4:
2374
        s->sr_index = val;
2375
        break;
2376
    case 0x3c5:
2377
        if (cirrus_hook_write_sr(s, s->sr_index, val))
2378
            break;
2379
#ifdef DEBUG_VGA_REG
2380
        printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
2381
#endif
2382
        s->sr[s->sr_index] = val & sr_mask[s->sr_index];
2383
        break;
2384
    case 0x3c6:
2385
        cirrus_write_hidden_dac(s, val);
2386
        break;
2387
    case 0x3c7:
2388
        s->dac_read_index = val;
2389
        s->dac_sub_index = 0;
2390
        s->dac_state = 3;
2391
        break;
2392
    case 0x3c8:
2393
        s->dac_write_index = val;
2394
        s->dac_sub_index = 0;
2395
        s->dac_state = 0;
2396
        break;
2397
    case 0x3c9:
2398
        if (cirrus_hook_write_palette(s, val))
2399
            break;
2400
        s->dac_cache[s->dac_sub_index] = val;
2401
        if (++s->dac_sub_index == 3) {
2402
            memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
2403
            s->dac_sub_index = 0;
2404
            s->dac_write_index++;
2405
        }
2406
        break;
2407
    case 0x3ce:
2408
        s->gr_index = val;
2409
        break;
2410
    case 0x3cf:
2411
        if (cirrus_hook_write_gr(s, s->gr_index, val))
2412
            break;
2413
#ifdef DEBUG_VGA_REG
2414
        printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
2415
#endif
2416
        s->gr[s->gr_index] = val & gr_mask[s->gr_index];
2417
        break;
2418
    case 0x3b4:
2419
    case 0x3d4:
2420
        s->cr_index = val;
2421
        break;
2422
    case 0x3b5:
2423
    case 0x3d5:
2424
        if (cirrus_hook_write_cr(s, s->cr_index, val))
2425
            break;
2426
#ifdef DEBUG_VGA_REG
2427
        printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
2428
#endif
2429
        /* handle CR0-7 protection */
2430
        if ((s->cr[11] & 0x80) && s->cr_index <= 7) {
2431
            /* can always write bit 4 of CR7 */
2432
            if (s->cr_index == 7)
2433
                s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
2434
            return;
2435
        }
2436
        switch (s->cr_index) {
2437
        case 0x01:                /* horizontal display end */
2438
        case 0x07:
2439
        case 0x09:
2440
        case 0x0c:
2441
        case 0x0d:
2442
        case 0x12:                /* veritcal display end */
2443
            s->cr[s->cr_index] = val;
2444
            break;
2445

    
2446
        default:
2447
            s->cr[s->cr_index] = val;
2448
            break;
2449
        }
2450
        break;
2451
    case 0x3ba:
2452
    case 0x3da:
2453
        s->fcr = val & 0x10;
2454
        break;
2455
    }
2456
}
2457

    
2458
/***************************************
2459
 *
2460
 *  memory-mapped I/O access
2461
 *
2462
 ***************************************/
2463

    
2464
static uint32_t cirrus_mmio_readb(void *opaque, target_phys_addr_t addr)
2465
{
2466
    CirrusVGAState *s = (CirrusVGAState *) opaque;
2467

    
2468
    addr &= CIRRUS_PNPMMIO_SIZE - 1;
2469

    
2470
    if (addr >= 0x100) {
2471
        return cirrus_mmio_blt_read(s, addr - 0x100);
2472
    } else {
2473
        return vga_ioport_read(s, addr + 0x3c0);
2474
    }
2475
}
2476

    
2477
static uint32_t cirrus_mmio_readw(void *opaque, target_phys_addr_t addr)
2478
{
2479
    uint32_t v;
2480
#ifdef TARGET_WORDS_BIGENDIAN
2481
    v = cirrus_mmio_readb(opaque, addr) << 8;
2482
    v |= cirrus_mmio_readb(opaque, addr + 1);
2483
#else
2484
    v = cirrus_mmio_readb(opaque, addr);
2485
    v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
2486
#endif
2487
    return v;
2488
}
2489

    
2490
static uint32_t cirrus_mmio_readl(void *opaque, target_phys_addr_t addr)
2491
{
2492
    uint32_t v;
2493
#ifdef TARGET_WORDS_BIGENDIAN
2494
    v = cirrus_mmio_readb(opaque, addr) << 24;
2495
    v |= cirrus_mmio_readb(opaque, addr + 1) << 16;
2496
    v |= cirrus_mmio_readb(opaque, addr + 2) << 8;
2497
    v |= cirrus_mmio_readb(opaque, addr + 3);
2498
#else
2499
    v = cirrus_mmio_readb(opaque, addr);
2500
    v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
2501
    v |= cirrus_mmio_readb(opaque, addr + 2) << 16;
2502
    v |= cirrus_mmio_readb(opaque, addr + 3) << 24;
2503
#endif
2504
    return v;
2505
}
2506

    
2507
static void cirrus_mmio_writeb(void *opaque, target_phys_addr_t addr,
2508
                               uint32_t val)
2509
{
2510
    CirrusVGAState *s = (CirrusVGAState *) opaque;
2511

    
2512
    addr &= CIRRUS_PNPMMIO_SIZE - 1;
2513

    
2514
    if (addr >= 0x100) {
2515
        cirrus_mmio_blt_write(s, addr - 0x100, val);
2516
    } else {
2517
        vga_ioport_write(s, addr + 0x3c0, val);
2518
    }
2519
}
2520

    
2521
static void cirrus_mmio_writew(void *opaque, target_phys_addr_t addr,
2522
                               uint32_t val)
2523
{
2524
#ifdef TARGET_WORDS_BIGENDIAN
2525
    cirrus_mmio_writeb(opaque, addr, (val >> 8) & 0xff);
2526
    cirrus_mmio_writeb(opaque, addr + 1, val & 0xff);
2527
#else
2528
    cirrus_mmio_writeb(opaque, addr, val & 0xff);
2529
    cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2530
#endif
2531
}
2532

    
2533
static void cirrus_mmio_writel(void *opaque, target_phys_addr_t addr,
2534
                               uint32_t val)
2535
{
2536
#ifdef TARGET_WORDS_BIGENDIAN
2537
    cirrus_mmio_writeb(opaque, addr, (val >> 24) & 0xff);
2538
    cirrus_mmio_writeb(opaque, addr + 1, (val >> 16) & 0xff);
2539
    cirrus_mmio_writeb(opaque, addr + 2, (val >> 8) & 0xff);
2540
    cirrus_mmio_writeb(opaque, addr + 3, val & 0xff);
2541
#else
2542
    cirrus_mmio_writeb(opaque, addr, val & 0xff);
2543
    cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
2544
    cirrus_mmio_writeb(opaque, addr + 2, (val >> 16) & 0xff);
2545
    cirrus_mmio_writeb(opaque, addr + 3, (val >> 24) & 0xff);
2546
#endif
2547
}
2548

    
2549

    
2550
static CPUReadMemoryFunc *cirrus_mmio_read[3] = {
2551
    cirrus_mmio_readb,
2552
    cirrus_mmio_readw,
2553
    cirrus_mmio_readl,
2554
};
2555

    
2556
static CPUWriteMemoryFunc *cirrus_mmio_write[3] = {
2557
    cirrus_mmio_writeb,
2558
    cirrus_mmio_writew,
2559
    cirrus_mmio_writel,
2560
};
2561

    
2562
/***************************************
2563
 *
2564
 *  initialize
2565
 *
2566
 ***************************************/
2567

    
2568
static void cirrus_init_common(CirrusVGAState * s)
2569
{
2570
    int vga_io_memory;
2571

    
2572
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2573

    
2574
    register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
2575
    register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
2576
    register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
2577
    register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
2578

    
2579
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2580

    
2581
    register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
2582
    register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
2583
    register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
2584
    register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
2585

    
2586
    vga_io_memory = cpu_register_io_memory(0, cirrus_vga_mem_read, 
2587
                                           cirrus_vga_mem_write, s);
2588
    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000, 
2589
                                 vga_io_memory);
2590

    
2591
    s->sr[0x06] = 0x0f;
2592
    s->sr[0x0F] = CIRRUS_MEMSIZE_2M;
2593
    s->sr[0x1F] = 0x22;                // MemClock
2594

    
2595
    s->cr[0x27] = CIRRUS_ID_CLGD5430;
2596

    
2597
    s->cirrus_hidden_dac_lockindex = 5;
2598
    s->cirrus_hidden_dac_data = 0;
2599

    
2600
    /* I/O handler for LFB */
2601
    s->cirrus_linear_io_addr =
2602
        cpu_register_io_memory(0, cirrus_linear_read, cirrus_linear_write,
2603
                               s);
2604
    /* I/O handler for memory-mapped I/O */
2605
    s->cirrus_mmio_io_addr =
2606
        cpu_register_io_memory(0, cirrus_mmio_read, cirrus_mmio_write, s);
2607

    
2608
    /* XXX: s->vram_size must be a power of two */
2609
    s->cirrus_addr_mask = s->vram_size - 1;
2610

    
2611
    s->get_bpp = cirrus_get_bpp;
2612
    s->get_offsets = cirrus_get_offsets;
2613
}
2614

    
2615
/***************************************
2616
 *
2617
 *  ISA bus support
2618
 *
2619
 ***************************************/
2620

    
2621
void isa_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base, 
2622
                         unsigned long vga_ram_offset, int vga_ram_size)
2623
{
2624
    CirrusVGAState *s;
2625

    
2626
    s = qemu_mallocz(sizeof(CirrusVGAState));
2627
    
2628
    vga_common_init((VGAState *)s, 
2629
                    ds, vga_ram_base, vga_ram_offset, vga_ram_size);
2630
    cirrus_init_common(s);
2631
    s->sr[0x17] = CIRRUS_BUSTYPE_ISA;
2632
    /* XXX ISA-LFB support */
2633
}
2634

    
2635
/***************************************
2636
 *
2637
 *  PCI bus support
2638
 *
2639
 ***************************************/
2640

    
2641
static void cirrus_pci_lfb_map(PCIDevice *d, int region_num,
2642
                               uint32_t addr, uint32_t size, int type)
2643
{
2644
    CirrusVGAState *s = &((PCICirrusVGAState *)d)->cirrus_vga;
2645

    
2646
    cpu_register_physical_memory(addr, s->vram_size,
2647
                                 s->cirrus_linear_io_addr);
2648
}
2649

    
2650
static void cirrus_pci_mmio_map(PCIDevice *d, int region_num,
2651
                                uint32_t addr, uint32_t size, int type)
2652
{
2653
    CirrusVGAState *s = &((PCICirrusVGAState *)d)->cirrus_vga;
2654

    
2655
    cpu_register_physical_memory(addr, CIRRUS_PNPMMIO_SIZE,
2656
                                 s->cirrus_mmio_io_addr);
2657
}
2658

    
2659
void pci_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base, 
2660
                         unsigned long vga_ram_offset, int vga_ram_size)
2661
{
2662
    PCICirrusVGAState *d;
2663
    uint8_t *pci_conf;
2664
    CirrusVGAState *s;
2665

    
2666
    /* setup PCI configuration registers */
2667
    d = (PCICirrusVGAState *)pci_register_device("Cirrus VGA", 
2668
                                                 sizeof(PCICirrusVGAState), 
2669
                                                 0, -1, NULL, NULL);
2670
    pci_conf = d->dev.config;
2671
    pci_conf[0x00] = (uint8_t) (PCI_VENDOR_CIRRUS & 0xff);
2672
    pci_conf[0x01] = (uint8_t) (PCI_VENDOR_CIRRUS >> 8);
2673
    pci_conf[0x02] = (uint8_t) (PCI_DEVICE_CLGD5430 & 0xff);
2674
    pci_conf[0x03] = (uint8_t) (PCI_DEVICE_CLGD5430 >> 8);
2675
    pci_conf[0x04] = PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS;
2676
    pci_conf[0x0a] = PCI_CLASS_SUB_VGA;
2677
    pci_conf[0x0b] = PCI_CLASS_BASE_DISPLAY;
2678
    pci_conf[0x0e] = PCI_CLASS_HEADERTYPE_00h;
2679

    
2680
    /* setup VGA */
2681
    s = &d->cirrus_vga;
2682
    vga_common_init((VGAState *)s, 
2683
                    ds, vga_ram_base, vga_ram_offset, vga_ram_size);
2684
    cirrus_init_common(s);
2685
    s->sr[0x17] = CIRRUS_BUSTYPE_PCI;
2686

    
2687
    /* setup memory space */
2688
    /* memory #0 LFB */
2689
    /* memory #1 memory-mapped I/O */
2690
    /* XXX: s->vram_size must be a power of two */
2691
    pci_register_io_region((PCIDevice *)d, 0, s->vram_size,
2692
                           PCI_ADDRESS_SPACE_MEM, cirrus_pci_lfb_map);
2693
    pci_register_io_region((PCIDevice *)d, 1, CIRRUS_PNPMMIO_SIZE,
2694
                           PCI_ADDRESS_SPACE_MEM, cirrus_pci_mmio_map);
2695
    /* XXX: ROM BIOS */
2696
}