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

1     /*
2      * drivers/video/clgenfb.c - driver for Cirrus Logic chipsets
3      *
4      * Copyright 1999-2001 Jeff Garzik <jgarzik@mandrakesoft.com>
5      *
6      * Contributors (thanks, all!)
7      *
8      *      Jeff Rugen:
9      *      Major contributions;  Motorola PowerStack (PPC and PCI) support,
10      *      GD54xx, 1280x1024 mode support, change MCLK based on VCLK.
11      *
12      *	Geert Uytterhoeven:
13      *	Excellent code review.
14      *
15      *	Lars Hecking:
16      *	Amiga updates and testing.
17      *
18      * Original clgenfb author:  Frank Neumann
19      *
20      * Based on retz3fb.c and clgen.c:
21      *      Copyright (C) 1997 Jes Sorensen
22      *      Copyright (C) 1996 Frank Neumann
23      *
24      ***************************************************************
25      *
26      * Format this code with GNU indent '-kr -i8 -pcs' options.
27      *
28      * This file is subject to the terms and conditions of the GNU General Public
29      * License.  See the file COPYING in the main directory of this archive
30      * for more details.
31      *
32      */
33     
34     #define CLGEN_VERSION "1.9.8"
35     
36     #include <linux/config.h>
37     #include <linux/module.h>
38     #include <linux/kernel.h>
39     #include <linux/errno.h>
40     #include <linux/string.h>
41     #include <linux/mm.h>
42     #include <linux/tty.h>
43     #include <linux/slab.h>
44     #include <linux/delay.h>
45     #include <linux/fb.h>
46     #include <linux/init.h>
47     #include <linux/selection.h>
48     #include <asm/pgtable.h>
49     
50     #ifdef CONFIG_ZORRO
51     #include <linux/zorro.h>
52     #endif
53     #ifdef CONFIG_PCI
54     #include <linux/pci.h>
55     #endif
56     #ifdef CONFIG_AMIGA
57     #include <asm/amigahw.h>
58     #endif
59     
60     #include <video/fbcon.h>
61     #include <video/fbcon-mfb.h>
62     #include <video/fbcon-cfb8.h>
63     #include <video/fbcon-cfb16.h>
64     #include <video/fbcon-cfb24.h>
65     #include <video/fbcon-cfb32.h>
66     
67     #include "clgenfb.h"
68     #include "vga.h"
69     
70     
71     /*****************************************************************
72      *
73      * debugging and utility macros
74      *
75      */
76     
77     /* enable debug output? */
78     /* #define CLGEN_DEBUG 1 */
79     
80     /* disable runtime assertions? */
81     /* #define CLGEN_NDEBUG */
82     
83     
84     /* debug output */
85     #ifdef CLGEN_DEBUG
86     #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
87     #else
88     #define DPRINTK(fmt, args...)
89     #endif
90     
91     /* debugging assertions */
92     #ifndef CLGEN_NDEBUG
93     #define assert(expr) \
94             if(!(expr)) { \
95             printk( "Assertion failed! %s,%s,%s,line=%d\n",\
96             #expr,__FILE__,__FUNCTION__,__LINE__); \
97             }
98     #else
99     #define assert(expr)
100     #endif
101     
102     #ifdef TRUE
103     #undef TRUE
104     #endif
105     #ifdef FALSE
106     #undef FALSE
107     #endif
108     #define TRUE  1
109     #define FALSE 0
110     
111     #define MB_ (1024*1024)
112     
113     #define MAX_NUM_BOARDS 7
114     
115     
116     /*****************************************************************
117      *
118      * chipset information
119      *
120      */
121     
122     /* board types */
123     typedef enum {
124     	BT_NONE = 0,
125     	BT_SD64,
126     	BT_PICCOLO,
127     	BT_PICASSO,
128     	BT_SPECTRUM,
129     	BT_PICASSO4,	/* GD5446 */
130     	BT_ALPINE,	/* GD543x/4x */
131     	BT_GD5480,
132     	BT_LAGUNA,	/* GD546x */
133     } clgen_board_t;
134     
135     
136     /*
137      * per-board-type information, used for enumerating and abstracting
138      * chip-specific information
139      * NOTE: MUST be in the same order as clgen_board_t in order to
140      * use direct indexing on this array
141      * NOTE: '__initdata' cannot be used as some of this info
142      * is required at runtime.  Maybe separate into an init-only and
143      * a run-time table?
144      */
145     static const struct clgen_board_info_rec {
146     	clgen_board_t btype;	/* chipset enum, not strictly necessary, as
147     				 * clgen_board_info[] is directly indexed
148     				 * by this value */
149     	char *name;		/* ASCII name of chipset */
150     	long maxclock;		/* maximum video clock */
151     	unsigned init_sr07 : 1;	/* init SR07 during init_vgachip() */
152     	unsigned init_sr1f : 1; /* write SR1F during init_vgachip() */
153     	unsigned scrn_start_bit19 : 1; /* construct bit 19 of screen start address */
154     
155     	/* initial SR07 value, then for each mode */
156     	unsigned char sr07;
157     	unsigned char sr07_1bpp;
158     	unsigned char sr07_1bpp_mux;
159     	unsigned char sr07_8bpp;
160     	unsigned char sr07_8bpp_mux;
161     
162     	unsigned char sr1f;	/* SR1F VGA initial register value */
163     } clgen_board_info[] = {
164     	{ BT_NONE, }, /* dummy record */
165     	{ BT_SD64,
166     		"CL SD64",
167     		140000,		/* the SD64/P4 have a higher max. videoclock */
168     		TRUE,
169     		TRUE,
170     		TRUE,
171     		0xF0,
172     		0xF0,
173     		0,		/* unused, does not multiplex */
174     		0xF1,
175     		0,		/* unused, does not multiplex */
176     		0x20 },
177     	{ BT_PICCOLO,
178     		"CL Piccolo",
179     		90000,
180     		TRUE,
181     		TRUE,
182     		FALSE,
183     		0x80,
184     		0x80,
185     		0,		/* unused, does not multiplex */
186     		0x81,
187     		0,		/* unused, does not multiplex */
188     		0x22 },
189     	{ BT_PICASSO,
190     		"CL Picasso",
191     		90000,
192     		TRUE,
193     		TRUE,
194     		FALSE,
195     		0x20,
196     		0x20,
197     		0,		/* unused, does not multiplex */
198     		0x21,
199     		0,		/* unused, does not multiplex */
200     		0x22 },
201     	{ BT_SPECTRUM,
202     		"CL Spectrum",
203     		90000,
204     		TRUE,
205     		TRUE,
206     		FALSE,
207     		0x80,
208     		0x80,
209     		0,		/* unused, does not multiplex */
210     		0x81,
211     		0,		/* unused, does not multiplex */
212     		0x22 },
213     	{ BT_PICASSO4,
214     		"CL Picasso4",
215     		140000,		/* the SD64/P4 have a higher max. videoclock */
216     		TRUE,
217     		FALSE,
218     		TRUE,
219     		0x20,
220     		0x20,
221     		0,		/* unused, does not multiplex */
222     		0x21,
223     		0,		/* unused, does not multiplex */
224     		0 },
225     	{ BT_ALPINE,
226     		"CL Alpine",
227     		110000,		/* 135100 for some, 85500 for others */
228     		TRUE,
229     		TRUE,
230     		TRUE,
231     		0xA0,
232     		0xA1,
233     		0xA7,
234     		0xA1,
235     		0xA7,
236     		0x1C },
237     	{ BT_GD5480,
238     		"CL GD5480",
239     		90000,
240     		TRUE,
241     		TRUE,
242     		TRUE,
243     		0x10,
244     		0x11,
245     		0,		/* unused, does not multiplex */
246     		0x11,
247     		0,		/* unused, does not multiplex */
248     		0x1C },
249     	{ BT_LAGUNA,
250     		"CL Laguna",
251     		135100,
252     		FALSE,
253     		FALSE,
254     		TRUE,
255     		0,		/* unused */
256     		0,		/* unused */
257     		0,		/* unused */
258     		0,		/* unused */
259     		0,		/* unused */
260     		0 },		/* unused */
261     };
262     
263     
264     #ifdef CONFIG_PCI
265     /* the list of PCI devices for which we probe, and the
266      * order in which we do it */
267     static const struct {
268     	clgen_board_t btype;
269     	const char *nameOverride; /* XXX unused... for now */
270     	unsigned short device;
271     } clgen_pci_probe_list[] __initdata = {
272     	{ BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_5436 },
273     	{ BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_5434_8 },
274     	{ BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_5434_4 },
275     	{ BT_ALPINE, NULL, PCI_DEVICE_ID_CIRRUS_5430 }, /* GD-5440 has identical id */
276     	{ BT_GD5480, NULL, PCI_DEVICE_ID_CIRRUS_5480 }, /* MacPicasso probably */
277     	{ BT_PICASSO4, NULL, PCI_DEVICE_ID_CIRRUS_5446 }, /* Picasso 4 is a GD5446 */
278     	{ BT_LAGUNA, "CL Laguna", PCI_DEVICE_ID_CIRRUS_5462 },
279     	{ BT_LAGUNA, "CL Laguna 3D", PCI_DEVICE_ID_CIRRUS_5464 },
280     	{ BT_LAGUNA, "CL Laguna 3DA", PCI_DEVICE_ID_CIRRUS_5465 },
281     };
282     #endif /* CONFIG_PCI */
283     
284     
285     #ifdef CONFIG_ZORRO
286     static const struct {
287     	clgen_board_t btype;
288     	zorro_id id, id2;
289     	unsigned long size;
290     } clgen_zorro_probe_list[] __initdata = {
291     	{ BT_SD64,
292     		ZORRO_PROD_HELFRICH_SD64_RAM,
293     		ZORRO_PROD_HELFRICH_SD64_REG,
294     		0x400000 },
295     	{ BT_PICCOLO,
296     		ZORRO_PROD_HELFRICH_PICCOLO_RAM,
297     		ZORRO_PROD_HELFRICH_PICCOLO_REG,
298     		0x200000 },
299     	{ BT_PICASSO,
300     		ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
301     		ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
302     		0x200000 },
303     	{ BT_SPECTRUM,
304     		ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
305     		ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
306     		0x200000 },
307     	{ BT_PICASSO4,
308     		ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
309     		0,
310     		0x400000 },
311     };
312     #endif /* CONFIG_ZORRO */
313     
314     
315     
316     struct clgenfb_par {
317     	struct fb_var_screeninfo var;
318     
319     	__u32 line_length;	/* in BYTES! */
320     	__u32 visual;
321     	__u32 type;
322     
323     	long freq;
324     	long nom;
325     	long den;
326     	long div;
327     	long multiplexing;
328     	long mclk;
329     	long divMCLK;
330     
331     	long HorizRes;		/* The x resolution in pixel */
332     	long HorizTotal;
333     	long HorizDispEnd;
334     	long HorizBlankStart;
335     	long HorizBlankEnd;
336     	long HorizSyncStart;
337     	long HorizSyncEnd;
338     
339     	long VertRes;		/* the physical y resolution in scanlines */
340     	long VertTotal;
341     	long VertDispEnd;
342     	long VertSyncStart;
343     	long VertSyncEnd;
344     	long VertBlankStart;
345     	long VertBlankEnd;
346     };
347     
348     
349     
350     #ifdef CLGEN_DEBUG
351     typedef enum {
352             CRT,
353             SEQ
354     } clgen_dbg_reg_class_t;
355     #endif                          /* CLGEN_DEBUG */
356     
357     
358     
359     
360     /* info about board */
361     struct clgenfb_info {
362     	struct fb_info_gen gen;
363     
364     	caddr_t fbmem;
365     	caddr_t regs;
366     	caddr_t mem;
367     	unsigned long size;
368     	clgen_board_t btype;
369     	int smallboard;
370     	unsigned char SFR;	/* Shadow of special function register */
371     
372     	unsigned long fbmem_phys;
373     	unsigned long fbregs_phys;
374     
375     	struct clgenfb_par currentmode;
376     
377     	struct { u8 red, green, blue, pad; } palette[256];
378     
379     	union {
380     #ifdef FBCON_HAS_CFB16
381     		u16 cfb16[16];
382     #endif
383     #ifdef FBCON_HAS_CFB24
384     		u32 cfb24[16];
385     #endif
386     #ifdef FBCON_HAS_CFB32
387     		u32 cfb32[16];
388     #endif
389     	} fbcon_cmap;
390     
391     #ifdef CONFIG_ZORRO
392     	unsigned long board_addr,
393     		      board_size;
394     #endif
395     
396     #ifdef CONFIG_PCI
397     	struct pci_dev *pdev;
398     #endif
399     };
400     
401     
402     
403     
404     static struct display disp;
405     
406     static struct clgenfb_info boards[MAX_NUM_BOARDS];	/* the boards */
407     
408     static unsigned clgen_def_mode = 1;
409     
410     static int release_io_ports = 0;
411     
412     
413     
414     /*
415      *    Predefined Video Modes
416      */
417     
418     static const struct {
419     	const char *name;
420     	struct fb_var_screeninfo var;
421     } clgenfb_predefined[] __initdata =
422     
423     {
424     	{"Autodetect",		/* autodetect mode */
425     	 {0}
426     	},
427     
428     	{"640x480",		/* 640x480, 31.25 kHz, 60 Hz, 25 MHz PixClock */
429     	 {
430     		 640, 480, 640, 480, 0, 0, 8, 0,
431     		 {0, 8, 0},
432     		 {0, 8, 0},
433     		 {0, 8, 0},
434     		 {0, 0, 0},
435     	       0, 0, -1, -1, FB_ACCEL_NONE, 40000, 32, 32, 33, 10, 96, 2,
436          FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
437     	 }
438     	},
439     
440     	/*
441     	   Modeline from XF86Config:
442     	   Mode "1024x768" 80  1024 1136 1340 1432  768 770 774 805
443     	 */
444     	{"1024x768",		/* 1024x768, 55.8 kHz, 70 Hz, 80 MHz PixClock */
445     		{
446     			1024, 768, 1024, 768, 0, 0, 8, 0,
447     			{0, 8, 0},
448     			{0, 8, 0},
449     			{0, 8, 0},
450     			{0, 0, 0},
451     	      0, 0, -1, -1, FB_ACCEL_NONE, 12500, 92, 112, 31, 2, 204, 4,
452          FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
453     		}
454     	}
455     };
456     
457     #define NUM_TOTAL_MODES    ARRAY_SIZE(clgenfb_predefined)
458     static struct fb_var_screeninfo clgenfb_default;
459     
460     /*
461      *    Frame Buffer Name
462      */
463     
464     static const char *clgenfb_name = "CLgen";
465     
466     /****************************************************************************/
467     /**** BEGIN PROTOTYPES ******************************************************/
468     
469     
470     /*--- Interface used by the world ------------------------------------------*/
471     int clgenfb_init (void);
472     int clgenfb_setup (char *options);
473     
474     static int clgenfb_open (struct fb_info *info, int user);
475     static int clgenfb_release (struct fb_info *info, int user);
476     
477     /* function table of the above functions */
478     static struct fb_ops clgenfb_ops = {
479     	owner:		THIS_MODULE,
480     	fb_open:	clgenfb_open,
481     	fb_release:	clgenfb_release,
482     	fb_get_fix:	fbgen_get_fix,
483     	fb_get_var:	fbgen_get_var,
484     	fb_set_var:	fbgen_set_var,
485     	fb_get_cmap:	fbgen_get_cmap,
486     	fb_set_cmap:	fbgen_set_cmap,
487     	fb_pan_display:	fbgen_pan_display,
488     };
489     
490     /*--- Hardware Specific Routines -------------------------------------------*/
491     static void clgen_detect (void);
492     static int clgen_encode_fix (struct fb_fix_screeninfo *fix, const void *par,
493     			     struct fb_info_gen *info);
494     static int clgen_decode_var (const struct fb_var_screeninfo *var, void *par,
495     			     struct fb_info_gen *info);
496     static int clgen_encode_var (struct fb_var_screeninfo *var, const void *par,
497     			     struct fb_info_gen *info);
498     static void clgen_get_par (void *par, struct fb_info_gen *info);
499     static void clgen_set_par (const void *par, struct fb_info_gen *info);
500     static int clgen_getcolreg (unsigned regno, unsigned *red, unsigned *green,
501     			    unsigned *blue, unsigned *transp,
502     			    struct fb_info *info);
503     static int clgen_setcolreg (unsigned regno, unsigned red, unsigned green,
504     			    unsigned blue, unsigned transp,
505     			    struct fb_info *info);
506     static int clgen_pan_display (const struct fb_var_screeninfo *var,
507     			      struct fb_info_gen *info);
508     static int clgen_blank (int blank_mode, struct fb_info_gen *info);
509     
510     static void clgen_set_disp (const void *par, struct display *disp,
511     			    struct fb_info_gen *info);
512     
513     /* function table of the above functions */
514     static struct fbgen_hwswitch clgen_hwswitch =
515     {
516     	clgen_detect,
517     	clgen_encode_fix,
518     	clgen_decode_var,
519     	clgen_encode_var,
520     	clgen_get_par,
521     	clgen_set_par,
522     	clgen_getcolreg,
523     	clgen_setcolreg,
524     	clgen_pan_display,
525     	clgen_blank,
526     	clgen_set_disp
527     };
528     
529     /* Text console acceleration */
530     
531     #ifdef FBCON_HAS_CFB8
532     static void fbcon_clgen8_bmove (struct display *p, int sy, int sx,
533     				int dy, int dx, int height, int width);
534     static void fbcon_clgen8_clear (struct vc_data *conp, struct display *p,
535     				int sy, int sx, int height, int width);
536     
537     static struct display_switch fbcon_clgen_8 = {
538     	setup:		fbcon_cfb8_setup,
539     	bmove:		fbcon_clgen8_bmove,
540     	clear:		fbcon_clgen8_clear,
541     	putc:		fbcon_cfb8_putc,
542     	putcs:		fbcon_cfb8_putcs,
543     	revc:		fbcon_cfb8_revc,
544     	clear_margins:	fbcon_cfb8_clear_margins,
545     	fontwidthmask:	FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16)
546     };
547     #endif
548     #ifdef FBCON_HAS_CFB16
549     static void fbcon_clgen16_bmove (struct display *p, int sy, int sx,
550     				 int dy, int dx, int height, int width);
551     static void fbcon_clgen16_clear (struct vc_data *conp, struct display *p,
552     				 int sy, int sx, int height, int width);
553     static struct display_switch fbcon_clgen_16 = {
554     	setup:		fbcon_cfb16_setup,
555     	bmove:		fbcon_clgen16_bmove,
556     	clear:		fbcon_clgen16_clear,
557     	putc:		fbcon_cfb16_putc,
558     	putcs:		fbcon_cfb16_putcs,
559     	revc:		fbcon_cfb16_revc,
560     	clear_margins:	fbcon_cfb16_clear_margins,
561     	fontwidthmask:	FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16)
562     };
563     #endif
564     #ifdef FBCON_HAS_CFB32
565     static void fbcon_clgen32_bmove (struct display *p, int sy, int sx,
566     				 int dy, int dx, int height, int width);
567     static void fbcon_clgen32_clear (struct vc_data *conp, struct display *p,
568     				 int sy, int sx, int height, int width);
569     static struct display_switch fbcon_clgen_32 = {
570     	setup:		fbcon_cfb32_setup,
571     	bmove:		fbcon_clgen32_bmove,
572     	clear:		fbcon_clgen32_clear,
573     	putc:		fbcon_cfb32_putc,
574     	putcs:		fbcon_cfb32_putcs,
575     	revc:		fbcon_cfb32_revc,
576     	clear_margins:	fbcon_cfb32_clear_margins,
577     	fontwidthmask:	FONTWIDTH (4) | FONTWIDTH (8) | FONTWIDTH (12) | FONTWIDTH (16)
578     };
579     #endif
580     
581     
582     
583     /*--- Internal routines ----------------------------------------------------*/
584     static void init_vgachip (struct clgenfb_info *fb_info);
585     static void switch_monitor (struct clgenfb_info *fb_info, int on);
586     static void WGen (const struct clgenfb_info *fb_info,
587     		  int regnum, unsigned char val);
588     static unsigned char RGen (const struct clgenfb_info *fb_info, int regnum);
589     static void AttrOn (const struct clgenfb_info *fb_info);
590     static void WHDR (const struct clgenfb_info *fb_info, unsigned char val);
591     static void WSFR (struct clgenfb_info *fb_info, unsigned char val);
592     static void WSFR2 (struct clgenfb_info *fb_info, unsigned char val);
593     static void WClut (struct clgenfb_info *fb_info, unsigned char regnum, unsigned char red,
594     		   unsigned char green,
595     		   unsigned char blue);
596     #if 0
597     static void RClut (struct clgenfb_info *fb_info, unsigned char regnum, unsigned char *red,
598     		   unsigned char *green,
599     		   unsigned char *blue);
600     #endif
601     static void clgen_WaitBLT (caddr_t regbase);
602     static void clgen_BitBLT (caddr_t regbase, u_short curx, u_short cury,
603     			  u_short destx, u_short desty,
604     			  u_short width, u_short height,
605     			  u_short line_length);
606     static void clgen_RectFill (struct clgenfb_info *fb_info, u_short x, u_short y,
607     			    u_short width, u_short height,
608     			    u_char color, u_short line_length);
609     
610     static void bestclock (long freq, long *best,
611     		       long *nom, long *den,
612     		       long *div, long maxfreq);
613     
614     #ifdef CLGEN_DEBUG
615     static void clgen_dump (void);
616     static void clgen_dbg_reg_dump (caddr_t regbase);
617     static void clgen_dbg_print_regs (caddr_t regbase, clgen_dbg_reg_class_t reg_class,...);
618     static void clgen_dbg_print_byte (const char *name, unsigned char val);
619     #endif /* CLGEN_DEBUG */
620     
621     /*** END   PROTOTYPES ********************************************************/
622     /*****************************************************************************/
623     /*** BEGIN Interface Used by the World ***************************************/
624     
625     static int opencount = 0;
626     
627     /*--- Open /dev/fbx ---------------------------------------------------------*/
628     static int clgenfb_open (struct fb_info *info, int user)
629     {
630     	if (opencount++ == 0)
631     		switch_monitor ((struct clgenfb_info *) info, 1);
632     	return 0;
633     }
634     
635     /*--- Close /dev/fbx --------------------------------------------------------*/
636     static int clgenfb_release (struct fb_info *info, int user)
637     {
638     	if (--opencount == 0)
639     		switch_monitor ((struct clgenfb_info *) info, 0);
640     	return 0;
641     }
642     
643     /**** END   Interface used by the World *************************************/
644     /****************************************************************************/
645     /**** BEGIN Hardware specific Routines **************************************/
646     
647     static void clgen_detect (void)
648     {
649     	DPRINTK ("ENTER\n");
650     	DPRINTK ("EXIT\n");
651     }
652     
653     static int clgen_encode_fix (struct fb_fix_screeninfo *fix, const void *par,
654     			     struct fb_info_gen *info)
655     {
656     	struct clgenfb_par *_par = (struct clgenfb_par *) par;
657     	struct clgenfb_info *_info = (struct clgenfb_info *) info;
658     
659     	DPRINTK ("ENTER\n");
660     
661     	memset (fix, 0, sizeof (struct fb_fix_screeninfo));
662     	strcpy (fix->id, clgenfb_name);
663     
664     	if (_info->btype == BT_GD5480) {
665     		/* Select proper byte-swapping aperture */
666     		switch (_par->var.bits_per_pixel) {
667     		case 1:
668     		case 8:
669     			fix->smem_start = _info->fbmem_phys;
670     			break;
671     		case 16:
672     			fix->smem_start = _info->fbmem_phys + 1 * MB_;
673     			break;
674     		case 24:
675     		case 32:
676     			fix->smem_start = _info->fbmem_phys + 2 * MB_;
677     			break;
678     		}
679     	} else {
680     		fix->smem_start = _info->fbmem_phys;
681     	}
682     
683     	/* monochrome: only 1 memory plane */
684     	/* 8 bit and above: Use whole memory area */
685     	fix->smem_len = _par->var.bits_per_pixel == 1 ? _info->size / 4
686     	    : _info->size;
687     	fix->type = _par->type;
688     	fix->type_aux = 0;
689     	fix->visual = _par->visual;
690     	fix->xpanstep = 1;
691     	fix->ypanstep = 1;
692     	fix->ywrapstep = 0;
693     	fix->line_length = _par->line_length;
694     
695     	/* FIXME: map region at 0xB8000 if available, fill in here */
696     	fix->mmio_start = 0;
697     	fix->mmio_len = 0;
698     	fix->accel = FB_ACCEL_NONE;
699     
700     	DPRINTK ("EXIT\n");
701     	return 0;
702     }
703     
704     
705     
706     /* Get a good MCLK value */
707     static long clgen_get_mclk (long freq, int bpp, long *div)
708     {
709     	long mclk;
710     
711     	assert (div != NULL);
712     
713     	/* Calculate MCLK, in case VCLK is high enough to require > 50MHz.
714     	 * Assume a 64-bit data path for now.  The formula is:
715     	 * ((B * PCLK * 2)/W) * 1.2
716     	 * B = bytes per pixel, PCLK = pixclock, W = data width in bytes */
717     	mclk = ((bpp / 8) * freq * 2) / 4;
718     	mclk = (mclk * 12) / 10;
719     	if (mclk < 50000)
720     		mclk = 50000;
721     	DPRINTK ("Use MCLK of %ld kHz\n", mclk);
722     
723     	/* Calculate value for SR1F.  Multiply by 2 so we can round up. */
724     	mclk = ((mclk * 16) / 14318);
725     	mclk = (mclk + 1) / 2;
726     	DPRINTK ("Set SR1F[5:0] to 0x%lx\n", mclk);
727     
728     	/* Determine if we should use MCLK instead of VCLK, and if so, what we
729     	   * should divide it by to get VCLK */
730     	switch (freq) {
731     	case 24751 ... 25249:
732     		*div = 2;
733     		DPRINTK ("Using VCLK = MCLK/2\n");
734     		break;
735     	case 49501 ... 50499:
736     		*div = 1;
737     		DPRINTK ("Using VCLK = MCLK\n");
738     		break;
739     	default:
740     		*div = 0;
741     		break;
742     	}
743     
744     	return mclk;
745     }
746     
747     static int clgen_decode_var (const struct fb_var_screeninfo *var, void *par,
748     			     struct fb_info_gen *info)
749     {
750     	long freq;
751     	long maxclock;
752     	int xres, hfront, hsync, hback;
753     	int yres, vfront, vsync, vback;
754     	int nom, den;		/* translyting from pixels->bytes */
755     	int i;
756     	static struct {
757     		int xres, yres;
758     	} modes[] = { {
759     			1600, 1280
760     	}, {
761     		1280, 1024
762     	}, {
763     		1024, 768
764     	},
765     	{
766     		800, 600
767     	}, {
768     		640, 480
769     	}, {
770     		-1, -1
771     	}
772     	};
773     
774     	struct clgenfb_par *_par = (struct clgenfb_par *) par;
775     	struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
776     
777     	assert (var != NULL);
778     	assert (par != NULL);
779     	assert (info != NULL);
780     
781     	DPRINTK ("ENTER\n");
782     
783     	DPRINTK ("Requested: %dx%dx%d\n", var->xres, var->yres, var->bits_per_pixel);
784     	DPRINTK ("  virtual: %dx%d\n", var->xres_virtual, var->yres_virtual);
785     	DPRINTK ("   offset: (%d,%d)\n", var->xoffset, var->yoffset);
786     	DPRINTK ("grayscale: %d\n", var->grayscale);
787     
788     	memset (par, 0, sizeof (struct clgenfb_par));
789     
790     	_par->var = *var;
791     
792     	switch (var->bits_per_pixel) {
793     	case 1:
794     		nom = 4;
795     		den = 8;
796     		break;		/* 8 pixel per byte, only 1/4th of mem usable */
797     	case 2 ... 8:
798     		_par->var.bits_per_pixel = 8;
799     		nom = 1;
800     		den = 1;
801     		break;		/* 1 pixel == 1 byte */
802     	case 9 ... 16:
803     		_par->var.bits_per_pixel = 16;
804     		nom = 2;
805     		den = 1;
806     		break;		/* 2 bytes per pixel */
807     	case 17 ... 24:
808     		_par->var.bits_per_pixel = 24;
809     		nom = 3;
810     		den = 1;
811     		break;		/* 3 bytes per pixel */
812     	case 25 ... 32:
813     		_par->var.bits_per_pixel = 32;
814     		nom = 4;
815     		den = 1;
816     		break;		/* 4 bytes per pixel */
817     	default:
818     		printk ("clgen: mode %dx%dx%d rejected...color depth not supported.\n",
819     			var->xres, var->yres, var->bits_per_pixel);
820     		DPRINTK ("EXIT - EINVAL error\n");
821     		return -EINVAL;
822     	}
823     
824     	if (_par->var.xres * nom / den * _par->var.yres > fb_info->size) {
825     		printk ("clgen: mode %dx%dx%d rejected...resolution too high to fit into video memory!\n",
826     			var->xres, var->yres, var->bits_per_pixel);
827     		DPRINTK ("EXIT - EINVAL error\n");
828     		return -EINVAL;
829     	}
830     	/* use highest possible virtual resolution */
831     	if (_par->var.xres_virtual == -1 &&
832     	    _par->var.yres_virtual == -1) {
833     		printk ("clgen: using maximum available virtual resolution\n");
834     		for (i = 0; modes[i].xres != -1; i++) {
835     			if (modes[i].xres * nom / den * modes[i].yres < fb_info->size / 2)
836     				break;
837     		}
838     		if (modes[i].xres == -1) {
839     			printk ("clgen: could not find a virtual resolution that fits into video memory!!\n");
840     			DPRINTK ("EXIT - EINVAL error\n");
841     			return -EINVAL;
842     		}
843     		_par->var.xres_virtual = modes[i].xres;
844     		_par->var.yres_virtual = modes[i].yres;
845     
846     		printk ("clgen: virtual resolution set to maximum of %dx%d\n",
847     			_par->var.xres_virtual, _par->var.yres_virtual);
848     	} else if (_par->var.xres_virtual == -1) {
849     		/* FIXME: maximize X virtual resolution only */
850     	} else if (_par->var.yres_virtual == -1) {
851     		/* FIXME: maximize Y virtual resolution only */
852     	}
853     	if (_par->var.xoffset < 0)
854     		_par->var.xoffset = 0;
855     	if (_par->var.yoffset < 0)
856     		_par->var.yoffset = 0;
857     
858     	/* truncate xoffset and yoffset to maximum if too high */
859     	if (_par->var.xoffset > _par->var.xres_virtual - _par->var.xres)
860     		_par->var.xoffset = _par->var.xres_virtual - _par->var.xres - 1;
861     
862     	if (_par->var.yoffset > _par->var.yres_virtual - _par->var.yres)
863     		_par->var.yoffset = _par->var.yres_virtual - _par->var.yres - 1;
864     
865     	switch (_par->var.bits_per_pixel) {
866     	case 1:
867     		_par->line_length = _par->var.xres_virtual / 8;
868     		_par->visual = FB_VISUAL_MONO10;
869     		break;
870     
871     	case 8:
872     		_par->line_length = _par->var.xres_virtual;
873     		_par->visual = FB_VISUAL_PSEUDOCOLOR;
874     		_par->var.red.offset = 0;
875     		_par->var.red.length = 6;
876     		_par->var.green.offset = 0;
877     		_par->var.green.length = 6;
878     		_par->var.blue.offset = 0;
879     		_par->var.blue.length = 6;
880     		break;
881     
882     	case 16:
883     		_par->line_length = _par->var.xres_virtual * 2;
884     		_par->visual = FB_VISUAL_DIRECTCOLOR;
885     #ifdef CONFIG_PREP
886     		_par->var.red.offset = 2;
887     		_par->var.green.offset = -3;
888     		_par->var.blue.offset = 8;
889     #else
890     		_par->var.red.offset = 10;
891     		_par->var.green.offset = 5;
892     		_par->var.blue.offset = 0;
893     #endif
894     		_par->var.red.length = 5;
895     		_par->var.green.length = 5;
896     		_par->var.blue.length = 5;
897     		break;
898     
899     	case 24:
900     		_par->line_length = _par->var.xres_virtual * 3;
901     		_par->visual = FB_VISUAL_DIRECTCOLOR;
902     #ifdef CONFIG_PREP
903     		_par->var.red.offset = 8;
904     		_par->var.green.offset = 16;
905     		_par->var.blue.offset = 24;
906     #else
907     		_par->var.red.offset = 16;
908     		_par->var.green.offset = 8;
909     		_par->var.blue.offset = 0;
910     #endif
911     		_par->var.red.length = 8;
912     		_par->var.green.length = 8;
913     		_par->var.blue.length = 8;
914     		break;
915     
916     	case 32:
917     		_par->line_length = _par->var.xres_virtual * 4;
918     		_par->visual = FB_VISUAL_DIRECTCOLOR;
919     #ifdef CONFIG_PREP
920     		_par->var.red.offset = 8;
921     		_par->var.green.offset = 16;
922     		_par->var.blue.offset = 24;
923     #else
924     		_par->var.red.offset = 16;
925     		_par->var.green.offset = 8;
926     		_par->var.blue.offset = 0;
927     #endif
928     		_par->var.red.length = 8;
929     		_par->var.green.length = 8;
930     		_par->var.blue.length = 8;
931     		break;
932     
933     	default:
934     		DPRINTK("Unsupported bpp size: %d\n", _par->var.bits_per_pixel);
935     		assert (FALSE);
936     		/* should never occur */
937     		break;
938     	}
939     
940     	_par->var.red.msb_right =
941     	    _par->var.green.msb_right =
942     	    _par->var.blue.msb_right =
943     	    _par->var.transp.offset =
944     	    _par->var.transp.length =
945     	    _par->var.transp.msb_right = 0;
946     
947     	_par->type = FB_TYPE_PACKED_PIXELS;
948     
949     	/* convert from ps to kHz */
950     	freq = 1000000000 / var->pixclock;
951     
952     	DPRINTK ("desired pixclock: %ld kHz\n", freq);
953     
954     	maxclock = clgen_board_info[fb_info->btype].maxclock;
955     	_par->multiplexing = 0;
956     
957     	/* If the frequency is greater than we can support, we might be able
958     	 * to use multiplexing for the video mode */
959     	if (freq > maxclock) {
960     		switch (fb_info->btype) {
961     		case BT_ALPINE:
962     		case BT_GD5480:
963     			_par->multiplexing = 1;
964     			break;
965     
966     		default:
967     			printk (KERN_WARNING "clgen: ERROR: Frequency greater than maxclock (%ld kHz)\n", maxclock);
968     			DPRINTK ("EXIT - return -EINVAL\n");
969     			return -EINVAL;
970     		}
971     	}
972     #if 0
973     	/* TODO: If we have a 1MB 5434, we need to put ourselves in a mode where
974     	 * the VCLK is double the pixel clock. */
975     	switch (var->bits_per_pixel) {
976     	case 16:
977     	case 32:
978     		if (_par->HorizRes <= 800)
979     			freq /= 2;	/* Xbh has this type of clock for 32-bit */
980     		break;
981     	}
982     #endif
983     
984     	bestclock (freq, &_par->freq, &_par->nom, &_par->den, &_par->div,
985     		   maxclock);
986     	_par->mclk = clgen_get_mclk (freq, _par->var.bits_per_pixel, &_par->divMCLK);
987     
988     	xres = _par->var.xres;
989     	hfront = _par->var.right_margin;
990     	hsync = _par->var.hsync_len;
991     	hback = _par->var.left_margin;
992     
993     	yres = _par->var.yres;
994     	vfront = _par->var.lower_margin;
995     	vsync = _par->var.vsync_len;
996     	vback = _par->var.upper_margin;
997     
998     	if (_par->var.vmode & FB_VMODE_DOUBLE) {
999     		yres *= 2;
1000     		vfront *= 2;
1001     		vsync *= 2;
1002     		vback *= 2;
1003     	} else if (_par->var.vmode & FB_VMODE_INTERLACED) {
1004     		yres = (yres + 1) / 2;
1005     		vfront = (vfront + 1) / 2;
1006     		vsync = (vsync + 1) / 2;
1007     		vback = (vback + 1) / 2;
1008     	}
1009     	_par->HorizRes = xres;
1010     	_par->HorizTotal = (xres + hfront + hsync + hback) / 8 - 5;
1011     	_par->HorizDispEnd = xres / 8 - 1;
1012     	_par->HorizBlankStart = xres / 8;
1013     	_par->HorizBlankEnd = _par->HorizTotal + 5;	/* does not count with "-5" */
1014     	_par->HorizSyncStart = (xres + hfront) / 8 + 1;
1015     	_par->HorizSyncEnd = (xres + hfront + hsync) / 8 + 1;
1016     
1017     	_par->VertRes = yres;
1018     	_par->VertTotal = yres + vfront + vsync + vback - 2;
1019     	_par->VertDispEnd = yres - 1;
1020     	_par->VertBlankStart = yres;
1021     	_par->VertBlankEnd = _par->VertTotal;
1022     	_par->VertSyncStart = yres + vfront - 1;
1023     	_par->VertSyncEnd = yres + vfront + vsync - 1;
1024     
1025     	if (_par->VertRes >= 1024) {
1026     		_par->VertTotal /= 2;
1027     		_par->VertSyncStart /= 2;
1028     		_par->VertSyncEnd /= 2;
1029     		_par->VertDispEnd /= 2;
1030     	}
1031     	if (_par->multiplexing) {
1032     		_par->HorizTotal /= 2;
1033     		_par->HorizSyncStart /= 2;
1034     		_par->HorizSyncEnd /= 2;
1035     		_par->HorizDispEnd /= 2;
1036     	}
1037     	if (_par->VertRes >= 1280) {
1038     		printk (KERN_WARNING "clgen: ERROR: VerticalTotal >= 1280; special treatment required! (TODO)\n");
1039     		DPRINTK ("EXIT - EINVAL error\n");
1040     		return -EINVAL;
1041     	}
1042     	DPRINTK ("EXIT\n");
1043     	return 0;
1044     }
1045     
1046     
1047     static int clgen_encode_var (struct fb_var_screeninfo *var, const void *par,
1048     			     struct fb_info_gen *info)
1049     {
1050     	DPRINTK ("ENTER\n");
1051     
1052     	*var = ((struct clgenfb_par *) par)->var;
1053     
1054     	DPRINTK ("EXIT\n");
1055     	return 0;
1056     }
1057     
1058     /* get current video mode */
1059     static void clgen_get_par (void *par, struct fb_info_gen *info)
1060     {
1061     	struct clgenfb_par *_par = (struct clgenfb_par *) par;
1062     	struct clgenfb_info *_info = (struct clgenfb_info *) info;
1063     
1064     	DPRINTK ("ENTER\n");
1065     
1066     	*_par = _info->currentmode;
1067     
1068     	DPRINTK ("EXIT\n");
1069     }
1070     
1071     static void clgen_set_mclk (const struct clgenfb_info *fb_info, int val, int div)
1072     {
1073     	assert (fb_info != NULL);
1074     
1075     	if (div == 2) {
1076     		/* VCLK = MCLK/2 */
1077     		unsigned char old = vga_rseq (fb_info->regs, CL_SEQR1E);
1078     		vga_wseq (fb_info->regs, CL_SEQR1E, old | 0x1);
1079     		vga_wseq (fb_info->regs, CL_SEQR1F, 0x40 | (val & 0x3f));
1080     	} else if (div == 1) {
1081     		/* VCLK = MCLK */
1082     		unsigned char old = vga_rseq (fb_info->regs, CL_SEQR1E);
1083     		vga_wseq (fb_info->regs, CL_SEQR1E, old & ~0x1);
1084     		vga_wseq (fb_info->regs, CL_SEQR1F, 0x40 | (val & 0x3f));
1085     	} else {
1086     		vga_wseq (fb_info->regs, CL_SEQR1F, val & 0x3f);
1087     	}
1088     }
1089     
1090     /*************************************************************************
1091     	clgen_set_par()
1092     
1093     	actually writes the values for a new video mode into the hardware,
1094     **************************************************************************/
1095     static void clgen_set_par (const void *par, struct fb_info_gen *info)
1096     {
1097     	unsigned char tmp;
1098     	int offset = 0;
1099     	struct clgenfb_par *_par = (struct clgenfb_par *) par;
1100     	struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
1101     	const struct clgen_board_info_rec *bi;
1102     
1103     	DPRINTK ("ENTER\n");
1104     	DPRINTK ("Requested mode: %dx%dx%d\n",
1105     	       _par->var.xres, _par->var.yres, _par->var.bits_per_pixel);
1106     	DPRINTK ("pixclock: %d\n", _par->var.pixclock);
1107     
1108     	bi = &clgen_board_info[fb_info->btype];
1109     
1110     
1111     	/* unlock register VGA_CRTC_H_TOTAL..CRT7 */
1112     	vga_wcrt (fb_info->regs, VGA_CRTC_V_SYNC_END, 0x20);	/* previously: 0x00) */
1113     
1114     	/* if debugging is enabled, all parameters get output before writing */
1115     	DPRINTK ("CRT0: %ld\n", _par->HorizTotal);
1116     	vga_wcrt (fb_info->regs, VGA_CRTC_H_TOTAL, _par->HorizTotal);
1117     
1118     	DPRINTK ("CRT1: %ld\n", _par->HorizDispEnd);
1119     	vga_wcrt (fb_info->regs, VGA_CRTC_H_DISP, _par->HorizDispEnd);
1120     
1121     	DPRINTK ("CRT2: %ld\n", _par->HorizBlankStart);
1122     	vga_wcrt (fb_info->regs, VGA_CRTC_H_BLANK_START, _par->HorizBlankStart);
1123     
1124     	DPRINTK ("CRT3: 128+%ld\n", _par->HorizBlankEnd % 32);	/*  + 128: Compatible read */
1125     	vga_wcrt (fb_info->regs, VGA_CRTC_H_BLANK_END, 128 + (_par->HorizBlankEnd % 32));
1126     
1127     	DPRINTK ("CRT4: %ld\n", _par->HorizSyncStart);
1128     	vga_wcrt (fb_info->regs, VGA_CRTC_H_SYNC_START, _par->HorizSyncStart);
1129     
1130     	tmp = _par->HorizSyncEnd % 32;
1131     	if (_par->HorizBlankEnd & 32)
1132     		tmp += 128;
1133     	DPRINTK ("CRT5: %d\n", tmp);
1134     	vga_wcrt (fb_info->regs, VGA_CRTC_H_SYNC_END, tmp);
1135     
1136     	DPRINTK ("CRT6: %ld\n", _par->VertTotal & 0xff);
1137     	vga_wcrt (fb_info->regs, VGA_CRTC_V_TOTAL, (_par->VertTotal & 0xff));
1138     
1139     	tmp = 16;		/* LineCompare bit #9 */
1140     	if (_par->VertTotal & 256)
1141     		tmp |= 1;
1142     	if (_par->VertDispEnd & 256)
1143     		tmp |= 2;
1144     	if (_par->VertSyncStart & 256)
1145     		tmp |= 4;
1146     	if (_par->VertBlankStart & 256)
1147     		tmp |= 8;
1148     	if (_par->VertTotal & 512)
1149     		tmp |= 32;
1150     	if (_par->VertDispEnd & 512)
1151     		tmp |= 64;
1152     	if (_par->VertSyncStart & 512)
1153     		tmp |= 128;
1154     	DPRINTK ("CRT7: %d\n", tmp);
1155     	vga_wcrt (fb_info->regs, VGA_CRTC_OVERFLOW, tmp);
1156     
1157     	tmp = 0x40;		/* LineCompare bit #8 */
1158     	if (_par->VertBlankStart & 512)
1159     		tmp |= 0x20;
1160     	if (_par->var.vmode & FB_VMODE_DOUBLE)
1161     		tmp |= 0x80;
1162     	DPRINTK ("CRT9: %d\n", tmp);
1163     	vga_wcrt (fb_info->regs, VGA_CRTC_MAX_SCAN, tmp);
1164     
1165     	DPRINTK ("CRT10: %ld\n", _par->VertSyncStart & 0xff);
1166     	vga_wcrt (fb_info->regs, VGA_CRTC_V_SYNC_START, (_par->VertSyncStart & 0xff));
1167     
1168     	DPRINTK ("CRT11: 64+32+%ld\n", _par->VertSyncEnd % 16);
1169     	vga_wcrt (fb_info->regs, VGA_CRTC_V_SYNC_END, (_par->VertSyncEnd % 16 + 64 + 32));
1170     
1171     	DPRINTK ("CRT12: %ld\n", _par->VertDispEnd & 0xff);
1172     	vga_wcrt (fb_info->regs, VGA_CRTC_V_DISP_END, (_par->VertDispEnd & 0xff));
1173     
1174     	DPRINTK ("CRT15: %ld\n", _par->VertBlankStart & 0xff);
1175     	vga_wcrt (fb_info->regs, VGA_CRTC_V_BLANK_START, (_par->VertBlankStart & 0xff));
1176     
1177     	DPRINTK ("CRT16: %ld\n", _par->VertBlankEnd & 0xff);
1178     	vga_wcrt (fb_info->regs, VGA_CRTC_V_BLANK_END, (_par->VertBlankEnd & 0xff));
1179     
1180     	DPRINTK ("CRT18: 0xff\n");
1181     	vga_wcrt (fb_info->regs, VGA_CRTC_LINE_COMPARE, 0xff);
1182     
1183     	tmp = 0;
1184     	if (_par->var.vmode & FB_VMODE_INTERLACED)
1185     		tmp |= 1;
1186     	if (_par->HorizBlankEnd & 64)
1187     		tmp |= 16;
1188     	if (_par->HorizBlankEnd & 128)
1189     		tmp |= 32;
1190     	if (_par->VertBlankEnd & 256)
1191     		tmp |= 64;
1192     	if (_par->VertBlankEnd & 512)
1193     		tmp |= 128;
1194     
1195     	DPRINTK ("CRT1a: %d\n", tmp);
1196     	vga_wcrt (fb_info->regs, CL_CRT1A, tmp);
1197     
1198     	/* set VCLK0 */
1199     	/* hardware RefClock: 14.31818 MHz */
1200     	/* formula: VClk = (OSC * N) / (D * (1+P)) */
1201     	/* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */
1202     
1203     	vga_wseq (fb_info->regs, CL_SEQRB, _par->nom);
1204     	tmp = _par->den << 1;
1205     	if (_par->div != 0)
1206     		tmp |= 1;
1207     
1208     	if ((fb_info->btype == BT_SD64) ||
1209     	    (fb_info->btype == BT_ALPINE) ||
1210     	    (fb_info->btype == BT_GD5480))
1211     		tmp |= 0x80;	/* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */
1212     
1213     	DPRINTK ("CL_SEQR1B: %ld\n", (long) tmp);
1214     	vga_wseq (fb_info->regs, CL_SEQR1B, tmp);
1215     
1216     	if (_par->VertRes >= 1024)
1217     		/* 1280x1024 */
1218     		vga_wcrt (fb_info->regs, VGA_CRTC_MODE, 0xc7);
1219     	else
1220     		/* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit
1221     		 * address wrap, no compat. */
1222     		vga_wcrt (fb_info->regs, VGA_CRTC_MODE, 0xc3);
1223     
1224     /* HAEH?        vga_wcrt (fb_info->regs, VGA_CRTC_V_SYNC_END, 0x20);  * previously: 0x00  unlock VGA_CRTC_H_TOTAL..CRT7 */
1225     
1226     	/* don't know if it would hurt to also program this if no interlaced */
1227     	/* mode is used, but I feel better this way.. :-) */
1228     	if (_par->var.vmode & FB_VMODE_INTERLACED)
1229     		vga_wcrt (fb_info->regs, VGA_CRTC_REGS, _par->HorizTotal / 2);
1230     	else
1231     		vga_wcrt (fb_info->regs, VGA_CRTC_REGS, 0x00);	/* interlace control */
1232     
1233     	vga_wseq (fb_info->regs, VGA_SEQ_CHARACTER_MAP, 0);
1234     
1235     	/* adjust horizontal/vertical sync type (low/high) */
1236     	tmp = 0x03;		/* enable display memory & CRTC I/O address for color mode */
1237     	if (_par->var.sync & FB_SYNC_HOR_HIGH_ACT)
1238     		tmp |= 0x40;
1239     	if (_par->var.sync & FB_SYNC_VERT_HIGH_ACT)
1240     		tmp |= 0x80;
1241     	WGen (fb_info, VGA_MIS_W, tmp);
1242     
1243     	vga_wcrt (fb_info->regs, VGA_CRTC_PRESET_ROW, 0);	/* Screen A Preset Row-Scan register */
1244     	vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_START, 0);	/* text cursor on and start line */
1245     	vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_END, 31);	/* text cursor end line */
1246     
1247     	/******************************************************
1248     	 *
1249     	 * 1 bpp
1250     	 *
1251     	 */
1252     
1253     	/* programming for different color depths */
1254     	if (_par->var.bits_per_pixel == 1) {
1255     		DPRINTK ("clgen: preparing for 1 bit deep display\n");
1256     		vga_wgfx (fb_info->regs, VGA_GFX_MODE, 0);	/* mode register */
1257     
1258     		/* SR07 */
1259     		switch (fb_info->btype) {
1260     		case BT_SD64:
1261     		case BT_PICCOLO:
1262     		case BT_PICASSO:
1263     		case BT_SPECTRUM:
1264     		case BT_PICASSO4:
1265     		case BT_ALPINE:
1266     		case BT_GD5480:
1267     			DPRINTK (" (for GD54xx)\n");
1268     			vga_wseq (fb_info->regs, CL_SEQR7,
1269     				  _par->multiplexing ?
1270     				  	bi->sr07_1bpp_mux : bi->sr07_1bpp);
1271     			break;
1272     
1273     		case BT_LAGUNA:
1274     			DPRINTK (" (for GD546x)\n");
1275     			vga_wseq (fb_info->regs, CL_SEQR7,
1276     				vga_rseq (fb_info->regs, CL_SEQR7) & ~0x01);
1277     			break;
1278     
1279     		default:
1280     			printk (KERN_WARNING "clgen: unknown Board\n");
1281     			break;
1282     		}
1283     
1284     		/* Extended Sequencer Mode */
1285     		switch (fb_info->btype) {
1286     		case BT_SD64:
1287     			/* setting the SEQRF on SD64 is not necessary (only during init) */
1288     			DPRINTK ("(for SD64)\n");
1289     			vga_wseq (fb_info->regs, CL_SEQR1F, 0x1a);		/*  MCLK select */
1290     			break;
1291     
1292     		case BT_PICCOLO:
1293     			DPRINTK ("(for Piccolo)\n");
1294     /* ### ueberall 0x22? */
1295     			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* ##vorher 1c MCLK select */
1296     			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* evtl d0 bei 1 bit? avoid FIFO underruns..? */
1297     			break;
1298     
1299     		case BT_PICASSO:
1300     			DPRINTK ("(for Picasso)\n");
1301     			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* ##vorher 22 MCLK select */
1302     			vga_wseq (fb_info->regs, CL_SEQRF, 0xd0);	/* ## vorher d0 avoid FIFO underruns..? */
1303     			break;
1304     
1305     		case BT_SPECTRUM:
1306     			DPRINTK ("(for Spectrum)\n");
1307     /* ### ueberall 0x22? */
1308     			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* ##vorher 1c MCLK select */
1309     			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* evtl d0? avoid FIFO underruns..? */
1310     			break;
1311     
1312     		case BT_PICASSO4:
1313     		case BT_ALPINE:
1314     		case BT_GD5480:
1315     		case BT_LAGUNA:
1316     			DPRINTK (" (for GD54xx)\n");
1317     			/* do nothing */
1318     			break;
1319     
1320     		default:
1321     			printk (KERN_WARNING "clgen: unknown Board\n");
1322     			break;
1323     		}
1324     
1325     		WGen (fb_info, VGA_PEL_MSK, 0x01);	/* pixel mask: pass-through for first plane */
1326     		if (_par->multiplexing)
1327     			WHDR (fb_info, 0x4a);	/* hidden dac reg: 1280x1024 */
1328     		else
1329     			WHDR (fb_info, 0);	/* hidden dac: nothing */
1330     		vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x06);	/* memory mode: odd/even, ext. memory */
1331     		vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0x01);	/* plane mask: only write to first plane */
1332     		offset = _par->var.xres_virtual / 16;
1333     	}
1334     
1335     	/******************************************************
1336     	 *
1337     	 * 8 bpp
1338     	 *
1339     	 */
1340     
1341     	else if (_par->var.bits_per_pixel == 8) {
1342     		DPRINTK ("clgen: preparing for 8 bit deep display\n");
1343     		switch (fb_info->btype) {
1344     		case BT_SD64:
1345     		case BT_PICCOLO:
1346     		case BT_PICASSO:
1347     		case BT_SPECTRUM:
1348     		case BT_PICASSO4:
1349     		case BT_ALPINE:
1350     		case BT_GD5480:
1351     			DPRINTK (" (for GD54xx)\n");
1352     			vga_wseq (fb_info->regs, CL_SEQR7,
1353     				  _par->multiplexing ?
1354     				  	bi->sr07_8bpp_mux : bi->sr07_8bpp);
1355     			break;
1356     
1357     		case BT_LAGUNA:
1358     			DPRINTK (" (for GD546x)\n");
1359     			vga_wseq (fb_info->regs, CL_SEQR7,
1360     				vga_rseq (fb_info->regs, CL_SEQR7) | 0x01);
1361     			break;
1362     
1363     		default:
1364     			printk (KERN_WARNING "clgen: unknown Board\n");
1365     			break;
1366     		}
1367     
1368     		switch (fb_info->btype) {
1369     		case BT_SD64:
1370     			vga_wseq (fb_info->regs, CL_SEQR1F, 0x1d);		/* MCLK select */
1371     			break;
1372     
1373     		case BT_PICCOLO:
1374     			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* ### vorher 1c MCLK select */
1375     			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* Fast Page-Mode writes */
1376     			break;
1377     
1378     		case BT_PICASSO:
1379     			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* ### vorher 1c MCLK select */
1380     			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* Fast Page-Mode writes */
1381     			break;
1382     
1383     		case BT_SPECTRUM:
1384     			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* ### vorher 1c MCLK select */
1385     			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* Fast Page-Mode writes */
1386     			break;
1387     
1388     		case BT_PICASSO4:
1389     			vga_wseq (fb_info->regs, CL_SEQRF, 0xb8);	/* ### INCOMPLETE!! */
1390     /*          vga_wseq (fb_info->regs, CL_SEQR1F, 0x1c); */
1391     			break;
1392     
1393     		case BT_ALPINE:
1394     			DPRINTK (" (for GD543x)\n");
1395     			clgen_set_mclk (fb_info, _par->mclk, _par->divMCLK);
1396     			/* We already set SRF and SR1F */
1397     			break;
1398     
1399     		case BT_GD5480:
1400     		case BT_LAGUNA:
1401     			DPRINTK (" (for GD54xx)\n");
1402     			/* do nothing */
1403     			break;
1404     
1405     		default:
1406     			printk (KERN_WARNING "clgen: unknown Board\n");
1407     			break;
1408     		}
1409     
1410     		vga_wgfx (fb_info->regs, VGA_GFX_MODE, 64);	/* mode register: 256 color mode */
1411     		WGen (fb_info, VGA_PEL_MSK, 0xff);	/* pixel mask: pass-through all planes */
1412     		if (_par->multiplexing)
1413     			WHDR (fb_info, 0x4a);	/* hidden dac reg: 1280x1024 */
1414     		else
1415     			WHDR (fb_info, 0);	/* hidden dac: nothing */
1416     		vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x0a);	/* memory mode: chain4, ext. memory */
1417     		vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff);	/* plane mask: enable writing to all 4 planes */
1418     		offset = _par->var.xres_virtual / 8;
1419     	}
1420     
1421     	/******************************************************
1422     	 *
1423     	 * 16 bpp
1424     	 *
1425     	 */
1426     
1427     	else if (_par->var.bits_per_pixel == 16) {
1428     		DPRINTK ("clgen: preparing for 16 bit deep display\n");
1429     		switch (fb_info->btype) {
1430     		case BT_SD64:
1431     			vga_wseq (fb_info->regs, CL_SEQR7, 0xf7);	/* Extended Sequencer Mode: 256c col. mode */
1432     			vga_wseq (fb_info->regs, CL_SEQR1F, 0x1e);		/* MCLK select */
1433     			break;
1434     
1435     		case BT_PICCOLO:
1436     			vga_wseq (fb_info->regs, CL_SEQR7, 0x87);
1437     			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* Fast Page-Mode writes */
1438     			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* MCLK select */
1439     			break;
1440     
1441     		case BT_PICASSO:
1442     			vga_wseq (fb_info->regs, CL_SEQR7, 0x27);
1443     			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* Fast Page-Mode writes */
1444     			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* MCLK select */
1445     			break;
1446     
1447     		case BT_SPECTRUM:
1448     			vga_wseq (fb_info->regs, CL_SEQR7, 0x87);
1449     			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* Fast Page-Mode writes */
1450     			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* MCLK select */
1451     			break;
1452     
1453     		case BT_PICASSO4:
1454     			vga_wseq (fb_info->regs, CL_SEQR7, 0x27);
1455     /*          vga_wseq (fb_info->regs, CL_SEQR1F, 0x1c);  */
1456     			break;
1457     
1458     		case BT_ALPINE:
1459     			DPRINTK (" (for GD543x)\n");
1460     			if (_par->HorizRes >= 1024)
1461     				vga_wseq (fb_info->regs, CL_SEQR7, 0xa7);
1462     			else
1463     				vga_wseq (fb_info->regs, CL_SEQR7, 0xa3);
1464     			clgen_set_mclk (fb_info, _par->mclk, _par->divMCLK);
1465     			break;
1466     
1467     		case BT_GD5480:
1468     			DPRINTK (" (for GD5480)\n");
1469     			vga_wseq (fb_info->regs, CL_SEQR7, 0x17);
1470     			/* We already set SRF and SR1F */
1471     			break;
1472     
1473     		case BT_LAGUNA:
1474     			DPRINTK (" (for GD546x)\n");
1475     			vga_wseq (fb_info->regs, CL_SEQR7,
1476     				vga_rseq (fb_info->regs, CL_SEQR7) & ~0x01);
1477     			break;
1478     
1479     		default:
1480     			printk (KERN_WARNING "CLGEN: unknown Board\n");
1481     			break;
1482     		}
1483     
1484     		vga_wgfx (fb_info->regs, VGA_GFX_MODE, 64);	/* mode register: 256 color mode */
1485     		WGen (fb_info, VGA_PEL_MSK, 0xff);	/* pixel mask: pass-through all planes */
1486     #ifdef CONFIG_PCI
1487     		WHDR (fb_info, 0xc0);	/* Copy Xbh */
1488     #elif defined(CONFIG_ZORRO)
1489     		/* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */
1490     		WHDR (fb_info, 0xa0);	/* hidden dac reg: nothing special */
1491     #endif
1492     		vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x0a);	/* memory mode: chain4, ext. memory */
1493     		vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff);	/* plane mask: enable writing to all 4 planes */
1494     		offset = _par->var.xres_virtual / 4;
1495     	}
1496     
1497     	/******************************************************
1498     	 *
1499     	 * 32 bpp
1500     	 *
1501     	 */
1502     
1503     	else if (_par->var.bits_per_pixel == 32) {
1504     		DPRINTK ("clgen: preparing for 24/32 bit deep display\n");
1505     		switch (fb_info->btype) {
1506     		case BT_SD64:
1507     			vga_wseq (fb_info->regs, CL_SEQR7, 0xf9);	/* Extended Sequencer Mode: 256c col. mode */
1508     			vga_wseq (fb_info->regs, CL_SEQR1F, 0x1e);		/* MCLK select */
1509     			break;
1510     
1511     		case BT_PICCOLO:
1512     			vga_wseq (fb_info->regs, CL_SEQR7, 0x85);
1513     			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* Fast Page-Mode writes */
1514     			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* MCLK select */
1515     			break;
1516     
1517     		case BT_PICASSO:
1518     			vga_wseq (fb_info->regs, CL_SEQR7, 0x25);
1519     			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* Fast Page-Mode writes */
1520     			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* MCLK select */
1521     			break;
1522     
1523     		case BT_SPECTRUM:
1524     			vga_wseq (fb_info->regs, CL_SEQR7, 0x85);
1525     			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);	/* Fast Page-Mode writes */
1526     			vga_wseq (fb_info->regs, CL_SEQR1F, 0x22);		/* MCLK select */
1527     			break;
1528     
1529     		case BT_PICASSO4:
1530     			vga_wseq (fb_info->regs, CL_SEQR7, 0x25);
1531     /*          vga_wseq (fb_info->regs, CL_SEQR1F, 0x1c);  */
1532     			break;
1533     
1534     		case BT_ALPINE:
1535     			DPRINTK (" (for GD543x)\n");
1536     			vga_wseq (fb_info->regs, CL_SEQR7, 0xa9);
1537     			clgen_set_mclk (fb_info, _par->mclk, _par->divMCLK);
1538     			break;
1539     
1540     		case BT_GD5480:
1541     			DPRINTK (" (for GD5480)\n");
1542     			vga_wseq (fb_info->regs, CL_SEQR7, 0x19);
1543     			/* We already set SRF and SR1F */
1544     			break;
1545     
1546     		case BT_LAGUNA:
1547     			DPRINTK (" (for GD546x)\n");
1548     			vga_wseq (fb_info->regs, CL_SEQR7,
1549     				vga_rseq (fb_info->regs, CL_SEQR7) & ~0x01);
1550     			break;
1551     
1552     		default:
1553     			printk (KERN_WARNING "clgen: unknown Board\n");
1554     			break;
1555     		}
1556     
1557     		vga_wgfx (fb_info->regs, VGA_GFX_MODE, 64);	/* mode register: 256 color mode */
1558     		WGen (fb_info, VGA_PEL_MSK, 0xff);	/* pixel mask: pass-through all planes */
1559     		WHDR (fb_info, 0xc5);	/* hidden dac reg: 8-8-8 mode (24 or 32) */
1560     		vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x0a);	/* memory mode: chain4, ext. memory */
1561     		vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff);	/* plane mask: enable writing to all 4 planes */
1562     		offset = _par->var.xres_virtual / 4;
1563     	}
1564     
1565     	/******************************************************
1566     	 *
1567     	 * unknown/unsupported bpp
1568     	 *
1569     	 */
1570     
1571     	else {
1572     		printk (KERN_ERR "clgen: What's this?? requested color depth == %d.\n",
1573     			_par->var.bits_per_pixel);
1574     	}
1575     
1576     	vga_wcrt (fb_info->regs, VGA_CRTC_OFFSET, offset & 0xff);
1577     	tmp = 0x22;
1578     	if (offset & 0x100)
1579     		tmp |= 0x10;	/* offset overflow bit */
1580     
1581     	vga_wcrt (fb_info->regs, CL_CRT1B, tmp);	/* screen start addr #16-18, fastpagemode cycles */
1582     
1583     	if (fb_info->btype == BT_SD64 ||
1584     	    fb_info->btype == BT_PICASSO4 ||
1585     	    fb_info->btype == BT_ALPINE ||
1586     	    fb_info->btype == BT_GD5480)
1587     		vga_wcrt (fb_info->regs, CL_CRT1D, 0x00);	/* screen start address bit 19 */
1588     
1589     	vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_HI, 0);	/* text cursor location high */
1590     	vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_LO, 0);	/* text cursor location low */
1591     	vga_wcrt (fb_info->regs, VGA_CRTC_UNDERLINE, 0);	/* underline row scanline = at very bottom */
1592     
1593     	vga_wattr (fb_info->regs, VGA_ATC_MODE, 1);	/* controller mode */
1594     	vga_wattr (fb_info->regs, VGA_ATC_OVERSCAN, 0);		/* overscan (border) color */
1595     	vga_wattr (fb_info->regs, VGA_ATC_PLANE_ENABLE, 15);	/* color plane enable */
1596     	vga_wattr (fb_info->regs, CL_AR33, 0);	/* pixel panning */
1597     	vga_wattr (fb_info->regs, VGA_ATC_COLOR_PAGE, 0);	/* color select */
1598     
1599     	/* [ EGS: SetOffset(); ] */
1600     	/* From SetOffset(): Turn on VideoEnable bit in Attribute controller */
1601     	AttrOn (fb_info);
1602     
1603     	vga_wgfx (fb_info->regs, VGA_GFX_SR_VALUE, 0);	/* set/reset register */
1604     	vga_wgfx (fb_info->regs, VGA_GFX_SR_ENABLE, 0);		/* set/reset enable */
1605     	vga_wgfx (fb_info->regs, VGA_GFX_COMPARE_VALUE, 0);	/* color compare */
1606     	vga_wgfx (fb_info->regs, VGA_GFX_DATA_ROTATE, 0);	/* data rotate */
1607     	vga_wgfx (fb_info->regs, VGA_GFX_PLANE_READ, 0);	/* read map select */
1608     	vga_wgfx (fb_info->regs, VGA_GFX_MISC, 1);	/* miscellaneous register */
1609     	vga_wgfx (fb_info->regs, VGA_GFX_COMPARE_MASK, 15);	/* color don't care */
1610     	vga_wgfx (fb_info->regs, VGA_GFX_BIT_MASK, 255);	/* bit mask */
1611     
1612     	vga_wseq (fb_info->regs, CL_SEQR12, 0x0);	/* graphics cursor attributes: nothing special */
1613     
1614     	/* finally, turn on everything - turn off "FullBandwidth" bit */
1615     	/* also, set "DotClock%2" bit where requested */
1616     	tmp = 0x01;
1617     
1618     /*** FB_VMODE_CLOCK_HALVE in linux/fb.h not defined anymore ?
1619         if (var->vmode & FB_VMODE_CLOCK_HALVE)
1620     	tmp |= 0x08;
1621     */
1622     
1623     	vga_wseq (fb_info->regs, VGA_SEQ_CLOCK_MODE, tmp);
1624     	DPRINTK ("CL_SEQR1: %d\n", tmp);
1625     
1626     	fb_info->currentmode = *_par;
1627     
1628     	DPRINTK ("virtual offset: (%d,%d)\n", _par->var.xoffset, _par->var.yoffset);
1629     	/* pan to requested offset */
1630     	clgen_pan_display (&fb_info->currentmode.var, (struct fb_info_gen *) fb_info);
1631     
1632     #ifdef CLGEN_DEBUG
1633     	clgen_dump ();
1634     #endif
1635     
1636     	DPRINTK ("EXIT\n");
1637     	return;
1638     }
1639     
1640     
1641     static int clgen_getcolreg (unsigned regno, unsigned *red, unsigned *green,
1642     			    unsigned *blue, unsigned *transp,
1643     			    struct fb_info *info)
1644     {
1645         struct clgenfb_info *fb_info = (struct clgenfb_info *)info;
1646     
1647         if (regno > 255)
1648     	return 1;
1649         *red = fb_info->palette[regno].red;
1650         *green = fb_info->palette[regno].green;
1651         *blue = fb_info->palette[regno].blue;
1652         *transp = 0;
1653         return 0;
1654     }
1655     
1656     
1657     static int clgen_setcolreg (unsigned regno, unsigned red, unsigned green,
1658     			    unsigned blue, unsigned transp,
1659     			    struct fb_info *info)
1660     {
1661     	struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
1662     
1663     	if (regno > 255)
1664     		return -EINVAL;
1665     
1666     #ifdef FBCON_HAS_CFB8
1667     	switch (fb_info->currentmode.var.bits_per_pixel) {
1668     	case 8:
1669     		/* "transparent" stuff is completely ignored. */
1670     		WClut (fb_info, regno, red >> 10, green >> 10, blue >> 10);
1671     		break;
1672     	default:
1673     		/* do nothing */
1674     		break;
1675     	}
1676     #endif	/* FBCON_HAS_CFB8 */
1677     
1678     	fb_info->palette[regno].red = red;
1679     	fb_info->palette[regno].green = green;
1680     	fb_info->palette[regno].blue = blue;
1681     
1682     	if (regno >= 16)
1683     		return 0;
1684     
1685     	switch (fb_info->currentmode.var.bits_per_pixel) {
1686     
1687     #ifdef FBCON_HAS_CFB16
1688     	case 16:
1689     		assert (regno < 16);
1690     #ifdef CONFIG_PREP
1691     		fb_info->fbcon_cmap.cfb16[regno] =
1692     		    ((red & 0xf800) >> 9) |
1693     		    ((green & 0xf800) >> 14) |
1694     		    ((green & 0xf800) << 2) |
1695     		    ((blue & 0xf800) >> 3);
1696     #else
1697     		fb_info->fbcon_cmap.cfb16[regno] =
1698     		    ((red & 0xf800) >> 1) |
1699     		    ((green & 0xf800) >> 6) |
1700     		    ((blue & 0xf800) >> 11);
1701     #endif
1702     #endif /* FBCON_HAS_CFB16 */
1703     
1704     #ifdef FBCON_HAS_CFB24
1705     	case 24:
1706     		assert (regno < 16);
1707     		fb_info->fbcon_cmap.cfb24[regno] =
1708     			(red   << fb_info->currentmode.var.red.offset)   |
1709     			(green << fb_info->currentmode.var.green.offset) |
1710     			(blue  << fb_info->currentmode.var.blue.offset);
1711     		break;
1712     #endif /* FBCON_HAS_CFB24 */
1713     
1714     #ifdef FBCON_HAS_CFB32
1715     	case 32:
1716     		assert (regno < 16);
1717     #ifdef CONFIG_PREP
1718     		fb_info->fbcon_cmap.cfb32[regno] =
1719     		    ((red & 0xff00)) |
1720     		    ((green & 0xff00) << 8) |
1721     		    ((blue & 0xff00) << 16);
1722     #else
1723     		fb_info->fbcon_cmap.cfb32[regno] =
1724     		    ((red & 0xff00) << 8) |
1725     		    ((green & 0xff00)) |
1726     		    ((blue & 0xff00) >> 8);
1727     #endif
1728     		break;
1729     #endif /* FBCON_HAS_CFB32 */
1730     	default:
1731     		/* do nothing */
1732     		break;
1733     	}
1734     
1735     	return 0;
1736     }
1737     
1738     /*************************************************************************
1739     	clgen_pan_display()
1740     
1741     	performs display panning - provided hardware permits this
1742     **************************************************************************/
1743     static int clgen_pan_display (const struct fb_var_screeninfo *var,
1744     			      struct fb_info_gen *info)
1745     {
1746     	int xoffset = 0;
1747     	int yoffset = 0;
1748     	unsigned long base;
1749     	unsigned char tmp = 0, tmp2 = 0, xpix;
1750     	struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
1751     
1752     	DPRINTK ("ENTER\n");
1753     
1754     	/* no range checks for xoffset and yoffset,   */
1755     	/* as fbgen_pan_display has already done this */
1756     
1757     	fb_info->currentmode.var.xoffset = var->xoffset;
1758     	fb_info->currentmode.var.yoffset = var->yoffset;
1759     
1760     	xoffset = var->xoffset * fb_info->currentmode.var.bits_per_pixel / 8;
1761     	yoffset = var->yoffset;
1762     
1763     	base = yoffset * fb_info->currentmode.line_length + xoffset;
1764     
1765     	if (fb_info->currentmode.var.bits_per_pixel == 1) {
1766     		/* base is already correct */
1767     		xpix = (unsigned char) (var->xoffset % 8);
1768     	} else {
1769     		base /= 4;
1770     		xpix = (unsigned char) ((xoffset % 4) * 2);
1771     	}
1772     
1773     	/* lower 8 + 8 bits of screen start address */
1774     	vga_wcrt (fb_info->regs, VGA_CRTC_START_LO, (unsigned char) (base & 0xff));
1775     	vga_wcrt (fb_info->regs, VGA_CRTC_START_HI, (unsigned char) (base >> 8));
1776     
1777     	/* construct bits 16, 17 and 18 of screen start address */
1778     	if (base & 0x10000)
1779     		tmp |= 0x01;
1780     	if (base & 0x20000)
1781     		tmp |= 0x04;
1782     	if (base & 0x40000)
1783     		tmp |= 0x08;
1784     
1785     	tmp2 = (vga_rcrt (fb_info->regs, CL_CRT1B) & 0xf2) | tmp;	/* 0xf2 is %11110010, exclude tmp bits */
1786     	vga_wcrt (fb_info->regs, CL_CRT1B, tmp2);
1787     
1788     	/* construct bit 19 of screen start address */
1789     	if (clgen_board_info[fb_info->btype].scrn_start_bit19) {
1790     		tmp2 = 0;
1791     		if (base & 0x80000)
1792     			tmp2 = 0x80;
1793     		vga_wcrt (fb_info->regs, CL_CRT1D, tmp2);
1794     	}
1795     
1796     	/* write pixel panning value to AR33; this does not quite work in 8bpp */
1797     	/* ### Piccolo..? Will this work? */
1798     	if (fb_info->currentmode.var.bits_per_pixel == 1)
1799     		vga_wattr (fb_info->regs, CL_AR33, xpix);
1800     
1801     
1802     	DPRINTK ("EXIT\n");
1803     	return (0);
1804     }
1805     
1806     
1807     static int clgen_blank (int blank_mode, struct fb_info_gen *info)
1808     {
1809     	/*
1810     	 *  Blank the screen if blank_mode != 0, else unblank. If blank == NULL
1811     	 *  then the caller blanks by setting the CLUT (Color Look Up Table) to all
1812     	 *  black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due
1813     	 *  to e.g. a video mode which doesn't support it. Implements VESA suspend
1814     	 *  and powerdown modes on hardware that supports disabling hsync/vsync:
1815     	 *    blank_mode == 2: suspend vsync
1816     	 *    blank_mode == 3: suspend hsync
1817     	 *    blank_mode == 4: powerdown
1818     	 */
1819     	unsigned char val;
1820     	static int current_mode = 0;
1821     	struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
1822     
1823     	DPRINTK ("ENTER, blank mode = %d\n", blank_mode);
1824     
1825     	if (current_mode == blank_mode) {
1826     		DPRINTK ("EXIT, returning 0\n");
1827     		return 0;
1828     	}
1829     
1830     	/* Undo current */
1831     	switch (current_mode) {
1832     	case 0:		/* Screen is normal */
1833     		break;
1834     	case 1:		/* Screen is blanked */
1835     		val = vga_rseq (fb_info->regs, VGA_SEQ_CLOCK_MODE);
1836     		vga_wseq (fb_info->regs, VGA_SEQ_CLOCK_MODE, val & 0xdf);	/* clear "FullBandwidth" bit */
1837     		break;
1838     	case 2:		/* vsync suspended */
1839     	case 3:		/* hsync suspended */
1840     	case 4:		/* sceen is powered down */
1841     		vga_wgfx (fb_info->regs, CL_GRE, 0x00);
1842     		break;
1843     	default:
1844     		DPRINTK ("EXIT, returning 1\n");
1845     		return 1;
1846     	}
1847     
1848     	/* set new */
1849     	switch (blank_mode) {
1850     	case 0:		/* Unblank screen */
1851     		break;
1852     	case 1:		/* Blank screen */
1853     		val = vga_rseq (fb_info->regs, VGA_SEQ_CLOCK_MODE);
1854     		vga_wseq (fb_info->regs, VGA_SEQ_CLOCK_MODE, val | 0x20);	/* set "FullBandwidth" bit */
1855     		break;
1856     	case 2:		/* suspend vsync */
1857     		vga_wgfx (fb_info->regs, CL_GRE, 0x04);
1858     		break;
1859     	case 3:		/* suspend hsync */
1860     		vga_wgfx (fb_info->regs, CL_GRE, 0x02);
1861     		break;
1862     	case 4:		/* powerdown */
1863     		vga_wgfx (fb_info->regs, CL_GRE, 0x06);
1864     		break;
1865     	default:
1866     		DPRINTK ("EXIT, returning 1\n");
1867     		return 1;
1868     	}
1869     
1870     	current_mode = blank_mode;
1871     	DPRINTK ("EXIT, returning 0\n");
1872     	return 0;
1873     }
1874     /**** END   Hardware specific Routines **************************************/
1875     /****************************************************************************/
1876     /**** BEGIN Internal Routines ***********************************************/
1877     
1878     static void __init init_vgachip (struct clgenfb_info *fb_info)
1879     {
1880     	const struct clgen_board_info_rec *bi;
1881     
1882     	DPRINTK ("ENTER\n");
1883     
1884     	assert (fb_info != NULL);
1885     
1886     	bi = &clgen_board_info[fb_info->btype];
1887     
1888     	/* reset board globally */
1889     	switch (fb_info->btype) {
1890     	case BT_PICCOLO:
1891     		WSFR (fb_info, 0x01);
1892     		udelay (500);
1893     		WSFR (fb_info, 0x51);
1894     		udelay (500);
1895     		break;
1896     	case BT_PICASSO:
1897     		WSFR2 (fb_info, 0xff);
1898     		udelay (500);
1899     		break;
1900     	case BT_SD64:
1901     	case BT_SPECTRUM:
1902     		WSFR (fb_info, 0x1f);
1903     		udelay (500);
1904     		WSFR (fb_info, 0x4f);
1905     		udelay (500);
1906     		break;
1907     	case BT_PICASSO4:
1908     		vga_wcrt (fb_info->regs, CL_CRT51, 0x00);	/* disable flickerfixer */
1909     		mdelay (100);
1910     		vga_wgfx (fb_info->regs, CL_GR2F, 0x00);	/* from Klaus' NetBSD driver: */
1911     		vga_wgfx (fb_info->regs, CL_GR33, 0x00);	/* put blitter into 542x compat */
1912     		vga_wgfx (fb_info->regs, CL_GR31, 0x00);	/* mode */
1913     		break;
1914     
1915     	case BT_GD5480:
1916     		vga_wgfx (fb_info->regs, CL_GR2F, 0x00);	/* from Klaus' NetBSD driver: */
1917     		break;
1918     
1919     	case BT_ALPINE:
1920     		/* Nothing to do to reset the board. */
1921     		break;
1922     
1923     	default:
1924     		printk (KERN_ERR "clgen: Warning: Unknown board type\n");
1925     		break;
1926     	}
1927     
1928     	assert (fb_info->size > 0); /* make sure RAM size set by this point */
1929     
1930     	/* assume it's a "large memory" board (2/4 MB) */
1931     	fb_info->smallboard = FALSE;
1932     
1933     	/* the P4 is not fully initialized here; I rely on it having been */
1934     	/* inited under AmigaOS already, which seems to work just fine    */
1935     	/* (Klaus advised to do it this way)                              */
1936     
1937     	if (fb_info->btype != BT_PICASSO4) {
1938     		WGen (fb_info, CL_VSSM, 0x10);	/* EGS: 0x16 */
1939     		WGen (fb_info, CL_POS102, 0x01);
1940     		WGen (fb_info, CL_VSSM, 0x08);	/* EGS: 0x0e */
1941     
1942     		if (fb_info->btype != BT_SD64)
1943     			WGen (fb_info, CL_VSSM2, 0x01);
1944     
1945     		vga_wseq (fb_info->regs, CL_SEQR0, 0x03);	/* reset sequencer logic */
1946     
1947     		vga_wseq (fb_info->regs, VGA_SEQ_CLOCK_MODE, 0x21);	/* FullBandwidth (video off) and 8/9 dot clock */
1948     		WGen (fb_info, VGA_MIS_W, 0xc1);	/* polarity (-/-), disable access to display memory, VGA_CRTC_START_HI base address: color */
1949     
1950     /*      vga_wgfx (fb_info->regs, CL_GRA, 0xce);    "magic cookie" - doesn't make any sense to me.. */
1951     		vga_wseq (fb_info->regs, CL_SEQR6, 0x12);	/* unlock all extension registers */
1952     
1953     		vga_wgfx (fb_info->regs, CL_GR31, 0x04);	/* reset blitter */
1954     
1955     		switch (fb_info->btype) {
1956     		case BT_GD5480:
1957     			vga_wseq (fb_info->regs, CL_SEQRF, 0x98);
1958     			break;
1959     		case BT_ALPINE:
1960     			break;
1961     		case BT_SD64:
1962     			vga_wseq (fb_info->regs, CL_SEQRF, 0xb8);
1963     			break;
1964     		default:
1965     			vga_wseq (fb_info->regs, CL_SEQR16, 0x0f);
1966     			vga_wseq (fb_info->regs, CL_SEQRF, 0xb0);
1967     			break;
1968     		}
1969     	}
1970     	vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff);	/* plane mask: nothing */
1971     	vga_wseq (fb_info->regs, VGA_SEQ_CHARACTER_MAP, 0x00);	/* character map select: doesn't even matter in gx mode */
1972     	vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x0e);	/* memory mode: chain-4, no odd/even, ext. memory */
1973     
1974     	/* controller-internal base address of video memory */
1975     	if (bi->init_sr07)
1976     		vga_wseq (fb_info->regs, CL_SEQR7, bi->sr07);
1977     
1978     	/*  vga_wseq (fb_info->regs, CL_SEQR8, 0x00); *//* EEPROM control: shouldn't be necessary to write to this at all.. */
1979     
1980     	vga_wseq (fb_info->regs, CL_SEQR10, 0x00);		/* graphics cursor X position (incomplete; position gives rem. 3 bits */
1981     	vga_wseq (fb_info->regs, CL_SEQR11, 0x00);		/* graphics cursor Y position (..."... ) */
1982     	vga_wseq (fb_info->regs, CL_SEQR12, 0x00);		/* graphics cursor attributes */
1983     	vga_wseq (fb_info->regs, CL_SEQR13, 0x00);		/* graphics cursor pattern address */
1984     
1985     	/* writing these on a P4 might give problems..  */
1986     	if (fb_info->btype != BT_PICASSO4) {
1987     		vga_wseq (fb_info->regs, CL_SEQR17, 0x00);		/* configuration readback and ext. color */
1988     		vga_wseq (fb_info->regs, CL_SEQR18, 0x02);		/* signature generator */
1989     	}
1990     
1991     	/* MCLK select etc. */
1992     	if (bi->init_sr1f)
1993     		vga_wseq (fb_info->regs, CL_SEQR1F, bi->sr1f);
1994     
1995     	vga_wcrt (fb_info->regs, VGA_CRTC_PRESET_ROW, 0x00);	/* Screen A preset row scan: none */
1996     	vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_START, 0x20);	/* Text cursor start: disable text cursor */
1997     	vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_END, 0x00);	/* Text cursor end: - */
1998     	vga_wcrt (fb_info->regs, VGA_CRTC_START_HI, 0x00);	/* Screen start address high: 0 */
1999     	vga_wcrt (fb_info->regs, VGA_CRTC_START_LO, 0x00);	/* Screen start address low: 0 */
2000     	vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_HI, 0x00);	/* text cursor location high: 0 */
2001     	vga_wcrt (fb_info->regs, VGA_CRTC_CURSOR_LO, 0x00);	/* text cursor location low: 0 */
2002     
2003     	vga_wcrt (fb_info->regs, VGA_CRTC_UNDERLINE, 0x00);	/* Underline Row scanline: - */
2004     	vga_wcrt (fb_info->regs, VGA_CRTC_MODE, 0xc3);	/* mode control: timing enable, byte mode, no compat modes */
2005     	vga_wcrt (fb_info->regs, VGA_CRTC_LINE_COMPARE, 0x00);	/* Line Compare: not needed */
2006     	/* ### add 0x40 for text modes with > 30 MHz pixclock */
2007     	vga_wcrt (fb_info->regs, CL_CRT1B, 0x02);	/* ext. display controls: ext.adr. wrap */
2008     
2009     	vga_wgfx (fb_info->regs, VGA_GFX_SR_VALUE, 0x00);	/* Set/Reset registes: - */
2010     	vga_wgfx (fb_info->regs, VGA_GFX_SR_ENABLE, 0x00);	/* Set/Reset enable: - */
2011     	vga_wgfx (fb_info->regs, VGA_GFX_COMPARE_VALUE, 0x00);	/* Color Compare: - */
2012     	vga_wgfx (fb_info->regs, VGA_GFX_DATA_ROTATE, 0x00);	/* Data Rotate: - */
2013     	vga_wgfx (fb_info->regs, VGA_GFX_PLANE_READ, 0x00);	/* Read Map Select: - */
2014     	vga_wgfx (fb_info->regs, VGA_GFX_MODE, 0x00);	/* Mode: conf. for 16/4/2 color mode, no odd/even, read/write mode 0 */
2015     	vga_wgfx (fb_info->regs, VGA_GFX_MISC, 0x01);	/* Miscellaneous: memory map base address, graphics mode */
2016     	vga_wgfx (fb_info->regs, VGA_GFX_COMPARE_MASK, 0x0f);	/* Color Don't care: involve all planes */
2017     	vga_wgfx (fb_info->regs, VGA_GFX_BIT_MASK, 0xff);	/* Bit Mask: no mask at all */
2018     	if (fb_info->btype == BT_ALPINE)
2019     		vga_wgfx (fb_info->regs, CL_GRB, 0x20);	/* (5434 can't have bit 3 set for bitblt) */
2020     	else
2021     		vga_wgfx (fb_info->regs, CL_GRB, 0x28);	/* Graphics controller mode extensions: finer granularity, 8byte data latches */
2022     
2023     	vga_wgfx (fb_info->regs, CL_GRC, 0xff);	/* Color Key compare: - */
2024     	vga_wgfx (fb_info->regs, CL_GRD, 0x00);	/* Color Key compare mask: - */
2025     	vga_wgfx (fb_info->regs, CL_GRE, 0x00);	/* Miscellaneous control: - */
2026     	/*  vga_wgfx (fb_info->regs, CL_GR10, 0x00); *//* Background color byte 1: - */
2027     /*  vga_wgfx (fb_info->regs, CL_GR11, 0x00); */
2028     
2029     	vga_wattr (fb_info->regs, VGA_ATC_PALETTE0, 0x00);	/* Attribute Controller palette registers: "identity mapping" */
2030     	vga_wattr (fb_info->regs, VGA_ATC_PALETTE1, 0x01);
2031     	vga_wattr (fb_info->regs, VGA_ATC_PALETTE2, 0x02);
2032     	vga_wattr (fb_info->regs, VGA_ATC_PALETTE3, 0x03);
2033     	vga_wattr (fb_info->regs, VGA_ATC_PALETTE4, 0x04);
2034     	vga_wattr (fb_info->regs, VGA_ATC_PALETTE5, 0x05);
2035     	vga_wattr (fb_info->regs, VGA_ATC_PALETTE6, 0x06);
2036     	vga_wattr (fb_info->regs, VGA_ATC_PALETTE7, 0x07);
2037     	vga_wattr (fb_info->regs, VGA_ATC_PALETTE8, 0x08);
2038     	vga_wattr (fb_info->regs, VGA_ATC_PALETTE9, 0x09);
2039     	vga_wattr (fb_info->regs, VGA_ATC_PALETTEA, 0x0a);
2040     	vga_wattr (fb_info->regs, VGA_ATC_PALETTEB, 0x0b);
2041     	vga_wattr (fb_info->regs, VGA_ATC_PALETTEC, 0x0c);
2042     	vga_wattr (fb_info->regs, VGA_ATC_PALETTED, 0x0d);
2043     	vga_wattr (fb_info->regs, VGA_ATC_PALETTEE, 0x0e);
2044     	vga_wattr (fb_info->regs, VGA_ATC_PALETTEF, 0x0f);
2045     
2046     	vga_wattr (fb_info->regs, VGA_ATC_MODE, 0x01);	/* Attribute Controller mode: graphics mode */
2047     	vga_wattr (fb_info->regs, VGA_ATC_OVERSCAN, 0x00);	/* Overscan color reg.: reg. 0 */
2048     	vga_wattr (fb_info->regs, VGA_ATC_PLANE_ENABLE, 0x0f);	/* Color Plane enable: Enable all 4 planes */
2049     /* ###  vga_wattr (fb_info->regs, CL_AR33, 0x00); * Pixel Panning: - */
2050     	vga_wattr (fb_info->regs, VGA_ATC_COLOR_PAGE, 0x00);	/* Color Select: - */
2051     
2052     	WGen (fb_info, VGA_PEL_MSK, 0xff);	/* Pixel mask: no mask */
2053     
2054     	if (fb_info->btype != BT_ALPINE && fb_info->btype != BT_GD5480)
2055     		WGen (fb_info, VGA_MIS_W, 0xc3);	/* polarity (-/-), enable display mem, VGA_CRTC_START_HI i/o base = color */
2056     
2057     	vga_wgfx (fb_info->regs, CL_GR31, 0x04);	/* BLT Start/status: Blitter reset */
2058     	vga_wgfx (fb_info->regs, CL_GR31, 0x00);	/* - " -           : "end-of-reset" */
2059     
2060     	/* CLUT setup */
2061     	WClut (fb_info, 0, 0x00, 0x00, 0x00);	/* background: black */
2062     	WClut (fb_info, 1, 0x3f, 0x3f, 0x3f);	/* foreground: white */
2063     	WClut (fb_info, 2, 0x00, 0x20, 0x00);
2064     	WClut (fb_info, 3, 0x00, 0x20, 0x20);
2065     	WClut (fb_info, 4, 0x20, 0x00, 0x00);
2066     	WClut (fb_info, 5, 0x20, 0x00, 0x20);
2067     	WClut (fb_info, 6, 0x20, 0x10, 0x00);
2068     	WClut (fb_info, 7, 0x20, 0x20, 0x20);
2069     	WClut (fb_info, 8, 0x10, 0x10, 0x10);
2070     	WClut (fb_info, 9, 0x10, 0x10, 0x30);
2071     	WClut (fb_info, 10, 0x10, 0x30, 0x10);
2072     	WClut (fb_info, 11, 0x10, 0x30, 0x30);
2073     	WClut (fb_info, 12, 0x30, 0x10, 0x10);
2074     	WClut (fb_info, 13, 0x30, 0x10, 0x30);
2075     	WClut (fb_info, 14, 0x30, 0x30, 0x10);
2076     	WClut (fb_info, 15, 0x30, 0x30, 0x30);
2077     
2078     	/* the rest a grey ramp */
2079     	{
2080     		int i;
2081     
2082     		for (i = 16; i < 256; i++)
2083     			WClut (fb_info, i, i >> 2, i >> 2, i >> 2);
2084     	}
2085     
2086     
2087     	/* misc... */
2088     	WHDR (fb_info, 0);	/* Hidden DAC register: - */
2089     
2090     	printk (KERN_INFO "clgen: This board has %ld bytes of DRAM memory\n", fb_info->size);
2091     	DPRINTK ("EXIT\n");
2092     	return;
2093     }
2094     
2095     static void switch_monitor (struct clgenfb_info *fb_info, int on)
2096     {
2097     #ifdef CONFIG_ZORRO /* only works on Zorro boards */
2098     	static int IsOn = 0;	/* XXX not ok for multiple boards */
2099     
2100     	DPRINTK ("ENTER\n");
2101     
2102     	if (fb_info->btype == BT_PICASSO4)
2103     		return;		/* nothing to switch */
2104     	if (fb_info->btype == BT_ALPINE)
2105     		return;		/* nothing to switch */
2106     	if (fb_info->btype == BT_GD5480)
2107     		return;		/* nothing to switch */
2108     	if (fb_info->btype == BT_PICASSO) {
2109     		if ((on && !IsOn) || (!on && IsOn))
2110     			WSFR (fb_info, 0xff);
2111     
2112     		DPRINTK ("EXIT\n");
2113     		return;
2114     	}
2115     	if (on) {
2116     		switch (fb_info->btype) {
2117     		case BT_SD64:
2118     			WSFR (fb_info, fb_info->SFR | 0x21);
2119     			break;
2120     		case BT_PICCOLO:
2121     			WSFR (fb_info, fb_info->SFR | 0x28);
2122     			break;
2123     		case BT_SPECTRUM:
2124     			WSFR (fb_info, 0x6f);
2125     			break;
2126     		default: /* do nothing */ break;
2127     		}
2128     	} else {
2129     		switch (fb_info->btype) {
2130     		case BT_SD64:
2131     			WSFR (fb_info, fb_info->SFR & 0xde);
2132     			break;
2133     		case BT_PICCOLO:
2134     			WSFR (fb_info, fb_info->SFR & 0xd7);
2135     			break;
2136     		case BT_SPECTRUM:
2137     			WSFR (fb_info, 0x4f);
2138     			break;
2139     		default: /* do nothing */ break;
2140     		}
2141     	}
2142     
2143     	DPRINTK ("EXIT\n");
2144     #endif /* CONFIG_ZORRO */
2145     }
2146     
2147     static void clgen_set_disp (const void *par, struct display *disp,
2148     			    struct fb_info_gen *info)
2149     {
2150     	struct clgenfb_par *_par = (struct clgenfb_par *) par;
2151     	struct clgenfb_info *fb_info = (struct clgenfb_info *) info;
2152     	int accel_text;
2153     
2154     	DPRINTK ("ENTER\n");
2155     
2156     	assert (_par != NULL);
2157     	assert (fb_info != NULL);
2158     
2159     	accel_text = _par->var.accel_flags & FB_ACCELF_TEXT;
2160     
2161     	printk ("Cirrus Logic video mode: ");
2162     	disp->screen_base = (char *) fb_info->fbmem;
2163     	switch (_par->var.bits_per_pixel) {
2164     #ifdef FBCON_HAS_MFB
2165     	case 1:
2166     		printk ("monochrome\n");
2167     		if (fb_info->btype == BT_GD5480)
2168     			disp->screen_base = (char *) fb_info->fbmem;
2169     		disp->dispsw = &fbcon_mfb;
2170     		break;
2171     #endif
2172     #ifdef FBCON_HAS_CFB8
2173     	case 8:
2174     		printk ("8 bit color depth\n");
2175     		if (fb_info->btype == BT_GD5480)
2176     			disp->screen_base = (char *) fb_info->fbmem;
2177     		if (accel_text)
2178     			disp->dispsw = &fbcon_clgen_8;
2179     		else
2180     			disp->dispsw = &fbcon_cfb8;
2181     		break;
2182     #endif
2183     #ifdef FBCON_HAS_CFB16
2184     	case 16:
2185     		printk ("16 bit color depth\n");
2186     		if (accel_text)
2187     			disp->dispsw = &fbcon_clgen_16;
2188     		else
2189     			disp->dispsw = &fbcon_cfb16;
2190     		if (fb_info->btype == BT_GD5480)
2191     			disp->screen_base = (char *) fb_info->fbmem + 1 * MB_;
2192     		disp->dispsw_data = fb_info->fbcon_cmap.cfb16;
2193     		break;
2194     #endif
2195     #ifdef FBCON_HAS_CFB24
2196     	case 24:
2197     		printk ("24 bit color depth\n");
2198     		disp->dispsw = &fbcon_cfb24;
2199     		if (fb_info->btype == BT_GD5480)
2200     			disp->screen_base = (char *) fb_info->fbmem + 2 * MB_;
2201     		disp->dispsw_data = fb_info->fbcon_cmap.cfb24;
2202     		break;
2203     #endif
2204     #ifdef FBCON_HAS_CFB32
2205     	case 32:
2206     		printk ("32 bit color depth\n");
2207     		if (accel_text)
2208     			disp->dispsw = &fbcon_clgen_32;
2209     		else
2210     			disp->dispsw = &fbcon_cfb32;
2211     		if (fb_info->btype == BT_GD5480)
2212     			disp->screen_base = (char *) fb_info->fbmem + 2 * MB_;
2213     		disp->dispsw_data = fb_info->fbcon_cmap.cfb32;
2214     		break;
2215     #endif
2216     
2217     	default:
2218     		printk ("unsupported color depth\n");
2219     		disp->dispsw = &fbcon_dummy;
2220     		disp->dispsw_data = NULL;
2221     		break;
2222     	}
2223     
2224     	DPRINTK ("EXIT\n");
2225     }
2226     
2227     #ifdef FBCON_HAS_CFB8
2228     static void fbcon_clgen8_bmove (struct display *p, int sy, int sx,
2229     				int dy, int dx, int height, int width)
2230     {
2231     	struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
2232     
2233     	DPRINTK ("ENTER\n");
2234     
2235     	sx *= fontwidth (p);
2236     	sy *= fontheight (p);
2237     	dx *= fontwidth (p);
2238     	dy *= fontheight (p);
2239     	width *= fontwidth (p);
2240     	height *= fontheight (p);
2241     
2242     	clgen_BitBLT (fb_info->regs, (unsigned short) sx, (unsigned short) sy,
2243     		      (unsigned short) dx, (unsigned short) dy,
2244     		      (unsigned short) width, (unsigned short) height,
2245     		      fb_info->currentmode.line_length);
2246     
2247     	DPRINTK ("EXIT\n");
2248     }
2249     
2250     static void fbcon_clgen8_clear (struct vc_data *conp, struct display *p,
2251     				int sy, int sx, int height, int width)
2252     {
2253     	struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
2254     	unsigned short col;
2255     
2256     	DPRINTK ("ENTER\n");
2257     
2258     	sx *= fontwidth (p);
2259     	sy *= fontheight (p);
2260     	width *= fontwidth (p);
2261     	height *= fontheight (p);
2262     
2263     	col = attr_bgcol_ec (p, conp);
2264     	col &= 0xff;
2265     
2266     	clgen_RectFill (fb_info, (unsigned short) sx, (unsigned short) sy,
2267     			(unsigned short) width, (unsigned short) height,
2268     			col, fb_info->currentmode.line_length);
2269     
2270     	DPRINTK ("EXIT\n");
2271     }
2272     
2273     #endif
2274     
2275     #ifdef FBCON_HAS_CFB16
2276     static void fbcon_clgen16_bmove (struct display *p, int sy, int sx,
2277     				 int dy, int dx, int height, int width)
2278     {
2279     	struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
2280     
2281     	DPRINTK ("ENTER\n");
2282     
2283     	sx *= fontwidth (p) * 2;	/* 2 bytes/pixel */
2284     	sy *= fontheight (p);
2285     	dx *= fontwidth (p) * 2;	/* 2 bytes/pixel */
2286     	dy *= fontheight (p);
2287     	width *= fontwidth (p) * 2;	/* 2 bytes/pixel */
2288     	height *= fontheight (p);
2289     
2290     	clgen_BitBLT (fb_info->regs, (unsigned short) sx, (unsigned short) sy,
2291     		      (unsigned short) dx, (unsigned short) dy,
2292     		      (unsigned short) width, (unsigned short) height,
2293     		      fb_info->currentmode.line_length);
2294     
2295     	DPRINTK ("EXIT\n");
2296     }
2297     
2298     static void fbcon_clgen16_clear (struct vc_data *conp, struct display *p,
2299     				 int sy, int sx, int height, int width)
2300     {
2301     	struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
2302     	unsigned short col;
2303     
2304     	DPRINTK ("ENTER\n");
2305     
2306     	sx *= fontwidth (p) * 2;	/* 2 bytes/pixel */
2307     	sy *= fontheight (p);
2308     	width *= fontwidth (p) * 2;	/* 2 bytes/pixel? */
2309     	height *= fontheight (p);
2310     
2311     	col = attr_bgcol_ec (p, conp);
2312     	col &= 0xff;
2313     
2314     	clgen_RectFill (fb_info, (unsigned short) sx, (unsigned short) sy,
2315     			(unsigned short) width, (unsigned short) height,
2316     			col, fb_info->currentmode.line_length);
2317     
2318     	DPRINTK ("EXIT\n");
2319     }
2320     
2321     #endif
2322     
2323     #ifdef FBCON_HAS_CFB32
2324     static void fbcon_clgen32_bmove (struct display *p, int sy, int sx,
2325     				 int dy, int dx, int height, int width)
2326     {
2327     	struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
2328     
2329     	DPRINTK ("ENTER\n");
2330     
2331     	sx *= fontwidth (p) * 4;	/* 4 bytes/pixel */
2332     	sy *= fontheight (p);
2333     	dx *= fontwidth (p) * 4;	/* 4 bytes/pixel */
2334     	dy *= fontheight (p);
2335     	width *= fontwidth (p) * 4;	/* 4 bytes/pixel */
2336     	height *= fontheight (p);
2337     
2338     	clgen_BitBLT (fb_info->regs, (unsigned short) sx, (unsigned short) sy,
2339     		      (unsigned short) dx, (unsigned short) dy,
2340     		      (unsigned short) width, (unsigned short) height,
2341     		      fb_info->currentmode.line_length);
2342     
2343     	DPRINTK ("EXIT\n");
2344     }
2345     
2346     static void fbcon_clgen32_clear (struct vc_data *conp, struct display *p,
2347     				 int sy, int sx, int height, int width)
2348     {
2349     	struct clgenfb_info *fb_info = (struct clgenfb_info *) p->fb_info;
2350     
2351     	unsigned short col;
2352     
2353     	DPRINTK ("ENTER\n");
2354     
2355     	sx *= fontwidth (p) * 4;	/* 4 bytes/pixel */
2356     	sy *= fontheight (p);
2357     	width *= fontwidth (p) * 4;	/* 4 bytes/pixel? */
2358     	height *= fontheight (p);
2359     
2360     	col = attr_bgcol_ec (p, conp);
2361     	col &= 0xff;
2362     
2363     	clgen_RectFill (fb_info, (unsigned short) sx, (unsigned short) sy,
2364     			(unsigned short) width, (unsigned short) height,
2365     			col, fb_info->currentmode.line_length);
2366     
2367     	DPRINTK ("EXIT\n");
2368     }
2369     
2370     #endif				/* FBCON_HAS_CFB32 */
2371     
2372     
2373     
2374     
2375     #ifdef CONFIG_PREP
2376     #define PREP_VIDEO_BASE ((volatile unsigned long) 0xC0000000)
2377     #define PREP_IO_BASE    ((volatile unsigned char *) 0x80000000)
2378     static void __init get_prep_addrs (unsigned long *display, unsigned long *registers)
2379     {
2380     	DPRINTK ("ENTER\n");
2381     
2382     	*display = PREP_VIDEO_BASE;
2383     	*registers = (unsigned long) PREP_IO_BASE;
2384     
2385     	DPRINTK ("EXIT\n");
2386     }
2387     
2388     #endif				/* CONFIG_PREP */
2389     
2390     
2391     
2392     
2393     #ifdef CONFIG_PCI
2394     /* Pulled the logic from XFree86 Cirrus driver to get the memory size,
2395      * based on the DRAM bandwidth bit and DRAM bank switching bit.  This
2396      * works with 1MB, 2MB and 4MB configurations (which the Motorola boards
2397      * seem to have. */
2398     static unsigned int __init clgen_get_memsize (caddr_t regbase)
2399     {
2400     	unsigned long mem = 1 * MB_;
2401     	unsigned char SRF;
2402     
2403     	DPRINTK ("ENTER\n");
2404     
2405     	SRF = vga_rseq (regbase, CL_SEQRF);
2406     	if ((SRF & 0x18) == 0x18) {
2407     		/* 64-bit DRAM data bus width; assume 2MB. Also indicates 2MB memory
2408     		   * on the 5430. */
2409     		mem *= 2;
2410     	}
2411     	if (SRF & 0x80) {
2412     		/* If DRAM bank switching is enabled, there must be twice as much
2413     		   * memory installed. (4MB on the 5434) */
2414     		mem *= 2;
2415     	}
2416     	return mem;
2417     
2418     	DPRINTK ("EXIT\n");
2419     }
2420     
2421     
2422     
2423     static struct pci_dev * __init clgen_pci_dev_get (clgen_board_t *btype)
2424     {
2425     	struct pci_dev *pdev;
2426     	int i;
2427     
2428     	DPRINTK ("ENTER\n");
2429     
2430     	for (i = 0; i < ARRAY_SIZE(clgen_pci_probe_list); i++) {
2431     		pdev = NULL;
2432     		while ((pdev = pci_find_device (PCI_VENDOR_ID_CIRRUS,
2433     				clgen_pci_probe_list[i].device, pdev)) != NULL) {
2434     			if (pci_enable_device(pdev) == 0) {
2435     				*btype = clgen_pci_probe_list[i].btype;
2436     				DPRINTK ("EXIT, returning pdev=%p\n", pdev);
2437     				return pdev;
2438     			}
2439     		}
2440     	}
2441     
2442     	DPRINTK ("EXIT, returning NULL\n");
2443     	return NULL;
2444     }
2445     
2446     
2447     
2448     
2449     static void __init get_pci_addrs (const struct pci_dev *pdev,
2450     			   unsigned long *display, unsigned long *registers)
2451     {
2452     	assert (pdev != NULL);
2453     	assert (display != NULL);
2454     	assert (registers != NULL);
2455     
2456     	DPRINTK ("ENTER\n");
2457     
2458     	*display = 0;
2459     	*registers = 0;
2460     
2461     	/* This is a best-guess for now */
2462     
2463     	if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
2464     		*display = pci_resource_start(pdev, 1);
2465     		*registers = pci_resource_start(pdev, 0);
2466     	} else {
2467     		*display = pci_resource_start(pdev, 0);
2468     		*registers = pci_resource_start(pdev, 1);
2469     	}
2470     
2471     	assert (*display != 0);
2472     
2473     	DPRINTK ("EXIT\n");
2474     }
2475     
2476     
2477     static void __exit clgen_pci_unmap (struct clgenfb_info *info)
2478     {
2479     	iounmap (info->fbmem);
2480     	release_mem_region(info->fbmem_phys, info->size);
2481     
2482     #if 0 /* if system didn't claim this region, we would... */
2483     	release_mem_region(0xA0000, 65535);
2484     #endif
2485     
2486     	if (release_io_ports)
2487     		release_region(0x3C0, 32);
2488     }
2489     
2490     
2491     static int __init clgen_pci_setup (struct clgenfb_info *info,
2492     				   clgen_board_t *btype)
2493     {
2494     	struct pci_dev *pdev;
2495     	unsigned long board_addr, board_size;
2496     
2497     	DPRINTK ("ENTER\n");
2498     
2499     	pdev = clgen_pci_dev_get (btype);
2500     	if (!pdev) {
2501     		printk (KERN_ERR " Couldn't find PCI device\n");
2502     		DPRINTK ("EXIT, returning 1\n");
2503     		return 1;
2504     	}
2505     	DPRINTK (" Found PCI device, base address 0 is 0x%lx, btype set to %d\n",
2506     		 pdev->resource[0].start, *btype);
2507     	DPRINTK (" base address 1 is 0x%lx\n", pdev->resource[1].start);
2508     
2509     	info->pdev = pdev;
2510     
2511     #ifdef CONFIG_PREP
2512     	/* Xbh does this, though 0 seems to be the init value */
2513     	pcibios_write_config_dword (0, pdev->devfn, PCI_BASE_ADDRESS_0, 0x00000000);
2514     #endif
2515     
2516     #ifdef CONFIG_PREP
2517     	get_prep_addrs (&board_addr, &info->fbregs_phys);
2518     #else				/* CONFIG_PREP */
2519     	DPRINTK ("Attempt to get PCI info for Cirrus Graphics Card\n");
2520     	get_pci_addrs (pdev, &board_addr, &info->fbregs_phys);
2521     #endif				/* CONFIG_PREP */
2522     
2523     	DPRINTK ("Board address: 0x%lx, register address: 0x%lx\n", board_addr, info->fbregs_phys);
2524     
2525     #ifdef CONFIG_PREP
2526     	/* PReP dies if we ioremap the IO registers, but it works w/out... */
2527     	info->regs = (char *) info->fbregs_phys;
2528     #else
2529     	info->regs = 0;		/* FIXME: this forces VGA.  alternatives? */
2530     #endif
2531     
2532     	if (*btype == BT_GD5480) {
2533     		board_size = 32 * MB_;
2534     	} else {
2535     		board_size = clgen_get_memsize (info->regs);
2536     	}
2537     
2538     	if (!request_mem_region(board_addr, board_size, "clgenfb")) {
2539     		printk(KERN_ERR "clgen: cannot reserve region 0x%lx, abort\n",
2540     		       board_addr);
2541     		return -1;
2542     	}
2543     #if 0 /* if the system didn't claim this region, we would... */
2544     	if (!request_mem_region(0xA0000, 65535, "clgenfb")) {
2545     		printk(KERN_ERR "clgen: cannot reserve region 0x%lx, abort\n",
2546     		       0xA0000L);
2547     		release_mem_region(board_addr, board_size);
2548     		return -1;
2549     	}
2550     #endif
2551     	if (request_region(0x3C0, 32, "clgenfb"))
2552     		release_io_ports = 1;
2553     
2554     	info->fbmem = ioremap (board_addr, board_size);
2555     	info->fbmem_phys = board_addr;
2556     	info->size = board_size;
2557     
2558     	printk (" RAM (%lu MB) at 0x%lx, ", info->size / MB_, board_addr);
2559     
2560     	printk (KERN_INFO "Cirrus Logic chipset on PCI bus\n");
2561     
2562     	DPRINTK ("EXIT, returning 0\n");
2563     	return 0;
2564     }
2565     #endif				/* CONFIG_PCI */
2566     
2567     
2568     
2569     
2570     #ifdef CONFIG_ZORRO
2571     static int __init clgen_zorro_find (struct zorro_dev **z_o,
2572     				    struct zorro_dev **z2_o,
2573     				    clgen_board_t *btype, unsigned long *size)
2574     {
2575     	struct zorro_dev *z = NULL;
2576     	int i;
2577     
2578     	assert (z_o != NULL);
2579     	assert (btype != NULL);
2580     
2581     	for (i = 0; i < ARRAY_SIZE(clgen_zorro_probe_list); i++)
2582     		if ((z = zorro_find_device(clgen_zorro_probe_list[i].id, NULL)))
2583     			break;
2584     
2585     	if (z) {
2586     		*z_o = z;
2587     		if (clgen_zorro_probe_list[i].id2)
2588     			*z2_o = zorro_find_device(clgen_zorro_probe_list[i].id2, NULL);
2589     		else
2590     			*z2_o = NULL;
2591     
2592     		*btype = clgen_zorro_probe_list[i].btype;
2593     		*size = clgen_zorro_probe_list[i].size;
2594     
2595     		printk (KERN_INFO "clgen: %s board detected; ",
2596     			clgen_board_info[*btype].name);
2597     
2598     		return 0;
2599     	}
2600     
2601     	printk (KERN_NOTICE "clgen: no supported board found.\n");
2602     	return -1;
2603     }
2604     
2605     
2606     static void __exit clgen_zorro_unmap (struct clgenfb_info *info)
2607     {
2608     	release_mem_region(info->board_addr, info->board_size);
2609     
2610     	if (info->btype == BT_PICASSO4) {
2611     		iounmap (info->board_addr);
2612     		iounmap (info->fbmem_phys);
2613     	} else {
2614     		if (info->board_addr > 0x01000000)
2615     			iounmap (info->board_addr);
2616     	}
2617     }
2618     
2619     
2620     static int __init clgen_zorro_setup (struct clgenfb_info *info,
2621     				     clgen_board_t *btype)
2622     {
2623     	struct zorro_dev *z = NULL, *z2 = NULL;
2624     	unsigned long board_addr, board_size, size;
2625     
2626     	assert (info != NULL);
2627     	assert (btype != NULL);
2628     
2629     	if (clgen_zorro_find (&z, &z2, btype, &size))
2630     		return -1;
2631     
2632     	assert (z > 0);
2633     	assert (z2 >= 0);
2634     	assert (*btype != BT_NONE);
2635     
2636     	info->board_addr = board_addr = z->resource.start;
2637     	info->board_size = board_size = z->resource.end-z->resource.start+1;
2638     	info->size = size;
2639     
2640     	if (!request_mem_region(board_addr, board_size, "clgenfb")) {
2641     		printk(KERN_ERR "clgen: cannot reserve region 0x%lx, abort\n",
2642     		       board_addr);
2643     		return -1;
2644     	}
2645     
2646     	printk (" RAM (%lu MB) at $%lx, ", board_size / MB_, board_addr);
2647     
2648     	if (*btype == BT_PICASSO4) {
2649     		printk (" REG at $%lx\n", board_addr + 0x600000);
2650     
2651     		/* To be precise, for the P4 this is not the */
2652     		/* begin of the board, but the begin of RAM. */
2653     		/* for P4, map in its address space in 2 chunks (### TEST! ) */
2654     		/* (note the ugly hardcoded 16M number) */
2655     		info->regs = ioremap (board_addr, 16777216);
2656     		DPRINTK ("clgen: Virtual address for board set to: $%p\n", info->regs);
2657     		info->regs += 0x600000;
2658     		info->fbregs_phys = board_addr + 0x600000;
2659     
2660     		info->fbmem_phys = board_addr + 16777216;
2661     		info->fbmem = ioremap (info->fbmem_phys, 16777216);
2662     	} else {
2663     		printk (" REG at $%lx\n", (unsigned long) z2->resource.start);
2664     
2665     		info->fbmem_phys = board_addr;
2666     		if (board_addr > 0x01000000)
2667     			info->fbmem = ioremap (board_addr, board_size);
2668     		else
2669     			info->fbmem = (caddr_t) ZTWO_VADDR (board_addr);
2670     
2671     		/* set address for REG area of board */
2672     		info->regs = (caddr_t) ZTWO_VADDR (z2->resource.start);
2673     		info->fbregs_phys = z2->resource.start;
2674     
2675     		DPRINTK ("clgen: Virtual address for board set to: $%p\n", info->regs);
2676     	}
2677     
2678     	printk (KERN_INFO "Cirrus Logic chipset on Zorro bus\n");
2679     
2680     	return 0;
2681     }
2682     #endif /* CONFIG_ZORRO */
2683     
2684     
2685     
2686     /********************************************************************/
2687     /* clgenfb_init() - master initialization function                  */
2688     /********************************************************************/
2689     int __init clgenfb_init(void)
2690     {
2691     	int err, j, k;
2692     
2693     	clgen_board_t btype = BT_NONE;
2694     	struct clgenfb_info *fb_info = NULL;
2695     
2696     	DPRINTK ("ENTER\n");
2697     
2698     	printk (KERN_INFO "clgen: Driver for Cirrus Logic based graphic boards, v" CLGEN_VERSION "\n");
2699     
2700     	fb_info = &boards[0];	/* FIXME support multiple boards ... */
2701     
2702     #ifdef CONFIG_PCI
2703     	if (clgen_pci_setup (fb_info, &btype)) { /* Also does OF setup */
2704     		DPRINTK ("EXIT, returning -ENXIO\n");
2705     		return -ENXIO;
2706     	}
2707     
2708     #elif defined(CONFIG_ZORRO)
2709     	/* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */
2710     	if (clgen_zorro_setup (fb_info, &btype)) {
2711     		DPRINTK ("EXIT, returning -ENXIO\n");
2712     		return -ENXIO;
2713     	}
2714     
2715     #else
2716     #error This driver requires Zorro or PCI bus.
2717     #endif				/* !CONFIG_PCI, !CONFIG_ZORRO */
2718     
2719     	/* sanity checks */
2720     	assert (btype != BT_NONE);
2721     	assert (btype == clgen_board_info[btype].btype);
2722     
2723     	fb_info->btype = btype;
2724     
2725     	DPRINTK ("clgen: (RAM start set to: 0x%p)\n", fb_info->fbmem);
2726     
2727     	init_vgachip (fb_info);
2728     
2729     	/* set up a few more things, register framebuffer driver etc */
2730     	fb_info->gen.parsize = sizeof (struct clgenfb_par);
2731     	fb_info->gen.fbhw = &clgen_hwswitch;
2732     
2733     	strncpy (fb_info->gen.info.modename, clgen_board_info[btype].name,
2734     		 sizeof (fb_info->gen.info.modename));
2735     	fb_info->gen.info.modename [sizeof (fb_info->gen.info.modename) - 1] = 0;
2736     
2737     	fb_info->gen.info.node = -1;
2738     	fb_info->gen.info.fbops = &clgenfb_ops;
2739     	fb_info->gen.info.disp = &disp;
2740     	fb_info->gen.info.changevar = NULL;
2741     	fb_info->gen.info.switch_con = &fbgen_switch;
2742     	fb_info->gen.info.updatevar = &fbgen_update_var;
2743     	fb_info->gen.info.blank = &fbgen_blank;
2744     	fb_info->gen.info.flags = FBINFO_FLAG_DEFAULT;
2745     
2746     	for (j = 0; j < 256; j++) {
2747     		if (j < 16) {
2748     			k = color_table[j];
2749     			fb_info->palette[j].red = default_red[k];
2750     			fb_info->palette[j].green = default_grn[k];
2751     			fb_info->palette[j].blue = default_blu[k];
2752     		} else {
2753     			fb_info->palette[j].red =
2754     			fb_info->palette[j].green =
2755     			fb_info->palette[j].blue = j;
2756     		}
2757     	}
2758     
2759     	/* now that we know the board has been registered n' stuff, we */
2760     	/* can finally initialize it to a default mode */
2761     	clgenfb_default = clgenfb_predefined[clgen_def_mode].var;
2762     	clgenfb_default.activate = FB_ACTIVATE_NOW;
2763     	clgenfb_default.yres_virtual = 480 * 3;		/* for fast scrolling (YPAN-Mode) */
2764     	err = fbgen_do_set_var (&clgenfb_default, 1, &fb_info->gen);
2765     
2766     	if (err) {
2767     		DPRINTK ("EXIT, returning -EINVAL\n");
2768     		return -EINVAL;
2769     	}
2770     
2771     	disp.var = clgenfb_default;
2772     	fbgen_set_disp (-1, &fb_info->gen);
2773     	fbgen_install_cmap (0, &fb_info->gen);
2774     
2775     	err = register_framebuffer (&fb_info->gen.info);
2776     	if (err) {
2777     		printk (KERN_ERR "clgen: ERROR - could not register fb device; err = %d!\n", err);
2778     		DPRINTK ("EXIT, returning -EINVAL\n");
2779     		return -EINVAL;
2780     	}
2781     	DPRINTK ("EXIT, returning 0\n");
2782     	return 0;
2783     }
2784     
2785     
2786     
2787         /*
2788          *  Cleanup (only needed for module)
2789          */
2790     static void __exit clgenfb_cleanup (struct clgenfb_info *info)
2791     {
2792     	DPRINTK ("ENTER\n");
2793     
2794     #ifdef CONFIG_ZORRO
2795     	switch_monitor (info, 0);
2796     
2797     	clgen_zorro_unmap (info);
2798     #else
2799     	clgen_pci_unmap (info);
2800     #endif				/* CONFIG_ZORRO */
2801     
2802     	unregister_framebuffer ((struct fb_info *) info);
2803     	printk ("Framebuffer unregistered\n");
2804     
2805     	DPRINTK ("EXIT\n");
2806     }
2807     
2808     
2809     #ifndef MODULE
2810     int __init clgenfb_setup(char *options) {
2811     	char *this_opt, s[32];
2812     	int i;
2813     
2814     	DPRINTK ("ENTER\n");
2815     
2816     	if (!options || !*options)
2817     		return 0;
2818     
2819     	for (this_opt = strtok (options, ","); this_opt != NULL;
2820     	     this_opt = strtok (NULL, ",")) {
2821     		if (!*this_opt) continue;
2822     
2823     		DPRINTK("clgenfb_setup: option '%s'\n", this_opt);
2824     
2825     		for (i = 0; i < NUM_TOTAL_MODES; i++) {
2826     			sprintf (s, "mode:%s", clgenfb_predefined[i].name);
2827     			if (strcmp (this_opt, s) == 0)
2828     				clgen_def_mode = i;
2829     		}
2830     	}
2831     	return 0;
2832     }
2833     #endif
2834     
2835     
2836         /*
2837          *  Modularization
2838          */
2839     
2840     MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@mandrakesoft.com>");
2841     MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips");
2842     
2843     static void __exit clgenfb_exit (void)
2844     {
2845     	DPRINTK ("ENTER\n");
2846     
2847     	clgenfb_cleanup (&boards[0]);	/* FIXME: support multiple boards */
2848     
2849     	DPRINTK ("EXIT\n");
2850     }
2851     
2852     #ifdef MODULE
2853     module_init(clgenfb_init);
2854     #endif
2855     module_exit(clgenfb_exit);
2856     
2857     
2858     /**********************************************************************/
2859     /* about the following functions - I have used the same names for the */
2860     /* functions as Markus Wild did in his Retina driver for NetBSD as    */
2861     /* they just made sense for this purpose. Apart from that, I wrote    */
2862     /* these functions myself.                                            */
2863     /**********************************************************************/
2864     
2865     /*** WGen() - write into one of the external/general registers ***/
2866     static void WGen (const struct clgenfb_info *fb_info,
2867     		  int regnum, unsigned char val)
2868     {
2869     	unsigned long regofs = 0;
2870     
2871     	if (fb_info->btype == BT_PICASSO) {
2872     		/* Picasso II specific hack */
2873     /*              if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D || regnum == CL_VSSM2) */
2874     		if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2875     			regofs = 0xfff;
2876     	}
2877     
2878     	vga_w (fb_info->regs, regofs + regnum, val);
2879     }
2880     
2881     /*** RGen() - read out one of the external/general registers ***/
2882     static unsigned char RGen (const struct clgenfb_info *fb_info, int regnum)
2883     {
2884     	unsigned long regofs = 0;
2885     
2886     	if (fb_info->btype == BT_PICASSO) {
2887     		/* Picasso II specific hack */
2888     /*              if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D || regnum == CL_VSSM2) */
2889     		if (regnum == VGA_PEL_IR || regnum == VGA_PEL_D)
2890     			regofs = 0xfff;
2891     	}
2892     
2893     	return vga_r (fb_info->regs, regofs + regnum);
2894     }
2895     
2896     /*** AttrOn() - turn on VideoEnable for Attribute controller ***/
2897     static void AttrOn (const struct clgenfb_info *fb_info)
2898     {
2899     	assert (fb_info != NULL);
2900     
2901     	DPRINTK ("ENTER\n");
2902     
2903     	if (vga_rcrt (fb_info->regs, CL_CRT24) & 0x80) {
2904     		/* if we're just in "write value" mode, write back the */
2905     		/* same value as before to not modify anything */
2906     		vga_w (fb_info->regs, VGA_ATT_IW,
2907     		       vga_r (fb_info->regs, VGA_ATT_R));
2908     	}
2909     	/* turn on video bit */
2910     /*      vga_w (fb_info->regs, VGA_ATT_IW, 0x20); */
2911     	vga_w (fb_info->regs, VGA_ATT_IW, 0x33);
2912     
2913     	/* dummy write on Reg0 to be on "write index" mode next time */
2914     	vga_w (fb_info->regs, VGA_ATT_IW, 0x00);
2915     
2916     	DPRINTK ("EXIT\n");
2917     }
2918     
2919     /*** WHDR() - write into the Hidden DAC register ***/
2920     /* as the HDR is the only extension register that requires special treatment
2921      * (the other extension registers are accessible just like the "ordinary"
2922      * registers of their functional group) here is a specialized routine for
2923      * accessing the HDR
2924      */
2925     static void WHDR (const struct clgenfb_info *fb_info, unsigned char val)
2926     {
2927     	unsigned char dummy;
2928     
2929     	if (fb_info->btype == BT_PICASSO) {
2930     		/* Klaus' hint for correct access to HDR on some boards */
2931     		/* first write 0 to pixel mask (3c6) */
2932     		WGen (fb_info, VGA_PEL_MSK, 0x00);
2933     		udelay (200);
2934     		/* next read dummy from pixel address (3c8) */
2935     		dummy = RGen (fb_info, VGA_PEL_IW);
2936     		udelay (200);
2937     	}
2938     	/* now do the usual stuff to access the HDR */
2939     
2940     	dummy = RGen (fb_info, VGA_PEL_MSK);
2941     	udelay (200);
2942     	dummy = RGen (fb_info, VGA_PEL_MSK);
2943     	udelay (200);
2944     	dummy = RGen (fb_info, VGA_PEL_MSK);
2945     	udelay (200);
2946     	dummy = RGen (fb_info, VGA_PEL_MSK);
2947     	udelay (200);
2948     
2949     	WGen (fb_info, VGA_PEL_MSK, val);
2950     	udelay (200);
2951     
2952     	if (fb_info->btype == BT_PICASSO) {
2953     		/* now first reset HDR access counter */
2954     		dummy = RGen (fb_info, VGA_PEL_IW);
2955     		udelay (200);
2956     
2957     		/* and at the end, restore the mask value */
2958     		/* ## is this mask always 0xff? */
2959     		WGen (fb_info, VGA_PEL_MSK, 0xff);
2960     		udelay (200);
2961     	}
2962     }
2963     
2964     
2965     /*** WSFR() - write to the "special function register" (SFR) ***/
2966     static void WSFR (struct clgenfb_info *fb_info, unsigned char val)
2967     {
2968     #ifdef CONFIG_ZORRO
2969     	assert (fb_info->regs != NULL);
2970     	fb_info->SFR = val;
2971     	z_writeb (val, fb_info->regs + 0x8000);
2972     #endif
2973     }
2974     
2975     /* The Picasso has a second register for switching the monitor bit */
2976     static void WSFR2 (struct clgenfb_info *fb_info, unsigned char val)
2977     {
2978     #ifdef CONFIG_ZORRO
2979     	/* writing an arbitrary value to this one causes the monitor switcher */
2980     	/* to flip to Amiga display */
2981     	assert (fb_info->regs != NULL);
2982     	fb_info->SFR = val;
2983     	z_writeb (val, fb_info->regs + 0x9000);
2984     #endif
2985     }
2986     
2987     
2988     /*** WClut - set CLUT entry (range: 0..63) ***/
2989     static void WClut (struct clgenfb_info *fb_info, unsigned char regnum, unsigned char red,
2990     	    unsigned char green, unsigned char blue)
2991     {
2992     	unsigned int data = VGA_PEL_D;
2993     
2994     	/* address write mode register is not translated.. */
2995     	vga_w (fb_info->regs, VGA_PEL_IW, regnum);
2996     
2997     	if (fb_info->btype == BT_PICASSO || fb_info->btype == BT_PICASSO4 ||
2998     	    fb_info->btype == BT_ALPINE || fb_info->btype == BT_GD5480) {
2999     		/* but DAC data register IS, at least for Picasso II */
3000     		if (fb_info->btype == BT_PICASSO)
3001     			data += 0xfff;
3002     		vga_w (fb_info->regs, data, red);
3003     		vga_w (fb_info->regs, data, green);
3004     		vga_w (fb_info->regs, data, blue);
3005     	} else {
3006     		vga_w (fb_info->regs, data, blue);
3007     		vga_w (fb_info->regs, data, green);
3008     		vga_w (fb_info->regs, data, red);
3009     	}
3010     }
3011     
3012     
3013     #if 0
3014     /*** RClut - read CLUT entry (range 0..63) ***/
3015     static void RClut (struct clgenfb_info *fb_info, unsigned char regnum, unsigned char *red,
3016     	    unsigned char *green, unsigned char *blue)
3017     {
3018     	unsigned int data = VGA_PEL_D;
3019     
3020     	vga_w (fb_info->regs, VGA_PEL_IR, regnum);
3021     
3022     	if (fb_info->btype == BT_PICASSO || fb_info->btype == BT_PICASSO4 ||
3023     	    fb_info->btype == BT_ALPINE || fb_info->btype == BT_GD5480) {
3024     		if (fb_info->btype == BT_PICASSO)
3025     			data += 0xfff;
3026     		*red = vga_r (fb_info->regs, data);
3027     		*green = vga_r (fb_info->regs, data);
3028     		*blue = vga_r (fb_info->regs, data);
3029     	} else {
3030     		*blue = vga_r (fb_info->regs, data);
3031     		*green = vga_r (fb_info->regs, data);
3032     		*red = vga_r (fb_info->regs, data);
3033     	}
3034     }
3035     #endif
3036     
3037     
3038     /*******************************************************************
3039     	clgen_WaitBLT()
3040     
3041     	Wait for the BitBLT engine to complete a possible earlier job
3042     *********************************************************************/
3043     
3044     /* FIXME: use interrupts instead */
3045     extern inline void clgen_WaitBLT (caddr_t regbase)
3046     {
3047     	/* now busy-wait until we're done */
3048     	while (vga_rgfx (regbase, CL_GR31) & 0x08)
3049     		/* do nothing */ ;
3050     }
3051     
3052     /*******************************************************************
3053     	clgen_BitBLT()
3054     
3055     	perform accelerated "scrolling"
3056     ********************************************************************/
3057     
3058     static void clgen_BitBLT (caddr_t regbase, u_short curx, u_short cury, u_short destx, u_short desty,
3059     		   u_short width, u_short height, u_short line_length)
3060     {
3061     	u_short nwidth, nheight;
3062     	u_long nsrc, ndest;
3063     	u_char bltmode;
3064     
3065     	DPRINTK ("ENTER\n");
3066     
3067     	nwidth = width - 1;
3068     	nheight = height - 1;
3069     
3070     	bltmode = 0x00;
3071     	/* if source adr < dest addr, do the Blt backwards */
3072     	if (cury <= desty) {
3073     		if (cury == desty) {
3074     			/* if src and dest are on the same line, check x */
3075     			if (curx < destx)
3076     				bltmode |= 0x01;
3077     		} else
3078     			bltmode |= 0x01;
3079     	}
3080     	if (!bltmode) {
3081     		/* standard case: forward blitting */
3082     		nsrc = (cury * line_length) + curx;
3083     		ndest = (desty * line_length) + destx;
3084     	} else {
3085     		/* this means start addresses are at the end, counting backwards */
3086     		nsrc = cury * line_length + curx + nheight * line_length + nwidth;
3087     		ndest = desty * line_length + destx + nheight * line_length + nwidth;
3088     	}
3089     
3090             clgen_WaitBLT(regbase);
3091     
3092     	/*
3093     	   run-down of registers to be programmed:
3094     	   destination pitch
3095     	   source pitch
3096     	   BLT width/height
3097     	   source start
3098     	   destination start
3099     	   BLT mode
3100     	   BLT ROP
3101     	   VGA_GFX_SR_VALUE / VGA_GFX_SR_ENABLE: "fill color"
3102     	   start/stop
3103     	 */
3104     
3105     	/* pitch: set to line_length */
3106     	vga_wgfx (regbase, CL_GR24, line_length & 0xff);	/* dest pitch low */
3107     	vga_wgfx (regbase, CL_GR25, (line_length >> 8));	/* dest pitch hi */
3108     	vga_wgfx (regbase, CL_GR26, line_length & 0xff);	/* source pitch low */
3109     	vga_wgfx (regbase, CL_GR27, (line_length >> 8));	/* source pitch hi */
3110     
3111     	/* BLT width: actual number of pixels - 1 */
3112     	vga_wgfx (regbase, CL_GR20, nwidth & 0xff);	/* BLT width low */
3113     	vga_wgfx (regbase, CL_GR21, (nwidth >> 8));	/* BLT width hi */
3114     
3115     	/* BLT height: actual number of lines -1 */
3116     	vga_wgfx (regbase, CL_GR22, nheight & 0xff);	/* BLT height low */
3117     	vga_wgfx (regbase, CL_GR23, (nheight >> 8));	/* BLT width hi */
3118     
3119     	/* BLT destination */
3120     	vga_wgfx (regbase, CL_GR28, (u_char) (ndest & 0xff));	/* BLT dest low */
3121     	vga_wgfx (regbase, CL_GR29, (u_char) (ndest >> 8));	/* BLT dest mid */
3122     	vga_wgfx (regbase, CL_GR2A, (u_char) (ndest >> 16));	/* BLT dest hi */
3123     
3124     	/* BLT source */
3125     	vga_wgfx (regbase, CL_GR2C, (u_char) (nsrc & 0xff));	/* BLT src low */
3126     	vga_wgfx (regbase, CL_GR2D, (u_char) (nsrc >> 8));		/* BLT src mid */
3127     	vga_wgfx (regbase, CL_GR2E, (u_char) (nsrc >> 16));	/* BLT src hi */
3128     
3129     	/* BLT mode */
3130     	vga_wgfx (regbase, CL_GR30, bltmode);	/* BLT mode */
3131     
3132     	/* BLT ROP: SrcCopy */
3133     	vga_wgfx (regbase, CL_GR32, 0x0d);		/* BLT ROP */
3134     
3135     	/* and finally: GO! */
3136     	vga_wgfx (regbase, CL_GR31, 0x02);		/* BLT Start/status */
3137     
3138     	DPRINTK ("EXIT\n");
3139     }
3140     
3141     
3142     /*******************************************************************
3143     	clgen_RectFill()
3144     
3145     	perform accelerated rectangle fill
3146     ********************************************************************/
3147     
3148     static void clgen_RectFill (struct clgenfb_info *fb_info,
3149     		     u_short x, u_short y, u_short width, u_short height,
3150     		     u_char color, u_short line_length)
3151     {
3152     	u_short nwidth, nheight;
3153     	u_long ndest;
3154     	u_char op;
3155     
3156     	DPRINTK ("ENTER\n");
3157     
3158     	nwidth = width - 1;
3159     	nheight = height - 1;
3160     
3161     	ndest = (y * line_length) + x;
3162     
3163             clgen_WaitBLT(fb_info->regs);
3164     
3165     	/* pitch: set to line_length */
3166     	vga_wgfx (fb_info->regs, CL_GR24, line_length & 0xff);	/* dest pitch low */
3167     	vga_wgfx (fb_info->regs, CL_GR25, (line_length >> 8));	/* dest pitch hi */
3168     	vga_wgfx (fb_info->regs, CL_GR26, line_length & 0xff);	/* source pitch low */
3169     	vga_wgfx (fb_info->regs, CL_GR27, (line_length >> 8));	/* source pitch hi */
3170     
3171     	/* BLT width: actual number of pixels - 1 */
3172     	vga_wgfx (fb_info->regs, CL_GR20, nwidth & 0xff);	/* BLT width low */
3173     	vga_wgfx (fb_info->regs, CL_GR21, (nwidth >> 8));	/* BLT width hi */
3174     
3175     	/* BLT height: actual number of lines -1 */
3176     	vga_wgfx (fb_info->regs, CL_GR22, nheight & 0xff);		/* BLT height low */
3177     	vga_wgfx (fb_info->regs, CL_GR23, (nheight >> 8));		/* BLT width hi */
3178     
3179     	/* BLT destination */
3180     	vga_wgfx (fb_info->regs, CL_GR28, (u_char) (ndest & 0xff));	/* BLT dest low */
3181     	vga_wgfx (fb_info->regs, CL_GR29, (u_char) (ndest >> 8));	/* BLT dest mid */
3182     	vga_wgfx (fb_info->regs, CL_GR2A, (u_char) (ndest >> 16));		/* BLT dest hi */
3183     
3184     	/* BLT source: set to 0 (is a dummy here anyway) */
3185     	vga_wgfx (fb_info->regs, CL_GR2C, 0x00);	/* BLT src low */
3186     	vga_wgfx (fb_info->regs, CL_GR2D, 0x00);	/* BLT src mid */
3187     	vga_wgfx (fb_info->regs, CL_GR2E, 0x00);	/* BLT src hi */
3188     
3189     	/* This is a ColorExpand Blt, using the */
3190     	/* same color for foreground and background */
3191     	vga_wgfx (fb_info->regs, VGA_GFX_SR_VALUE, color);	/* foreground color */
3192     	vga_wgfx (fb_info->regs, VGA_GFX_SR_ENABLE, color);	/* background color */
3193     
3194     	op = 0xc0;
3195     	if (fb_info->currentmode.var.bits_per_pixel == 16) {
3196     		vga_wgfx (fb_info->regs, CL_GR10, color);	/* foreground color */
3197     		vga_wgfx (fb_info->regs, CL_GR11, color);	/* background color */
3198     		op = 0x50;
3199     		op = 0xd0;
3200     	} else if (fb_info->currentmode.var.bits_per_pixel == 32) {
3201     		vga_wgfx (fb_info->regs, CL_GR10, color);	/* foreground color */
3202     		vga_wgfx (fb_info->regs, CL_GR11, color);	/* background color */
3203     		vga_wgfx (fb_info->regs, CL_GR12, color);	/* foreground color */
3204     		vga_wgfx (fb_info->regs, CL_GR13, color);	/* background color */
3205     		vga_wgfx (fb_info->regs, CL_GR14, 0);	/* foreground color */
3206     		vga_wgfx (fb_info->regs, CL_GR15, 0);	/* background color */
3207     		op = 0x50;
3208     		op = 0xf0;
3209     	}
3210     	/* BLT mode: color expand, Enable 8x8 copy (faster?) */
3211     	vga_wgfx (fb_info->regs, CL_GR30, op);	/* BLT mode */
3212     
3213     	/* BLT ROP: SrcCopy */
3214     	vga_wgfx (fb_info->regs, CL_GR32, 0x0d);	/* BLT ROP */
3215     
3216     	/* and finally: GO! */
3217     	vga_wgfx (fb_info->regs, CL_GR31, 0x02);	/* BLT Start/status */
3218     
3219     	DPRINTK ("EXIT\n");
3220     }
3221     
3222     
3223     /**************************************************************************
3224      * bestclock() - determine closest possible clock lower(?) than the
3225      * desired pixel clock
3226      **************************************************************************/
3227     #define abs(x) ((x)<0 ? -(x) : (x))
3228     static void bestclock (long freq, long *best, long *nom,
3229     		       long *den, long *div, long maxfreq)
3230     {
3231     	long n, h, d, f;
3232     
3233     	assert (best != NULL);
3234     	assert (nom != NULL);
3235     	assert (den != NULL);
3236     	assert (div != NULL);
3237     	assert (maxfreq > 0);
3238     
3239     	*nom = 0;
3240     	*den = 0;
3241     	*div = 0;
3242     
3243     	DPRINTK ("ENTER\n");
3244     
3245     	if (freq < 8000)
3246     		freq = 8000;
3247     
3248     	if (freq > maxfreq)
3249     		freq = maxfreq;
3250     
3251     	*best = 0;
3252     	f = freq * 10;
3253     
3254     	for (n = 32; n < 128; n++) {
3255     		d = (143181 * n) / f;
3256     		if ((d >= 7) && (d <= 63)) {
3257     			if (d > 31)
3258     				d = (d / 2) * 2;
3259     			h = (14318 * n) / d;
3260     			if (abs (h - freq) < abs (*best - freq)) {
3261     				*best = h;
3262     				*nom = n;
3263     				if (d < 32) {
3264     					*den = d;
3265     					*div = 0;
3266     				} else {
3267     					*den = d / 2;
3268     					*div = 1;
3269     				}
3270     			}
3271     		}
3272     		d = ((143181 * n) + f - 1) / f;
3273     		if ((d >= 7) && (d <= 63)) {
3274     			if (d > 31)
3275     				d = (d / 2) * 2;
3276     			h = (14318 * n) / d;
3277     			if (abs (h - freq) < abs (*best - freq)) {
3278     				*best = h;
3279     				*nom = n;
3280     				if (d < 32) {
3281     					*den = d;
3282     					*div = 0;
3283     				} else {
3284     					*den = d / 2;
3285     					*div = 1;
3286     				}
3287     			}
3288     		}
3289     	}
3290     
3291     	DPRINTK ("Best possible values for given frequency:\n");
3292     	DPRINTK ("        best: %ld kHz  nom: %ld  den: %ld  div: %ld\n",
3293     		 freq, *nom, *den, *div);
3294     
3295     	DPRINTK ("EXIT\n");
3296     }
3297     
3298     
3299     /* -------------------------------------------------------------------------
3300      *
3301      * debugging functions
3302      *
3303      * -------------------------------------------------------------------------
3304      */
3305     
3306     #ifdef CLGEN_DEBUG
3307     
3308     /**
3309      * clgen_dbg_print_byte
3310      * @name: name associated with byte value to be displayed
3311      * @val: byte value to be displayed
3312      *
3313      * DESCRIPTION:
3314      * Display an indented string, along with a hexidecimal byte value, and
3315      * its decoded bits.  Bits 7 through 0 are listed in left-to-right
3316      * order.
3317      */
3318     
3319     static
3320     void clgen_dbg_print_byte (const char *name, unsigned char val)
3321     {
3322     	DPRINTK ("%8s = 0x%02X (bits 7-0: %c%c%c%c%c%c%c%c)\n",
3323     		 name, val,
3324     		 val & 0x80 ? '1' : '0',
3325     		 val & 0x40 ? '1' : '0',
3326     		 val & 0x20 ? '1' : '0',
3327     		 val & 0x10 ? '1' : '0',
3328     		 val & 0x08 ? '1' : '0',
3329     		 val & 0x04 ? '1' : '0',
3330     		 val & 0x02 ? '1' : '0',
3331     		 val & 0x01 ? '1' : '0');
3332     }
3333     
3334     
3335     /**
3336      * clgen_dbg_print_regs
3337      * @base: If using newmmio, the newmmio base address, otherwise %NULL
3338      * @reg_class: type of registers to read: %CRT, or %SEQ
3339      *
3340      * DESCRIPTION:
3341      * Dumps the given list of VGA CRTC registers.  If @base is %NULL,
3342      * old-style I/O ports are queried for information, otherwise MMIO is
3343      * used at the given @base address to query the information.
3344      */
3345     
3346     static
3347     void clgen_dbg_print_regs (caddr_t regbase, clgen_dbg_reg_class_t reg_class,...)
3348     {
3349     	va_list list;
3350     	unsigned char val = 0;
3351     	unsigned reg;
3352     	char *name;
3353     
3354     	va_start (list, reg_class);
3355     
3356     	name = va_arg (list, char *);
3357     	while (name != NULL) {
3358     		reg = va_arg (list, int);
3359     
3360     		switch (reg_class) {
3361     		case CRT:
3362     			val = vga_rcrt (regbase, (unsigned char) reg);
3363     			break;
3364     		case SEQ:
3365     			val = vga_rseq (regbase, (unsigned char) reg);
3366     			break;
3367     		default:
3368     			/* should never occur */
3369     			assert (FALSE);
3370     			break;
3371     		}
3372     
3373     		clgen_dbg_print_byte (name, val);
3374     
3375     		name = va_arg (list, char *);
3376     	}
3377     
3378     	va_end (list);
3379     }
3380     
3381     
3382     /**
3383      * clgen_dump
3384      * @clgeninfo:
3385      *
3386      * DESCRIPTION:
3387      */
3388     
3389     static
3390     void clgen_dump (void)
3391     {
3392     	clgen_dbg_reg_dump (NULL);
3393     }
3394     
3395     
3396     /**
3397      * clgen_dbg_reg_dump
3398      * @base: If using newmmio, the newmmio base address, otherwise %NULL
3399      *
3400      * DESCRIPTION:
3401      * Dumps a list of interesting VGA and CLGEN registers.  If @base is %NULL,
3402      * old-style I/O ports are queried for information, otherwise MMIO is
3403      * used at the given @base address to query the information.
3404      */
3405     
3406     static
3407     void clgen_dbg_reg_dump (caddr_t regbase)
3408     {
3409     	DPRINTK ("CLGEN VGA CRTC register dump:\n");
3410     
3411     	clgen_dbg_print_regs (regbase, CRT,
3412     			   "CR00", 0x00,
3413     			   "CR01", 0x01,
3414     			   "CR02", 0x02,
3415     			   "CR03", 0x03,
3416     			   "CR04", 0x04,
3417     			   "CR05", 0x05,
3418     			   "CR06", 0x06,
3419     			   "CR07", 0x07,
3420     			   "CR08", 0x08,
3421     			   "CR09", 0x09,
3422     			   "CR0A", 0x0A,
3423     			   "CR0B", 0x0B,
3424     			   "CR0C", 0x0C,
3425     			   "CR0D", 0x0D,
3426     			   "CR0E", 0x0E,
3427     			   "CR0F", 0x0F,
3428     			   "CR10", 0x10,
3429     			   "CR11", 0x11,
3430     			   "CR12", 0x12,
3431     			   "CR13", 0x13,
3432     			   "CR14", 0x14,
3433     			   "CR15", 0x15,
3434     			   "CR16", 0x16,
3435     			   "CR17", 0x17,
3436     			   "CR18", 0x18,
3437     			   "CR22", 0x22,
3438     			   "CR24", 0x24,
3439     			   "CR26", 0x26,
3440     			   "CR2D", 0x2D,
3441     			   "CR2E", 0x2E,
3442     			   "CR2F", 0x2F,
3443     			   "CR30", 0x30,
3444     			   "CR31", 0x31,
3445     			   "CR32", 0x32,
3446     			   "CR33", 0x33,
3447     			   "CR34", 0x34,
3448     			   "CR35", 0x35,
3449     			   "CR36", 0x36,
3450     			   "CR37", 0x37,
3451     			   "CR38", 0x38,
3452     			   "CR39", 0x39,
3453     			   "CR3A", 0x3A,
3454     			   "CR3B", 0x3B,
3455     			   "CR3C", 0x3C,
3456     			   "CR3D", 0x3D,
3457     			   "CR3E", 0x3E,
3458     			   "CR3F", 0x3F,
3459     			   NULL);
3460     
3461     	DPRINTK ("\n");
3462     
3463     	DPRINTK ("CLGEN VGA SEQ register dump:\n");
3464     
3465     	clgen_dbg_print_regs (regbase, SEQ,
3466     			   "SR00", 0x00,
3467     			   "SR01", 0x01,
3468     			   "SR02", 0x02,
3469     			   "SR03", 0x03,
3470     			   "SR04", 0x04,
3471     			   "SR08", 0x08,
3472     			   "SR09", 0x09,
3473     			   "SR0A", 0x0A,
3474     			   "SR0B", 0x0B,
3475     			   "SR0D", 0x0D,
3476     			   "SR10", 0x10,
3477     			   "SR11", 0x11,
3478     			   "SR12", 0x12,
3479     			   "SR13", 0x13,
3480     			   "SR14", 0x14,
3481     			   "SR15", 0x15,
3482     			   "SR16", 0x16,
3483     			   "SR17", 0x17,
3484     			   "SR18", 0x18,
3485     			   "SR19", 0x19,
3486     			   "SR1A", 0x1A,
3487     			   "SR1B", 0x1B,
3488     			   "SR1C", 0x1C,
3489     			   "SR1D", 0x1D,
3490     			   "SR1E", 0x1E,
3491     			   "SR1F", 0x1F,
3492     			   NULL);
3493     
3494     	DPRINTK ("\n");
3495     }
3496     
3497     #endif				/* CLGEN_DEBUG */
3498     
3499