Revision e6e5ad80

b/hw/cirrus_vga.c
1
/*
2
 * QEMU Cirrus VGA Emulator.
3
 * 
4
 * Copyright (c) 2004 Fabrice Bellard
5
 * Copyright (c) 2004 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
#include "vl.h"
26
#include "vga_int.h"
27

  
28
/***************************************
29
 *
30
 *  definitions
31
 *
32
 ***************************************/
33

  
34
#define qemu_MIN(a,b) ((a) < (b) ? (a) : (b))
35

  
36
// ID
37
#define CIRRUS_ID_CLGD5422  (0x23<<2)
38
#define CIRRUS_ID_CLGD5426  (0x24<<2)
39
#define CIRRUS_ID_CLGD5424  (0x25<<2)
40
#define CIRRUS_ID_CLGD5428  (0x26<<2)
41
#define CIRRUS_ID_CLGD5430  (0x28<<2)
42
#define CIRRUS_ID_CLGD5434  (0x2A<<2)
43
#define CIRRUS_ID_CLGD5446  (0x2E<<2)
44

  
45
// sequencer 0x07
46
#define CIRRUS_SR7_BPP_VGA            0x00
47
#define CIRRUS_SR7_BPP_SVGA           0x01
48
#define CIRRUS_SR7_BPP_MASK           0x0e
49
#define CIRRUS_SR7_BPP_8              0x00
50
#define CIRRUS_SR7_BPP_16_DOUBLEVCLK  0x02
51
#define CIRRUS_SR7_BPP_24             0x04
52
#define CIRRUS_SR7_BPP_16             0x06
53
#define CIRRUS_SR7_BPP_32             0x08
54
#define CIRRUS_SR7_ISAADDR_MASK       0xe0
55

  
56
// sequencer 0x0f
57
#define CIRRUS_MEMSIZE_512k        0x08
58
#define CIRRUS_MEMSIZE_1M          0x10
59
#define CIRRUS_MEMSIZE_2M          0x18
60
#define CIRRUS_MEMFLAGS_BANKSWITCH 0x80	// bank switching is enabled.
61

  
62
// sequencer 0x12
63
#define CIRRUS_CURSOR_SHOW         0x01
64
#define CIRRUS_CURSOR_HIDDENPEL    0x02
65
#define CIRRUS_CURSOR_LARGE        0x04	// 64x64 if set, 32x32 if clear
66

  
67
// sequencer 0x17
68
#define CIRRUS_BUSTYPE_VLBFAST   0x10
69
#define CIRRUS_BUSTYPE_PCI       0x20
70
#define CIRRUS_BUSTYPE_VLBSLOW   0x30
71
#define CIRRUS_BUSTYPE_ISA       0x38
72
#define CIRRUS_MMIO_ENABLE       0x04
73
#define CIRRUS_MMIO_USE_PCIADDR  0x40	// 0xb8000 if cleared.
74
#define CIRRUS_MEMSIZEEXT_DOUBLE 0x80
75

  
76
// control 0x0b
77
#define CIRRUS_BANKING_DUAL             0x01
78
#define CIRRUS_BANKING_GRANULARITY_16K  0x20	// set:16k, clear:4k
79

  
80
// control 0x30
81
#define CIRRUS_BLTMODE_BACKWARDS        0x01
82
#define CIRRUS_BLTMODE_MEMSYSDEST       0x02
83
#define CIRRUS_BLTMODE_MEMSYSSRC        0x04
84
#define CIRRUS_BLTMODE_TRANSPARENTCOMP  0x08
85
#define CIRRUS_BLTMODE_PATTERNCOPY      0x40
86
#define CIRRUS_BLTMODE_COLOREXPAND      0x80
87
#define CIRRUS_BLTMODE_PIXELWIDTHMASK   0x30
88
#define CIRRUS_BLTMODE_PIXELWIDTH8      0x00
89
#define CIRRUS_BLTMODE_PIXELWIDTH16     0x10
90
#define CIRRUS_BLTMODE_PIXELWIDTH24     0x20
91
#define CIRRUS_BLTMODE_PIXELWIDTH32     0x30
92

  
93
// control 0x31
94
#define CIRRUS_BLT_BUSY                 0x01
95
#define CIRRUS_BLT_START                0x02
96
#define CIRRUS_BLT_RESET                0x04
97
#define CIRRUS_BLT_FIFOUSED             0x10
98

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

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

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

  
192
#define CIRRUS_PNPMMIO_SIZE         0x800
193

  
194

  
195
/* I/O and memory hook */
196
#define CIRRUS_HOOK_NOT_HANDLED 0
197
#define CIRRUS_HOOK_HANDLED 1
198

  
199
typedef void (*cirrus_bitblt_rop_t) (uint8_t * dst, const uint8_t * src,
200
				     int dstpitch, int srcpitch,
201
				     int bltwidth, int bltheight);
202

  
203
typedef void (*cirrus_bitblt_handler_t) (void *opaque);
204

  
205
typedef struct CirrusVGAState {
206
    /* XXX: we use the anonymous struct/union gcc 3.x extension */
207
    struct VGAState;
208

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

  
242
typedef struct PCICirrusVGAState {
243
    PCIDevice dev;
244
    CirrusVGAState cirrus_vga;
245
} PCICirrusVGAState;
246

  
247
/***************************************
248
 *
249
 *  prototypes.
250
 *
251
 ***************************************/
252

  
253

  
254
static void cirrus_bitblt_reset(CirrusVGAState * s);
255

  
256
/***************************************
257
 *
258
 *  raster operations
259
 *
260
 ***************************************/
261

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

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

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

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

  
338
static cirrus_bitblt_rop_t cirrus_get_fwd_rop_handler(uint8_t rop)
339
{
340
    cirrus_bitblt_rop_t rop_handler = cirrus_bitblt_rop_fwd_nop;
341

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

  
398
    return rop_handler;
399
}
400

  
401
static cirrus_bitblt_rop_t cirrus_get_bkwd_rop_handler(uint8_t rop)
402
{
403
    cirrus_bitblt_rop_t rop_handler = cirrus_bitblt_rop_bkwd_nop;
404

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

  
461
    return rop_handler;
462
}
463

  
464
/***************************************
465
 *
466
 *  color expansion
467
 *
468
 ***************************************/
469

  
470
static void
471
cirrus_colorexpand_8(CirrusVGAState * s, uint8_t * dst,
472
		     const uint8_t * src, int count)
473
{
474
    int x;
475
    uint8_t colors[2];
476
    unsigned bits;
477
    unsigned bitmask;
478
    int srcskipleft = 0;
479

  
480
    colors[0] = s->gr[0x00];
481
    colors[1] = s->gr[0x01];
482

  
483
    bitmask = 0x80 >> srcskipleft;
484
    bits = *src++;
485
    for (x = 0; x < count; x++) {
486
	if ((bitmask & 0xff) == 0) {
487
	    bitmask = 0x80;
488
	    bits = *src++;
489
	}
490
	*dst++ = colors[!!(bits & bitmask)];
491
	bitmask >>= 1;
492
    }
493
}
494

  
495
static void
496
cirrus_colorexpand_16(CirrusVGAState * s, uint8_t * dst,
497
		      const uint8_t * src, int count)
498
{
499
    int x;
500
    uint8_t colors[2][2];
501
    unsigned bits;
502
    unsigned bitmask;
503
    unsigned index;
504
    int srcskipleft = 0;
505

  
506
    colors[0][0] = s->gr[0x00];
507
    colors[0][1] = s->gr[0x10];
508
    colors[1][0] = s->gr[0x01];
509
    colors[1][1] = s->gr[0x11];
510

  
511
    bitmask = 0x80 >> srcskipleft;
512
    bits = *src++;
513
    for (x = 0; x < count; x++) {
514
	if ((bitmask & 0xff) == 0) {
515
	    bitmask = 0x80;
516
	    bits = *src++;
517
	}
518
	index = !!(bits & bitmask);
519
	*dst++ = colors[index][0];
520
	*dst++ = colors[index][1];
521
	bitmask >>= 1;
522
    }
523
}
524

  
525
static void
526
cirrus_colorexpand_24(CirrusVGAState * s, uint8_t * dst,
527
		      const uint8_t * src, int count)
528
{
529
    int x;
530
    uint8_t colors[2][3];
531
    unsigned bits;
532
    unsigned bitmask;
533
    unsigned index;
534
    int srcskipleft = 0;
535

  
536
    colors[0][0] = s->gr[0x00];
537
    colors[0][1] = s->gr[0x10];
538
    colors[0][2] = s->gr[0x12];
539
    colors[1][0] = s->gr[0x01];
540
    colors[1][1] = s->gr[0x11];
541
    colors[1][2] = s->gr[0x13];
542

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

  
558
static void
559
cirrus_colorexpand_32(CirrusVGAState * s, uint8_t * dst,
560
		      const uint8_t * src, int count)
561
{
562
    int x;
563
    uint8_t colors[2][4];
564
    unsigned bits;
565
    unsigned bitmask;
566
    unsigned index;
567
    int srcskipleft = 0;
568

  
569
    colors[0][0] = s->gr[0x00];
570
    colors[0][1] = s->gr[0x10];
571
    colors[0][2] = s->gr[0x12];
572
    colors[0][3] = s->gr[0x14];
573
    colors[1][0] = s->gr[0x01];
574
    colors[1][1] = s->gr[0x11];
575
    colors[1][2] = s->gr[0x13];
576
    colors[1][3] = s->gr[0x15];
577

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

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

  
620
static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin,
621
				     int off_pitch, int bytesperline,
622
				     int lines)
623
{
624
    int y;
625
    int off_cur;
626
    int off_cur_end;
627

  
628
    for (y = 0; y < lines; y++) {
629
	off_cur = off_begin;
630
	off_cur_end = off_cur + bytesperline;
631
	off_cur &= TARGET_PAGE_MASK;
632
	while (off_cur < off_cur_end) {
633
	    cpu_physical_memory_set_dirty(s->vram_offset + off_cur);
634
	    off_cur += TARGET_PAGE_SIZE;
635
	}
636
	off_begin += off_pitch;
637
    }
638
}
639

  
640

  
641

  
642
static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s,
643
					    const uint8_t * src)
644
{
645
    uint8_t work_colorexp[256];
646
    uint8_t *dst;
647
    uint8_t *dstc;
648
    int x, y;
649
    int tilewidth, tileheight;
650
    int patternbytes = s->cirrus_blt_pixelwidth * 8;
651

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

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

  
684
/***************************************
685
 *
686
 *  bitblt (video-to-video)
687
 *
688
 ***************************************/
689

  
690
static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
691
{
692
    return cirrus_bitblt_common_patterncopy(s,
693
					    s->vram_ptr +
694
					    s->cirrus_blt_srcaddr);
695
}
696

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

  
713
    (*s->cirrus_rop) (s->vram_ptr + s->cirrus_blt_dstaddr,
714
		      s->vram_ptr + s->cirrus_blt_srcaddr,
715
		      s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
716
		      s->cirrus_blt_width, s->cirrus_blt_height);
717
    cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
718
			     s->cirrus_blt_dstpitch, s->cirrus_blt_width,
719
			     s->cirrus_blt_height);
720
    return 1;
721
}
722

  
723
/***************************************
724
 *
725
 *  bitblt (cpu-to-video)
726
 *
727
 ***************************************/
728

  
729
static void cirrus_bitblt_cputovideo_patterncopy(void *opaque)
730
{
731
    CirrusVGAState *s = (CirrusVGAState *) opaque;
732
    int data_count;
733

  
734
    data_count = s->cirrus_srcptr - &s->cirrus_bltbuf[0];
735

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

  
748
static void cirrus_bitblt_cputovideo_copy(void *opaque)
749
{
750
    CirrusVGAState *s = (CirrusVGAState *) opaque;
751
    int data_count;
752
    int data_avail;
753
    uint8_t work_colorexp[256];
754
    uint8_t *src_ptr = NULL;
755
    int src_avail = 0;
756
    int src_processing;
757
    int src_linepad = 0;
758

  
759
    if (s->cirrus_blt_height <= 0) {
760
	s->cirrus_srcptr = s->cirrus_srcptr_end;
761
	return;
762
    }
763

  
764
    s->cirrus_srcptr = &s->cirrus_bltbuf[0];
765
    while (1) {
766
	/* get BLT source. */
767
	if (src_avail <= 0) {
768
	    data_count = s->cirrus_srcptr_end - s->cirrus_srcptr;
769
	    if (data_count <= 0)
770
		break;
771

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

  
808
	/* 1-line BLT */
809
	src_processing =
810
	    s->cirrus_blt_srcpitch - s->cirrus_blt_horz_counter;
811
	src_processing = qemu_MIN(src_avail, src_processing);
812
	(*s->cirrus_rop) (s->vram_ptr + s->cirrus_blt_dstaddr,
813
			  src_ptr, 0, 0, src_processing, 1);
814
	cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0,
815
				 src_processing, 1);
816

  
817
	s->cirrus_blt_dstaddr += src_processing;
818
	src_ptr += src_processing;
819
	src_avail -= src_processing;
820
	s->cirrus_blt_horz_counter += src_processing;
821
	if (s->cirrus_blt_horz_counter >= s->cirrus_blt_srcpitch) {
822
	    src_ptr += src_linepad;
823
	    src_avail -= src_linepad;
824
	    s->cirrus_blt_dstaddr +=
825
		s->cirrus_blt_dstpitch - s->cirrus_blt_srcpitch;
826
	    s->cirrus_blt_horz_counter = 0;
827
	    s->cirrus_blt_height--;
828
	    if (s->cirrus_blt_height <= 0) {
829
		s->cirrus_srcptr = s->cirrus_srcptr_end;
830
		return;
831
	    }
832
	}
833
    }
834
}
835

  
836
static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s)
837
{
838
    int copy_count;
839
    int avail_count;
840

  
841
    s->cirrus_blt_handler(s);
842

  
843
    if (s->cirrus_srccounter > 0) {
844
	s->cirrus_srccounter -= s->cirrus_srcptr - &s->cirrus_bltbuf[0];
845
	copy_count = s->cirrus_srcptr_end - s->cirrus_srcptr;
846
	memmove(&s->cirrus_bltbuf[0], s->cirrus_srcptr, copy_count);
847
	avail_count = qemu_MIN(CIRRUS_BLTBUFSIZE, s->cirrus_srccounter);
848
	s->cirrus_srcptr = &s->cirrus_bltbuf[0];
849
	s->cirrus_srcptr_end = s->cirrus_srcptr + avail_count;
850
	if (s->cirrus_srccounter <= 0) {
851
	    cirrus_bitblt_reset(s);
852
	}
853
    }
854
}
855

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

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

  
875
static int cirrus_bitblt_cputovideo(CirrusVGAState * s)
876
{
877
    s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_MEMSYSSRC;
878
    s->cirrus_srcptr = &s->cirrus_bltbuf[0];
879
    s->cirrus_srcptr_end = &s->cirrus_bltbuf[0];
880

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

  
903
	s->cirrus_blt_handler = cirrus_bitblt_cputovideo_copy;
904
	s->cirrus_blt_horz_counter = 0;
905
    }
906

  
907
    cirrus_bitblt_cputovideo_next(s);
908
    return 1;
909
}
910

  
911
static int cirrus_bitblt_videotocpu(CirrusVGAState * s)
912
{
913
    /* XXX */
914
#ifdef DEBUG_CIRRUS
915
    printf("cirrus: bitblt (video to cpu) is not implemented yet\n");
916
#endif
917
    return 0;
918
}
919

  
920
static int cirrus_bitblt_videotovideo(CirrusVGAState * s)
921
{
922
    int ret;
923

  
924
    if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
925
	ret = cirrus_bitblt_videotovideo_patterncopy(s);
926
    } else {
927
	ret = cirrus_bitblt_videotovideo_copy(s);
928
    }
929

  
930
    if (ret)
931
	cirrus_bitblt_reset(s);
932
    return ret;
933
}
934

  
935
static void cirrus_bitblt_start(CirrusVGAState * s)
936
{
937
    uint8_t blt_rop;
938

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

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

  
971
    if ((s->
972
	 cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSSRC |
973
			    CIRRUS_BLTMODE_MEMSYSDEST))
974
	== (CIRRUS_BLTMODE_MEMSYSSRC | CIRRUS_BLTMODE_MEMSYSDEST)) {
975
#ifdef DEBUG_CIRRUS
976
	printf("cirrus: bitblt - memory-to-memory copy is requested\n");
977
#endif
978
	goto bitblt_ignore;
979
    }
980

  
981
    if (s->cirrus_blt_mode & CIRRUS_BLTMODE_BACKWARDS) {
982
	s->cirrus_blt_dstpitch = -s->cirrus_blt_dstpitch;
983
	s->cirrus_blt_srcpitch = -s->cirrus_blt_srcpitch;
984
	s->cirrus_rop = cirrus_get_bkwd_rop_handler(blt_rop);
985
    } else {
986
	s->cirrus_rop = cirrus_get_fwd_rop_handler(blt_rop);
987
    }
988

  
989
    // setup bitblt engine.
990
    if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSSRC) {
991
	if (!cirrus_bitblt_cputovideo(s))
992
	    goto bitblt_ignore;
993
    } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST) {
994
	if (!cirrus_bitblt_videotocpu(s))
995
	    goto bitblt_ignore;
996
    } else {
997
	if (!cirrus_bitblt_videotovideo(s))
998
	    goto bitblt_ignore;
999
    }
1000

  
1001
    return;
1002
  bitblt_ignore:;
1003
    cirrus_bitblt_reset(s);
1004
}
1005

  
1006
static void cirrus_write_bitblt(CirrusVGAState * s, unsigned reg_value)
1007
{
1008
    unsigned old_value;
1009

  
1010
    old_value = s->gr[0x31];
1011
    s->gr[0x31] = reg_value;
1012

  
1013
    if (((old_value & CIRRUS_BLT_RESET) != 0) &&
1014
	((reg_value & CIRRUS_BLT_RESET) == 0)) {
1015
	cirrus_bitblt_reset(s);
1016
    } else if (((old_value & CIRRUS_BLT_START) == 0) &&
1017
	       ((reg_value & CIRRUS_BLT_START) != 0)) {
1018
	s->gr[0x31] |= CIRRUS_BLT_BUSY;
1019
	cirrus_bitblt_start(s);
1020
    }
1021
}
1022

  
1023

  
1024
/***************************************
1025
 *
1026
 *  basic parameters
1027
 *
1028
 ***************************************/
1029

  
1030
static void cirrus_get_offsets(VGAState *s1, 
1031
                                   uint32_t *pline_offset,
1032
                                   uint32_t *pstart_addr)
1033
{
1034
    CirrusVGAState * s = (CirrusVGAState *)s1;
1035
    uint32_t start_addr;
1036
    uint32_t line_offset;
1037

  
1038
    line_offset = s->cr[0x13]
1039
	| ((s->cr[0x1b] & 0x10) << 8);
1040
    line_offset <<= 3;
1041
    *pline_offset = line_offset;
1042

  
1043
    start_addr = (s->cr[0x0c] << 8)
1044
	| s->cr[0x0d]
1045
	| ((s->cr[0x1b] & 0x01) << 16)
1046
	| ((s->cr[0x1b] & 0x0c) << 15)
1047
	| ((s->cr[0x1d] & 0x80) << 12);
1048
    *pstart_addr = start_addr;
1049
}
1050

  
1051
static uint32_t cirrus_get_bpp16_depth(CirrusVGAState * s)
1052
{
1053
    uint32_t ret = 16;
1054

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

  
1073
static int cirrus_get_bpp(VGAState *s1)
1074
{
1075
    CirrusVGAState * s = (CirrusVGAState *)s1;
1076
    uint32_t ret = 8;
1077

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

  
1108
    return ret;
1109
}
1110

  
1111
/***************************************
1112
 *
1113
 * bank memory
1114
 *
1115
 ***************************************/
1116

  
1117
static void cirrus_update_bank_ptr(CirrusVGAState * s, unsigned bank_index)
1118
{
1119
    unsigned offset;
1120
    unsigned limit;
1121

  
1122
    if ((s->gr[0x0b] & 0x01) != 0)	/* dual bank */
1123
	offset = s->gr[0x09 + bank_index];
1124
    else			/* single bank */
1125
	offset = s->gr[0x09];
1126

  
1127
    if ((s->gr[0x0b] & 0x20) != 0)
1128
	offset <<= 14;
1129
    else
1130
	offset <<= 12;
1131

  
1132
    if (s->vram_size <= offset)
1133
	limit = 0;
1134
    else
1135
	limit = s->vram_size - offset;
1136

  
1137
    if (((s->gr[0x0b] & 0x01) == 0) && (bank_index != 0)) {
1138
	if (limit > 0x8000) {
1139
	    offset += 0x8000;
1140
	    limit -= 0x8000;
1141
	} else {
1142
	    limit = 0;
1143
	}
1144
    }
1145

  
1146
    if (limit > 0) {
1147
	s->cirrus_bank_base[bank_index] = offset;
1148
	s->cirrus_bank_limit[bank_index] = limit;
1149
    } else {
1150
	s->cirrus_bank_base[bank_index] = 0;
1151
	s->cirrus_bank_limit[bank_index] = 0;
1152
    }
1153
}
1154

  
1155
/***************************************
1156
 *
1157
 *  I/O access between 0x3c4-0x3c5
1158
 *
1159
 ***************************************/
1160

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

  
1227
    return CIRRUS_HOOK_HANDLED;
1228
}
1229

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

  
1307
    return CIRRUS_HOOK_HANDLED;
1308
}
1309

  
1310
/***************************************
1311
 *
1312
 *  I/O access at 0x3c6
1313
 *
1314
 ***************************************/
1315

  
1316
static void cirrus_read_hidden_dac(CirrusVGAState * s, int *reg_value)
1317
{
1318
    *reg_value = 0xff;
1319
    if (s->cirrus_hidden_dac_lockindex < 5) {
1320
	if (s->cirrus_hidden_dac_lockindex == 4) {
1321
	    *reg_value = s->cirrus_hidden_dac_data;
1322
	}
1323
	s->cirrus_hidden_dac_lockindex++;
1324
    }
1325
}
1326

  
1327
static void cirrus_write_hidden_dac(CirrusVGAState * s, int reg_value)
1328
{
1329
    if (s->cirrus_hidden_dac_lockindex == 4) {
1330
	s->cirrus_hidden_dac_data = reg_value;
1331
#ifdef DEBUG_CIRRUS
1332
	printf("cirrus: outport hidden DAC, value %02x\n", reg_value);
1333
#endif
1334
    }
1335
    s->cirrus_hidden_dac_lockindex = 0;
1336
}
1337

  
1338
/***************************************
1339
 *
1340
 *  I/O access at 0x3c9
1341
 *
1342
 ***************************************/
1343

  
1344
static int cirrus_hook_read_palette(CirrusVGAState * s, int *reg_value)
1345
{
1346
    if (!(s->sr[0x12] & CIRRUS_CURSOR_HIDDENPEL))
1347
	return CIRRUS_HOOK_NOT_HANDLED;
1348
    if (s->dac_read_index < 0x10) {
1349
	*reg_value =
1350
	    s->cirrus_hidden_palette[s->dac_read_index * 3 +
1351
				     s->dac_sub_index];
1352
    } else {
1353
	*reg_value = 0xff;	/* XXX */
1354
    }
1355
    if (++s->dac_sub_index == 3) {
1356
	s->dac_sub_index = 0;
1357
	s->dac_read_index++;
1358
    }
1359
    return CIRRUS_HOOK_HANDLED;
1360
}
1361

  
1362
static int cirrus_hook_write_palette(CirrusVGAState * s, int reg_value)
1363
{
1364
    if (!(s->sr[0x12] & CIRRUS_CURSOR_HIDDENPEL))
1365
	return CIRRUS_HOOK_NOT_HANDLED;
1366
    s->dac_cache[s->dac_sub_index] = reg_value;
1367
    if (++s->dac_sub_index == 3) {
1368
	if (s->dac_read_index < 0x10) {
1369
	    memcpy(&s->cirrus_hidden_palette[s->dac_write_index * 3],
1370
		   s->dac_cache, 3);
1371
	    /* XXX update cursor */
1372
	}
1373
	s->dac_sub_index = 0;
1374
	s->dac_write_index++;
1375
    }
1376
    return CIRRUS_HOOK_HANDLED;
1377
}
1378

  
1379
/***************************************
1380
 *
1381
 *  I/O access between 0x3ce-0x3cf
1382
 *
1383
 ***************************************/
1384

  
1385
static int
1386
cirrus_hook_read_gr(CirrusVGAState * s, unsigned reg_index, int *reg_value)
1387
{
1388
    switch (reg_index) {
1389
    case 0x02:			// Standard VGA
1390
    case 0x03:			// Standard VGA
1391
    case 0x04:			// Standard VGA
1392
    case 0x06:			// Standard VGA
1393
    case 0x07:			// Standard VGA
1394
    case 0x08:			// Standard VGA
1395
	return CIRRUS_HOOK_NOT_HANDLED;
1396
    case 0x05:			// Standard VGA, Cirrus extended mode
1397
    default:
1398
	break;
1399
    }
1400

  
1401
    if (reg_index < 0x3a) {
1402
	*reg_value = s->gr[reg_index];
1403
    } else {
1404
#ifdef DEBUG_CIRRUS
1405
	printf("cirrus: inport gr_index %02x\n", reg_index);
1406
#endif
1407
	*reg_value = 0xff;
1408
    }
1409

  
1410
    return CIRRUS_HOOK_HANDLED;
1411
}
1412

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

  
1483
    return CIRRUS_HOOK_HANDLED;
1484
}
1485

  
1486
/***************************************
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff