File: /usr/src/linux/drivers/video/cyberfb.c

1     /*
2     * linux/drivers/video/cyberfb.c -- CyberVision64 frame buffer device
3     * $Id: cyberfb.c,v 1.6 1998/09/11 04:54:58 abair Exp $
4     *
5     *    Copyright (C) 1998 Alan Bair
6     *
7     * This file is based on two CyberVision64 frame buffer device drivers
8     *
9     * The second CyberVision64 frame buffer device (cvision.c cvision_core.c):
10     *
11     *   Copyright (c) 1997 Antonio Santos
12     *
13     * Released as a patch to 2.1.35, but never included in the source tree.
14     * This is based on work from the NetBSD CyberVision64 frame buffer driver 
15     * and support files (grf_cv.c, grf_cvreg.h, ite_cv.c):
16     * Permission to use the source of this driver was obtained from the
17     * author Michael Teske by Alan Bair.
18     *
19     *   Copyright (c) 1995 Michael Teske
20     *
21     * The first CyberVision64 frame buffer device (cyberfb.c):
22     *
23     *    Copyright (C) 1996 Martin Apel
24     *                       Geert Uytterhoeven
25     *
26     * Which is based on the Amiga frame buffer device (amifb.c):
27     *
28     *    Copyright (C) 1995 Geert Uytterhoeven
29     *
30     *
31     * History:
32     *   - 22 Dec 95: Original version by Martin Apel
33     *   - 05 Jan 96: Geert: integration into the current source tree
34     *   - 01 Aug 98: Alan: Merge in code from cvision.c and cvision_core.c
35     * $Log: cyberfb.c,v $
36     * Revision 1.6  1998/09/11 04:54:58  abair
37     * Update for 2.1.120 change in include file location.
38     * Clean up for public release.
39     *
40     * Revision 1.5  1998/09/03 04:27:13  abair
41     * Move cv64_load_video_mode to cyber_set_video so a new video mode is install
42     * with each change of the 'var' data.
43     *
44     * Revision 1.4  1998/09/01 00:31:17  abair
45     * Put in a set of default 8,16,24 bpp modes and map cyber8,16 to them.
46     * Update operations with 'par' to handle a more complete set of parameter
47     * values for encode/decode process.
48     *
49     * Revision 1.3  1998/08/31 21:31:33  abair
50     * Swap 800x490 for 640x480 video mode and more cleanup.
51     * Abandon idea to resurrect "custom" mode setting via kernel opts,
52     * instead work on making use of fbset program to do this.
53     *
54     * Revision 1.2  1998/08/31 06:17:08  abair
55     * Make updates for changes in cyberfb.c released in 2.1.119
56     * and do some cleanup of the code.
57     *
58     * Revision 1.1  1998/08/29 18:38:31  abair
59     * Initial revision
60     *
61     * Revision 1.3  1998/08/17 06:21:53  abair
62     * Remove more redundant code after merging in cvision_core.c
63     * Set blanking by colormap to pale red to detect this vs trying to
64     * use video blanking. More formating to Linux code style.
65     *
66     * Revision 1.2  1998/08/15 17:51:37  abair
67     * Added cvision_core.c code from 2.1.35 patches.
68     * Changed to compile correctly and switch to using initialization
69     * code. Added debugging and dropping of duplicate code.
70     *
71     *
72     *
73     * This file is subject to the terms and conditions of the GNU General Public
74     * License.  See the file COPYING in the main directory of this archive
75     * for more details.
76     */
77     
78     
79     #include <linux/module.h>
80     #include <linux/kernel.h>
81     #include <linux/errno.h>
82     #include <linux/string.h>
83     #include <linux/mm.h>
84     #include <linux/tty.h>
85     #include <linux/slab.h>
86     #include <linux/delay.h>
87     #include <linux/zorro.h>
88     #include <linux/fb.h>
89     #include <linux/init.h>
90     #include <asm/uaccess.h>
91     #include <asm/system.h>
92     #include <asm/irq.h>
93     #include <asm/pgtable.h>
94     #include <asm/amigahw.h>
95     #include <asm/io.h>
96     
97     #include "cyberfb.h"
98     #include <video/fbcon.h>
99     #include <video/fbcon-cfb8.h>
100     #include <video/fbcon-cfb16.h>
101     
102     /*#define CYBERFBDEBUG*/
103     #ifdef CYBERFBDEBUG
104     #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
105     static void cv64_dump(void);
106     #else
107     #define DPRINTK(fmt, args...)
108     #endif
109     
110     #define wb_64(regs,reg,dat) (*(((volatile unsigned char *)regs) + reg) = dat)
111     #define rb_64(regs, reg) (*(((volatile unsigned char *)regs) + reg))
112     
113     #define ww_64(regs,reg,dat) (*((volatile unsigned short *)(regs + reg) = dat)
114     
115     struct cyberfb_par {
116     	struct fb_var_screeninfo var;
117     	__u32 type;
118     	__u32 type_aux;
119     	__u32 visual;
120     	__u32 line_length;
121     };
122     
123     static struct cyberfb_par current_par;
124     
125     static int current_par_valid = 0;
126     static int currcon = 0;
127     
128     static struct display disp;
129     static struct fb_info fb_info;
130     
131     
132     /*
133      *    Frame Buffer Name
134      */
135     
136     static char cyberfb_name[16] = "Cybervision";
137     
138     
139     /*
140      *    CyberVision Graphics Board
141      */
142     
143     static unsigned char Cyber_colour_table [256][3];
144     static unsigned long CyberSize;
145     static volatile unsigned char *CyberBase;
146     static volatile unsigned char *CyberMem;
147     static volatile unsigned char *CyberRegs;
148     static unsigned long CyberMem_phys;
149     static unsigned long CyberRegs_phys;
150     
151     /*
152      *    Predefined Video Modes
153      */
154     
155     static struct {
156         const char *name;
157         struct fb_var_screeninfo var;
158     } cyberfb_predefined[] __initdata = {
159     	{ "640x480-8", {		/* Default 8 BPP mode (cyber8) */
160     		640, 480, 640, 480, 0, 0, 8, 0,
161     		{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
162     		0, 0, -1, -1, FB_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2,
163     		FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, 
164     		FB_VMODE_NONINTERLACED
165     	}}, 
166     	{ "640x480-16", {		/* Default 16 BPP mode (cyber16) */
167     		640, 480, 640, 480, 0, 0, 16, 0,
168     		{11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
169     		0, 0, -1, -1, FB_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2,
170     		FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, 
171     		FB_VMODE_NONINTERLACED
172     	}}, 
173     	{ "640x480-24", {		/* Default 24 BPP mode */
174     		640, 480, 640, 480, 0, 0, 24, 0,
175     		{16, 8, 0}, {8, 8, 0}, {0, 8, 0}, {0, 0, 0},
176     		0, 0, -1, -1, FB_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2,
177     		FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, 
178     		FB_VMODE_NONINTERLACED
179     	}}, 
180     	{ "800x490-8", {		/* Cybervision 8 bpp */
181     		/* NO Acceleration */
182     		800, 490, 800, 490, 0, 0, 8, 0,
183     		{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
184     		0, 0, -1, -1, FB_ACCEL_NONE, 33333, 80, 24, 23, 1, 56, 8,
185     		FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
186     		FB_VMODE_NONINTERLACED
187     	}},
188     /* I can't test these with my monitor, but I suspect they will
189      * be OK, since Antonio Santos indicated he had tested them in
190      * his system.
191      */
192     	{ "800x600-8", {		/* Cybervision 8 bpp */
193     		800, 600, 800, 600, 0, 0, 8, 0,
194     		{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
195     		0, 0, -1, -1, FB_ACCELF_TEXT, 27778, 64, 24, 22, 1, 72, 2,
196     		FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
197     		FB_VMODE_NONINTERLACED
198     	}},
199     	{ "1024x768-8", {		/* Cybervision 8 bpp */
200     		1024, 768, 1024, 768, 0, 0, 8, 0,
201     		{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
202     		0, 0, -1, -1, FB_ACCELF_TEXT, 16667, 224, 72, 60, 12, 168, 4,
203     		FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
204     		FB_VMODE_NONINTERLACED
205     	}},
206     	{ "1152x886-8", {		/* Cybervision 8 bpp */
207     		1152, 886, 1152, 886, 0, 0, 8, 0,
208     		{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
209     		0, 0, -1, -1, FB_ACCELF_TEXT, 15873, 184, 40, 24, 1, 56, 16,
210     		FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
211     		FB_VMODE_NONINTERLACED
212     	}},
213     	{ "1280x1024-8", {	/* Cybervision 8 bpp */
214     		1280, 1024, 1280, 1024, 0, 0, 8, 0,
215     		{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
216     		0, 0, -1, -1, FB_ACCELF_TEXT, 16667, 256, 48, 50, 12, 72, 4,
217     		FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
218     		FB_VMODE_INTERLACED
219     	}}
220     };
221     
222     #define NUM_TOTAL_MODES    ARRAY_SIZE(cyberfb_predefined)
223     
224     static int Cyberfb_inverse = 0;
225     
226     /*
227      *    Some default modes
228      */
229     
230     #define CYBER8_DEFMODE     (0)
231     #define CYBER16_DEFMODE    (1)
232     
233     static struct fb_var_screeninfo cyberfb_default;
234     static int cyberfb_usermode __initdata = 0;
235     
236     /*
237      *    Interface used by the world
238      */
239     
240     int cyberfb_setup(char *options);
241     
242     static int cyberfb_get_fix(struct fb_fix_screeninfo *fix, int con,
243     			   struct fb_info *info);
244     static int cyberfb_get_var(struct fb_var_screeninfo *var, int con,
245     			   struct fb_info *info);
246     static int cyberfb_set_var(struct fb_var_screeninfo *var, int con,
247     			   struct fb_info *info);
248     static int cyberfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
249     			    struct fb_info *info);
250     static int cyberfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
251     			    struct fb_info *info);
252     
253     /*
254      *    Interface to the low level console driver
255      */
256     
257     int cyberfb_init(void);
258     static int Cyberfb_switch(int con, struct fb_info *info);
259     static int Cyberfb_updatevar(int con, struct fb_info *info);
260     static void Cyberfb_blank(int blank, struct fb_info *info);
261     
262     /*
263      *    Text console acceleration
264      */
265     
266     #ifdef FBCON_HAS_CFB8
267     static struct display_switch fbcon_cyber8;
268     #endif
269     
270     /*
271      *    Accelerated Functions used by the low level console driver
272      */
273     
274     static void Cyber_WaitQueue(u_short fifo);
275     static void Cyber_WaitBlit(void);
276     static void Cyber_BitBLT(u_short curx, u_short cury, u_short destx,
277     			 u_short desty, u_short width, u_short height,
278     			 u_short mode);
279     static void Cyber_RectFill(u_short x, u_short y, u_short width, u_short height,
280     			   u_short mode, u_short color);
281     #if 0
282     static void Cyber_MoveCursor(u_short x, u_short y);
283     #endif
284     
285     /*
286      *   Hardware Specific Routines
287      */
288     
289     static int Cyber_init(void);
290     static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
291     			    struct cyberfb_par *par);
292     static int Cyber_decode_var(struct fb_var_screeninfo *var,
293     			    struct cyberfb_par *par);
294     static int Cyber_encode_var(struct fb_var_screeninfo *var,
295     			    struct cyberfb_par *par);
296     static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
297     			   u_int *transp, struct fb_info *info);
298     static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
299     			   u_int transp, struct fb_info *info);
300     
301     /*
302      *    Internal routines
303      */
304     
305     static void cyberfb_get_par(struct cyberfb_par *par);
306     static void cyberfb_set_par(struct cyberfb_par *par);
307     static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive);
308     static void do_install_cmap(int con, struct fb_info *info);
309     static void cyberfb_set_disp(int con, struct fb_info *info);
310     static int get_video_mode(const char *name);
311     
312     /* For cvision_core.c */
313     static unsigned short cv64_compute_clock(unsigned long);
314     static int cv_has_4mb (volatile unsigned char *);
315     static void cv64_board_init (void);
316     static void cv64_load_video_mode (struct fb_var_screeninfo *);
317     
318     
319     /* -------------------- Hardware specific routines ------------------------- */
320     
321     
322     /*
323      *    Initialization
324      *
325      *    Set the default video mode for this chipset. If a video mode was
326      *    specified on the command line, it will override the default mode.
327      */
328     
329     static int Cyber_init(void)
330     {
331     	volatile unsigned char *regs = CyberRegs;
332     	volatile unsigned long *CursorBase;
333     	int i;
334     	DPRINTK("ENTER\n");
335     
336     /* Init local cmap as greyscale levels */
337     	for (i = 0; i < 256; i++) {
338     		Cyber_colour_table [i][0] = i;
339     		Cyber_colour_table [i][1] = i;
340     		Cyber_colour_table [i][2] = i;
341     	}
342     
343     /* Initialize the board and determine fbmem size */
344     	cv64_board_init(); 
345     #ifdef CYBERFBDEBUG
346     	DPRINTK("Register state after initing board\n");
347     	cv64_dump();
348     #endif
349     /* Clear framebuffer memory */
350     	DPRINTK("Clear framebuffer memory\n");
351     	memset ((char *)CyberMem, 0, CyberSize);
352     
353     /* Disable hardware cursor */
354     	DPRINTK("Disable HW cursor\n");
355     	wb_64(regs, S3_CRTC_ADR, S3_REG_LOCK2);
356     	wb_64(regs, S3_CRTC_DATA, 0xa0);
357     	wb_64(regs, S3_CRTC_ADR, S3_HGC_MODE);
358     	wb_64(regs, S3_CRTC_DATA, 0x00);
359     	wb_64(regs, S3_CRTC_ADR, S3_HWGC_DX);
360     	wb_64(regs, S3_CRTC_DATA, 0x00);
361     	wb_64(regs, S3_CRTC_ADR, S3_HWGC_DY);
362     	wb_64(regs, S3_CRTC_DATA, 0x00);
363     
364     /* Initialize hardware cursor */
365     	DPRINTK("Init HW cursor\n");
366     	CursorBase = (u_long *)((char *)(CyberMem) + CyberSize - 0x400);
367     	for (i=0; i < 8; i++)
368     	{
369     		*(CursorBase  +(i*4)) = 0xffffff00;
370     		*(CursorBase+1+(i*4)) = 0xffff0000;
371     		*(CursorBase+2+(i*4)) = 0xffff0000;
372     		*(CursorBase+3+(i*4)) = 0xffff0000;
373     	}
374     	for (i=8; i < 64; i++)
375     	{
376     		*(CursorBase  +(i*4)) = 0xffff0000;
377     		*(CursorBase+1+(i*4)) = 0xffff0000;
378     		*(CursorBase+2+(i*4)) = 0xffff0000;
379     		*(CursorBase+3+(i*4)) = 0xffff0000;
380     	}
381     
382     	Cyber_setcolreg (255, 56<<8, 100<<8, 160<<8, 0, NULL /* unused */);
383     	Cyber_setcolreg (254, 0, 0, 0, 0, NULL /* unused */);
384     
385     	DPRINTK("EXIT\n");
386     	return 0;
387     }
388     
389     
390     /*
391      *    This function should fill in the `fix' structure based on the
392      *    values in the `par' structure.
393      */
394     
395     static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
396     			    struct cyberfb_par *par)
397     {
398     	DPRINTK("ENTER\n");
399     	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
400     	strcpy(fix->id, cyberfb_name);
401     	fix->smem_start = CyberMem_phys;
402     	fix->smem_len = CyberSize;
403     	fix->mmio_start = CyberRegs_phys;
404     	fix->mmio_len = 0x10000;
405     
406     	fix->type = FB_TYPE_PACKED_PIXELS;
407     	fix->type_aux = 0;
408     	if (par->var.bits_per_pixel == 15 || par->var.bits_per_pixel == 16 ||
409     	    par->var.bits_per_pixel == 24 || par->var.bits_per_pixel == 32) {
410     		fix->visual = FB_VISUAL_DIRECTCOLOR;
411     	} else {
412     		fix->visual = FB_VISUAL_PSEUDOCOLOR;
413     	}
414     
415     	fix->xpanstep = 0;
416     	fix->ypanstep = 0;
417     	fix->ywrapstep = 0;
418     	fix->line_length = 0;
419     	fix->accel = FB_ACCEL_S3_TRIO64;
420     
421     	DPRINTK("EXIT\n");
422     	return(0);
423     }
424     
425     
426     /*
427     *    Fill the `par' structure based on the values in `var'.
428     *    TODO: Verify and adjust values, return -EINVAL if bad.
429     */
430     
431     static int Cyber_decode_var(struct fb_var_screeninfo *var,
432     			    struct cyberfb_par *par)
433     {
434     	DPRINTK("ENTER\n");
435     	par->var.xres = var->xres;
436     	par->var.yres = var->yres;
437     	par->var.xres_virtual = var->xres_virtual;
438     	par->var.yres_virtual = var->yres_virtual;
439     	par->var.xoffset = var->xoffset;
440     	par->var.yoffset = var->yoffset;
441     	par->var.bits_per_pixel = var->bits_per_pixel;
442     	par->var.grayscale = var->grayscale;
443     	par->var.red = var->red;
444     	par->var.green = var->green;
445     	par->var.blue = var->blue;
446     	par->var.transp = var->transp;
447     	par->var.nonstd = var->nonstd;
448     	par->var.activate = var->activate;
449     	par->var.height = var->height;
450     	par->var.width = var->width;
451     	if (var->accel_flags & FB_ACCELF_TEXT) {
452     		par->var.accel_flags = FB_ACCELF_TEXT;
453     	} else {
454     		par->var.accel_flags = 0;
455     	}
456     	par->var.pixclock = var->pixclock;
457     	par->var.left_margin = var->left_margin;
458     	par->var.right_margin = var->right_margin;
459     	par->var.upper_margin = var->upper_margin;
460     	par->var.lower_margin = var->lower_margin;
461     	par->var.hsync_len = var->hsync_len;
462     	par->var.vsync_len = var->vsync_len;
463     	par->var.sync = var->sync;
464     	par->var.vmode = var->vmode;
465     	DPRINTK("EXIT\n");
466     	return(0);
467     }
468     
469     /*
470     *    Fill the `var' structure based on the values in `par' and maybe
471     *    other values read out of the hardware.
472     */
473     
474     static int Cyber_encode_var(struct fb_var_screeninfo *var,
475     			    struct cyberfb_par *par)
476     {
477     	DPRINTK("ENTER\n");
478     	var->xres = par->var.xres;
479     	var->yres = par->var.yres;
480     	var->xres_virtual = par->var.xres_virtual;
481     	var->yres_virtual = par->var.yres_virtual;
482     	var->xoffset = par->var.xoffset;
483     	var->yoffset = par->var.yoffset;
484     
485     	var->bits_per_pixel = par->var.bits_per_pixel;
486     	var->grayscale = par->var.grayscale;
487     
488     	var->red = par->var.red;
489     	var->green = par->var.green;
490     	var->blue = par->var.blue;
491     	var->transp = par->var.transp;
492     
493     	var->nonstd = par->var.nonstd;
494     	var->activate = par->var.activate;
495     
496     	var->height = par->var.height;
497     	var->width = par->var.width;
498     
499     	var->accel_flags = par->var.accel_flags;
500     
501     	var->pixclock = par->var.pixclock;
502     	var->left_margin = par->var.left_margin;
503     	var->right_margin = par->var.right_margin;
504     	var->upper_margin = par->var.upper_margin;
505     	var->lower_margin = par->var.lower_margin;
506     	var->hsync_len = par->var.hsync_len;
507     	var->vsync_len = par->var.vsync_len;
508     	var->sync = par->var.sync;
509     	var->vmode = par->var.vmode;
510     	
511     	DPRINTK("EXIT\n");
512     	return(0);
513     }
514     
515     
516     /*
517      *    Set a single color register. Return != 0 for invalid regno.
518      */
519     
520     static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
521     			   u_int transp, struct fb_info *info)
522     {
523     	volatile unsigned char *regs = CyberRegs;
524     
525     	/*DPRINTK("ENTER\n");*/
526     	if (regno > 255) {
527     		DPRINTK("EXIT - Register # > 255\n");
528     		return (1);
529     	}
530     
531     	wb_64(regs, 0x3c8, (unsigned char) regno);
532     
533      	red >>= 10;
534      	green >>= 10;
535      	blue >>= 10;
536     
537     	Cyber_colour_table [regno][0] = red;
538     	Cyber_colour_table [regno][1] = green;
539     	Cyber_colour_table [regno][2] = blue;
540     
541     	wb_64(regs, 0x3c9, red);
542     	wb_64(regs, 0x3c9, green);
543     	wb_64(regs, 0x3c9, blue);
544     
545     	/*DPRINTK("EXIT\n");*/
546     	return (0);
547     }
548     
549     
550     /*
551     *    Read a single color register and split it into
552     *    colors/transparent. Return != 0 for invalid regno.
553     */
554     
555     static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
556     			   u_int *transp, struct fb_info *info)
557     {
558     	int t;
559     
560     	/*DPRINTK("ENTER\n");*/
561     	if (regno > 255) {
562     		DPRINTK("EXIT - Register # > 255\n");
563     		return (1);
564     	}
565     	/* ARB This shifting & oring seems VERY strange */
566      	t	= Cyber_colour_table [regno][0];
567      	*red	= (t<<10) | (t<<4) | (t>>2);
568      	t	= Cyber_colour_table [regno][1];
569      	*green	= (t<<10) | (t<<4) | (t>>2);
570      	t	= Cyber_colour_table [regno][2];
571      	*blue	= (t<<10) | (t<<4) | (t>>2);
572      	*transp = 0;
573     	/*DPRINTK("EXIT\n");*/
574     	return (0);
575     }
576     
577     
578     /*
579     *    (Un)Blank the screen
580     *    blank: 1 = zero fb cmap
581     *           0 = restore fb cmap from local cmap
582     */
583     
584     void Cyberfb_blank(int blank, struct fb_info *info)
585     {
586     	volatile unsigned char *regs = CyberRegs;
587     	int i;
588     
589     	DPRINTK("ENTER\n");
590     #if 0
591     /* Blank by turning gfx off */
592     	gfx_on_off (1, regs);
593     #else
594     	if (blank) {
595     		for (i = 0; i < 256; i++) {
596     			wb_64(regs, 0x3c8, (unsigned char) i);
597     			/* ARB Pale red to detect this blanking method */
598     			wb_64(regs, 0x3c9, 48); 
599     			wb_64(regs, 0x3c9, 0);
600     			wb_64(regs, 0x3c9, 0);
601     		}
602     	} else {
603     		for (i = 0; i < 256; i++) {
604     			wb_64(regs, 0x3c8, (unsigned char) i);
605     			wb_64(regs, 0x3c9, Cyber_colour_table[i][0]);
606     			wb_64(regs, 0x3c9, Cyber_colour_table[i][1]);
607     			wb_64(regs, 0x3c9, Cyber_colour_table[i][2]);
608     		}
609     	}
610     #endif
611     	DPRINTK("EXIT\n");
612     }
613     
614     
615     /**************************************************************
616      * We are waiting for "fifo" FIFO-slots empty
617      */
618     static void Cyber_WaitQueue (u_short fifo)
619     {
620     	unsigned short status;
621     
622     	DPRINTK("ENTER\n");
623     	do {
624     		status = *((u_short volatile *)(CyberRegs + S3_GP_STAT));
625     	} while (status & fifo);
626     	DPRINTK("EXIT\n");
627     }
628     
629     /**************************************************************
630      * We are waiting for Hardware (Graphics Engine) not busy
631      */
632     static void Cyber_WaitBlit (void)
633     {
634     	unsigned short status;
635     
636     	DPRINTK("ENTER\n");
637     	do {
638     		status = *((u_short volatile *)(CyberRegs + S3_GP_STAT));
639     	} while (status & S3_HDW_BUSY);
640     	DPRINTK("EXIT\n");
641     }
642     
643     /**************************************************************
644      * BitBLT - Through the Plane
645      */
646     static void Cyber_BitBLT (u_short curx, u_short cury, u_short destx,
647     			  u_short desty, u_short width, u_short height,
648     			  u_short mode)
649     {
650     	volatile unsigned char *regs = CyberRegs;
651     	u_short blitcmd = S3_BITBLT;
652     
653     	DPRINTK("ENTER\n");
654     	/* Set drawing direction */
655     	/* -Y, X maj, -X (default) */
656     	if (curx > destx) {
657     		blitcmd |= 0x0020;  /* Drawing direction +X */
658     	} else {
659     		curx  += (width - 1);
660     		destx += (width - 1);
661     	}
662     
663     	if (cury > desty) {
664     		blitcmd |= 0x0080;  /* Drawing direction +Y */
665     	} else {
666     		cury  += (height - 1);
667     		desty += (height - 1);
668     	}
669     
670     	Cyber_WaitQueue (0x8000);
671     
672     	*((u_short volatile *)(regs + S3_PIXEL_CNTL)) = 0xa000;
673     	*((u_short volatile *)(regs + S3_FRGD_MIX)) = (0x0060 | mode);
674     
675     	*((u_short volatile *)(regs + S3_CUR_X)) = curx;
676     	*((u_short volatile *)(regs + S3_CUR_Y)) = cury;
677     
678     	*((u_short volatile *)(regs + S3_DESTX_DIASTP)) = destx;
679     	*((u_short volatile *)(regs + S3_DESTY_AXSTP)) = desty;
680     
681     	*((u_short volatile *)(regs + S3_MIN_AXIS_PCNT)) = height - 1;
682     	*((u_short volatile *)(regs + S3_MAJ_AXIS_PCNT)) = width  - 1;
683     
684     	*((u_short volatile *)(regs + S3_CMD)) = blitcmd;
685     	DPRINTK("EXIT\n");
686     }
687     
688     /**************************************************************
689      * Rectangle Fill Solid
690      */
691     static void Cyber_RectFill (u_short x, u_short y, u_short width,
692     			    u_short height, u_short mode, u_short color)
693     {
694     	volatile unsigned char *regs = CyberRegs;
695     	u_short blitcmd = S3_FILLEDRECT;
696     
697     	DPRINTK("ENTER\n");
698     	Cyber_WaitQueue (0x8000);
699     
700     	*((u_short volatile *)(regs + S3_PIXEL_CNTL)) = 0xa000;
701     	*((u_short volatile *)(regs + S3_FRGD_MIX)) = (0x0020 | mode);
702     
703     	*((u_short volatile *)(regs + S3_MULT_MISC)) = 0xe000;
704     	*((u_short volatile *)(regs + S3_FRGD_COLOR)) = color;
705     
706     	*((u_short volatile *)(regs + S3_CUR_X)) = x;
707     	*((u_short volatile *)(regs + S3_CUR_Y)) = y;
708     
709     	*((u_short volatile *)(regs + S3_MIN_AXIS_PCNT)) = height - 1;
710     	*((u_short volatile *)(regs + S3_MAJ_AXIS_PCNT)) = width  - 1;
711     
712     	*((u_short volatile *)(regs + S3_CMD)) = blitcmd;
713     	DPRINTK("EXIT\n");
714     }
715     
716     
717     #if 0
718     /**************************************************************
719      * Move cursor to x, y
720      */
721     static void Cyber_MoveCursor (u_short x, u_short y)
722     {
723     	volatile unsigned char *regs = CyberRegs;
724     	DPRINTK("ENTER\n");
725     	*(regs + S3_CRTC_ADR)  = 0x39;
726     	*(regs + S3_CRTC_DATA) = 0xa0;
727     
728     	*(regs + S3_CRTC_ADR)  = S3_HWGC_ORGX_H;
729     	*(regs + S3_CRTC_DATA) = (char)((x & 0x0700) >> 8);
730     	*(regs + S3_CRTC_ADR)  = S3_HWGC_ORGX_L;
731     	*(regs + S3_CRTC_DATA) = (char)(x & 0x00ff);
732     
733     	*(regs + S3_CRTC_ADR)  = S3_HWGC_ORGY_H;
734     	*(regs + S3_CRTC_DATA) = (char)((y & 0x0700) >> 8);
735     	*(regs + S3_CRTC_ADR)  = S3_HWGC_ORGY_L;
736     	*(regs + S3_CRTC_DATA) = (char)(y & 0x00ff);
737     	DPRINTK("EXIT\n");
738     }
739     #endif
740     
741     
742     /* -------------------- Generic routines ---------------------------------- */
743     
744     
745     /*
746      *    Fill the hardware's `par' structure.
747      */
748     
749     static void cyberfb_get_par(struct cyberfb_par *par)
750     {
751     	DPRINTK("ENTER\n");
752     	if (current_par_valid) {
753     		*par = current_par;
754     	} else {
755     		Cyber_decode_var(&cyberfb_default, par);
756     	}
757     	DPRINTK("EXIT\n");
758     }
759     
760     
761     static void cyberfb_set_par(struct cyberfb_par *par)
762     {
763     	DPRINTK("ENTER\n");
764     	current_par = *par;
765     	current_par_valid = 1;
766     	DPRINTK("EXIT\n");
767     }
768     
769     
770     static void cyber_set_video(struct fb_var_screeninfo *var)
771     {
772     
773     	/* Load the video mode defined by the 'var' data */
774     	cv64_load_video_mode (var);
775     #ifdef CYBERFBDEBUG
776     	DPRINTK("Register state after loading video mode\n");
777     	cv64_dump();
778     #endif
779     }
780     
781     
782     static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
783     {
784     	int err, activate;
785     	struct cyberfb_par par;
786     
787     	DPRINTK("ENTER\n");
788     	if ((err = Cyber_decode_var(var, &par))) {
789     		DPRINTK("EXIT - decode_var failed\n");
790     		return(err);
791     	}
792     	activate = var->activate;
793     	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
794     		cyberfb_set_par(&par);
795     	Cyber_encode_var(var, &par);
796     	var->activate = activate;
797     
798     	cyber_set_video(var);
799     	DPRINTK("EXIT\n");
800     	return 0;
801     }
802     
803     
804     static void do_install_cmap(int con, struct fb_info *info)
805     {
806     	DPRINTK("ENTER\n");
807     	if (con != currcon) {
808     		DPRINTK("EXIT - Not current console\n");
809     		return;
810     	}
811     	if (fb_display[con].cmap.len) {
812     		DPRINTK("Use console cmap\n");
813     		fb_set_cmap(&fb_display[con].cmap, 1, Cyber_setcolreg, info);
814     	} else {
815     		DPRINTK("Use default cmap\n");
816     		fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
817     			    1, Cyber_setcolreg, info);
818     	}
819     	DPRINTK("EXIT\n");
820     }
821     
822     /*
823      *    Get the Fixed Part of the Display
824      */
825     
826     static int cyberfb_get_fix(struct fb_fix_screeninfo *fix, int con,
827     			   struct fb_info *info)
828     {
829     	struct cyberfb_par par;
830     	int error = 0;
831     
832     	DPRINTK("ENTER\n");
833     	if (con == -1) {
834     		cyberfb_get_par(&par);
835     	} else {
836     		error = Cyber_decode_var(&fb_display[con].var, &par);
837     	}
838     	DPRINTK("EXIT\n");
839     	return(error ? error : Cyber_encode_fix(fix, &par));
840     }
841     
842     
843     /*
844      *    Get the User Defined Part of the Display
845      */
846     
847     static int cyberfb_get_var(struct fb_var_screeninfo *var, int con,
848     			   struct fb_info *info)
849     {
850     	struct cyberfb_par par;
851     	int error = 0;
852     
853     	DPRINTK("ENTER\n");
854     	if (con == -1) {
855     		cyberfb_get_par(&par);
856     		error = Cyber_encode_var(var, &par);
857     		disp.var = *var;   /* ++Andre: don't know if this is the right place */
858     	} else {
859     		*var = fb_display[con].var;
860     	}
861     
862     	DPRINTK("EXIT\n");
863     	return(error);
864     }
865     
866     
867     static void cyberfb_set_disp(int con, struct fb_info *info)
868     {
869     	struct fb_fix_screeninfo fix;
870     	struct display *display;
871     
872     	DPRINTK("ENTER\n");
873     	if (con >= 0)
874     		display = &fb_display[con];
875     	else
876     		display = &disp;	/* used during initialization */
877     
878     	cyberfb_get_fix(&fix, con, info);
879     	if (con == -1)
880     		con = 0;
881     	display->screen_base = (unsigned char *)CyberMem;
882     	display->visual = fix.visual;
883     	display->type = fix.type;
884     	display->type_aux = fix.type_aux;
885     	display->ypanstep = fix.ypanstep;
886     	display->ywrapstep = fix.ywrapstep;
887     	display->can_soft_blank = 1;
888     	display->inverse = Cyberfb_inverse;
889     	switch (display->var.bits_per_pixel) {
890     #ifdef FBCON_HAS_CFB8
891     	    case 8:
892     		if (display->var.accel_flags & FB_ACCELF_TEXT) {
893     		    display->dispsw = &fbcon_cyber8;
894     #warning FIXME: We should reinit the graphics engine here
895     		} else
896     		    display->dispsw = &fbcon_cfb8;
897     		break;
898     #endif
899     #ifdef FBCON_HAS_CFB16
900     	    case 16:
901     		display->dispsw = &fbcon_cfb16;
902     		break;
903     #endif
904     	    default:
905     		display->dispsw = NULL;
906     		break;
907     	}
908     	DPRINTK("EXIT\n");
909     }
910     
911     
912     /*
913      *    Set the User Defined Part of the Display
914      */
915     
916     static int cyberfb_set_var(struct fb_var_screeninfo *var, int con,
917     			   struct fb_info *info)
918     {
919     	int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel;
920     
921     	DPRINTK("ENTER\n");
922     	if ((err = do_fb_set_var(var, con == currcon))) {
923     		DPRINTK("EXIT - do_fb_set_var failed\n");
924     		return(err);
925     	}
926     	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
927     		oldxres = fb_display[con].var.xres;
928     		oldyres = fb_display[con].var.yres;
929     		oldvxres = fb_display[con].var.xres_virtual;
930     		oldvyres = fb_display[con].var.yres_virtual;
931     		oldbpp = fb_display[con].var.bits_per_pixel;
932     		oldaccel = fb_display[con].var.accel_flags;
933     		fb_display[con].var = *var;
934     		if (oldxres != var->xres || oldyres != var->yres ||
935     		    oldvxres != var->xres_virtual ||
936     		    oldvyres != var->yres_virtual ||
937     		    oldbpp != var->bits_per_pixel ||
938     		    oldaccel != var->accel_flags) {
939     			cyberfb_set_disp(con, info);
940     			(*fb_info.changevar)(con);
941     			fb_alloc_cmap(&fb_display[con].cmap, 0, 0);
942     			do_install_cmap(con, info);
943     		}
944     	}
945     	var->activate = 0;
946     	DPRINTK("EXIT\n");
947     	return(0);
948     }
949     
950     
951     /*
952      *    Get the Colormap
953      */
954     
955     static int cyberfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
956     			    struct fb_info *info)
957     {
958     	DPRINTK("ENTER\n");
959     	if (con == currcon) { /* current console? */
960     		DPRINTK("EXIT - console is current console\n");
961     		return(fb_get_cmap(cmap, kspc, Cyber_getcolreg, info));
962     	} else if (fb_display[con].cmap.len) { /* non default colormap? */
963     		DPRINTK("Use console cmap\n");
964     		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
965     	} else {
966     		DPRINTK("Use default cmap\n");
967     		fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
968     			     cmap, kspc ? 0 : 2);
969     	}
970     	DPRINTK("EXIT\n");
971     	return(0);
972     }
973     
974     
975     /*
976      *    Set the Colormap
977      */
978     
979     static int cyberfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
980     			    struct fb_info *info)
981     {
982     	int err;
983     
984     	DPRINTK("ENTER\n");
985     	if (!fb_display[con].cmap.len) {       /* no colormap allocated? */
986     		if ((err = fb_alloc_cmap(&fb_display[con].cmap,
987     					 1<<fb_display[con].var.bits_per_pixel,
988     					 0))) {
989     			DPRINTK("EXIT - fb_alloc_cmap failed\n");
990     			return(err);
991     		}
992     	}
993     	if (con == currcon) {		 /* current console? */
994     		DPRINTK("EXIT - Current console\n");
995     		return(fb_set_cmap(cmap, kspc, Cyber_setcolreg, info));
996     	} else {
997     		fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
998     	}
999     	DPRINTK("EXIT\n");
1000     	return(0);
1001     }
1002     
1003     
1004     static struct fb_ops cyberfb_ops = {
1005     	owner:		THIS_MODULE,
1006     	fb_get_fix:	cyberfb_get_fix,
1007     	fb_get_var:	cyberfb_get_var,
1008     	fb_set_var:	cyberfb_set_var,
1009     	fb_get_cmap:	cyberfb_get_cmap,
1010     	fb_set_cmap:	cyberfb_set_cmap,
1011     };
1012     
1013     int __init cyberfb_setup(char *options)
1014     {
1015     	char *this_opt;
1016     	DPRINTK("ENTER\n");
1017     
1018     	fb_info.fontname[0] = '\0';
1019     
1020     	if (!options || !*options) {
1021     		DPRINTK("EXIT - no options\n");
1022     		return 0;
1023     	}
1024     
1025     	for (this_opt = strtok(options, ","); this_opt;
1026     	     this_opt = strtok(NULL, ",")) {
1027     		if (!strcmp(this_opt, "inverse")) {
1028     			Cyberfb_inverse = 1;
1029     			fb_invert_cmaps();
1030     		} else if (!strncmp(this_opt, "font:", 5)) {
1031     			strcpy(fb_info.fontname, this_opt+5);
1032     		} else if (!strcmp (this_opt, "cyber8")) {
1033     			cyberfb_default = cyberfb_predefined[CYBER8_DEFMODE].var;
1034     			cyberfb_usermode = 1;
1035     		} else if (!strcmp (this_opt, "cyber16")) {
1036     			cyberfb_default = cyberfb_predefined[CYBER16_DEFMODE].var;
1037     			cyberfb_usermode = 1;
1038     		} else get_video_mode(this_opt);
1039     	}
1040     
1041     	DPRINTK("default mode: xres=%d, yres=%d, bpp=%d\n",
1042     		cyberfb_default.xres,
1043     		cyberfb_default.yres,
1044     		cyberfb_default.bits_per_pixel);
1045     	DPRINTK("EXIT\n");
1046     	return 0;
1047     }
1048     
1049     /*
1050      *    Initialization
1051      */
1052     
1053     int __init cyberfb_init(void)
1054     {
1055     	unsigned long board_addr, board_size;
1056     	struct cyberfb_par par;
1057     	struct zorro_dev *z = NULL;
1058     	DPRINTK("ENTER\n");
1059     
1060     	while ((z = zorro_find_device(ZORRO_PROD_PHASE5_CYBERVISION64, z))) {
1061     	    board_addr = z->resource.start;
1062     	    board_size = z->resource.end-z->resource.start+1;
1063     	    CyberMem_phys = board_addr + 0x01400000;
1064     	    CyberRegs_phys = CyberMem_phys + 0x00c00000;
1065     	    if (!request_mem_region(CyberRegs_phys, 0x10000, "S3 Trio64"))
1066     		continue;
1067     	    if (!request_mem_region(CyberMem_phys, 0x400000, "RAM")) {
1068     		release_mem_region(CyberRegs_phys, 0x10000);
1069     		continue;
1070     	    }
1071     	    DPRINTK("board_addr=%08lx\n", board_addr);
1072     	    DPRINTK("board_size=%08lx\n", board_size);
1073     
1074     	    CyberBase = ioremap(board_addr, board_size);
1075     	    CyberRegs = CyberBase + 0x02000000;
1076     	    CyberMem = CyberBase + 0x01400000;
1077     	    DPRINTK("CyberBase=%08lx CyberRegs=%08lx CyberMem=%08lx\n",
1078     		    CyberBase, (long unsigned int)CyberRegs, CyberMem);
1079     
1080     #ifdef CYBERFBDEBUG
1081     	    DPRINTK("Register state just after mapping memory\n");
1082     	    cv64_dump();
1083     #endif
1084     
1085     	    strcpy(fb_info.modename, cyberfb_name);
1086     	    fb_info.changevar = NULL;
1087     	    fb_info.node = -1;
1088     	    fb_info.fbops = &cyberfb_ops;
1089     	    fb_info.disp = &disp;
1090     	    fb_info.switch_con = &Cyberfb_switch;
1091     	    fb_info.updatevar = &Cyberfb_updatevar;
1092     	    fb_info.blank = &Cyberfb_blank;
1093     
1094     	    Cyber_init();
1095     	    /* ++Andre: set cyberfb default mode */
1096     	    if (!cyberfb_usermode) {
1097     		    cyberfb_default = cyberfb_predefined[CYBER8_DEFMODE].var;
1098     		    DPRINTK("Use default cyber8 mode\n");
1099     	    }
1100     	    Cyber_decode_var(&cyberfb_default, &par);
1101     	    Cyber_encode_var(&cyberfb_default, &par);
1102     
1103     	    do_fb_set_var(&cyberfb_default, 1);
1104     	    cyberfb_get_var(&fb_display[0].var, -1, &fb_info);
1105     	    cyberfb_set_disp(-1, &fb_info);
1106     	    do_install_cmap(0, &fb_info);
1107     
1108     	    if (register_framebuffer(&fb_info) < 0) {
1109     		    DPRINTK("EXIT - register_framebuffer failed\n");
1110     		    release_mem_region(CyberMem_phys, 0x400000);
1111     		    release_mem_region(CyberRegs_phys, 0x10000);
1112     		    return -EINVAL;
1113     	    }
1114     
1115     	    printk("fb%d: %s frame buffer device, using %ldK of video memory\n",
1116     		   GET_FB_IDX(fb_info.node), fb_info.modename, CyberSize>>10);
1117     
1118     	    /* TODO: This driver cannot be unloaded yet */
1119     	    MOD_INC_USE_COUNT;
1120     	    DPRINTK("EXIT\n");
1121     	    return 0;
1122     	}
1123     	return -ENXIO;
1124     }
1125     
1126     
1127     static int Cyberfb_switch(int con, struct fb_info *info)
1128     {
1129             DPRINTK("ENTER\n");
1130     	/* Do we have to save the colormap? */
1131     	if (fb_display[currcon].cmap.len) {
1132     		fb_get_cmap(&fb_display[currcon].cmap, 1, Cyber_getcolreg,
1133     			    info);
1134     	}
1135     
1136     	do_fb_set_var(&fb_display[con].var, 1);
1137     	currcon = con;
1138     	/* Install new colormap */
1139     	do_install_cmap(con, info);
1140     	DPRINTK("EXIT\n");
1141     	return(0);
1142     }
1143     
1144     
1145     /*
1146      *    Update the `var' structure (called by fbcon.c)
1147      *
1148      *    This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
1149      *    Since it's called by a kernel driver, no range checking is done.
1150      */
1151     
1152     static int Cyberfb_updatevar(int con, struct fb_info *info)
1153     {
1154     	DPRINTK("Enter - Exit\n");
1155     	return(0);
1156     }
1157     
1158     
1159     /*
1160      *    Get a Video Mode
1161      */
1162     
1163     static int __init get_video_mode(const char *name)
1164     {
1165     	int i;
1166     
1167     	DPRINTK("ENTER\n");
1168     	for (i = 0; i < NUM_TOTAL_MODES; i++) {
1169     		if (!strcmp(name, cyberfb_predefined[i].name)) {
1170     			cyberfb_default = cyberfb_predefined[i].var;
1171     			cyberfb_usermode = 1;
1172     			DPRINTK("EXIT - Matched predefined mode\n");
1173     			return(i);
1174     		}
1175     	}
1176     	return(0);
1177     }
1178     
1179     
1180     /*
1181      *    Text console acceleration
1182      */
1183     
1184     #ifdef FBCON_HAS_CFB8
1185     static void fbcon_cyber8_bmove(struct display *p, int sy, int sx, int dy,
1186     			       int dx, int height, int width)
1187     {
1188     	DPRINTK("ENTER\n");
1189     	sx *= 8; dx *= 8; width *= 8;
1190     	Cyber_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
1191     		     (u_short)(dy*fontheight(p)), (u_short)width,
1192     		     (u_short)(height*fontheight(p)), (u_short)S3_NEW);
1193     	DPRINTK("EXIT\n");
1194     }
1195     
1196     static void fbcon_cyber8_clear(struct vc_data *conp, struct display *p, int sy,
1197     			       int sx, int height, int width)
1198     {
1199     	unsigned char bg;
1200     
1201     	DPRINTK("ENTER\n");
1202     	sx *= 8; width *= 8;
1203     	bg = attr_bgcol_ec(p,conp);
1204     	Cyber_RectFill((u_short)sx,
1205     		       (u_short)(sy*fontheight(p)),
1206     		       (u_short)width,
1207     		       (u_short)(height*fontheight(p)),
1208     		       (u_short)S3_NEW,
1209     		       (u_short)bg);
1210     	DPRINTK("EXIT\n");
1211     }
1212     
1213     static void fbcon_cyber8_putc(struct vc_data *conp, struct display *p, int c,
1214     			      int yy, int xx)
1215     {
1216     	DPRINTK("ENTER\n");
1217     	Cyber_WaitBlit();
1218     	fbcon_cfb8_putc(conp, p, c, yy, xx);
1219     	DPRINTK("EXIT\n");
1220     }
1221     
1222     static void fbcon_cyber8_putcs(struct vc_data *conp, struct display *p,
1223     			       const unsigned short *s, int count,
1224     			       int yy, int xx)
1225     {
1226     	DPRINTK("ENTER\n");
1227     	Cyber_WaitBlit();
1228     	fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
1229     	DPRINTK("EXIT\n");
1230     }
1231     
1232     static void fbcon_cyber8_revc(struct display *p, int xx, int yy)
1233     {
1234     	DPRINTK("ENTER\n");
1235     	Cyber_WaitBlit();
1236     	fbcon_cfb8_revc(p, xx, yy);
1237     	DPRINTK("EXIT\n");
1238     }
1239     
1240     static struct display_switch fbcon_cyber8 = {
1241     	setup:		fbcon_cfb8_setup,
1242     	bmove:		fbcon_cyber8_bmove,
1243     	clear:		fbcon_cyber8_clear,
1244     	putc:		fbcon_cyber8_putc,
1245     	putcs:		fbcon_cyber8_putcs,
1246     	revc:		fbcon_cyber8_revc,
1247     	clear_margins:	fbcon_cfb8_clear_margins,
1248     	fontwidthmask:	FONTWIDTH(8)
1249     };
1250     #endif
1251     
1252     
1253     #ifdef MODULE
1254     MODULE_LICENSE("GPL");
1255     
1256     int init_module(void)
1257     {
1258     	return cyberfb_init();
1259     }
1260     
1261     void cleanup_module(void)
1262     {
1263     	/* Not reached because the usecount will never be
1264     	   decremented to zero */
1265     	unregister_framebuffer(&fb_info);
1266     	/* TODO: clean up ... */
1267     }
1268     #endif /* MODULE */
1269     
1270     /*
1271      *
1272      * Low level initialization routines for the CyberVision64 graphics card
1273      *
1274      * Most of the following code is from cvision_core.c
1275      *
1276      */
1277     
1278     #define MAXPIXELCLOCK 135000000 /* safety */
1279     
1280     #ifdef CV_AGGRESSIVE_TIMING
1281     long cv64_memclk = 55000000;
1282     #else
1283     long cv64_memclk = 50000000;
1284     #endif
1285     
1286     /*********************/
1287     
1288     static unsigned char clocks[]={
1289       0x13, 0x61, 0x6b, 0x6d, 0x51, 0x69, 0x54, 0x69,
1290       0x4f, 0x68, 0x6b, 0x6b, 0x18, 0x61, 0x7b, 0x6c,
1291       0x51, 0x67, 0x24, 0x62, 0x56, 0x67, 0x77, 0x6a,
1292       0x1d, 0x61, 0x53, 0x66, 0x6b, 0x68, 0x79, 0x69,
1293       0x7c, 0x69, 0x7f, 0x69, 0x22, 0x61, 0x54, 0x65,
1294       0x56, 0x65, 0x58, 0x65, 0x67, 0x66, 0x41, 0x63,
1295       0x27, 0x61, 0x13, 0x41, 0x37, 0x62, 0x6b, 0x4d,
1296       0x23, 0x43, 0x51, 0x49, 0x79, 0x66, 0x54, 0x49,
1297       0x7d, 0x66, 0x34, 0x56, 0x4f, 0x63, 0x1f, 0x42,
1298       0x6b, 0x4b, 0x7e, 0x4d, 0x18, 0x41, 0x2a, 0x43,
1299       0x7b, 0x4c, 0x74, 0x4b, 0x51, 0x47, 0x65, 0x49,
1300       0x24, 0x42, 0x68, 0x49, 0x56, 0x47, 0x75, 0x4a,
1301       0x77, 0x4a, 0x31, 0x43, 0x1d, 0x41, 0x71, 0x49,
1302       0x53, 0x46, 0x29, 0x42, 0x6b, 0x48, 0x1f, 0x41,
1303       0x79, 0x49, 0x6f, 0x48, 0x7c, 0x49, 0x38, 0x43,
1304       0x7f, 0x49, 0x5d, 0x46, 0x22, 0x41, 0x53, 0x45,
1305       0x54, 0x45, 0x55, 0x45, 0x56, 0x45, 0x57, 0x45,
1306       0x58, 0x45, 0x25, 0x41, 0x67, 0x46, 0x5b, 0x45,
1307       0x41, 0x43, 0x78, 0x47, 0x27, 0x41, 0x51, 0x44,
1308       0x13, 0x21, 0x7d, 0x47, 0x37, 0x42, 0x71, 0x46,
1309       0x6b, 0x2d, 0x14, 0x21, 0x23, 0x23, 0x7d, 0x2f,
1310       0x51, 0x29, 0x61, 0x2b, 0x79, 0x46, 0x1d, 0x22,
1311       0x54, 0x29, 0x45, 0x27, 0x7d, 0x46, 0x7f, 0x46,
1312       0x4f, 0x43, 0x2f, 0x41, 0x1f, 0x22, 0x6a, 0x2b,
1313       0x6b, 0x2b, 0x5b, 0x29, 0x7e, 0x2d, 0x65, 0x44,
1314       0x18, 0x21, 0x5e, 0x29, 0x2a, 0x23, 0x45, 0x26,
1315       0x7b, 0x2c, 0x19, 0x21, 0x74, 0x2b, 0x75, 0x2b,
1316       0x51, 0x27, 0x3f, 0x25, 0x65, 0x29, 0x40, 0x25,
1317       0x24, 0x22, 0x41, 0x25, 0x68, 0x29, 0x42, 0x25,
1318       0x56, 0x27, 0x7e, 0x2b, 0x75, 0x2a, 0x1c, 0x21,
1319       0x77, 0x2a, 0x4f, 0x26, 0x31, 0x23, 0x6f, 0x29,
1320       0x1d, 0x21, 0x32, 0x23, 0x71, 0x29, 0x72, 0x29,
1321       0x53, 0x26, 0x69, 0x28, 0x29, 0x22, 0x75, 0x29,
1322       0x6b, 0x28, 0x1f, 0x21, 0x1f, 0x21, 0x6d, 0x28,
1323       0x79, 0x29, 0x2b, 0x22, 0x6f, 0x28, 0x59, 0x26,
1324       0x7c, 0x29, 0x7d, 0x29, 0x38, 0x23, 0x21, 0x21,
1325       0x7f, 0x29, 0x39, 0x23, 0x5d, 0x26, 0x75, 0x28,
1326       0x22, 0x21, 0x77, 0x28, 0x53, 0x25, 0x6c, 0x27,
1327       0x54, 0x25, 0x61, 0x26, 0x55, 0x25, 0x30, 0x22,
1328       0x56, 0x25, 0x63, 0x26, 0x57, 0x25, 0x71, 0x27,
1329       0x58, 0x25, 0x7f, 0x28, 0x25, 0x21, 0x74, 0x27,
1330       0x67, 0x26, 0x40, 0x23, 0x5b, 0x25, 0x26, 0x21,
1331       0x41, 0x23, 0x34, 0x22, 0x78, 0x27, 0x6b, 0x26,
1332       0x27, 0x21, 0x35, 0x22, 0x51, 0x24, 0x7b, 0x27,
1333       0x13, 0x1,  0x13, 0x1,  0x7d, 0x27, 0x4c, 0x9,
1334       0x37, 0x22, 0x5b, 0xb,  0x71, 0x26, 0x5c, 0xb,
1335       0x6b, 0xd,  0x47, 0x23, 0x14, 0x1,  0x4f, 0x9,
1336       0x23, 0x3,  0x75, 0x26, 0x7d, 0xf,  0x1c, 0x2,
1337       0x51, 0x9,  0x59, 0x24, 0x61, 0xb,  0x69, 0x25,
1338       0x79, 0x26, 0x34, 0x5,  0x1d, 0x2,  0x6b, 0x25,
1339       0x54, 0x9,  0x35, 0x5,  0x45, 0x7,  0x6d, 0x25,
1340       0x7d, 0x26, 0x16, 0x1,  0x7f, 0x26, 0x77, 0xd,
1341       0x4f, 0x23, 0x78, 0xd,  0x2f, 0x21, 0x27, 0x3,
1342       0x1f, 0x2,  0x59, 0x9,  0x6a, 0xb,  0x73, 0x25,
1343       0x6b, 0xb,  0x63, 0x24, 0x5b, 0x9,  0x20, 0x2,
1344       0x7e, 0xd,  0x4b, 0x7,  0x65, 0x24, 0x43, 0x22,
1345       0x18, 0x1,  0x6f, 0xb,  0x5e, 0x9,  0x70, 0xb,
1346       0x2a, 0x3,  0x33, 0x4,  0x45, 0x6,  0x60, 0x9,
1347       0x7b, 0xc,  0x19, 0x1,  0x19, 0x1,  0x7d, 0xc,
1348       0x74, 0xb,  0x50, 0x7,  0x75, 0xb,  0x63, 0x9,
1349       0x51, 0x7,  0x23, 0x2,  0x3f, 0x5,  0x1a, 0x1,
1350       0x65, 0x9,  0x2d, 0x3,  0x40, 0x5,  0x0,  0x0,
1351     };
1352     
1353     /* Console colors */
1354     unsigned char cvconscolors[16][3] = {	/* background, foreground, hilite */
1355       /*  R     G     B  */
1356       {0x30, 0x30, 0x30},
1357       {0x00, 0x00, 0x00},
1358       {0x80, 0x00, 0x00},
1359       {0x00, 0x80, 0x00},
1360       {0x00, 0x00, 0x80},
1361       {0x80, 0x80, 0x00},
1362       {0x00, 0x80, 0x80},
1363       {0x80, 0x00, 0x80},
1364       {0xff, 0xff, 0xff},
1365       {0x40, 0x40, 0x40},
1366       {0xff, 0x00, 0x00},
1367       {0x00, 0xff, 0x00},
1368       {0x00, 0x00, 0xff},
1369       {0xff, 0xff, 0x00},
1370       {0x00, 0xff, 0xff},
1371       {0x00, 0x00, 0xff}
1372     };
1373     
1374     /* -------------------- Hardware specific routines ------------------------- */
1375     
1376     /* Read Attribute Controller Register=idx */
1377     inline unsigned char RAttr (volatile unsigned char *regs, short idx)
1378     {
1379     	wb_64 (regs, ACT_ADDRESS_W, idx);
1380     	mb();
1381     	udelay(100);
1382     	return (rb_64(regs, ACT_ADDRESS_R));
1383     }
1384     
1385     /* Read Sequencer Register=idx */
1386     inline unsigned char RSeq (volatile unsigned char *regs, short idx)
1387     {
1388     	wb_64 (regs, SEQ_ADDRESS, idx);
1389     	mb();
1390     	return (rb_64(regs, SEQ_ADDRESS_R));
1391     }
1392     
1393     /* Read CRT Controller Register=idx */
1394     inline unsigned char RCrt (volatile unsigned char *regs, short idx)
1395     {
1396     	wb_64 (regs, CRT_ADDRESS, idx);
1397     	mb();
1398     	return (rb_64(regs, CRT_ADDRESS_R));
1399     }
1400     
1401     /* Read Graphics Controller Register=idx */
1402     inline unsigned char RGfx (volatile unsigned char *regs, short idx)
1403     {
1404     	wb_64 (regs, GCT_ADDRESS, idx);
1405     	mb();
1406     	return (rb_64(regs, GCT_ADDRESS_R));
1407     }
1408     
1409     /*
1410      * Special wakeup/passthrough registers on graphics boards
1411      */
1412     
1413     inline void cv64_write_port (unsigned short bits,
1414     			     volatile unsigned char *base)
1415     {
1416     	volatile unsigned char *addr;
1417     	static unsigned char cvportbits = 0; /* Mirror port bits here */
1418     	DPRINTK("ENTER\n");
1419     
1420     	addr = base + 0x40001;
1421     	if (bits & 0x8000) {
1422     		cvportbits |= bits & 0xff; /* Set bits */
1423     		DPRINTK("Set bits: %04x\n", bits);
1424     	} else {
1425     		bits = bits & 0xff;
1426     		bits = (~bits) & 0xff;
1427     		cvportbits &= bits; /* Clear bits */
1428     		DPRINTK("Clear bits: %04x\n", bits);
1429     	}
1430     
1431     	*addr = cvportbits;
1432     	DPRINTK("EXIT\n");
1433     }
1434     
1435     /*
1436      * Monitor switch on CyberVision board
1437      *
1438      *  toggle:
1439      *    0 = CyberVision Signal
1440      *    1 = Amiga Signal
1441      *  board = board addr
1442      *
1443      */
1444     inline void cvscreen (int toggle, volatile unsigned char *board)
1445     {
1446     	DPRINTK("ENTER\n");
1447     	if (toggle == 1) {
1448     		DPRINTK("Show Amiga video\n");
1449     		cv64_write_port (0x10, board);
1450     	} else {
1451     		DPRINTK("Show CyberVision video\n");
1452     		cv64_write_port (0x8010, board);
1453     	}
1454     	DPRINTK("EXIT\n");
1455     }
1456     
1457     /* Control screen display */
1458     /* toggle: 0 = on, 1 = off */
1459     /* board = registerbase */
1460     inline void gfx_on_off(int toggle, volatile unsigned char *regs)
1461     {
1462     	int r;
1463     	DPRINTK("ENTER\n");
1464     	
1465     	toggle &= 0x1;
1466     	toggle = toggle << 5;
1467     	DPRINTK("Turn display %s\n", (toggle ? "off" : "on"));
1468     	
1469     	r = (int) RSeq(regs, SEQ_ID_CLOCKING_MODE);
1470     	r &= 0xdf;	/* Set bit 5 to 0 */
1471     	
1472     	WSeq (regs, SEQ_ID_CLOCKING_MODE, r | toggle);
1473     	DPRINTK("EXIT\n");
1474     }
1475     
1476     /*
1477      * Computes M, N, and R values from
1478      * given input frequency. It uses a table of
1479      * precomputed values, to keep CPU time low.
1480      *
1481      * The return value consist of:
1482      * lower byte:  Bits 4-0: N Divider Value
1483      *	        Bits 5-6: R Value          for e.g. SR10 or SR12
1484      * higher byte: Bits 0-6: M divider value  for e.g. SR11 or SR13
1485      */
1486     static unsigned short cv64_compute_clock(unsigned long freq)
1487     {
1488     	static unsigned char *mnr, *save;	/* M, N + R vals */
1489     	unsigned long work_freq, r;
1490     	unsigned short erg;
1491     	long diff, d2;
1492     
1493     	DPRINTK("ENTER\n");
1494     	if (freq < 12500000 || freq > MAXPIXELCLOCK) {
1495     		printk("CV64 driver: Illegal clock frequency %ld, using 25MHz\n",
1496     		       freq);
1497     		freq = 25000000;
1498     	}
1499     	DPRINTK("Freq = %ld\n", freq);
1500     	mnr = clocks;	/* there the vals are stored */
1501     	d2 = 0x7fffffff;
1502     
1503     	while (*mnr) {	/* mnr vals are 0-terminated */
1504     		work_freq = (0x37EE * (mnr[0] + 2)) / ((mnr[1] & 0x1F) + 2);
1505     
1506     		r = (mnr[1] >> 5) & 0x03;
1507     		if (r != 0) {
1508     			work_freq = work_freq >> r;	/* r is the freq divider */
1509     		}
1510     
1511     		work_freq *= 0x3E8;	/* 2nd part of OSC */
1512     
1513     		diff = abs(freq - work_freq);
1514     
1515     		if (d2 >= diff) {
1516     			d2 = diff;
1517     			/* In save are the vals for minimal diff */
1518     			save = mnr;
1519     		}
1520     		mnr += 2;
1521     	}
1522     	erg = *((unsigned short *)save);
1523     
1524     	DPRINTK("EXIT\n");
1525     	return (erg);
1526     }
1527     
1528     static int cv_has_4mb (volatile unsigned char *fb)
1529     {
1530     	volatile unsigned long *tr, *tw;
1531     	DPRINTK("ENTER\n");
1532     
1533     	/* write patterns in memory and test if they can be read */
1534     	tw = (volatile unsigned long *) fb;
1535     	tr = (volatile unsigned long *) (fb + 0x02000000);
1536     
1537     	*tw = 0x87654321;
1538     	
1539     	if (*tr != 0x87654321) {
1540     		DPRINTK("EXIT - <4MB\n");
1541     		return (0);
1542     	}
1543     
1544     	/* upper memory region */
1545     	tw = (volatile unsigned long *) (fb + 0x00200000);
1546     	tr = (volatile unsigned long *) (fb + 0x02200000);
1547     
1548     	*tw = 0x87654321;
1549     
1550     	if (*tr != 0x87654321) {
1551     		DPRINTK("EXIT - <4MB\n");
1552     		return (0);
1553     	}
1554     
1555     	*tw = 0xAAAAAAAA;
1556     
1557     	if (*tr != 0xAAAAAAAA) {
1558     		DPRINTK("EXIT - <4MB\n");
1559     		return (0);
1560     	}
1561     
1562     	*tw = 0x55555555;
1563     
1564     	if (*tr != 0x55555555) {
1565     		DPRINTK("EXIT - <4MB\n");
1566     		return (0);
1567     	}
1568     
1569     	DPRINTK("EXIT\n");
1570     	return (1);
1571     }
1572     
1573     static void cv64_board_init (void)
1574     {
1575     	volatile unsigned char *regs = CyberRegs;
1576     	int i;
1577     	unsigned int clockpar;
1578     	unsigned char test;
1579     	
1580     	DPRINTK("ENTER\n");
1581     
1582     	/*
1583     	 * Special CyberVision 64 board operations
1584     	 */
1585     	/* Reset board */
1586     	for (i = 0; i < 6; i++) {
1587     		cv64_write_port (0xff, CyberBase);
1588     	}
1589     	/* Return to operational mode */
1590     	cv64_write_port (0x8004, CyberBase);
1591     	
1592     	/*
1593     	 * Generic (?) S3 chip wakeup
1594     	 */
1595     	/* Disable I/O & memory decoders, video in setup mode */
1596     	wb_64 (regs, SREG_VIDEO_SUBS_ENABLE, 0x10);
1597     	/* Video responds to cmds, addrs & data */
1598     	wb_64 (regs, SREG_OPTION_SELECT, 0x1);
1599     	/* Enable I/O & memory decoders, video in operational mode */
1600     	wb_64 (regs, SREG_VIDEO_SUBS_ENABLE, 0x8);
1601     	/* VGA color emulation, enable cpu access to display mem */ 
1602     	wb_64 (regs, GREG_MISC_OUTPUT_W, 0x03);
1603     	/* Unlock S3 VGA regs */
1604     	WCrt (regs, CRT_ID_REGISTER_LOCK_1, 0x48); 
1605     	/* Unlock system control & extension registers */
1606     	WCrt (regs, CRT_ID_REGISTER_LOCK_2, 0xA5);
1607     /* GRF - Enable interrupts */
1608     	/* Enable enhanced regs access, Ready cntl 0 wait states */
1609     	test = RCrt (regs, CRT_ID_SYSTEM_CONFIG);
1610     	test = test | 0x01;		/* enable enhanced register access */
1611     	test = test & 0xEF;		/* clear bit 4, 0 wait state */
1612     	WCrt (regs, CRT_ID_SYSTEM_CONFIG, test);
1613     	/*
1614     	 * bit 0=1: Enable enhaced mode functions
1615     	 * bit 2=0: Enhanced mode 8+ bits/pixel
1616     	 * bit 4=1: Enable linear addressing
1617     	 * bit 5=1: Enable MMIO
1618     	 */
1619     	wb_64 (regs, ECR_ADV_FUNC_CNTL, 0x31);
1620     	/*
1621     	 * bit 0=1: Color emulation
1622     	 * bit 1=1: Enable CPU access to display memory
1623     	 * bit 5=1: Select high 64K memory page
1624     	 */
1625     /* GRF - 0xE3 */
1626     	wb_64 (regs, GREG_MISC_OUTPUT_W, 0x23);
1627     	
1628     	/* Cpu base addr */
1629     	WCrt (regs, CRT_ID_EXT_SYS_CNTL_4, 0x0);
1630     	
1631     	/* Reset. This does nothing on Trio, but standard VGA practice */
1632     	/* WSeq (CyberRegs, SEQ_ID_RESET, 0x03); */
1633     	/* Character clocks 8 dots wide */
1634     	WSeq (regs, SEQ_ID_CLOCKING_MODE, 0x01);
1635     	/* Enable cpu write to all color planes */
1636     	WSeq (regs, SEQ_ID_MAP_MASK, 0x0F);
1637     	/* Font table in 1st 8k of plane 2, font A=B disables swtich */
1638     	WSeq (regs, SEQ_ID_CHAR_MAP_SELECT, 0x0);
1639     	/* Allow mem access to 256kb */
1640     	WSeq (regs, SEQ_ID_MEMORY_MODE, 0x2);
1641     	/* Unlock S3 extensions to VGA Sequencer regs */
1642     	WSeq (regs, SEQ_ID_UNLOCK_EXT, 0x6);
1643     	
1644     	/* Enable 4MB fast page mode */
1645     	test = RSeq (regs, SEQ_ID_BUS_REQ_CNTL);
1646     	test = test | 1 << 6;
1647     	WSeq (regs, SEQ_ID_BUS_REQ_CNTL, test);
1648     	
1649     	/* Faster LUT write: 1 DCLK LUT write cycle, RAMDAC clk doubled */
1650     	WSeq (regs, SEQ_ID_RAMDAC_CNTL, 0xC0);
1651     
1652     	/* Clear immediate clock load bit */
1653     	test = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
1654     	test = test & 0xDF;
1655     	/* If > 55MHz, enable 2 cycle memory write */
1656     	if (cv64_memclk >= 55000000) {
1657     		test |= 0x80;
1658     	}
1659     	WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, test);
1660     
1661     	/* Set MCLK value */
1662     	clockpar = cv64_compute_clock (cv64_memclk);
1663     	test = (clockpar & 0xFF00) >> 8;
1664     	WSeq (regs, SEQ_ID_MCLK_HI, test);
1665     	test = clockpar & 0xFF;
1666     	WSeq (regs, SEQ_ID_MCLK_LO, test);
1667     
1668     	/* Chip rev specific: Not in my Trio manual!!! */
1669     	if (RCrt (regs, CRT_ID_REVISION) == 0x10)
1670     		WSeq (regs, SEQ_ID_MORE_MAGIC, test);
1671     
1672     	/* We now load an 25 MHz, 31kHz, 640x480 standard VGA Mode. */
1673     
1674     	/* Set DCLK value */
1675     	WSeq (regs, SEQ_ID_DCLK_HI, 0x13);
1676     	WSeq (regs, SEQ_ID_DCLK_LO, 0x41);
1677     
1678     	/* Load DCLK (and MCLK?) immediately */
1679     	test = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
1680     	test = test | 0x22;
1681     	WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, test);
1682     
1683     	/* Enable loading of DCLK */
1684     	test = rb_64(regs, GREG_MISC_OUTPUT_R);
1685     	test = test | 0x0C;
1686     	wb_64 (regs, GREG_MISC_OUTPUT_W, test);
1687     
1688     	/* Turn off immediate xCLK load */
1689     	WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, 0x2);
1690     
1691     	/* Horizontal character clock counts */
1692     	/* 8 LSB of 9 bits = total line - 5 */
1693     	WCrt (regs, CRT_ID_HOR_TOTAL, 0x5F);
1694     	/* Active display line */
1695     	WCrt (regs, CRT_ID_HOR_DISP_ENA_END, 0x4F);
1696     	/* Blank assertion start */
1697     	WCrt (regs, CRT_ID_START_HOR_BLANK, 0x50);
1698     	/* Blank assertion end */
1699     	WCrt (regs, CRT_ID_END_HOR_BLANK, 0x82);
1700     	/* HSYNC assertion start */
1701     	WCrt (regs, CRT_ID_START_HOR_RETR, 0x54);
1702     	/* HSYNC assertion end */
1703     	WCrt (regs, CRT_ID_END_HOR_RETR, 0x80);
1704     	WCrt (regs, CRT_ID_VER_TOTAL, 0xBF);
1705     	WCrt (regs, CRT_ID_OVERFLOW, 0x1F);
1706     	WCrt (regs, CRT_ID_PRESET_ROW_SCAN, 0x0);
1707     	WCrt (regs, CRT_ID_MAX_SCAN_LINE, 0x40);
1708     	WCrt (regs, CRT_ID_CURSOR_START, 0x00);
1709     	WCrt (regs, CRT_ID_CURSOR_END, 0x00);
1710     	WCrt (regs, CRT_ID_START_ADDR_HIGH, 0x00);
1711     	WCrt (regs, CRT_ID_START_ADDR_LOW, 0x00);
1712     	WCrt (regs, CRT_ID_CURSOR_LOC_HIGH, 0x00);
1713     	WCrt (regs, CRT_ID_CURSOR_LOC_LOW, 0x00);
1714     	WCrt (regs, CRT_ID_START_VER_RETR, 0x9C);
1715     	WCrt (regs, CRT_ID_END_VER_RETR, 0x0E);
1716     	WCrt (regs, CRT_ID_VER_DISP_ENA_END, 0x8F);
1717     	WCrt (regs, CRT_ID_SCREEN_OFFSET, 0x50);
1718     	WCrt (regs, CRT_ID_UNDERLINE_LOC, 0x00);
1719     	WCrt (regs, CRT_ID_START_VER_BLANK, 0x96);
1720     	WCrt (regs, CRT_ID_END_VER_BLANK, 0xB9);
1721     	WCrt (regs, CRT_ID_MODE_CONTROL, 0xE3);
1722     	WCrt (regs, CRT_ID_LINE_COMPARE, 0xFF);
1723     	WCrt (regs, CRT_ID_BACKWAD_COMP_3, 0x10);	/* FIFO enabled */
1724     	WCrt (regs, CRT_ID_MISC_1, 0x35);
1725     	WCrt (regs, CRT_ID_DISPLAY_FIFO, 0x5A);
1726     	WCrt (regs, CRT_ID_EXT_MEM_CNTL_2, 0x70);
1727     	WCrt (regs, CRT_ID_LAW_POS_LO, 0x40);
1728     	WCrt (regs, CRT_ID_EXT_MEM_CNTL_3, 0xFF);
1729     
1730     	WGfx (regs, GCT_ID_SET_RESET, 0x0);
1731     	WGfx (regs, GCT_ID_ENABLE_SET_RESET, 0x0);
1732     	WGfx (regs, GCT_ID_COLOR_COMPARE, 0x0);
1733     	WGfx (regs, GCT_ID_DATA_ROTATE, 0x0);
1734     	WGfx (regs, GCT_ID_READ_MAP_SELECT, 0x0);
1735     	WGfx (regs, GCT_ID_GRAPHICS_MODE, 0x40);
1736     	WGfx (regs, GCT_ID_MISC, 0x01);
1737     	WGfx (regs, GCT_ID_COLOR_XCARE, 0x0F);
1738     	WGfx (regs, GCT_ID_BITMASK, 0xFF);
1739     
1740     	/* Colors for text mode */
1741     	for (i = 0; i < 0xf; i++)
1742     		WAttr (regs, i, i);
1743     
1744     	WAttr (regs, ACT_ID_ATTR_MODE_CNTL, 0x41);
1745     	WAttr (regs, ACT_ID_OVERSCAN_COLOR, 0x01);
1746     	WAttr (regs, ACT_ID_COLOR_PLANE_ENA, 0x0F);
1747     	WAttr (regs, ACT_ID_HOR_PEL_PANNING, 0x0);
1748     	WAttr (regs, ACT_ID_COLOR_SELECT, 0x0);
1749     
1750     	wb_64 (regs, VDAC_MASK, 0xFF);
1751     
1752     	*((unsigned long *) (regs + ECR_FRGD_COLOR)) = 0xFF;
1753     	*((unsigned long *) (regs + ECR_BKGD_COLOR)) = 0;
1754     
1755     	/* Colors initially set to grayscale */
1756     
1757     	wb_64 (regs, VDAC_ADDRESS_W, 0);
1758     	for (i = 255; i >= 0; i--) {
1759     		wb_64(regs, VDAC_DATA, i);
1760     		wb_64(regs, VDAC_DATA, i);
1761     		wb_64(regs, VDAC_DATA, i);
1762     	}
1763     
1764     	/* GFx hardware cursor off */
1765     	WCrt (regs, CRT_ID_HWGC_MODE, 0x00);
1766     
1767     	/* Set first to 4MB, so test will work */
1768     	WCrt (regs, CRT_ID_LAW_CNTL, 0x13);
1769     	/* Find "correct" size of fbmem of Z3 board */
1770     	if (cv_has_4mb (CyberMem)) {
1771     		CyberSize = 1024 * 1024 * 4;
1772     		WCrt (regs, CRT_ID_LAW_CNTL, 0x13);
1773     		DPRINTK("4MB board\n");
1774     	} else {
1775     		CyberSize = 1024 * 1024 * 2;
1776     		WCrt (regs, CRT_ID_LAW_CNTL, 0x12);
1777     		DPRINTK("2MB board\n");
1778     	}
1779     
1780     	/* Initialize graphics engine */
1781     	Cyber_WaitBlit();
1782     	vgaw16 (regs, ECR_FRGD_MIX, 0x27);
1783     	vgaw16 (regs, ECR_BKGD_MIX, 0x07);
1784     	vgaw16 (regs, ECR_READ_REG_DATA, 0x1000);
1785     	udelay(200);
1786     	vgaw16 (regs, ECR_READ_REG_DATA, 0x2000);
1787     	Cyber_WaitBlit();
1788     	vgaw16 (regs, ECR_READ_REG_DATA, 0x3FFF);
1789     	Cyber_WaitBlit();
1790     	udelay(200);
1791     	vgaw16 (regs, ECR_READ_REG_DATA, 0x4FFF);
1792     	Cyber_WaitBlit();
1793     	vgaw16 (regs, ECR_BITPLANE_WRITE_MASK, ~0);
1794     	Cyber_WaitBlit();
1795     	vgaw16 (regs, ECR_READ_REG_DATA, 0xE000);
1796     	vgaw16 (regs, ECR_CURRENT_Y_POS2, 0x00);
1797     	vgaw16 (regs, ECR_CURRENT_X_POS2, 0x00);
1798     	vgaw16 (regs, ECR_READ_REG_DATA, 0xA000);
1799     	vgaw16 (regs, ECR_DEST_Y__AX_STEP, 0x00);
1800     	vgaw16 (regs, ECR_DEST_Y2__AX_STEP2, 0x00);
1801     	vgaw16 (regs, ECR_DEST_X__DIA_STEP, 0x00);
1802     	vgaw16 (regs, ECR_DEST_X2__DIA_STEP2, 0x00);
1803     	vgaw16 (regs, ECR_SHORT_STROKE, 0x00);
1804     	vgaw16 (regs, ECR_DRAW_CMD, 0x01);
1805     
1806     	Cyber_WaitBlit();
1807     
1808     	vgaw16 (regs, ECR_READ_REG_DATA, 0x4FFF);
1809     	vgaw16 (regs, ECR_BKGD_COLOR, 0x01);
1810     	vgaw16 (regs, ECR_FRGD_COLOR, 0x00);
1811     
1812     
1813     	/* Enable video display (set bit 5) */
1814     /* ARB - Would also seem to write to AR13.
1815      *       May want to use parts of WAttr to set JUST bit 5
1816      */
1817     	WAttr (regs, 0x33, 0);
1818     	
1819     /* GRF - function code ended here */
1820     
1821     	/* Turn gfx on again */
1822     	gfx_on_off (0, regs);
1823     
1824     	/* Pass-through */
1825     	cvscreen (0, CyberBase);
1826     
1827     	DPRINTK("EXIT\n");
1828     }
1829     
1830     static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode)
1831     {
1832       volatile unsigned char *regs = CyberRegs;
1833       int fx, fy;
1834       unsigned short mnr;
1835       unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS, VSE, VT;
1836       char LACE, DBLSCAN, TEXT, CONSOLE;
1837       int cr50, sr15, sr18, clock_mode, test;
1838       int m, n;
1839       int tfillm, temptym;
1840       int hmul;
1841     	
1842       /* ---------------- */
1843       int xres, hfront, hsync, hback;
1844       int yres, vfront, vsync, vback;
1845       int bpp;
1846     #if 0
1847       float freq_f;
1848     #endif
1849       long freq;
1850       /* ---------------- */
1851     	
1852       DPRINTK("ENTER\n");
1853       TEXT = 0;	/* if depth == 4 */
1854       CONSOLE = 0;	/* mode num == 255 (console) */
1855       fx = fy = 8;	/* force 8x8 font */
1856     
1857     /* GRF - Disable interrupts */	
1858     	
1859       gfx_on_off (1, regs);
1860     	
1861       switch (video_mode->bits_per_pixel) {
1862       case 15:
1863       case 16:
1864         hmul = 2;
1865         break;
1866     		
1867       default:
1868         hmul = 1;
1869         break;
1870       }
1871     	
1872       bpp = video_mode->bits_per_pixel;
1873       xres = video_mode->xres;
1874       hfront = video_mode->right_margin;
1875       hsync = video_mode->hsync_len;
1876       hback = video_mode->left_margin;
1877     
1878       LACE = 0;
1879       DBLSCAN = 0;
1880     
1881       if (video_mode->vmode & FB_VMODE_DOUBLE) {
1882         yres = video_mode->yres * 2;
1883         vfront = video_mode->lower_margin * 2;
1884         vsync = video_mode->vsync_len * 2;
1885         vback = video_mode->upper_margin * 2;
1886         DBLSCAN = 1;
1887       } else if (video_mode->vmode & FB_VMODE_INTERLACED) {
1888         yres = (video_mode->yres + 1) / 2;
1889         vfront = (video_mode->lower_margin + 1) / 2;
1890         vsync = (video_mode->vsync_len + 1) / 2;
1891         vback = (video_mode->upper_margin + 1) / 2;
1892         LACE = 1;
1893       } else {
1894         yres = video_mode->yres;
1895         vfront = video_mode->lower_margin;
1896         vsync = video_mode->vsync_len;
1897         vback = video_mode->upper_margin;
1898       }
1899     
1900       /* ARB Dropping custom setup method from cvision.c */
1901     #if 0
1902       if (cvision_custom_mode) {
1903         HBS = hbs / 8 * hmul;
1904         HBE = hbe / 8 * hmul;
1905         HSS = hss / 8 * hmul;
1906         HSE = hse / 8 * hmul;
1907         HT  = ht / 8 * hmul - 5;
1908     		
1909         VBS = vbs - 1;
1910         VSS = vss;
1911         VSE = vse;
1912         VBE = vbe;
1913         VT  = vt - 2;
1914       } else {
1915     #else
1916         {
1917     #endif
1918         HBS = hmul * (xres / 8);
1919         HBE = hmul * ((xres/8) + (hfront/8) + (hsync/8) + (hback/8) - 2);
1920         HSS = hmul * ((xres/8) + (hfront/8) + 2);
1921         HSE = hmul * ((xres/8) + (hfront/8) + (hsync/8) + 1);
1922         HT  = hmul * ((xres/8) + (hfront/8) + (hsync/8) + (hback/8));
1923     	
1924         VBS = yres;
1925         VBE = yres + vfront + vsync + vback - 2;
1926         VSS = yres + vfront - 1;
1927         VSE = yres + vfront + vsync - 1;
1928         VT  = yres + vfront + vsync + vback - 2;
1929       }
1930     
1931       wb_64 (regs, ECR_ADV_FUNC_CNTL, (TEXT ? 0x00 : 0x31));
1932     	
1933       if (TEXT)
1934         HDE = ((video_mode->xres + fx - 1) / fx) - 1;
1935       else
1936         HDE = (video_mode->xres + 3) * hmul / 8 - 1;
1937     	
1938       VDE = video_mode->yres - 1;
1939     
1940       WCrt (regs, CRT_ID_HWGC_MODE, 0x00);
1941       WCrt (regs, CRT_ID_EXT_DAC_CNTL, 0x00);
1942     	
1943       WSeq (regs, SEQ_ID_MEMORY_MODE,
1944     	(TEXT || (video_mode->bits_per_pixel == 1)) ? 0x06 : 0x0e);
1945       WGfx (regs, GCT_ID_READ_MAP_SELECT, 0x00);
1946       WSeq (regs, SEQ_ID_MAP_MASK,
1947     	(video_mode->bits_per_pixel == 1) ? 0x01 : 0xFF);
1948       WSeq (regs, SEQ_ID_CHAR_MAP_SELECT, 0x00);
1949     	
1950       /* cv64_compute_clock accepts arguments in Hz */
1951       /* pixclock is in ps ... convert to Hz */
1952     	
1953     #if 0
1954       freq_f = (1.0 / (float) video_mode->pixclock) * 1000000000;
1955       freq = ((long) freq_f) * 1000;
1956     #else
1957     /* freq = (long) ((long long)1000000000000 / (long long) video_mode->pixclock);
1958      */
1959       freq = (1000000000 / video_mode->pixclock) * 1000;
1960     #endif
1961     
1962       mnr = cv64_compute_clock (freq);
1963       WSeq (regs, SEQ_ID_DCLK_HI, ((mnr & 0xFF00) >> 8));
1964       WSeq (regs, SEQ_ID_DCLK_LO, (mnr & 0xFF));
1965     	
1966       /* Load display parameters into board */
1967       WCrt (regs, CRT_ID_EXT_HOR_OVF,
1968     	((HT & 0x100) ? 0x01 : 0x00) |
1969     	((HDE & 0x100) ? 0x02 : 0x00) |
1970     	((HBS & 0x100) ? 0x04 : 0x00) |
1971     	/* ((HBE & 0x40) ? 0x08 : 0x00) | */
1972     	((HSS & 0x100) ? 0x10 : 0x00) |
1973     	/* ((HSE & 0x20) ? 0x20 : 0x00) | */
1974     	(((HT-5) & 0x100) ? 0x40 : 0x00)
1975     	);
1976     	
1977       WCrt (regs, CRT_ID_EXT_VER_OVF,
1978     	0x40 |
1979     	((VT & 0x400) ? 0x01 : 0x00) |
1980     	((VDE & 0x400) ? 0x02 : 0x00) |
1981     	((VBS & 0x400) ? 0x04 : 0x00) |
1982     	((VSS & 0x400) ? 0x10 : 0x00)
1983     	);
1984     	
1985       WCrt (regs, CRT_ID_HOR_TOTAL, HT);
1986       WCrt (regs, CRT_ID_DISPLAY_FIFO, HT - 5);
1987       WCrt (regs, CRT_ID_HOR_DISP_ENA_END, ((HDE >= HBS) ? (HBS - 1) : HDE));
1988       WCrt (regs, CRT_ID_START_HOR_BLANK, HBS);
1989       WCrt (regs, CRT_ID_END_HOR_BLANK, ((HBE & 0x1F) | 0x80));
1990       WCrt (regs, CRT_ID_START_HOR_RETR, HSS);
1991       WCrt (regs, CRT_ID_END_HOR_RETR,
1992     	(HSE & 0x1F) |
1993     	((HBE & 0x20) ? 0x80 : 0x00)
1994     	);
1995       WCrt (regs, CRT_ID_VER_TOTAL, VT);
1996       WCrt (regs, CRT_ID_OVERFLOW,
1997     	0x10 |
1998     	((VT & 0x100) ? 0x01 : 0x00) |
1999     	((VDE & 0x100) ? 0x02 : 0x00) |
2000     	((VSS & 0x100) ? 0x04 : 0x00) |
2001     	((VBS & 0x100) ? 0x08 : 0x00) |
2002     	((VT & 0x200) ? 0x20 : 0x00) |
2003     	((VDE & 0x200) ? 0x40 : 0x00) |
2004     	((VSS & 0x200) ? 0x80 : 0x00)
2005     	);
2006       WCrt (regs, CRT_ID_MAX_SCAN_LINE,
2007     	0x40 |
2008     	(DBLSCAN ? 0x80 : 0x00) |
2009     	((VBS & 0x200) ? 0x20 : 0x00) |
2010     	(TEXT ? ((fy - 1) & 0x1F) : 0x00)
2011     	);
2012     	
2013       WCrt (regs, CRT_ID_MODE_CONTROL, 0xE3);
2014     
2015       /* Text cursor */
2016     	
2017       if (TEXT) {
2018     #if 1
2019         WCrt (regs, CRT_ID_CURSOR_START, (fy & 0x1f) - 2);
2020         WCrt (regs, CRT_ID_CURSOR_END, (fy & 0x1F) - 1);
2021     #else
2022         WCrt (regs, CRT_ID_CURSOR_START, 0x00);
2023         WCrt (regs, CRT_ID_CURSOR_END, fy & 0x1F);
2024     #endif
2025         WCrt (regs, CRT_ID_UNDERLINE_LOC, (fy - 1) & 0x1F);
2026         WCrt (regs, CRT_ID_CURSOR_LOC_HIGH, 0x00);
2027         WCrt (regs, CRT_ID_CURSOR_LOC_LOW, 0x00);
2028       }
2029     	
2030       WCrt (regs, CRT_ID_START_ADDR_HIGH, 0x00);
2031       WCrt (regs, CRT_ID_START_ADDR_LOW, 0x00);
2032       WCrt (regs, CRT_ID_START_VER_RETR, VSS);
2033       WCrt (regs, CRT_ID_END_VER_RETR, (VSE & 0x0F));
2034       WCrt (regs, CRT_ID_VER_DISP_ENA_END, VDE);
2035       WCrt (regs, CRT_ID_START_VER_BLANK, VBS);
2036       WCrt (regs, CRT_ID_END_VER_BLANK, VBE);
2037       WCrt (regs, CRT_ID_LINE_COMPARE, 0xFF);
2038       WCrt (regs, CRT_ID_LACE_RETR_START, HT / 2);
2039       WCrt (regs, CRT_ID_LACE_CONTROL, (LACE ? 0x20 : 0x00));
2040       WGfx (regs, GCT_ID_GRAPHICS_MODE,
2041     	((TEXT || (video_mode->bits_per_pixel == 1)) ? 0x00 : 0x40));
2042       WGfx (regs, GCT_ID_MISC, (TEXT ? 0x04 : 0x01));
2043       WSeq (regs, SEQ_ID_MEMORY_MODE,
2044     	((TEXT || (video_mode->bits_per_pixel == 1)) ? 0x06 : 0x02));
2045     	
2046       wb_64 (regs, VDAC_MASK, 0xFF);
2047     	
2048       /* Blank border */
2049       test = RCrt (regs, CRT_ID_BACKWAD_COMP_2);
2050       WCrt (regs, CRT_ID_BACKWAD_COMP_2, (test | 0x20));
2051     	
2052       sr15 = RSeq (regs, SEQ_ID_CLKSYN_CNTL_2);
2053       sr15 &= 0xEF;
2054       sr18 = RSeq (regs, SEQ_ID_RAMDAC_CNTL);
2055       sr18 &= 0x7F;
2056       clock_mode = 0x00;
2057       cr50 = 0x00;
2058     	
2059       test = RCrt (regs, CRT_ID_EXT_MISC_CNTL_2);
2060       test &= 0xD;
2061     	
2062       /* Clear roxxler byte-swapping... */
2063       cv64_write_port (0x0040, CyberBase);
2064       cv64_write_port (0x0020, CyberBase);
2065     	
2066       switch (video_mode->bits_per_pixel) {
2067       case 1:
2068       case 4:	/* text */
2069         HDE = video_mode->xres / 16;
2070         break;
2071     		
2072       case 8:
2073         if (freq > 80000000) {
2074           clock_mode = 0x10 | 0x02;
2075           sr15 |= 0x10;
2076           sr18 |= 0x80;
2077         }
2078         HDE = video_mode->xres / 8;
2079         cr50 |= 0x00;
2080         break;
2081     		
2082       case 15:
2083         cv64_write_port (0x8020, CyberBase);
2084         clock_mode = 0x30;
2085         HDE = video_mode->xres / 4;
2086         cr50 |= 0x10;
2087         break;
2088     		
2089       case 16:
2090         cv64_write_port (0x8020, CyberBase);
2091         clock_mode = 0x50;
2092         HDE = video_mode->xres / 4;
2093         cr50 |= 0x10;
2094         break;
2095     		
2096       case 24:
2097       case 32:
2098         cv64_write_port (0x8040, CyberBase);
2099         clock_mode = 0xD0;
2100         HDE = video_mode->xres / 2;
2101         cr50 |= 0x30;
2102         break;
2103       }
2104     
2105       WCrt (regs, CRT_ID_EXT_MISC_CNTL_2, clock_mode | test);
2106       WSeq (regs, SEQ_ID_CLKSYN_CNTL_2, sr15);
2107       WSeq (regs, SEQ_ID_RAMDAC_CNTL, sr18);
2108       WCrt (regs, CRT_ID_SCREEN_OFFSET, HDE);
2109     
2110       WCrt (regs, CRT_ID_MISC_1, (TEXT ? 0x05 : 0x35));
2111     	
2112       test = RCrt (regs, CRT_ID_EXT_SYS_CNTL_2);
2113       test &= ~0x30;
2114       test |= (HDE >> 4) & 0x30;
2115       WCrt (regs, CRT_ID_EXT_SYS_CNTL_2, test);
2116     	
2117       /* Set up graphics engine */
2118       switch (video_mode->xres) {
2119       case 1024:
2120         cr50 |= 0x00;
2121         break;
2122     		
2123       case 640:
2124         cr50 |= 0x40;
2125         break;
2126     		
2127       case 800:
2128         cr50 |= 0x80;
2129         break;
2130     		
2131       case 1280:
2132         cr50 |= 0xC0;
2133         break;
2134     		
2135       case 1152:
2136         cr50 |= 0x01;
2137         break;
2138     		
2139       case 1600:
2140         cr50 |= 0x81;
2141         break;
2142     		
2143       default:	/* XXX */
2144         break;
2145       }
2146     	
2147       WCrt (regs, CRT_ID_EXT_SYS_CNTL_1, cr50);
2148     	
2149       udelay(100);
2150       WAttr (regs, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x08 : 0x41));
2151       udelay(100);
2152       WAttr (regs, ACT_ID_COLOR_PLANE_ENA,
2153     	 (video_mode->bits_per_pixel == 1) ? 0x01 : 0x0F);
2154       udelay(100);
2155     	
2156       tfillm = (96 * (cv64_memclk / 1000)) / 240000;
2157     	
2158       switch (video_mode->bits_per_pixel) {
2159       case 32:
2160       case 24:
2161         temptym = (24 * (cv64_memclk / 1000)) / (freq / 1000);
2162         break;
2163       case 15:
2164       case 16:
2165         temptym = (48 * (cv64_memclk / 1000)) / (freq / 1000);
2166         break;
2167       case 4:
2168         temptym = (192 * (cv64_memclk / 1000)) / (freq / 1000);
2169         break;
2170       default:
2171         temptym = (96 * (cv64_memclk / 1000)) / (freq / 1000);
2172         break;
2173       }
2174     	
2175       m = (temptym - tfillm - 9) / 2;
2176       if (m < 0)
2177         m = 0;
2178       m = (m & 0x1F) << 3;
2179       if (m < 0x18)
2180         m = 0x18;
2181       n = 0xFF;
2182     	
2183       WCrt (regs, CRT_ID_EXT_MEM_CNTL_2, m);
2184       WCrt (regs, CRT_ID_EXT_MEM_CNTL_3, n);
2185       udelay(10);
2186     	
2187       /* Text initialization */
2188     	
2189       if (TEXT) {
2190         /* Do text initialization here ! */
2191       }
2192     	
2193       if (CONSOLE) {
2194         int i;
2195         wb_64 (regs, VDAC_ADDRESS_W, 0);
2196         for (i = 0; i < 4; i++) {
2197           wb_64 (regs, VDAC_DATA, cvconscolors [i][0]);
2198           wb_64 (regs, VDAC_DATA, cvconscolors [i][1]);
2199           wb_64 (regs, VDAC_DATA, cvconscolors [i][2]);
2200         }
2201       }
2202     	
2203       WAttr (regs, 0x33, 0);
2204     	
2205       /* Turn gfx on again */
2206       gfx_on_off (0, (volatile unsigned char *) regs);
2207     	
2208       /* Pass-through */
2209       cvscreen (0, CyberBase);
2210     
2211     DPRINTK("EXIT\n");
2212     }
2213     
2214     void cvision_bitblt (u_short sx, u_short sy, u_short dx, u_short dy,
2215     		     u_short w, u_short h)
2216     {
2217     	volatile unsigned char *regs = CyberRegs;
2218     	unsigned short drawdir = 0;
2219     	
2220     	DPRINTK("ENTER\n");
2221     	if (sx > dx) {
2222     		drawdir |= 1 << 5;
2223     	} else {
2224     		sx += w - 1;
2225     		dx += w - 1;
2226     	}
2227     	
2228     	if (sy > dy) {
2229     		drawdir |= 1 << 7;
2230     	} else {
2231     		sy += h - 1;
2232     		dy += h - 1;
2233     	}
2234     	
2235     	Cyber_WaitBlit();
2236     	vgaw16 (regs, ECR_READ_REG_DATA, 0xA000);
2237     	vgaw16 (regs, ECR_BKGD_MIX, 0x7);
2238     	vgaw16 (regs, ECR_FRGD_MIX, 0x67);
2239     	vgaw16 (regs, ECR_BKGD_COLOR, 0x0);
2240     	vgaw16 (regs, ECR_FRGD_COLOR, 0x1);
2241     	vgaw16 (regs, ECR_BITPLANE_READ_MASK, 0x1);
2242     	vgaw16 (regs, ECR_BITPLANE_WRITE_MASK, 0xFFF);
2243     	vgaw16 (regs, ECR_CURRENT_Y_POS, sy);
2244     	vgaw16 (regs, ECR_CURRENT_X_POS, sx);
2245     	vgaw16 (regs, ECR_DEST_Y__AX_STEP, dy);
2246     	vgaw16 (regs, ECR_DEST_X__DIA_STEP, dx);
2247     	vgaw16 (regs, ECR_READ_REG_DATA, h - 1);
2248     	vgaw16 (regs, ECR_MAJ_AXIS_PIX_CNT, w - 1);
2249     	vgaw16 (regs, ECR_DRAW_CMD, 0xC051 | drawdir);
2250     	DPRINTK("EXIT\n");
2251     }
2252     
2253     void cvision_clear (u_short dx, u_short dy, u_short w, u_short h, u_short bg)
2254     {
2255     	volatile unsigned char *regs = CyberRegs;
2256     	DPRINTK("ENTER\n");
2257     	Cyber_WaitBlit();
2258     	vgaw16 (regs, ECR_FRGD_MIX, 0x0027);
2259     	vgaw16 (regs, ECR_FRGD_COLOR, bg);
2260     	vgaw16 (regs, ECR_READ_REG_DATA, 0xA000);
2261     	vgaw16 (regs, ECR_CURRENT_Y_POS, dy);
2262     	vgaw16 (regs, ECR_CURRENT_X_POS, dx);
2263     	vgaw16 (regs, ECR_READ_REG_DATA, h - 1);
2264     	vgaw16 (regs, ECR_MAJ_AXIS_PIX_CNT, w - 1);
2265     	vgaw16 (regs, ECR_DRAW_CMD, 0x40B1);	
2266     	DPRINTK("EXIT\n");
2267     }
2268     
2269     #ifdef CYBERFBDEBUG
2270     /*
2271      * Dump internal settings of CyberVision board
2272      */
2273     static void cv64_dump (void)
2274     {
2275     	volatile unsigned char *regs = CyberRegs;
2276     	DPRINTK("ENTER\n");
2277             /* Dump the VGA setup values */
2278     	*(regs + S3_CRTC_ADR) = 0x00;
2279     	DPRINTK("CR00 = %x\n", *(regs + S3_CRTC_DATA));
2280     	*(regs + S3_CRTC_ADR) = 0x01;
2281     	DPRINTK("CR01 = %x\n", *(regs + S3_CRTC_DATA));
2282     	*(regs + S3_CRTC_ADR) = 0x02;
2283     	DPRINTK("CR02 = %x\n", *(regs + S3_CRTC_DATA));
2284     	*(regs + S3_CRTC_ADR) = 0x03;
2285     	DPRINTK("CR03 = %x\n", *(regs + S3_CRTC_DATA));
2286     	*(regs + S3_CRTC_ADR) = 0x04;
2287     	DPRINTK("CR04 = %x\n", *(regs + S3_CRTC_DATA));
2288     	*(regs + S3_CRTC_ADR) = 0x05;
2289     	DPRINTK("CR05 = %x\n", *(regs + S3_CRTC_DATA));
2290     	*(regs + S3_CRTC_ADR) = 0x06;
2291     	DPRINTK("CR06 = %x\n", *(regs + S3_CRTC_DATA));
2292     	*(regs + S3_CRTC_ADR) = 0x07;
2293     	DPRINTK("CR07 = %x\n", *(regs + S3_CRTC_DATA));
2294     	*(regs + S3_CRTC_ADR) = 0x08;
2295     	DPRINTK("CR08 = %x\n", *(regs + S3_CRTC_DATA));
2296     	*(regs + S3_CRTC_ADR) = 0x09;
2297     	DPRINTK("CR09 = %x\n", *(regs + S3_CRTC_DATA));
2298     	*(regs + S3_CRTC_ADR) = 0x10;
2299     	DPRINTK("CR10 = %x\n", *(regs + S3_CRTC_DATA));
2300     	*(regs + S3_CRTC_ADR) = 0x11;
2301     	DPRINTK("CR11 = %x\n", *(regs + S3_CRTC_DATA));
2302     	*(regs + S3_CRTC_ADR) = 0x12;
2303     	DPRINTK("CR12 = %x\n", *(regs + S3_CRTC_DATA));
2304     	*(regs + S3_CRTC_ADR) = 0x13;
2305     	DPRINTK("CR13 = %x\n", *(regs + S3_CRTC_DATA));
2306     	*(regs + S3_CRTC_ADR) = 0x15;
2307     	DPRINTK("CR15 = %x\n", *(regs + S3_CRTC_DATA));
2308     	*(regs + S3_CRTC_ADR) = 0x16;
2309     	DPRINTK("CR16 = %x\n", *(regs + S3_CRTC_DATA));
2310     	*(regs + S3_CRTC_ADR) = 0x36;
2311     	DPRINTK("CR36 = %x\n", *(regs + S3_CRTC_DATA));
2312     	*(regs + S3_CRTC_ADR) = 0x37;
2313     	DPRINTK("CR37 = %x\n", *(regs + S3_CRTC_DATA));
2314     	*(regs + S3_CRTC_ADR) = 0x42;
2315     	DPRINTK("CR42 = %x\n", *(regs + S3_CRTC_DATA));
2316     	*(regs + S3_CRTC_ADR) = 0x43;
2317     	DPRINTK("CR43 = %x\n", *(regs + S3_CRTC_DATA));
2318     	*(regs + S3_CRTC_ADR) = 0x50;
2319     	DPRINTK("CR50 = %x\n", *(regs + S3_CRTC_DATA));
2320     	*(regs + S3_CRTC_ADR) = 0x51;
2321     	DPRINTK("CR51 = %x\n", *(regs + S3_CRTC_DATA));
2322     	*(regs + S3_CRTC_ADR) = 0x53;
2323     	DPRINTK("CR53 = %x\n", *(regs + S3_CRTC_DATA));
2324     	*(regs + S3_CRTC_ADR) = 0x58;
2325     	DPRINTK("CR58 = %x\n", *(regs + S3_CRTC_DATA));
2326     	*(regs + S3_CRTC_ADR) = 0x59;
2327     	DPRINTK("CR59 = %x\n", *(regs + S3_CRTC_DATA));
2328     	*(regs + S3_CRTC_ADR) = 0x5A;
2329     	DPRINTK("CR5A = %x\n", *(regs + S3_CRTC_DATA));
2330     	*(regs + S3_CRTC_ADR) = 0x5D;
2331     	DPRINTK("CR5D = %x\n", *(regs + S3_CRTC_DATA));
2332     	*(regs + S3_CRTC_ADR) = 0x5E;
2333     	DPRINTK("CR5E = %x\n", *(regs + S3_CRTC_DATA));
2334     	DPRINTK("MISC = %x\n", *(regs + GREG_MISC_OUTPUT_R));
2335     	*(regs + SEQ_ADDRESS) = 0x01;
2336     	DPRINTK("SR01 = %x\n", *(regs + SEQ_ADDRESS_R));
2337     	*(regs + SEQ_ADDRESS) = 0x02;
2338     	DPRINTK("SR02 = %x\n", *(regs + SEQ_ADDRESS_R));
2339     	*(regs + SEQ_ADDRESS) = 0x03;
2340     	DPRINTK("SR03 = %x\n", *(regs + SEQ_ADDRESS_R));
2341     	*(regs + SEQ_ADDRESS) = 0x09;
2342     	DPRINTK("SR09 = %x\n", *(regs + SEQ_ADDRESS_R));
2343     	*(regs + SEQ_ADDRESS) = 0x10;
2344     	DPRINTK("SR10 = %x\n", *(regs + SEQ_ADDRESS_R));
2345     	*(regs + SEQ_ADDRESS) = 0x11;
2346     	DPRINTK("SR11 = %x\n", *(regs + SEQ_ADDRESS_R));
2347     	*(regs + SEQ_ADDRESS) = 0x12;
2348     	DPRINTK("SR12 = %x\n", *(regs + SEQ_ADDRESS_R));
2349     	*(regs + SEQ_ADDRESS) = 0x13;
2350     	DPRINTK("SR13 = %x\n", *(regs + SEQ_ADDRESS_R));
2351     	*(regs + SEQ_ADDRESS) = 0x15;
2352     	DPRINTK("SR15 = %x\n", *(regs + SEQ_ADDRESS_R));
2353     	
2354     	return;
2355     }
2356     #endif
2357