~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/video/virgefb.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * linux/drivers/video/virgefb.c -- CyberVision64/3D frame buffer device
  3  *
  4  *    Copyright (C) 1997 André Heynatz
  5  *
  6  *
  7  * This file is based on the CyberVision frame buffer device (cyberfb.c):
  8  *
  9  *    Copyright (C) 1996 Martin Apel
 10  *                       Geert Uytterhoeven
 11  *
 12  * This file is subject to the terms and conditions of the GNU General Public
 13  * License.  See the file COPYING in the main directory of this archive
 14  * for more details.
 15  */
 16 
 17 #undef VIRGEFBDEBUG
 18 
 19 #include <linux/module.h>
 20 #include <linux/kernel.h>
 21 #include <linux/errno.h>
 22 #include <linux/string.h>
 23 #include <linux/mm.h>
 24 #include <linux/tty.h>
 25 #include <linux/malloc.h>
 26 #include <linux/delay.h>
 27 #include <linux/zorro.h>
 28 #include <linux/fb.h>
 29 #include <linux/init.h>
 30 #include <asm/uaccess.h>
 31 #include <asm/system.h>
 32 #include <asm/irq.h>
 33 #include <asm/pgtable.h>
 34 #include <asm/amigahw.h>
 35 #include <asm/io.h>
 36 
 37 #include <video/s3blit.h>
 38 #include <video/fbcon.h>
 39 #include <video/fbcon-cfb8.h>
 40 #include <video/fbcon-cfb16.h>
 41 
 42 
 43 #ifdef VIRGEFBDEBUG
 44 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
 45 #else
 46 #define DPRINTK(fmt, args...)
 47 #endif
 48 
 49 #if 1
 50 #define vgawb_3d(reg,dat) \
 51         if (cv3d_on_zorro2) { \
 52         *((unsigned char volatile *)((Cyber_vcode_switch_base) + 0x04)) = \
 53         (0x01 & 0xffff); asm volatile ("nop"); \
 54         } \
 55         (*((unsigned char *)(CyberVGARegs + (reg ^ 3))) = dat); \
 56         if (cv3d_on_zorro2) { \
 57         *((unsigned char volatile *)((Cyber_vcode_switch_base) + 0x04)) = \
 58         (0x02 & 0xffff); asm volatile ("nop"); \
 59         }
 60 #define vgaww_3d(reg,dat) \
 61                 (*((unsigned word *)(CyberVGARegs + (reg ^ 2))) = swab16(dat))
 62 #define vgawl_3d(reg,dat) \
 63                 (*((unsigned long *)(CyberVGARegs + reg)) = swab32(dat))
 64 #else
 65      /*
 66       * Dunno why this doesn't work at the moment - we'll have to look at
 67       * it later.
 68       */
 69 #define vgawb_3d(reg,dat) \
 70                 (*((unsigned char *)(CyberRegs + 0x8000 + reg)) = dat)
 71 #define vgaww_3d(reg,dat) \
 72                 (*((unsigned word *)(CyberRegs + 0x8000 + reg)) = dat)
 73 #define vgawl_3d(reg,dat) \
 74                 (*((unsigned long *)(CyberRegs + 0x8000 + reg)) = dat)
 75 #endif
 76 
 77      /*
 78       * We asume P5 mapped the big-endian version of these registers.
 79       */
 80 #define wb_3d(reg,dat) \
 81                 (*((unsigned char volatile *)(CyberRegs + reg)) = dat)
 82 #define ww_3d(reg,dat) \
 83                 (*((unsigned word volatile *)(CyberRegs + reg)) = dat)
 84 #define wl_3d(reg,dat) \
 85                 (*((unsigned long volatile *)(CyberRegs + reg)) = dat)
 86 #define rl_3d(reg) \
 87                 (*((unsigned long volatile *)(CyberRegs + reg)))
 88 
 89 #define Select_Zorro2_FrameBuffer(flag) \
 90         do { \
 91                 *((unsigned char volatile *)((Cyber_vcode_switch_base) + 0x08)) = \
 92                 ((flag * 0x40) & 0xffff); asm volatile ("nop"); \
 93         } while (0)
 94 /*
 95  *      may be needed when we initialize the board?
 96  *      8bit: flag = 2, 16 bit: flag = 1, 24/32bit: flag = 0 
 97  *      _when_ the board is initialized, depth doesnt matter, we allways write
 98  *      to the same address, aperture seems not to matter on Z2.
 99  */
100 
101 struct virgefb_par {
102    int xres;
103    int yres;
104    int bpp;
105    int accel;
106 };
107 
108 static struct virgefb_par current_par;
109 
110 static int current_par_valid = 0;
111 static int currcon = 0;
112 
113 static struct display disp;
114 static struct fb_info fb_info;
115 
116 static union {
117 #ifdef FBCON_HAS_CFB16
118     u16 cfb16[16];
119 #endif
120 } fbcon_cmap;
121 
122 /*
123  *    Switch for Chipset Independency
124  */
125 
126 static struct fb_hwswitch {
127 
128    /* Initialisation */
129 
130    int (*init)(void);
131 
132    /* Display Control */
133 
134    int (*encode_fix)(struct fb_fix_screeninfo *fix, struct virgefb_par *par);
135    int (*decode_var)(struct fb_var_screeninfo *var, struct virgefb_par *par);
136    int (*encode_var)(struct fb_var_screeninfo *var, struct virgefb_par *par);
137    int (*getcolreg)(u_int regno, u_int *red, u_int *green, u_int *blue,
138                     u_int *transp, struct fb_info *info);
139    int (*setcolreg)(u_int regno, u_int red, u_int green, u_int blue,
140                     u_int transp, struct fb_info *info);
141    void (*blank)(int blank);
142 } *fbhw;
143 
144 static int blit_maybe_busy = 0;
145 
146 /*
147  *    Frame Buffer Name
148  */
149 
150 static char virgefb_name[16] = "Cybervision/3D";
151 
152 
153 /*
154  *    Cybervision Graphics Board
155  */
156 
157 #define VIRGE8_WIDTH 1152
158 #define VIRGE8_HEIGHT 886
159 #define VIRGE8_PIXCLOCK 12500    /* ++Geert: Just a guess */
160 
161 #if 1
162 #define VIRGE16_WIDTH 800
163 #define VIRGE16_HEIGHT 600
164 #endif
165 #define VIRGE16_PIXCLOCK 25000   /* ++Geert: Just a guess */
166 
167 
168 static unsigned char Cyber_colour_table [256][3];
169 static unsigned long CyberMem;
170 static unsigned long CyberSize;
171 static volatile char *CyberRegs;
172 static volatile unsigned long CyberVGARegs; /* ++Andre: for CV64/3D, see macros at the beginning */
173 static unsigned long CyberMem_phys;
174 static unsigned long CyberRegs_phys;
175 static unsigned long Cyber_register_base;
176 static unsigned long Cyber_vcode_switch_base;
177 static unsigned char cv3d_on_zorro2;
178  
179 #define CYBMEM_OFFSET_8  0x800000       /* offsets from start of video - */ 
180 #define CYBMEM_OFFSET_16 0x400000       /* ram to appropriate aperture */
181 
182 /*
183  *    Predefined Video Modes
184  */
185 
186 static struct {
187     const char *name;
188     struct fb_var_screeninfo var;
189 } virgefb_predefined[] __initdata = {
190     {
191         "640x480-8", {          /* Cybervision 8 bpp */
192             640, 480, 640, 480, 0, 0, 8, 0,
193             {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
194             0, 0, -1, -1, FB_ACCELF_TEXT, VIRGE8_PIXCLOCK, 64, 96, 35, 12, 112, 2,
195             FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
196         }
197     }, {
198         "800x600-8", {          /* Cybervision 8 bpp */
199             800, 600, 800, 600, 0, 0, 8, 0,
200             {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
201             0, 0, -1, -1, FB_ACCELF_TEXT, VIRGE8_PIXCLOCK, 64, 96, 35, 12, 112, 2,
202             FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
203         }
204     }, {
205         "1024x768-8", {         /* Cybervision 8 bpp */
206             1024, 768, 1024, 768, 0, 0, 8, 0,
207             {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
208             0, 0, -1, -1, FB_ACCELF_TEXT, VIRGE8_PIXCLOCK, 64, 96, 35, 12, 112, 2,
209             FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
210         }
211     }, {
212         "1152x886-8", {         /* Cybervision 8 bpp */
213             1152, 886, 1152, 886, 0, 0, 8, 0,
214             {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
215             0, 0, -1, -1, FB_ACCELF_TEXT, VIRGE8_PIXCLOCK, 64, 96, 35, 12, 112, 2,
216             FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
217         }
218     }, {
219         "1280x1024-8", {        /* Cybervision 8 bpp */
220             1280, 1024, 1280, 1024, 0, 0, 8, 0,
221             {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
222             0, 0, -1, -1, FB_ACCELF_TEXT, VIRGE8_PIXCLOCK, 64, 96, 35, 12, 112, 2,
223             FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
224         }
225     }, {
226         "1600x1200-8", {        /* Cybervision 8 bpp */
227             1600, 1200, 1600, 1200, 0, 0, 8, 0,
228             {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
229             0, 0, -1, -1, FB_ACCELF_TEXT, VIRGE8_PIXCLOCK, 64, 96, 35, 12, 112, 2,
230             FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
231         }
232     }, {
233         "640x480-16", {         /* Cybervision 16 bpp */
234             640, 480, 640, 480, 0, 0, 16, 0,
235             {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
236             0, 0, -1, -1, FB_ACCELF_TEXT, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
237             FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
238         }
239     }, {
240         "800x600-16", {         /* Cybervision 16 bpp */
241             800, 600, 800, 600, 0, 0, 16, 0,
242             {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
243             0, 0, -1, -1, FB_ACCELF_TEXT, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
244             FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
245         }
246     }, {
247         "1024x768-16", {         /* Cybervision 16 bpp */
248             1024, 768, 1024, 768, 0, 0, 16, 0,
249             {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
250             0, 0, -1, -1, FB_ACCELF_TEXT, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
251             FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
252        }
253     }, {
254         "1152x886-16", {         /* Cybervision 16 bpp */
255             1152, 886, 1152, 886, 0, 0, 16, 0,
256             {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
257             0, 0, -1, -1, FB_ACCELF_TEXT, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
258             FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
259        }
260     }, {
261         "1280x1024-16", {         /* Cybervision 16 bpp */
262             1280, 1024, 1280, 1024, 0, 0, 16, 0,
263             {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
264             0, 0, -1, -1, FB_ACCELF_TEXT, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
265             FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
266        }
267     }, {
268         "1600x1200-16", {         /* Cybervision 16 bpp */
269             1600, 1200, 1600, 1200, 0, 0, 16, 0,
270             {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
271             0, 0, -1, -1, FB_ACCELF_TEXT, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
272             FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
273        }
274     }
275 };
276 
277 
278 #define NUM_TOTAL_MODES    ARRAY_SIZE(virgefb_predefined)
279 
280 
281 static int Cyberfb_inverse = 0;
282 
283 /*
284  *    Some default modes
285  */
286 
287 #define VIRGE8_DEFMODE     (1)
288 #define VIRGE16_DEFMODE    (7)
289 
290 static struct fb_var_screeninfo virgefb_default;
291 
292 
293 /*
294  *    Interface used by the world
295  */
296 
297 int virgefb_setup(char*);
298 
299 static int virgefb_get_fix(struct fb_fix_screeninfo *fix, int con, struct
300 fb_info *info);
301 static int virgefb_get_var(struct fb_var_screeninfo *var, int con, struct
302 fb_info *info);
303 static int virgefb_set_var(struct fb_var_screeninfo *var, int con, struct
304 fb_info *info);
305 static int virgefb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
306                             struct fb_info *info);
307 static int virgefb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
308                             struct fb_info *info);
309 
310 
311 /*
312  *    Interface to the low level console driver
313  */
314 
315 int virgefb_init(void);
316 static int Cyberfb_switch(int con, struct fb_info *info);
317 static int Cyberfb_updatevar(int con, struct fb_info *info);
318 static void Cyberfb_blank(int blank, struct fb_info *info);
319 
320 
321 /*
322  *    Text console acceleration
323  */
324 
325 #ifdef FBCON_HAS_CFB8
326 static struct display_switch fbcon_virge8;
327 #endif
328 
329 #ifdef FBCON_HAS_CFB16
330 static struct display_switch fbcon_virge16;
331 #endif
332 
333 /*
334  *   Hardware Specific Routines
335  */
336 
337 static int Cyber_init(void);
338 static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
339                           struct virgefb_par *par);
340 static int Cyber_decode_var(struct fb_var_screeninfo *var,
341                           struct virgefb_par *par);
342 static int Cyber_encode_var(struct fb_var_screeninfo *var,
343                           struct virgefb_par *par);
344 static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
345                          u_int *transp, struct fb_info *info);
346 static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
347                          u_int transp, struct fb_info *info);
348 static void Cyber_blank(int blank);
349 
350 
351 /*
352  *    Internal routines
353  */
354 
355 static void virgefb_get_par(struct virgefb_par *par);
356 static void virgefb_set_par(struct virgefb_par *par);
357 static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive);
358 static void do_install_cmap(int con, struct fb_info *info);
359 static void virgefb_set_disp(int con, struct fb_info *info);
360 static int get_video_mode(const char *name);
361 
362 
363 /* -------------------- Hardware specific routines ------------------------- */
364 
365 
366 /*
367  *    Initialization
368  *
369  *    Set the default video mode for this chipset. If a video mode was
370  *    specified on the command line, it will override the default mode.
371  */
372 
373 static int Cyber_init(void)
374 {
375         int i;
376 
377         for (i = 0; i < 256; i++)
378         {
379                 Cyber_colour_table [i][0] = i;
380                 Cyber_colour_table [i][1] = i;
381                 Cyber_colour_table [i][2] = i;
382         }
383 
384         /*
385          * Just clear the thing for the biggest mode.
386          *
387          * ++Andre, TODO: determine size first, then clear all memory
388          *                (the 3D penguin might need texture memory :-) )
389          */
390 
391         if (cv3d_on_zorro2) {
392                 CyberSize = 0x00380000; /* 3.5 MB , we need some space for the registers? */
393         } else {
394                 CyberSize = 0x00400000; /* 4 MB */
395         }
396 
397         memset ((char*)CyberMem, 0, CyberSize);
398 
399         /* Disable hardware cursor */
400         vgawb_3d(0x3c8, 255);
401         vgawb_3d(0x3c9, 56);
402         vgawb_3d(0x3c9, 100);
403         vgawb_3d(0x3c9, 160);
404 
405         vgawb_3d(0x3c8, 254);
406         vgawb_3d(0x3c9, 0);
407         vgawb_3d(0x3c9, 0);
408         vgawb_3d(0x3c9, 0);
409 
410         /* Disable hardware cursor */
411         vgawb_3d(S3_CRTC_ADR, S3_REG_LOCK2);
412         vgawb_3d(S3_CRTC_DATA, 0xa0);
413         vgawb_3d(S3_CRTC_ADR, S3_HGC_MODE);
414         vgawb_3d(S3_CRTC_DATA, 0x00);
415         vgawb_3d(S3_CRTC_ADR, S3_HWGC_DX);
416         vgawb_3d(S3_CRTC_DATA, 0x00);
417         vgawb_3d(S3_CRTC_ADR, S3_HWGC_DY);
418         vgawb_3d(S3_CRTC_DATA, 0x00);
419 
420         return 0; /* TODO: hardware cursor for CV64/3D */
421 }
422 
423 
424 /*
425  *    This function should fill in the `fix' structure based on the
426  *    values in the `par' structure.
427  */
428 
429 static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
430                             struct virgefb_par *par)
431 {
432         memset(fix, 0, sizeof(struct fb_fix_screeninfo));
433         strcpy(fix->id, virgefb_name);
434         if (cv3d_on_zorro2) {
435                 fix->smem_start = CyberMem_phys;
436         } else {
437                 switch (par->bpp) {
438                         case 8:
439                                 fix->smem_start = (CyberMem_phys + CYBMEM_OFFSET_8);
440                                 break;
441                         case 16:
442                                 fix->smem_start = (CyberMem_phys + CYBMEM_OFFSET_16);
443                                 break;
444                 }
445         }
446         fix->smem_len = CyberSize;
447         fix->mmio_start = CyberRegs_phys;
448         fix->mmio_len = 0x10000; /* TODO: verify this for the CV64/3D */
449 
450         fix->type = FB_TYPE_PACKED_PIXELS;
451         fix->type_aux = 0;
452         if (par->bpp == 8)
453                 fix->visual = FB_VISUAL_PSEUDOCOLOR;
454         else
455                 fix->visual = FB_VISUAL_TRUECOLOR;
456 
457         fix->xpanstep = 0;
458         fix->ypanstep = 0;
459         fix->ywrapstep = 0;
460         fix->line_length = 0;
461         fix->accel = FB_ACCEL_S3_VIRGE;
462         return(0);
463 }
464 
465 
466 /*
467  *    Get the video params out of `var'. If a value doesn't fit, round
468  *    it up, if it's too big, return -EINVAL.
469  */
470 
471 static int Cyber_decode_var(struct fb_var_screeninfo *var,
472                             struct virgefb_par *par)
473 {
474 #if 1
475         par->xres = var->xres;
476         par->yres = var->yres;
477         par->bpp = var->bits_per_pixel;
478         if (var->accel_flags & FB_ACCELF_TEXT)
479             par->accel = FB_ACCELF_TEXT;
480         else
481             par->accel = 0;
482 #else
483         if (Cyberfb_Cyber8) {
484                 par->xres = VIRGE8_WIDTH;
485                 par->yres = VIRGE8_HEIGHT;
486                 par->bpp = 8;
487         } else {
488                 par->xres = VIRGE16_WIDTH;
489                 par->yres = VIRGE16_HEIGHT;
490                 par->bpp = 16;
491         }
492 #endif
493         return(0);
494 }
495 
496 
497 /*
498  *    Fill the `var' structure based on the values in `par' and maybe
499  *    other values read out of the hardware.
500  */
501 
502 static int Cyber_encode_var(struct fb_var_screeninfo *var,
503                             struct virgefb_par *par)
504 {
505         memset(var, 0, sizeof(struct fb_var_screeninfo));
506         var->xres = par->xres;
507         var->yres = par->yres;
508         var->xres_virtual = par->xres;
509         var->yres_virtual = par->yres;
510         var->xoffset = 0;
511         var->yoffset = 0;
512 
513         var->bits_per_pixel = par->bpp;
514         var->grayscale = 0;
515 
516         switch (var->bits_per_pixel) {
517                 case 8:         /* CLUT */
518                         var->red.offset = 0;
519                         var->red.length = 6;
520                         var->red.msb_right = 0;
521                         var->blue = var->green = var->red;
522                         break;
523                 case 16:        /* RGB 565 */
524                         var->red.offset = 11;
525                         var->red.length = 5;
526                         var->green.offset = 5;
527                         var->green.length = 6;
528                         var->blue.offset = 0;
529                         var->blue.length = 5;
530                         var->transp.offset = 0;
531                         var->transp.length = 0;
532                         break;
533         }
534         var->red.msb_right = 0;
535         var->green.msb_right = 0;
536         var->blue.msb_right = 0;
537         var->transp.msb_right = 0;
538 
539         var->nonstd = 0;
540         var->activate = 0;
541 
542         var->height = -1;
543         var->width = -1;
544 
545         var->accel_flags = (par->accel &&
546                 ((par->bpp == 8) || (par->bpp == 16))) ? FB_ACCELF_TEXT : 0;
547 
548 /*      printk("CV64/3D : %s\n",(var->accel_flags ? "accel" : "no accel")); */
549 
550         var->vmode = FB_VMODE_NONINTERLACED;
551 
552         /* Dummy values */
553 
554         if (par->bpp == 8)
555                 var->pixclock = VIRGE8_PIXCLOCK;
556         else
557                 var->pixclock = VIRGE16_PIXCLOCK;
558         var->sync = 0;
559         var->left_margin = 64;
560         var->right_margin = 96;
561         var->upper_margin = 35;
562         var->lower_margin = 12;
563         var->hsync_len = 112;
564         var->vsync_len = 2;
565 
566         return(0);
567 }
568 
569 
570 /*
571  *    Set a single color register. The values supplied are already
572  *    rounded down to the hardware's capabilities (according to the
573  *    entries in the var structure). Return != 0 for invalid regno.
574  */
575 
576 static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
577                            u_int transp, struct fb_info *info)
578 {
579         if (((current_par.bpp==8) && (regno>255)) ||
580                 ((current_par.bpp!=8) && (regno>15)))
581                         return (1);
582 
583         if (((current_par.bpp==8) && (regno<256)) || ((current_par.bpp==16) &&(regno<16))) {
584                 Cyber_colour_table [regno][0] = red >> 10;
585                 Cyber_colour_table [regno][1] = green >> 10;
586                 Cyber_colour_table [regno][2] = blue >> 10;
587         }
588 
589         switch (current_par.bpp) {
590 #ifdef FBCON_HAS_CFB8
591                 case 8:
592                         vgawb_3d(0x3c8, (unsigned char) regno);
593                         vgawb_3d(0x3c9, ((unsigned char) (red >> 10)));
594                         vgawb_3d(0x3c9, ((unsigned char) (green >> 10)));
595                         vgawb_3d(0x3c9, ((unsigned char) (blue >> 10)));
596                         break;
597 #endif
598 #ifdef FBCON_HAS_CFB16
599                 case 16:
600                         fbcon_cmap.cfb16[regno] =
601                                 ((red  & 0xf800) |
602                                 ((green & 0xfc00) >> 5) |
603                                 ((blue  & 0xf800) >> 11));
604                         break;
605 #endif
606         }
607         return (0);
608 }
609 
610 
611 /*
612  *    Read a single color register and split it into
613  *    colors/transparent. Return != 0 for invalid regno.
614  */
615 
616 static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
617                            u_int *transp, struct fb_info *info)
618 {
619         int t;
620 
621         if (regno > 255)
622                 return (1);
623 
624         if (((current_par.bpp==8) && (regno<256)) || ((current_par.bpp==16) && (regno<16))) {
625 
626                 t = Cyber_colour_table [regno][0];
627                 *red    = (t<<10) | (t<<4) | (t>>2);
628                 t = Cyber_colour_table [regno][1];
629                 *green  = (t<<10) | (t<<4) | (t>>2);
630                 t = Cyber_colour_table [regno][2];
631                 *blue   = (t<<10) | (t<<4) | (t>>2);
632         }
633         *transp = 0;
634         return (0);
635 }
636 
637 
638 /*
639  *    (Un)Blank the screen
640  */
641 
642 void Cyber_blank(int blank)
643 {
644         int i;
645 
646         if (blank)
647         {
648                 for (i = 0; i < 256; i++)
649                 {
650                         vgawb_3d(0x3c8, (unsigned char) i);
651                         vgawb_3d(0x3c9, 0);
652                         vgawb_3d(0x3c9, 0);
653                         vgawb_3d(0x3c9, 0);
654                 }
655         }
656         else
657         {
658                 for (i = 0; i < 256; i++)
659                 {
660                         vgawb_3d(0x3c8, (unsigned char) i);
661                         vgawb_3d(0x3c9, Cyber_colour_table[i][0]);
662                         vgawb_3d(0x3c9, Cyber_colour_table[i][1]);
663                         vgawb_3d(0x3c9, Cyber_colour_table[i][2]);
664                 }
665         }
666 }
667 
668 /*
669  * CV3D low-level support
670  */
671 
672 #define Cyber3D_WaitQueue(v) \
673 { \
674          do { \
675                 while ((rl_3d(0x8504) & 0x1f00) < (((v)+2) << 8)); \
676          } \
677         while (0); \
678 }
679 
680 static inline void Cyber3D_WaitBusy(void)
681 {
682 unsigned long status;
683 
684         do {
685                 mb();
686                 status = rl_3d(0x8504);
687         } while (!(status & (1 << 13)));
688         blit_maybe_busy = 0;
689 }
690 
691 #define S3V_BITBLT      (0x0 << 27)
692 #define S3V_RECTFILL    (0x2 << 27)
693 #define S3V_AUTOEXE     0x01
694 #define S3V_HWCLIP      0x02
695 #define S3V_DRAW        0x20
696 #define S3V_DST_8BPP    0x00
697 #define S3V_DST_16BPP   0x04
698 #define S3V_DST_24BPP   0x08
699 #define S3V_MONO_PAT    0x100
700 
701 #define S3V_BLT_COPY    (0xcc<<17)
702 #define S3V_BLT_CLEAR   (0x00<<17)
703 #define S3V_BLT_SET     (0xff<<17)
704 
705  /*
706   * BitBLT - Through the Plane
707   */
708 
709 static void Cyber3D_BitBLT(u_short curx, u_short cury, u_short destx,
710                            u_short desty, u_short width, u_short height, u_short depth)
711 {
712         unsigned int blitcmd = S3V_BITBLT | S3V_DRAW | S3V_BLT_COPY;
713 
714         switch (depth) {
715 #ifdef FBCON_HAS_CFB8
716                 case 8 :
717                         blitcmd |= S3V_DST_8BPP;
718                         break;
719 #endif
720 #ifdef FBCON_HAS_CFB16
721                 case 16 :
722                         blitcmd |= S3V_DST_16BPP;
723                         break;
724 #endif
725         }
726 
727         /* Set drawing direction */
728         /* -Y, X maj, -X (default) */
729         if (curx > destx)
730         {
731                 blitcmd |= (1 << 25);  /* Drawing direction +X */
732         }
733         else
734         {
735                 curx  += (width - 1);
736                 destx += (width - 1);
737         }
738 
739         if (cury > desty)
740         {
741                 blitcmd |= (1 << 26);  /* Drawing direction +Y */
742         }
743         else
744         {
745                 cury  += (height - 1);
746                 desty += (height - 1);
747         }
748 
749         if (blit_maybe_busy)
750                 Cyber3D_WaitBusy();
751         blit_maybe_busy = 1;
752 
753         wl_3d(0xa4f4, 1); /* pattern fb color */
754 
755         wl_3d(0xa4e8, ~0); /* mono pat 0 */
756         wl_3d(0xa4ec, ~0); /* mono pat 1 */
757 
758         wl_3d(0xa504, ((width << 16) | height));        /* rwidth_height */
759         wl_3d(0xa508, ((curx << 16)  | cury));          /* rsrc_xy */
760         wl_3d(0xa50c, ((destx << 16) | desty));         /* rdest_xy */
761 
762         wl_3d(0xa500, blitcmd);                         /* GO! */
763 }
764 
765 /*
766  * Rectangle Fill Solid
767  */
768 
769 static void Cyber3D_RectFill(u_short x, u_short y, u_short width,
770                              u_short height, u_short color, u_short depth)
771 {
772         unsigned int tmp;
773         unsigned int blitcmd = S3V_RECTFILL | S3V_DRAW |
774                 S3V_BLT_CLEAR | S3V_MONO_PAT | (1 << 26) | (1 << 25);
775 
776         if (blit_maybe_busy)
777                 Cyber3D_WaitBusy();
778         blit_maybe_busy = 1;
779 
780         switch (depth) {
781 #ifdef FBCON_HAS_CFB8
782                 case 8 :
783                         blitcmd |= S3V_DST_8BPP;
784                         break;
785 #endif
786 #ifdef FBCON_HAS_CFB16
787                 case 16 :
788                         blitcmd |= S3V_DST_16BPP;
789                         break;
790 #endif
791         }
792 
793         tmp = color & 0xff;
794         wl_3d(0xa4f4, tmp);
795 
796         wl_3d(0xa504, ((width << 16) | height));        /* rwidth_height */
797         wl_3d(0xa50c, ((x << 16) | y));                 /* rdest_xy */
798 
799         wl_3d(0xa500, blitcmd);                         /* GO! */
800 }
801 
802 
803 /**************************************************************
804  * Move cursor to x, y
805  */
806 
807 #if 0
808 static void Cyber_MoveCursor (u_short x, u_short y)
809 {
810         printk(KERN_DEBUG "Yuck .... MoveCursor on a 3D\n");
811         return;
812 }
813 #endif
814 
815 /* -------------------- Interfaces to hardware functions -------------------- */
816 
817 
818 static struct fb_hwswitch Cyber_switch = {
819         Cyber_init, Cyber_encode_fix, Cyber_decode_var, Cyber_encode_var,
820         Cyber_getcolreg, Cyber_setcolreg, Cyber_blank
821 };
822 
823 
824 /* -------------------- Generic routines ------------------------------------ */
825 
826 
827 /*
828  *    Fill the hardware's `par' structure.
829  */
830 
831 static void virgefb_get_par(struct virgefb_par *par)
832 {
833         if (current_par_valid)
834         {
835                 *par = current_par;
836         }
837         else
838         {
839                 fbhw->decode_var(&virgefb_default, par);
840         }
841 }
842 
843 
844 static void virgefb_set_par(struct virgefb_par *par)
845 {
846         current_par = *par;
847         current_par_valid = 1;
848 }
849 
850 
851 static void virge_set_video(struct fb_var_screeninfo *var)
852 {
853         /* Set clipping rectangle to current screen size */
854  
855         unsigned int clip;
856 
857         clip = ((0 << 16) | (var->xres - 1));
858         wl_3d(0xa4dc, clip);
859         clip = ((0 << 16) | (var->yres - 1));
860         wl_3d(0xa4e0, clip);
861 }
862 
863 
864 static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
865 {
866         int err, activate;
867         struct virgefb_par par;
868 
869         if ((err = fbhw->decode_var(var, &par)))
870                 return(err);
871         activate = var->activate;
872         if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
873                 virgefb_set_par(&par);
874         fbhw->encode_var(var, &par);
875         var->activate = activate;
876 
877         virge_set_video(var);
878         return 0;
879 }
880 
881 
882 static void do_install_cmap(int con, struct fb_info *info)
883 {
884         if (con != currcon)
885                 return;
886         if (fb_display[con].cmap.len)
887                 fb_set_cmap(&fb_display[con].cmap, 1, fbhw->setcolreg, info);
888         else
889                 fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
890                             1, fbhw->setcolreg, info);
891 }
892 
893 /*
894  *    Get the Fixed Part of the Display
895  */
896 
897 static int virgefb_get_fix(struct fb_fix_screeninfo *fix, int con,
898                            struct fb_info *info)
899 {
900         struct virgefb_par par;
901         int error = 0;
902 
903         if (con == -1)
904                 virgefb_get_par(&par);
905         else
906                 error = fbhw->decode_var(&fb_display[con].var, &par);
907         return(error ? error : fbhw->encode_fix(fix, &par));
908 }
909 
910 
911 /*
912  *    Get the User Defined Part of the Display
913  */
914 
915 static int virgefb_get_var(struct fb_var_screeninfo *var, int con,
916                            struct fb_info *info)
917 {
918         struct virgefb_par par;
919         int error = 0;
920 
921         if (con == -1)
922         {
923                 virgefb_get_par(&par);
924                 error = fbhw->encode_var(var, &par);
925                 disp.var = *var;   /* ++Andre: don't know if this is the right place */
926         }
927         else
928         {
929                 *var = fb_display[con].var;
930         }
931 
932         return(error);
933 }
934 
935 
936 static void virgefb_set_disp(int con, struct fb_info *info)
937 {
938         struct fb_fix_screeninfo fix;
939         struct display *display;
940 
941         if (con >= 0)
942                 display = &fb_display[con];
943         else
944                 display = &disp;        /* used during initialization */
945 
946         virgefb_get_fix(&fix, con, info);
947         if (con == -1)
948                 con = 0;
949         if (cv3d_on_zorro2) {
950                 display->screen_base = (char*) CyberMem;
951         } else {
952                 switch (display->var.bits_per_pixel) {
953                         case 8:
954                                 display->screen_base = (char*) (CyberMem + CYBMEM_OFFSET_8);
955                                 break;
956                         case 16:
957                                 display->screen_base = (char*) (CyberMem + CYBMEM_OFFSET_16);
958                                 break;
959                 }
960         }
961         display->visual = fix.visual;
962         display->type = fix.type;
963         display->type_aux = fix.type_aux;
964         display->ypanstep = fix.ypanstep;
965         display->ywrapstep = fix.ywrapstep;
966         display->can_soft_blank = 1;
967         display->inverse = Cyberfb_inverse;
968         switch (display->var.bits_per_pixel) {
969 #ifdef FBCON_HAS_CFB8
970                 case 8:
971                         if (display->var.accel_flags & FB_ACCELF_TEXT) {
972                                 display->dispsw = &fbcon_virge8;
973 #warning FIXME: We should reinit the graphics engine here
974                         } else
975                                 display->dispsw = &fbcon_cfb8;
976                         break;
977 #endif
978 #ifdef FBCON_HAS_CFB16
979                 case 16:
980                         if (display->var.accel_flags & FB_ACCELF_TEXT) {
981                                 display->dispsw = &fbcon_virge16;
982                         } else
983                                 display->dispsw = &fbcon_cfb16;
984                         display->dispsw_data = &fbcon_cmap.cfb16;
985                         break;
986 #endif
987                 default:
988                         display->dispsw = &fbcon_dummy;
989                         break;
990         }
991 }
992 
993 
994 /*
995  *    Set the User Defined Part of the Display
996  */
997 
998 static int virgefb_set_var(struct fb_var_screeninfo *var, int con,
999                            struct fb_info *info)
1000 {
1001         int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel;
1002 
1003         if ((err = do_fb_set_var(var, con == currcon)))
1004                 return(err);
1005         if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
1006                 oldxres = fb_display[con].var.xres;
1007                 oldyres = fb_display[con].var.yres;
1008                 oldvxres = fb_display[con].var.xres_virtual;
1009                 oldvyres = fb_display[con].var.yres_virtual;
1010                 oldbpp = fb_display[con].var.bits_per_pixel;
1011                 oldaccel = fb_display[con].var.accel_flags;
1012                 fb_display[con].var = *var;
1013                 if (oldxres != var->xres || oldyres != var->yres ||
1014                     oldvxres != var->xres_virtual ||
1015                     oldvyres != var->yres_virtual ||
1016                     oldbpp != var->bits_per_pixel ||
1017                     oldaccel != var->accel_flags) {
1018                         virgefb_set_disp(con, info);
1019                         (*fb_info.changevar)(con);
1020                         fb_alloc_cmap(&fb_display[con].cmap, 0, 0);
1021                         do_install_cmap(con, info);
1022                 }
1023         }
1024         var->activate = 0;
1025         return(0);
1026 }
1027 
1028 
1029 /*
1030  *    Get the Colormap
1031  */
1032 
1033 static int virgefb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
1034                             struct fb_info *info)
1035 {
1036         if (con == currcon) /* current console? */
1037                 return(fb_get_cmap(cmap, kspc, fbhw->getcolreg, info));
1038         else if (fb_display[con].cmap.len) /* non default colormap? */
1039                 fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
1040         else
1041                 fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
1042                              cmap, kspc ? 0 : 2);
1043         return(0);
1044 }
1045 
1046 
1047 /*
1048  *    Set the Colormap
1049  */
1050 
1051 static int virgefb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
1052                             struct fb_info *info)
1053 {
1054         int err;
1055 
1056         if (!fb_display[con].cmap.len) {       /* no colormap allocated? */
1057                 if ((err = fb_alloc_cmap(&fb_display[con].cmap,
1058                                 1<<fb_display[con].var.bits_per_pixel, 0)))
1059                         return(err);
1060         }
1061         if (con == currcon)              /* current console? */
1062                 return(fb_set_cmap(cmap, kspc, fbhw->setcolreg, info));
1063         else
1064                 fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
1065         return(0);
1066 }
1067 
1068 
1069 static struct fb_ops virgefb_ops = {
1070         owner:          THIS_MODULE,
1071         fb_get_fix:     virgefb_get_fix,
1072         fb_get_var:     virgefb_get_var,
1073         fb_set_var:     virgefb_set_var,
1074         fb_get_cmap:    virgefb_get_cmap,
1075         fb_set_cmap:    virgefb_set_cmap,
1076 };
1077 
1078 
1079 int __init virgefb_setup(char *options)
1080 {
1081         char *this_opt;
1082 
1083         fb_info.fontname[0] = '\0';
1084 
1085         if (!options || !*options)
1086                 return 0;
1087 
1088         for (this_opt = strtok(options, ","); this_opt; this_opt = strtok(NULL, ","))
1089                 if (!strcmp(this_opt, "inverse")) {
1090                         Cyberfb_inverse = 1;
1091                         fb_invert_cmaps();
1092                 } else if (!strncmp(this_opt, "font:", 5))
1093                         strcpy(fb_info.fontname, this_opt+5);
1094                 else if (!strcmp (this_opt, "virge8")){
1095                         virgefb_default = virgefb_predefined[VIRGE8_DEFMODE].var;
1096                 }
1097                 else if (!strcmp (this_opt, "virge16")){
1098                         virgefb_default = virgefb_predefined[VIRGE16_DEFMODE].var;
1099                 }
1100                 else
1101                         get_video_mode(this_opt);
1102 
1103         DPRINTK("default mode: xres=%d, yres=%d, bpp=%d\n",virgefb_default.xres,
1104                                                            virgefb_default.yres,
1105                                                            virgefb_default.bits_per_pixel);
1106         return 0;
1107 }
1108 
1109 
1110 /*
1111  *    Initialization
1112  */
1113 
1114 int __init virgefb_init(void)
1115 {
1116         struct virgefb_par par;
1117         unsigned long board_addr, ramsize;
1118         struct zorro_dev *z = NULL;
1119 
1120         while ((z = zorro_find_device(ZORRO_PROD_PHASE5_CYBERVISION64_3D, z))) {
1121             board_addr = z->resource.start;
1122             if (board_addr < 0x01000000) {
1123                 /*
1124                  * Ok we got the board running in Z2 space.
1125                  */
1126                  CyberRegs_phys = (unsigned long)(board_addr + 0x003e0000);
1127                  CyberMem_phys = board_addr;
1128                  ramsize = 0x00380000;
1129             } else {
1130                 CyberRegs_phys = board_addr + 0x05000000;
1131                 CyberMem_phys  = board_addr + 0x04000000;       /* was 0x04800000 */
1132                 ramsize = 0x00400000;
1133             }
1134             if (!request_mem_region(CyberRegs_phys, 0x10000, "S3 ViRGE"))
1135                 continue;
1136             if (!request_mem_region(CyberMem_phys, ramsize, "RAM")) {
1137                 release_mem_region(CyberRegs_phys, 0x10000);
1138                 continue;
1139             }
1140 
1141             if (board_addr < 0x01000000) {
1142                 /*
1143                  * Ok we got the board running in Z2 space.
1144                  */
1145 
1146                 CyberMem = ZTWO_VADDR(CyberMem_phys);
1147                 CyberVGARegs = (unsigned long) \
1148                         ZTWO_VADDR(board_addr + 0x003c0000);
1149                 CyberRegs = (unsigned char *)ZTWO_VADDR(CyberRegs_phys);
1150                 Cyber_register_base = (unsigned long) \
1151                         ZTWO_VADDR(board_addr + 0x003c8000);
1152                 Cyber_vcode_switch_base = (unsigned long) \
1153                         ZTWO_VADDR(board_addr + 0x003a0000);
1154                 cv3d_on_zorro2 = 1;
1155                 printk(KERN_INFO "CV3D detected running in Z2 mode.\n");
1156             } else {
1157                 CyberVGARegs = (unsigned long)ioremap(board_addr+0x0c000000, 0x00010000);
1158                 CyberRegs = ioremap(CyberRegs_phys, 0x00010000);
1159                 CyberMem = (unsigned long)ioremap(CyberMem_phys, 0x01000000);   /* was 0x00400000 */
1160                 cv3d_on_zorro2 = 0;
1161                 printk(KERN_INFO "CV3D detected running in Z3 mode.\n");
1162             }
1163 
1164             fbhw = &Cyber_switch;
1165 
1166             strcpy(fb_info.modename, virgefb_name);
1167             fb_info.changevar = NULL;
1168             fb_info.node = -1;
1169             fb_info.fbops = &virgefb_ops;
1170             fb_info.disp = &disp;
1171             fb_info.switch_con = &Cyberfb_switch;
1172             fb_info.updatevar = &Cyberfb_updatevar;
1173             fb_info.blank = &Cyberfb_blank;
1174             fb_info.flags = FBINFO_FLAG_DEFAULT;
1175 
1176             fbhw->init();
1177             fbhw->decode_var(&virgefb_default, &par);
1178             fbhw->encode_var(&virgefb_default, &par);
1179 
1180             do_fb_set_var(&virgefb_default, 1);
1181             virgefb_get_var(&fb_display[0].var, -1, &fb_info);
1182             virgefb_set_disp(-1, &fb_info);
1183             do_install_cmap(0, &fb_info);
1184 
1185             if (register_framebuffer(&fb_info) < 0) {
1186                 printk(KERN_ERR "virgefb.c: register_framebuffer failed\n");
1187                 return -EINVAL;
1188             }
1189 
1190             printk(KERN_INFO "fb%d: %s frame buffer device, using %ldK of "
1191                    "video memory\n", GET_FB_IDX(fb_info.node),
1192                    fb_info.modename, CyberSize>>10);
1193 
1194             /* TODO: This driver cannot be unloaded yet */
1195             MOD_INC_USE_COUNT;
1196             return 0;
1197         }
1198         return -ENODEV;
1199 }
1200 
1201 
1202 static int Cyberfb_switch(int con, struct fb_info *info)
1203 {
1204         /* Do we have to save the colormap? */
1205         if (fb_display[currcon].cmap.len)
1206                 fb_get_cmap(&fb_display[currcon].cmap, 1, fbhw->getcolreg,
1207                             info);
1208 
1209         do_fb_set_var(&fb_display[con].var, 1);
1210         currcon = con;
1211         /* Install new colormap */
1212         do_install_cmap(con, info);
1213         return(0);
1214 }
1215 
1216 
1217 /*
1218  *    Update the `var' structure (called by fbcon.c)
1219  *
1220  *    This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
1221  *    Since it's called by a kernel driver, no range checking is done.
1222  */
1223 
1224 static int Cyberfb_updatevar(int con, struct fb_info *info)
1225 {
1226         return(0);
1227 }
1228 
1229 
1230 /*
1231  *    Blank the display.
1232  */
1233 
1234 static void Cyberfb_blank(int blank, struct fb_info *info)
1235 {
1236         fbhw->blank(blank);
1237 }
1238 
1239 
1240 /*
1241  *    Get a Video Mode
1242  */
1243 
1244 static int __init get_video_mode(const char *name)
1245 {
1246         int i;
1247 
1248         for (i = 0; i < NUM_TOTAL_MODES; i++) {
1249                 if (!strcmp(name, virgefb_predefined[i].name)) {
1250                         virgefb_default = virgefb_predefined[i].var;
1251                         return(i);
1252                 }
1253         }
1254         /* ++Andre: set virgefb default mode */
1255         virgefb_default = virgefb_predefined[VIRGE8_DEFMODE].var;
1256         return(0);
1257 }
1258 
1259 
1260 /*
1261  *    Text console acceleration
1262  */
1263 
1264 #ifdef FBCON_HAS_CFB8
1265 static void fbcon_virge8_bmove(struct display *p, int sy, int sx, int dy,
1266                                int dx, int height, int width)
1267 {
1268         sx *= 8; dx *= 8; width *= 8;
1269         Cyber3D_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
1270                        (u_short)(dy*fontheight(p)), (u_short)width,
1271                        (u_short)(height*fontheight(p)), 8);
1272 }
1273 
1274 static void fbcon_virge8_clear(struct vc_data *conp, struct display *p, int sy,
1275                                int sx, int height, int width)
1276 {
1277         unsigned char bg;
1278 
1279         sx *= 8; width *= 8;
1280         bg = attr_bgcol_ec(p,conp);
1281         Cyber3D_RectFill((u_short)sx, (u_short)(sy*fontheight(p)),
1282                          (u_short)width, (u_short)(height*fontheight(p)),
1283                          (u_short)bg, 8);
1284 }
1285 
1286 static void fbcon_virge8_putc(struct vc_data *conp, struct display *p, int c, int yy,
1287                               int xx)
1288 {
1289         if (blit_maybe_busy)
1290                 Cyber3D_WaitBusy();
1291         fbcon_cfb8_putc(conp, p, c, yy, xx);
1292 }
1293 
1294 static void fbcon_virge8_putcs(struct vc_data *conp, struct display *p,
1295                       const unsigned short *s, int count, int yy, int xx)
1296 {
1297         if (blit_maybe_busy)
1298                 Cyber3D_WaitBusy();
1299         fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
1300 }
1301 
1302 static void fbcon_virge8_revc(struct display *p, int xx, int yy)
1303 {
1304         if (blit_maybe_busy)
1305                 Cyber3D_WaitBusy();
1306         fbcon_cfb8_revc(p, xx, yy);
1307 }
1308 
1309 static void fbcon_virge8_clear_margins(struct vc_data *conp, struct display *p,
1310                               int bottom_only)
1311 {
1312         if (blit_maybe_busy)
1313                 Cyber3D_WaitBusy();
1314         fbcon_cfb8_clear_margins(conp, p, bottom_only);
1315 }
1316 
1317 static struct display_switch fbcon_virge8 = {
1318    setup:               fbcon_cfb8_setup,
1319    bmove:               fbcon_virge8_bmove,
1320    clear:               fbcon_virge8_clear,
1321    putc:                fbcon_virge8_putc,
1322    putcs:               fbcon_virge8_putcs,
1323    revc:                fbcon_virge8_revc,
1324    clear_margins:       fbcon_virge8_clear_margins,
1325    fontwidthmask:       FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
1326 };
1327 #endif
1328 
1329 #ifdef FBCON_HAS_CFB16
1330 static void fbcon_virge16_bmove(struct display *p, int sy, int sx, int dy,
1331                                int dx, int height, int width)
1332 {
1333         sx *= 8; dx *= 8; width *= 8;
1334         Cyber3D_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
1335                        (u_short)(dy*fontheight(p)), (u_short)width,
1336                        (u_short)(height*fontheight(p)), 16);
1337 }
1338                 
1339 static void fbcon_virge16_clear(struct vc_data *conp, struct display *p, int sy,
1340                                int sx, int height, int width)
1341 {
1342         unsigned char bg;   
1343                 
1344         sx *= 8; width *= 8;
1345         bg = attr_bgcol_ec(p,conp);
1346         Cyber3D_RectFill((u_short)sx, (u_short)(sy*fontheight(p)),
1347                          (u_short)width, (u_short)(height*fontheight(p)),
1348                          (u_short)bg, 16);
1349 }
1350    
1351 static void fbcon_virge16_putc(struct vc_data *conp, struct display *p, int c, int yy,
1352                               int xx)
1353 {
1354         if (blit_maybe_busy)
1355                 Cyber3D_WaitBusy();
1356         fbcon_cfb16_putc(conp, p, c, yy, xx);
1357 }
1358 
1359 static void fbcon_virge16_putcs(struct vc_data *conp, struct display *p,
1360                       const unsigned short *s, int count, int yy, int xx)
1361 {
1362         if (blit_maybe_busy)
1363                 Cyber3D_WaitBusy();
1364         fbcon_cfb16_putcs(conp, p, s, count, yy, xx);
1365 }
1366 
1367 static void fbcon_virge16_revc(struct display *p, int xx, int yy)
1368 {
1369         if (blit_maybe_busy)
1370                 Cyber3D_WaitBusy();
1371         fbcon_cfb16_revc(p, xx, yy);
1372 }
1373 
1374 static void fbcon_virge16_clear_margins(struct vc_data *conp, struct display *p,
1375                               int bottom_only)
1376 {
1377         if (blit_maybe_busy)
1378                 Cyber3D_WaitBusy();
1379         fbcon_cfb16_clear_margins(conp, p, bottom_only);
1380 }
1381 
1382 static struct display_switch fbcon_virge16 = {
1383    setup:               fbcon_cfb16_setup,
1384    bmove:               fbcon_virge16_bmove,
1385    clear:               fbcon_virge16_clear,
1386    putc:                fbcon_virge16_putc,
1387    putcs:               fbcon_virge16_putcs,
1388    revc:                fbcon_virge16_revc,
1389    clear_margins:       fbcon_virge16_clear_margins,
1390    fontwidthmask:       FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
1391 };
1392 #endif
1393 
1394 #ifdef MODULE
1395 int init_module(void)
1396 {
1397         return virgefb_init();
1398 }
1399 
1400 void cleanup_module(void)
1401 {
1402         /* Not reached because the usecount will never be
1403            decremented to zero */
1404         unregister_framebuffer(&fb_info);
1405         /* TODO: clean up ... */
1406 }
1407 #endif /* MODULE */
1408 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.