summaryrefslogtreecommitdiff
path: root/hw/kdrive/savage/s3.h
blob: 86e1863b45994f71f453fa6121f42b3098f89822 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
/*
 * Id: s3.h,v 1.2 1999/11/02 08:17:24 keithp Exp $
 *
 * Copyright 1999 SuSE, Inc.
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of SuSE not be used in advertising or
 * publicity pertaining to distribution of the software without specific,
 * written prior permission.  SuSE makes no representations about the
 * suitability of this software for any purpose.  It is provided "as is"
 * without express or implied warranty.
 *
 * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Author:  Keith Packard, SuSE, Inc.
 */
/* $RCSId: xc/programs/Xserver/hw/kdrive/savage/s3.h,v 1.4 2000/05/06 22:17:45 keithp Exp $ */

#ifndef _S3_H_
#define _S3_H_

#include "kdrive.h"
#include "s3reg.h"

/* VESA Approved Register Definitions */

/*
 *  Linear Addressing		000 0000 - 0ff ffff (16m)
 *  Image data transfer		100 0000 - 100 7fff (32k)
 *  PCI config			100 8000 - 100 8043
 *  Packed enhanced regs	100 8100 - 100 814a
 *  Streams regs		100 8180 - 100 81ff
 *  Current Y pos		100 82e8
 *  CRT VGA 3b? regs		100 83b0 - 100 83bf
 *  CRT VGA 3c? regs		100 83c0 - 100 83cf
 *  CRT VGA 3d? regs		100 83d0 - 100 83df
 *  Subsystem status (42e8h)	100 8504
 *  Advanced function (42e8h)	100 850c
 *  Enhanced regs		100 86e8 - 100 eeea
 *  Local peripheral bus	100 ff00 - 100 ff5c
 *
 * We don't care about the image transfer or PCI regs, so
 * this structure starts at the packed enhanced regs
 */
    
typedef volatile CARD32 VOL32;
typedef volatile CARD16 VOL16;
typedef volatile CARD8 VOL8;

typedef volatile struct _s3 {
    VOL32	alt_curxy;		/* 8100 */
    VOL32	_pad0;			/* 8104 */
    VOL32	alt_step;		/* 8108 */
    VOL32	_pad1;			/* 810c */
    VOL32	err_term;		/* 8110 */
    VOL32	_pad2;			/* 8114 */
    VOL32	cmd_gp_stat; 		/* 8118 */
    VOL32	short_stroke;		/* 811c */
    VOL32	bg;			/* 8120 */
    VOL32	fg;			/* 8124 */
    VOL32	write_mask;		/* 8128 */
    VOL32	read_mask;		/* 812c */
    VOL32	color_cmp;		/* 8130 */
    VOL32	alt_mix;		/* 8134 */
    VOL32	scissors_tl;		/* 8138 */
    VOL32	scissors_br;		/* 813c */
#if 0
    VOL16	pix_cntl;		/* 8140 */
    VOL16	mult_misc2;		/* 8142 */
#else
    VOL32	pix_cntl_mult_misc2;	/* 8140 */
#endif
    VOL32	mult_misc_read_sel;	/* 8144 */
    VOL32	alt_pcnt;		/* 8148 min_axis_pcnt, maj_axis_pcnt */
    VOL8	_pad3a[0x1c];		/* 814c */
    VOL32	global_bitmap_1;	/* 8168 */
    VOL32	global_bitmap_2;	/* 816c */
    VOL32	primary_bitmap_1;	/* 8170 */
    VOL32	primary_bitmap_2;	/* 8174 */
    VOL32	secondary_bitmap_1;	/* 8178 */
    VOL32	secondary_bitmap_2;	/* 817c */
    VOL32	primary_stream_control;	/* 8180 */
    VOL32	chroma_key_control;	/* 8184 */
    VOL32	genlocking_control;	/* 8188 */
    VOL8	_pad3b[0x4];		/* 818c */
    VOL32	secondary_stream_control;   /* 8190 */
    VOL32	chroma_key_upper_bound;	/* 8194 */
    VOL32	secondary_stream_h_scale;   /* 8198 */
    VOL32	color_adjustment;	/* 819c */
    VOL32	blend_control;		/* 81a0 */
    VOL8	_pad3c[0x1c];		/* 81a4 */
    VOL32	primary_stream_addr_0;	/* 81c0 */
    VOL32	primary_stream_addr_1;	/* 81c4 */
    VOL32	primary_stream_stride;	/* 81c8 */
    VOL32       secondary_stream_mbuf;	/* 81cc */
    VOL32       secondary_stream_addr_0;/* 81d0 */
    VOL32       secondary_stream_addr_1;/* 81d4 */
    VOL32       secondary_stream_stride;/* 81d8 */
    VOL8	_pad81dc[4];		/* 81dc */
    VOL32       secondary_stream_vscale;/* 81e0 */
    VOL32       secondary_stream_vinit;	/* 81e4 */
    VOL32       secondary_stream_scount;/* 81e8 */
    VOL32       streams_fifo;		/* 81ec */
    VOL32       primary_stream_xy;	/* 81f0 */
    VOL32       primary_stream_size;	/* 81f4 */
    VOL32	secondary_stream_xy;	/* 81f8 */
    VOL32	secondary_stream_size;	/* 81fc */
    VOL8	_pad8200[0xe8];		/* 8200 */
    VOL32	cur_y;			/* 82e8 */
    VOL8	_pad4[0x14];		/* 82ec */
    VOL32	primary_stream_mem;	/* 8300 */
    VOL32	secondary_stream_mem;	/* 8304 */
    VOL8	_pad8308[0xD2];		/* 8308 */
    VOL8	input_status_1;		/* 83da */
    VOL8	_pad83db[0x131];	/* 83db */
    VOL32	adv_func_cntl;		/* 850c */
    VOL8	_pad8510[0x5dd8];	/* 8510 */
    VOL32	pix_trans;		/* e2e8 */
    VOL8	_pade2ec[0x3a92c];	/*  e2ec */
    VOL32	cmd_overflow_buf_ptr;	/* 48c18 */
    VOL8	_pad48c1c[0x8];		/* 48c1c */
    VOL32	bci_power_management;	/* 48c24 */
    VOL8	_pad48c28[0x38];	/* 48c28 */
    VOL32	alt_status_0;		/* 48c60 */
    VOL32	alt_status_1;		/* 48c64 */
} S3, *S3Ptr;

#define VGA_STATUS_1_DTM    0x01
#define VGA_STATUS_1_VSY    0x08

#define	DAC_MASK	0x03c6
#define	DAC_R_INDEX	0x03c7
#define	DAC_W_INDEX	0x03c8
#define	DAC_DATA	0x03c9
#define	DISP_STAT	0x02e8
#define	H_TOTAL		0x02e8
#define	H_DISP		0x06e8
#define	H_SYNC_STRT	0x0ae8
#define	H_SYNC_WID	0x0ee8
#define	V_TOTAL		0x12e8
#define	V_DISP		0x16e8
#define	V_SYNC_STRT	0x1ae8
#define	V_SYNC_WID	0x1ee8
#define	DISP_CNTL	0x22e8
#define	ADVFUNC_CNTL	0x4ae8
#define	SUBSYS_STAT	0x42e8
#define	SUBSYS_CNTL	0x42e8
#define	ROM_PAGE_SEL	0x46e8
#define	CUR_Y		0x82e8
#define	CUR_X		0x86e8
#define	DESTY_AXSTP	0x8ae8
#define	DESTX_DIASTP	0x8ee8
#define	ERR_TERM	0x92e8
#define	MAJ_AXIS_PCNT	0x96e8
#define	GP_STAT		0x9ae8
#define	CMD		0x9ae8
#define	SHORT_STROKE	0x9ee8
#define	BKGD_COLOR	0xa2e8
#define	FRGD_COLOR	0xa6e8
#define	WRT_MASK	0xaae8
#define	RD_MASK		0xaee8
#define	COLOR_CMP	0xb2e8
#define	BKGD_MIX	0xb6e8
#define	FRGD_MIX	0xbae8
#define	MULTIFUNC_CNTL	0xbee8
#define	MIN_AXIS_PCNT	0x0000
#define	SCISSORS_T	0x1000
#define	SCISSORS_L	0x2000
#define	SCISSORS_B	0x3000
#define	SCISSORS_R	0x4000
#define	MEM_CNTL	0x5000
#define	PATTERN_L	0x8000
#define	PATTERN_H	0x9000
#define	PIX_CNTL	0xa000
#define CONTROL_MISC2	0xd000
#define	PIX_TRANS	0xe2e8

/* Advanced Function Control Regsiter */
#define	CLKSEL		0x0004
#define	DISABPASSTHRU	0x0001

/* Graphics Processor Status Register */

#define GPNSLOT		13

#define GPBUSY_1	0x0080
#define GPBUSY_2	0x0040
#define GPBUSY_3	0x0020
#define GPBUSY_4	0x0010
#define GPBUSY_5	0x0008
#define GPBUSY_6	0x0004
#define GPBUSY_7	0x0002
#define GPBUSY_8	0x0001
#define GPBUSY_9	0x8000
#define GPBUSY_10	0x4000
#define GPBUSY_11	0x2000
#define GPBUSY_12	0x1000
#define GPBUSY_13	0x0800

#define GPEMPTY		0x0400
#define	GPBUSY		0x0200
#define	DATDRDY		0x0100

/* Command Register */
#define	CMD_NOP		0x0000
#define	CMD_LINE	0x2000
#define	CMD_RECT	0x4000
#define	CMD_RECTV1	0x6000
#define	CMD_RECTV2	0x8000
#define	CMD_LINEAF	0xa000
#define	CMD_BITBLT	0xc000
#define CMD_PATBLT	0xe000
#define	CMD_OP_MSK	0xe000
#define	BYTSEQ		0x1000
#define _32BITNOPAD	0x0600
#define _32BIT		0x0400
#define	_16BIT		0x0200
#define _8BIT		0x0000
#define	PCDATA		0x0100
#define	INC_Y		0x0080
#define	YMAJAXIS	0x0040
#define	INC_X		0x0020
#define	DRAW		0x0010
#define	LINETYPE	0x0008
#define	LASTPIX		0x0004	    /* Draw last pixel in line */
#define	PLANAR		0x0002
#define	WRTDATA		0x0001

/* Background Mix Register */
#define	BSS_BKGDCOL	0x0000
#define	BSS_FRGDCOL	0x0020
#define	BSS_PCDATA	0x0040
#define	BSS_BITBLT	0x0060

/* Foreground Mix Register */
#define	FSS_BKGDCOL	0x0000
#define	FSS_FRGDCOL	0x0020
#define	FSS_PCDATA	0x0040
#define	FSS_BITBLT	0x0060

/* The Mixes */
#define	MIX_MASK			0x001f

#define	MIX_NOT_DST			0x0000
#define	MIX_0				0x0001
#define	MIX_1				0x0002
#define	MIX_DST				0x0003
#define	MIX_NOT_SRC			0x0004
#define	MIX_XOR				0x0005
#define	MIX_XNOR			0x0006
#define	MIX_SRC				0x0007
#define	MIX_NAND			0x0008
#define	MIX_NOT_SRC_OR_DST		0x0009
#define	MIX_SRC_OR_NOT_DST		0x000a
#define	MIX_OR				0x000b
#define	MIX_AND				0x000c
#define	MIX_SRC_AND_NOT_DST		0x000d
#define	MIX_NOT_SRC_AND_DST		0x000e
#define	MIX_NOR				0x000f

#define	MIX_MIN				0x0010
#define	MIX_DST_MINUS_SRC		0x0011
#define	MIX_SRC_MINUS_DST		0x0012
#define	MIX_PLUS			0x0013
#define	MIX_MAX				0x0014
#define	MIX_HALF__DST_MINUS_SRC		0x0015
#define	MIX_HALF__SRC_MINUS_DST		0x0016
#define	MIX_AVERAGE			0x0017
#define	MIX_DST_MINUS_SRC_SAT		0x0018
#define	MIX_SRC_MINUS_DST_SAT		0x001a
#define	MIX_HALF__DST_MINUS_SRC_SAT	0x001c
#define	MIX_HALF__SRC_MINUS_DST_SAT	0x001e
#define	MIX_AVERAGE_SAT			0x001f

/* Pixel Control Register */
#define	MIXSEL_FRGDMIX	0x0000
#define	MIXSEL_PATT	0x0040
#define	MIXSEL_EXPPC	0x0080
#define	MIXSEL_EXPBLT	0x00c0
#define COLCMPOP_F	0x0000
#define COLCMPOP_T	0x0008
#define COLCMPOP_GE	0x0010
#define COLCMPOP_LT	0x0018
#define COLCMPOP_NE	0x0020
#define COLCMPOP_EQ	0x0028
#define COLCMPOP_LE	0x0030
#define COLCMPOP_GT	0x0038
#define	PLANEMODE	0x0004

/* Multifunction Control Misc 8144 */
#define MISC_DST_BA_0	(0x0 << 0)
#define MISC_DST_BA_1	(0x1 << 0)
#define MISC_DST_BA_2	(0x2 << 0)
#define MISC_DST_BA_3	(0x3 << 0)
#define MISC_SRC_BA_0	(0x0 << 2)
#define MISC_SRC_BA_1	(0x1 << 2)
#define MISC_SRC_BA_2	(0x2 << 2)
#define MISC_SRC_BA_3	(0x3 << 2)
#define MISC_RSF	(1 << 4)
#define MISC_EXT_CLIP	(1 << 5)
#define MISC_SRC_NE	(1 << 7)
#define MISC_ENB_CMP	(1 << 8)
#define MISC_32B	(1 << 9)
#define MISC_DC		(1 << 11)
#define MISC_INDEX_E	(0xe << 12)

#define S3_SAVAGE4_SLOTS    0x0001ffff
#define S3_SAVAGE4_2DI	    0x00800000

#define _s3WaitLoop(s3,mask,value){ \
    int	__loop = 1000000; \
    while (((s3)->alt_status_0 & (mask)) != (value)) \
	if (--__loop == 0) { \
	    ErrorF ("savage wait loop failed 0x%x\n", s3->alt_status_0); \
	    break; \
	} \
}

#define S3_SAVAGE4_ROOM	    10

#define _s3WaitSlots(s3,n) { \
    int __loop = 1000000; \
    while (((s3)->alt_status_0 & S3_SAVAGE4_SLOTS) >= S3_SAVAGE4_ROOM-(n)) \
	if (--__loop == 0) { \
	    ErrorF ("savage wait loop failed 0x%x\n", s3->alt_status_0); \
	    break; \
	} \
}
    
#define _s3WaitEmpty(s3)	_s3WaitLoop(s3,S3_SAVAGE4_SLOTS, 0)
#define _s3WaitIdleEmpty(s3)	_s3WaitLoop(s3,S3_SAVAGE4_SLOTS|S3_SAVAGE4_2DI, S3_SAVAGE4_2DI)
#define _s3WaitIdle(s3)		_s3WaitLoop(s3,S3_SAVAGE4_2DI, S3_SAVAGE4_2DI)

typedef struct _s3Cursor {
    int		width, height;
    int		xhot, yhot;
    Bool	has_cursor;
    CursorPtr	pCursor;
    Pixel	source, mask;
} S3Cursor;

typedef struct _s3PatternCache {
    int		id;
    int		x, y;
} S3PatternCache;

typedef struct _s3Patterns {
    S3PatternCache	*cache;
    int			ncache;
    int			last_used;
    int			last_id;
} S3Patterns;

#define S3_CLOCK_REF	14318	/* KHz */

#define S3_CLOCK(m,n,r)	((S3_CLOCK_REF * ((m) + 2)) / (((n) + 2) * (1 << (r))))

#define S3_MAX_CLOCK	150000	/* KHz */

typedef struct _s3Timing {
    /* label */
    int		horizontal;
    int		vertical;
    int		rate;
    /* horizontal timing */
    int		hfp;	    /* front porch */
    int		hbp;	    /* back porch */
    int		hblank;	    /* blanking */
    /* vertical timing */
    int		vfp;	    /* front porch */
    int		vbp;	    /* back porch */
    int		vblank;	    /* blanking */
    /* clock values */
    int		dac_m;
    int		dac_n;
    int		dac_r;
} S3Timing;

#define S3_TEXT_SAVE	(64*1024)

typedef struct _s3Save {
    CARD8		cursor_fg;
    CARD8		cursor_bg;
    CARD8		lock1;
    CARD8		lock2;
    CARD8		locksrtc;
    CARD8		clock_mode;
    CARD32		alt_mix;
    CARD32		write_mask;
    CARD32		fg;
    CARD32		bg;
    CARD32		global_bitmap_1;
    CARD32		global_bitmap_2;
    CARD32		adv_func_cntl;
    CARD32		primary_bitmap_1;
    CARD32		primary_bitmap_2;
    CARD32		secondary_bitmap_1;
    CARD32		secondary_bitmap_2;
    CARD32		primary_stream_control;
    CARD32		blend_control;
    CARD32		primary_stream_addr_0;
    CARD32		primary_stream_addr_1;
    CARD32		primary_stream_stride;
    CARD32		primary_stream_xy;
    CARD32		primary_stream_size;
    CARD32		primary_stream_mem;
    CARD32		secondary_stream_xy;
    CARD32		secondary_stream_size;
    CARD32		streams_fifo;
    CARD8		text_save[S3_TEXT_SAVE];
} S3Save;

typedef struct _s3CardInfo {
    S3Ptr	s3;		    /* pointer to register structure */
    int		memory;		    /* amount of memory */
    CARD8	*frameBuffer;	    /* pointer to frame buffer */
    CARD8	*registers;	    /* pointer to register map */
    S3Vga	s3vga;
    S3Save	save;
    Bool	need_sync;
    Bool	bios_initialized;   /* whether the bios has been run */
} S3CardInfo;

typedef struct _s3FbInfo {
    CARD8	*offscreen;	    /* pointer to offscreen area */
    int		offscreen_y;	    /* top y coordinate of offscreen area */
    int		offscreen_x;	    /* top x coordinate of offscreen area */
    int		offscreen_width;    /* width of offscreen area */
    int		offscreen_height;   /* height of offscreen area */
    S3Patterns	patterns;
    CARD32	bitmap_offset;
    int		accel_stride;
    int		accel_bpp;
    CARD32	chroma_key;
} S3FBInfo;
    
typedef struct _s3ScreenInfo {
    CARD8	*cursor_base;	    /* pointer to cursor area */
    S3Cursor	cursor;
    Bool	managing_border;
    Bool	use_streams;
    int		primary_depth;
    int		current_ma;
    CARD32	border_pixel;
    S3FBInfo	fb[KD_MAX_FB];
    RegionRec	region[KD_MAX_FB];
    int		fbmap[KD_MAX_FB+1];   /* map from fb to stream */
} S3ScreenInfo;

#define getS3CardInfo(kd)   ((S3CardInfo *) ((kd)->card->driver))
#define s3CardInfo(kd)	    S3CardInfo *s3c = getS3CardInfo(kd)

#define getS3ScreenInfo(kd) ((S3ScreenInfo *) ((kd)->screen->driver))
#define s3ScreenInfo(kd)    S3ScreenInfo *s3s = getS3ScreenInfo(kd)

Bool	s3CardInit (KdCardInfo *);
Bool	s3ScreenInit (KdScreenInfo *);
Bool	s3Enable (ScreenPtr pScreen);
void	s3Disable (ScreenPtr pScreen);
void	s3Fini (ScreenPtr pScreen);

Bool	s3CursorInit (ScreenPtr pScreen);
void	s3CursorEnable (ScreenPtr pScreen);
void	s3CursorDisable (ScreenPtr pScreen);
void	s3CursorFini (ScreenPtr pScreen);
void	s3RecolorCursor (ScreenPtr pScreen, int ndef, xColorItem *pdefs);

void	s3DumbPaintWindow (WindowPtr pWin, RegionPtr pRegion, int what);
void	s3DumbCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc);
    
Bool	s3DrawInit (ScreenPtr pScreen);
void	s3DrawEnable (ScreenPtr pScreen);
void	s3DrawSync (ScreenPtr pScreen);
void	s3DrawDisable (ScreenPtr pScreen);
void	s3DrawFini (ScreenPtr pScreen);

void	s3GetColors (ScreenPtr pScreen, int fb, int ndef, xColorItem *pdefs);
void	s3PutColors (ScreenPtr pScreen, int fb, int ndef, xColorItem *pdefs);

void	S3InitCard (KdCardAttr *attr);

void	s3GetClock (int target, int *Mp, int *Np, int *Rp, int maxM, int maxN, int maxR, int minVco);

extern KdCardFuncs  s3Funcs;

/*
 * Wait for the begining of the retrace interval
 */

#define S3_RETRACE_LOOP_CHECK if (++_loop_count > 300000) {\
    DRAW_DEBUG ((DEBUG_FAILURE, "S3 wait loop failed at %s:%d", \
		__FILE__, __LINE__)); \
    break; \
}

#define DRAW_DEBUG(a)

#define _s3WaitVRetrace(s3vga) { \
    int _loop_count; \
    _loop_count = 0; \
    while (s3GetImm(s3vga, s3_vertical_sync_active) != 0) S3_RETRACE_LOOP_CHECK; \
    _loop_count = 0; \
    while (s3GetImm(s3vga, s3_vertical_sync_active) == 0) S3_RETRACE_LOOP_CHECK; \
}
#define _s3WaitVRetraceFast(s3) { \
    int _loop_count; \
    _loop_count = 0; \
    while (s3->input_status_1 & 8) S3_RETRACE_LOOP_CHECK; \
    _loop_count = 0; \
    while ((s3->input_status_1 & 8) == 0) S3_RETRACE_LOOP_CHECK; \
}
/*
 * Wait for the begining of the retrace interval
 */
#define _s3WaitVRetraceEnd(s3vga) { \
    int _loop_count; \
    _loop_count = 0; \
    while (s3GetImm(s3vga, s3_vertical_sync_active) == 0) S3_RETRACE_LOOP_CHECK; \
    _loop_count = 0; \
    while (s3GetImm(s3vga, s3_vertical_sync_active) != 0) S3_RETRACE_LOOP_CHECK; \
}

#define S3_CURSOR_WIDTH	    64
#define S3_CURSOR_HEIGHT    64
#define S3_CURSOR_SIZE	    ((S3_CURSOR_WIDTH * S3_CURSOR_HEIGHT + 7) / 8)

#define S3_TILE_SIZE	    8

#endif /* _S3_H_ */