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