OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [or32/] [console/] [fbcon.c] - Diff between revs 1765 and 1782

Only display areas with differences | Details | Blame | View Log

Rev 1765 Rev 1782
/*
/*
 * linux/arch/or32/console/fbcon.c -- Low level frame buffer based console
 * linux/arch/or32/console/fbcon.c -- Low level frame buffer based console
 *                                    driver
 *                                    driver
 *
 *
 *    Copyright (C) 2001,2002 Simon Srot <srot@opencores.org>,
 *    Copyright (C) 2001,2002 Simon Srot <srot@opencores.org>,
 *                            www.opencores.org
 *                            www.opencores.org
 *
 *
 * Based on:
 * Based on:
 *
 *
 * linux/arch/m68knommu/console/fbcon.c -- Low level frame buffer based console
 * linux/arch/m68knommu/console/fbcon.c -- Low level frame buffer based console
 *                                    driver
 *                                    driver
 *
 *
 *    Copyright (C) 1998,1999 Kenneth Albanowski <kjahds@kjahds.com>,
 *    Copyright (C) 1998,1999 Kenneth Albanowski <kjahds@kjahds.com>,
 *                         The Silver Hammer Group, Ltd.
 *                         The Silver Hammer Group, Ltd.
 *
 *
 * linux/arch/m68k/console/fbcon.c -- Low level frame buffer based console
 * linux/arch/m68k/console/fbcon.c -- Low level frame buffer based console
 *                                    driver
 *                                    driver
 *
 *
 *    Copyright (C) 1995 Geert Uytterhoeven
 *    Copyright (C) 1995 Geert Uytterhoeven
 *
 *
 *
 *
 * This file is based on the original Amiga console driver (amicon.c):
 * This file is based on the original Amiga console driver (amicon.c):
 *
 *
 *    Copyright (C) 1993 Hamish Macdonald
 *    Copyright (C) 1993 Hamish Macdonald
 *                       Greg Harp
 *                       Greg Harp
 *    Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk]
 *    Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk]
 *
 *
 *          with work by William Rucklidge (wjr@cs.cornell.edu)
 *          with work by William Rucklidge (wjr@cs.cornell.edu)
 *                       Geert Uytterhoeven
 *                       Geert Uytterhoeven
 *                       Jes Sorensen (jds@kom.auc.dk)
 *                       Jes Sorensen (jds@kom.auc.dk)
 *                       Martin Apel
 *                       Martin Apel
 *
 *
 * and on the original Atari console driver (atacon.c):
 * and on the original Atari console driver (atacon.c):
 *
 *
 *    Copyright (C) 1993 Bjoern Brauel
 *    Copyright (C) 1993 Bjoern Brauel
 *                       Roman Hodek
 *                       Roman Hodek
 *
 *
 *          with work by Guenther Kelleter
 *          with work by Guenther Kelleter
 *                       Martin Schaller
 *                       Martin Schaller
 *                       Andreas Schwab
 *                       Andreas Schwab
 *
 *
 *
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file COPYING in the main directory of this archive
 * License.  See the file COPYING in the main directory of this archive
 * for more details.
 * for more details.
 */
 */
 
 
/*
/*
 * To do:
 * To do:
 *  - Implement 16 plane mode.
 *  - Implement 16 plane mode.
 *  - Add support for 16/24/32 bit packed pixels
 *  - Add support for 16/24/32 bit packed pixels
 *  - Hardware cursor
 *  - Hardware cursor
 */
 */
 
 
 
 
#include <linux/types.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/tty.h>
#include <linux/tty.h>
#include <linux/console.h>
#include <linux/console.h>
#include <linux/string.h>
#include <linux/string.h>
#include <linux/config.h>
#include <linux/config.h>
#include <linux/kd.h>
#include <linux/kd.h>
#include <linux/malloc.h>
#include <linux/malloc.h>
 
 
#include <asm/irq.h>
#include <asm/irq.h>
#include <linux/fb.h>
#include <linux/fb.h>
#include <asm/font.h>
#include <asm/font.h>
#include <asm/machdep.h>
#include <asm/machdep.h>
 
 
#include <asm/system.h>
#include <asm/system.h>
 
 
#include "../../../drivers/char/vt_kern.h"   /* vt_cons and vc_resize_con() */
#include "../../../drivers/char/vt_kern.h"   /* vt_cons and vc_resize_con() */
 
 
extern void vc_resize_con(unsigned long lines, unsigned long columns, unsigned int currcons);
extern void vc_resize_con(unsigned long lines, unsigned long columns, unsigned int currcons);
extern struct fb_info *crt_fb_init(long *mem_start);
extern struct fb_info *crt_fb_init(long *mem_start);
 
 
 
 
/* Import console_blanked from console.c */
/* Import console_blanked from console.c */
 
 
extern int console_blanked;
extern int console_blanked;
 
 
 
 
   /*
   /*
    *    The following symbols select what modes are supported. They should
    *    The following symbols select what modes are supported. They should
    *    be settable by the user ("make config") later.
    *    be settable by the user ("make config") later.
    */
    */
 
 
/* Clear all definitions */
/* Clear all definitions */
 
 
#undef CONFIG_FBCON_MONO
#undef CONFIG_FBCON_MONO
#undef CONFIG_FBCON_ILBM
#undef CONFIG_FBCON_ILBM
#undef CONFIG_FBCON_PLANES
#undef CONFIG_FBCON_PLANES
#undef CONFIG_FBCON_2PLANE
#undef CONFIG_FBCON_2PLANE
#undef CONFIG_FBCON_4PLANE
#undef CONFIG_FBCON_4PLANE
#undef CONFIG_FBCON_8PLANE
#undef CONFIG_FBCON_8PLANE
#undef CONFIG_FBCON_8PACKED
#undef CONFIG_FBCON_8PACKED
#undef CONFIG_FBCON_8PACKED_NOTLIGNED
#undef CONFIG_FBCON_8PACKED_NOTLIGNED
#undef CONFIG_FBCON_16PACKED
#undef CONFIG_FBCON_16PACKED
#undef CONFIG_FBCON_24PACKED
#undef CONFIG_FBCON_24PACKED
#undef CONFIG_FBCON_32PACKED
#undef CONFIG_FBCON_32PACKED
#undef CONFIG_FBCON_CYBER
#undef CONFIG_FBCON_CYBER
 
 
/* Frame buffer notaligned wrap boundary */
/* Frame buffer notaligned wrap boundary */
#define CRT_WRAP_BOUNDARY (512*1024)
#define CRT_WRAP_BOUNDARY (512*1024)
#define CRT_WRAP(base, add)     (((base) & ~(CRT_WRAP_BOUNDARY - 1)) | ((add) & (CRT_WRAP_BOUNDARY - 1)))
#define CRT_WRAP(base, add)     (((base) & ~(CRT_WRAP_BOUNDARY - 1)) | ((add) & (CRT_WRAP_BOUNDARY - 1)))
 
 
/* Monochrome is default */
/* Monochrome is default */
 
 
#define CONFIG_FBCON_MONO
#define CONFIG_FBCON_MONO
#define CONFIG_FBCON_8PACKED_NOTALIGNED
#define CONFIG_FBCON_8PACKED_NOTALIGNED
 
 
/* Extra definitions to make the code more readable */
/* Extra definitions to make the code more readable */
 
 
#if defined(CONFIG_FBCON_2PLANE) || defined(CONFIG_FBCON_4PLANE) || \
#if defined(CONFIG_FBCON_2PLANE) || defined(CONFIG_FBCON_4PLANE) || \
    defined(CONFIG_FBCON_8PLANE)
    defined(CONFIG_FBCON_8PLANE)
#define CONFIG_FBCON_IPLAN2
#define CONFIG_FBCON_IPLAN2
#else
#else
#undef CONFIG_FBCON_IPLAN2
#undef CONFIG_FBCON_IPLAN2
#endif
#endif
 
 
#if defined(CONFIG_FBCON_CYBER) || defined(CONFIG_FBCON_8PACKED) || \
#if defined(CONFIG_FBCON_CYBER) || defined(CONFIG_FBCON_8PACKED) || \
    defined(CONFIG_FBCON_8PACKED_NOTALIGNED) || \
    defined(CONFIG_FBCON_8PACKED_NOTALIGNED) || \
    defined(CONFIG_FBCON_16PACKED) || defined(CONFIG_FBCON_24PACKED) || \
    defined(CONFIG_FBCON_16PACKED) || defined(CONFIG_FBCON_24PACKED) || \
    defined(CONFIG_FBCON_32PACKED)
    defined(CONFIG_FBCON_32PACKED)
#define CONFIG_FBCON_PACKED
#define CONFIG_FBCON_PACKED
#else
#else
#undef CONFIG_FBCON_PACKED
#undef CONFIG_FBCON_PACKED
#endif
#endif
 
 
 
 
struct fb_info *fb_info;
struct fb_info *fb_info;
struct display *disp;
struct display *disp;
 
 
 
 
/* ++Geert: Sorry, no hardware cursor support at the moment;
/* ++Geert: Sorry, no hardware cursor support at the moment;
   use Atari alike software cursor */
   use Atari alike software cursor */
 
 
static int cursor_drawn = 0;
static int cursor_drawn = 0;
 
 
#define CURSOR_DRAW_DELAY           (2)
#define CURSOR_DRAW_DELAY           (2)
 
 
/* # VBL ints between cursor state changes */
/* # VBL ints between cursor state changes */
#define AMIGA_CURSOR_BLINK_RATE   (20)
#define AMIGA_CURSOR_BLINK_RATE   (20)
#define ATARI_CURSOR_BLINK_RATE   (42)
#define ATARI_CURSOR_BLINK_RATE   (42)
 
 
static int vbl_cursor_cnt = 0;
static int vbl_cursor_cnt = 0;
static int cursor_on = 0;
static int cursor_on = 0;
static int cursor_blink_rate;
static int cursor_blink_rate;
 
 
static __inline__ int CURSOR_UNDRAWN(void)
static __inline__ int CURSOR_UNDRAWN(void)
{
{
   int cursor_was_drawn;
   int cursor_was_drawn;
   vbl_cursor_cnt = 0;
   vbl_cursor_cnt = 0;
   cursor_was_drawn = cursor_drawn;
   cursor_was_drawn = cursor_drawn;
   cursor_drawn = 0;
   cursor_drawn = 0;
   return(cursor_was_drawn);
   return(cursor_was_drawn);
}
}
 
 
   /*
   /*
    *    Attribute Decoding
    *    Attribute Decoding
    */
    */
 
 
/* Color */
/* Color */
#define attr_fgcol(p,conp)    \
#define attr_fgcol(p,conp)    \
        (((conp)->vc_attr >> ((p)->inverse ? 4 : 0)) & 0x0f)
        (((conp)->vc_attr >> ((p)->inverse ? 4 : 0)) & 0x0f)
#define attr_bgcol(p,conp)    \
#define attr_bgcol(p,conp)    \
        (((conp)->vc_attr >> ((p)->inverse ? 0 : 4)) & 0x0f)
        (((conp)->vc_attr >> ((p)->inverse ? 0 : 4)) & 0x0f)
#define attr_bgcol_ec(p,conp) \
#define attr_bgcol_ec(p,conp) \
        (((conp)->vc_video_erase_char >> ((p)->inverse ? 8 : 12)) & 0x0f)
        (((conp)->vc_video_erase_char >> ((p)->inverse ? 8 : 12)) & 0x0f)
 
 
/* Monochrome */
/* Monochrome */
#define attr_bold(p,conp)     \
#define attr_bold(p,conp)     \
        (((conp)->vc_attr & 3) == 2)
        (((conp)->vc_attr & 3) == 2)
#define attr_reverse(p,conp)  \
#define attr_reverse(p,conp)  \
        (((conp)->vc_attr & 8) ^ ((p)->inverse ? 8 : 0))
        (((conp)->vc_attr & 8) ^ ((p)->inverse ? 8 : 0))
#define attr_underline(p,conp) \
#define attr_underline(p,conp) \
        (((conp)->vc_attr) & 4)
        (((conp)->vc_attr) & 4)
 
 
 
 
   /*
   /*
    *    Scroll Method
    *    Scroll Method
    */
    */
 
 
#define SCROLL_YWRAP                    (0)
#define SCROLL_YWRAP                    (0)
#define SCROLL_YPAN                     (1)
#define SCROLL_YPAN                     (1)
#define SCROLL_YMOVE                    (2)
#define SCROLL_YMOVE                    (2)
#define SCROLL_YWRAP_NOTALIGNED         (4)
#define SCROLL_YWRAP_NOTALIGNED         (4)
 
 
#define divides(a, b)         ((!(a) || (b)%(a)) ? 0 : 1)
#define divides(a, b)         ((!(a) || (b)%(a)) ? 0 : 1)
 
 
 
 
   /*
   /*
    *    Interface used by the world
    *    Interface used by the world
    */
    */
 
 
static u_long fbcon_startup(u_long kmem_start, char **display_desc);
static u_long fbcon_startup(u_long kmem_start, char **display_desc);
static void fbcon_init(struct vc_data *conp);
static void fbcon_init(struct vc_data *conp);
static int fbcon_deinit(struct vc_data *conp);
static int fbcon_deinit(struct vc_data *conp);
static int fbcon_changevar(int con);
static int fbcon_changevar(int con);
static int fbcon_clear(struct vc_data *conp, int sy, int sx, int height,
static int fbcon_clear(struct vc_data *conp, int sy, int sx, int height,
                       int width);
                       int width);
static int fbcon_putc(struct vc_data *conp, int c, int y, int x);
static int fbcon_putc(struct vc_data *conp, int c, int y, int x);
static int fbcon_putcs(struct vc_data *conp, const char *s, int count, int y,
static int fbcon_putcs(struct vc_data *conp, const char *s, int count, int y,
                       int x);
                       int x);
static int fbcon_cursor(struct vc_data *conp, int mode);
static int fbcon_cursor(struct vc_data *conp, int mode);
static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir, int count);
static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir, int count);
static int fbcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
static int fbcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
                       int height, int width);
                       int height, int width);
static int fbcon_switch(struct vc_data *conp);
static int fbcon_switch(struct vc_data *conp);
static int fbcon_blank(int blank);
static int fbcon_blank(int blank);
 
 
 
 
   /*
   /*
    *    Internal routines
    *    Internal routines
    */
    */
 
 
static void fbcon_setup(int con, int setcol, int cls);
static void fbcon_setup(int con, int setcol, int cls);
static __inline__ void *mymemclear_small(void *s, size_t count);
static __inline__ void *mymemclear_small(void *s, size_t count);
static __inline__ void *mymemclear(void *s, size_t count);
static __inline__ void *mymemclear(void *s, size_t count);
static __inline__ void *mymemset(void *s, size_t count);
static __inline__ void *mymemset(void *s, size_t count);
static __inline__ void *mymemmove(void *d, void *s, size_t count);
static __inline__ void *mymemmove(void *d, void *s, size_t count);
static __inline__ void *mymemmove_notaligned(void *d, void *s, size_t count);
static __inline__ void *mymemmove_notaligned(void *d, void *s, size_t count);
static __inline__ void fast_memmove(char *dst, char *src, size_t size);
static __inline__ void fast_memmove(char *dst, char *src, size_t size);
static __inline__ void memclear_4p_col(void *d, size_t h, u_long val, int bpr);
static __inline__ void memclear_4p_col(void *d, size_t h, u_long val, int bpr);
static __inline__ void memset_even_4p(void *d, size_t count, u_long val1,
static __inline__ void memset_even_4p(void *d, size_t count, u_long val1,
                                      u_long val2);
                                      u_long val2);
static __inline__ void memmove_4p_col(void *d, void *s, int h, int bpr);
static __inline__ void memmove_4p_col(void *d, void *s, int h, int bpr);
static __inline__ u_long expand4l(u_char c);
static __inline__ u_long expand4l(u_char c);
static __inline__ void expand4dl(u_char c, u_long *ret1, u_long *ret2);
static __inline__ void expand4dl(u_char c, u_long *ret1, u_long *ret2);
static __inline__ u_long dup4l(u_char c);
static __inline__ u_long dup4l(u_char c);
static __inline__ void memclear_8p_col(void *d, size_t h, u_long val1,
static __inline__ void memclear_8p_col(void *d, size_t h, u_long val1,
                                       u_long val2, int bpr);
                                       u_long val2, int bpr);
static __inline__ void memset_even_8p(void *d, size_t count, u_long val1,
static __inline__ void memset_even_8p(void *d, size_t count, u_long val1,
                                      u_long val2, u_long val3, u_long val4);
                                      u_long val2, u_long val3, u_long val4);
static __inline__ void memmove_8p_col(void *d, void *s, int h, int bpr);
static __inline__ void memmove_8p_col(void *d, void *s, int h, int bpr);
static __inline__ void expand8dl(u_char c, u_long *ret1, u_long *ret2);
static __inline__ void expand8dl(u_char c, u_long *ret1, u_long *ret2);
static __inline__ void memclear_2p_col(void *d, size_t h, u_short val, int bpr);
static __inline__ void memclear_2p_col(void *d, size_t h, u_short val, int bpr);
static __inline__ void memset_even_2p(void *d, size_t count, u_long val);
static __inline__ void memset_even_2p(void *d, size_t count, u_long val);
static __inline__ void memmove_2p_col(void *d, void *s, int h, int bpr);
static __inline__ void memmove_2p_col(void *d, void *s, int h, int bpr);
static __inline__ u_short expand2w(u_char c);
static __inline__ u_short expand2w(u_char c);
static __inline__ u_long expand2l(u_char c);
static __inline__ u_long expand2l(u_char c);
static __inline__ u_short dup2w(u_char c);
static __inline__ u_short dup2w(u_char c);
static __inline__ int real_y(struct display *p, int y);
static __inline__ int real_y(struct display *p, int y);
static void fbcon_vbl_handler(int irq, struct pt_regs *fp, void *dummy);
static void fbcon_vbl_handler(int irq, struct pt_regs *fp, void *dummy);
static void fbcon_bmove_rec(struct display *p, int sy, int sx, int dy, int dx,
static void fbcon_bmove_rec(struct display *p, int sy, int sx, int dy, int dx,
                            int height, int width, u_int y_break);
                            int height, int width, u_int y_break);
 
 
 
 
   /*
   /*
    *    Monochrome
    *    Monochrome
    */
    */
 
 
#ifdef CONFIG_FBCON_MONO
#ifdef CONFIG_FBCON_MONO
static void bmove_mono(struct display *p, int sy, int sx, int dy, int dx,
static void bmove_mono(struct display *p, int sy, int sx, int dy, int dx,
                       int height, int width);
                       int height, int width);
static void clear_mono(struct vc_data *conp, struct display *p, int sy, int sx,
static void clear_mono(struct vc_data *conp, struct display *p, int sy, int sx,
                       int height, int width);
                       int height, int width);
static void putc_mono(struct vc_data *conp, struct display *p, int c, int y,
static void putc_mono(struct vc_data *conp, struct display *p, int c, int y,
                      int x);
                      int x);
static void putcs_mono(struct vc_data *conp, struct display *p, const char *s,
static void putcs_mono(struct vc_data *conp, struct display *p, const char *s,
                       int count, int y, int x);
                       int count, int y, int x);
static void rev_char_mono(struct display *p, int x, int y);
static void rev_char_mono(struct display *p, int x, int y);
#endif /* CONFIG_FBCON_MONO */
#endif /* CONFIG_FBCON_MONO */
 
 
 
 
   /*
   /*
    *    Color Interleaved Planes
    *    Color Interleaved Planes
    */
    */
 
 
#ifdef CONFIG_FBCON_ILBM
#ifdef CONFIG_FBCON_ILBM
static void bmove_ilbm(struct display *p, int sy, int sx, int dy, int dx,
static void bmove_ilbm(struct display *p, int sy, int sx, int dy, int dx,
                       int height, int width);
                       int height, int width);
static void clear_ilbm(struct vc_data *conp, struct display *p, int sy, int sx,
static void clear_ilbm(struct vc_data *conp, struct display *p, int sy, int sx,
                       int height, int width);
                       int height, int width);
static void putc_ilbm(struct vc_data *conp, struct display *p, int c, int y,
static void putc_ilbm(struct vc_data *conp, struct display *p, int c, int y,
                      int x);
                      int x);
static void putcs_ilbm(struct vc_data *conp, struct display *p, const char *s,
static void putcs_ilbm(struct vc_data *conp, struct display *p, const char *s,
                       int count, int y, int x);
                       int count, int y, int x);
static void rev_char_ilbm(struct display *p, int x, int y);
static void rev_char_ilbm(struct display *p, int x, int y);
#endif /* CONFIG_FBCON_ILBM */
#endif /* CONFIG_FBCON_ILBM */
 
 
 
 
   /*
   /*
    *    Color Planes
    *    Color Planes
    */
    */
 
 
#ifdef CONFIG_FBCON_PLANES
#ifdef CONFIG_FBCON_PLANES
static void bmove_plan(struct display *p, int sy, int sx, int dy, int dx,
static void bmove_plan(struct display *p, int sy, int sx, int dy, int dx,
                       int height, int width);
                       int height, int width);
static void clear_plan(struct vc_data *conp, struct display *p, int sy, int sx,
static void clear_plan(struct vc_data *conp, struct display *p, int sy, int sx,
                       int height, int width);
                       int height, int width);
static void putc_plan(struct vc_data *conp, struct display *p, int c, int y,
static void putc_plan(struct vc_data *conp, struct display *p, int c, int y,
                      int x);
                      int x);
static void putcs_plan(struct vc_data *conp, struct display *p, const char *s,
static void putcs_plan(struct vc_data *conp, struct display *p, const char *s,
                       int count, int y, int x);
                       int count, int y, int x);
static void rev_char_plan(struct display *p, int x, int y);
static void rev_char_plan(struct display *p, int x, int y);
#endif /* CONFIG_FBCON_PLANES */
#endif /* CONFIG_FBCON_PLANES */
 
 
 
 
   /*
   /*
    *    2 Planes (2-bytes interleave)
    *    2 Planes (2-bytes interleave)
    */
    */
 
 
#ifdef CONFIG_FBCON_2PLANE
#ifdef CONFIG_FBCON_2PLANE
static void bmove_2_plane(struct display *p, int sy, int sx, int dy, int dx,
static void bmove_2_plane(struct display *p, int sy, int sx, int dy, int dx,
                          int height, int width);
                          int height, int width);
static void clear_2_plane(struct vc_data *conp, struct display *p, int sy,
static void clear_2_plane(struct vc_data *conp, struct display *p, int sy,
                          int sx, int height, int width);
                          int sx, int height, int width);
static void putc_2_plane(struct vc_data *conp, struct display *p, int c, int y,
static void putc_2_plane(struct vc_data *conp, struct display *p, int c, int y,
                         int x);
                         int x);
static void putcs_2_plane(struct vc_data *conp, struct display *p,
static void putcs_2_plane(struct vc_data *conp, struct display *p,
                          const char *s, int count, int y, int x);
                          const char *s, int count, int y, int x);
static void rev_char_2_plane(struct display *display, int x, int y);
static void rev_char_2_plane(struct display *display, int x, int y);
#endif /* CONFIG_FBCON_2PLANE */
#endif /* CONFIG_FBCON_2PLANE */
 
 
 
 
   /*
   /*
    *    4 Planes (2-bytes interleave)
    *    4 Planes (2-bytes interleave)
    */
    */
 
 
#ifdef CONFIG_FBCON_4PLANE
#ifdef CONFIG_FBCON_4PLANE
static void bmove_4_plane(struct display *p, int sy, int sx, int dy, int dx,
static void bmove_4_plane(struct display *p, int sy, int sx, int dy, int dx,
                          int height, int width);
                          int height, int width);
static void clear_4_plane(struct vc_data *conp, struct display *p, int sy,
static void clear_4_plane(struct vc_data *conp, struct display *p, int sy,
                          int sx, int height, int width);
                          int sx, int height, int width);
static void putc_4_plane(struct vc_data *conp, struct display *p, int c, int y,
static void putc_4_plane(struct vc_data *conp, struct display *p, int c, int y,
                         int x);
                         int x);
static void putcs_4_plane(struct vc_data *conp, struct display *p,
static void putcs_4_plane(struct vc_data *conp, struct display *p,
                          const char *s, int count, int y, int x);
                          const char *s, int count, int y, int x);
static void rev_char_4_plane(struct display *p, int x, int y);
static void rev_char_4_plane(struct display *p, int x, int y);
#endif /* CONFIG_FBCON_4PLANE */
#endif /* CONFIG_FBCON_4PLANE */
 
 
 
 
   /*
   /*
    *    8 Planes (2-bytes interleave)
    *    8 Planes (2-bytes interleave)
    */
    */
 
 
#ifdef CONFIG_FBCON_8PLANE
#ifdef CONFIG_FBCON_8PLANE
static void bmove_8_plane(struct display *p, int sy, int sx, int dy, int dx,
static void bmove_8_plane(struct display *p, int sy, int sx, int dy, int dx,
                          int height, int width);
                          int height, int width);
static void clear_8_plane(struct vc_data *conp, struct display *p, int sy,
static void clear_8_plane(struct vc_data *conp, struct display *p, int sy,
                          int sx, int height, int width);
                          int sx, int height, int width);
static void putc_8_plane(struct vc_data *conp, struct display *p, int c, int y,
static void putc_8_plane(struct vc_data *conp, struct display *p, int c, int y,
                         int x);
                         int x);
static void putcs_8_plane(struct vc_data *conp, struct display *p,
static void putcs_8_plane(struct vc_data *conp, struct display *p,
                          const char *s, int count, int y, int x);
                          const char *s, int count, int y, int x);
static void rev_char_8_plane(struct display *display, int x, int y);
static void rev_char_8_plane(struct display *display, int x, int y);
#endif /* CONFIG_FBCON_8PLANE */
#endif /* CONFIG_FBCON_8PLANE */
 
 
 
 
   /*
   /*
    *    8 bpp Packed Pixels
    *    8 bpp Packed Pixels
    */
    */
 
 
#ifdef CONFIG_FBCON_8PACKED
#ifdef CONFIG_FBCON_8PACKED
static void bmove_8_packed(struct display *p, int sy, int sx, int dy, int dx,
static void bmove_8_packed(struct display *p, int sy, int sx, int dy, int dx,
                           int height, int width);
                           int height, int width);
static void clear_8_packed(struct vc_data *conp, struct display *p, int sy,
static void clear_8_packed(struct vc_data *conp, struct display *p, int sy,
                           int sx, int height, int width);
                           int sx, int height, int width);
static void putc_8_packed(struct vc_data *conp, struct display *p, int c, int y,
static void putc_8_packed(struct vc_data *conp, struct display *p, int c, int y,
                          int x);
                          int x);
static void putcs_8_packed(struct vc_data *conp, struct display *p,
static void putcs_8_packed(struct vc_data *conp, struct display *p,
                           const char *s, int count, int y, int x);
                           const char *s, int count, int y, int x);
static void rev_char_8_packed(struct display *p, int x, int y);
static void rev_char_8_packed(struct display *p, int x, int y);
#endif /* CONFIG_FBCON_8PACKED */
#endif /* CONFIG_FBCON_8PACKED */
 
 
 
 
 
 
   /*
   /*
    *    8 bpp Packed Pixels
    *    8 bpp Packed Pixels
    */
    */
 
 
#ifdef CONFIG_FBCON_8PACKED_NOTALIGNED
#ifdef CONFIG_FBCON_8PACKED_NOTALIGNED
static void bmove_8_packed(struct display *p, int sy, int sx, int dy, int dx,
static void bmove_8_packed(struct display *p, int sy, int sx, int dy, int dx,
                           int height, int width);
                           int height, int width);
static void clear_8_packed(struct vc_data *conp, struct display *p, int sy,
static void clear_8_packed(struct vc_data *conp, struct display *p, int sy,
                           int sx, int height, int width);
                           int sx, int height, int width);
static void putc_8_packed(struct vc_data *conp, struct display *p, int c, int y,
static void putc_8_packed(struct vc_data *conp, struct display *p, int c, int y,
                          int x);
                          int x);
static void putcs_8_packed(struct vc_data *conp, struct display *p,
static void putcs_8_packed(struct vc_data *conp, struct display *p,
                           const char *s, int count, int y, int x);
                           const char *s, int count, int y, int x);
static void rev_char_8_packed(struct display *p, int x, int y);
static void rev_char_8_packed(struct display *p, int x, int y);
#endif /* CONFIG_FBCON_8PACKED_NOTALIGNED */
#endif /* CONFIG_FBCON_8PACKED_NOTALIGNED */
 
 
 
 
   /*
   /*
    *    16 bpp Packed Pixels
    *    16 bpp Packed Pixels
    */
    */
 
 
#ifdef CONFIG_FBCON_16PACKED
#ifdef CONFIG_FBCON_16PACKED
static void bmove_16_packed(struct display *p, int sy, int sx, int dy, int dx,
static void bmove_16_packed(struct display *p, int sy, int sx, int dy, int dx,
                            int height, int width);
                            int height, int width);
static void clear_16_packed(struct vc_data *conp, struct display *p, int sy,
static void clear_16_packed(struct vc_data *conp, struct display *p, int sy,
                            int sx, int height, int width);
                            int sx, int height, int width);
static void putc_16_packed(struct vc_data *conp, struct display *p, int c,
static void putc_16_packed(struct vc_data *conp, struct display *p, int c,
                           int y, int x);
                           int y, int x);
static void putcs_16_packed(struct vc_data *conp, struct display *p,
static void putcs_16_packed(struct vc_data *conp, struct display *p,
                            const char *s, int count, int y, int x);
                            const char *s, int count, int y, int x);
static void rev_char_16_packed(struct display *p, int x, int y);
static void rev_char_16_packed(struct display *p, int x, int y);
#endif /* CONFIG_FBCON_8PACKED */
#endif /* CONFIG_FBCON_8PACKED */
 
 
 
 
   /*
   /*
    *    Cybervision (accelerated)
    *    Cybervision (accelerated)
    */
    */
 
 
#ifdef CONFIG_FBCON_CYBER
#ifdef CONFIG_FBCON_CYBER
static void bmove_cyber(struct display *p, int sy, int sx, int dy, int dx,
static void bmove_cyber(struct display *p, int sy, int sx, int dy, int dx,
                        int height, int width);
                        int height, int width);
static void clear_cyber(struct vc_data *conp, struct display *p, int sy, int sx,
static void clear_cyber(struct vc_data *conp, struct display *p, int sy, int sx,
                        int height, int width);
                        int height, int width);
static void putc_cyber(struct vc_data *conp, struct display *p, int c, int y,
static void putc_cyber(struct vc_data *conp, struct display *p, int c, int y,
                       int x);
                       int x);
static void putcs_cyber(struct vc_data *conp, struct display *p, const char *s,
static void putcs_cyber(struct vc_data *conp, struct display *p, const char *s,
                        int count, int y, int x);
                        int count, int y, int x);
static void rev_char_cyber(struct display *p, int x, int y);
static void rev_char_cyber(struct display *p, int x, int y);
 
 
extern void Cyber_WaitQueue(u_short fifo);
extern void Cyber_WaitQueue(u_short fifo);
extern void Cyber_WaitBlit(void);
extern void Cyber_WaitBlit(void);
extern void Cyber_BitBLT(u_short curx, u_short cury, u_short destx,
extern void Cyber_BitBLT(u_short curx, u_short cury, u_short destx,
                         u_short desty, u_short width, u_short height,
                         u_short desty, u_short width, u_short height,
                         u_short mode);
                         u_short mode);
extern void Cyber_RectFill(u_short x, u_short y, u_short width, u_short height,
extern void Cyber_RectFill(u_short x, u_short y, u_short width, u_short height,
                           u_short mode, u_short color);
                           u_short mode, u_short color);
extern void Cyber_MoveCursor(u_short x, u_short y);
extern void Cyber_MoveCursor(u_short x, u_short y);
#endif /* CONFIG_FBCON_CYBER */
#endif /* CONFIG_FBCON_CYBER */
 
 
 
 
   /*
   /*
    *    `switch' for the Low Level Operations
    *    `switch' for the Low Level Operations
    */
    */
 
 
struct display_switch {
struct display_switch {
    void (*bmove)(struct display *p, int sy, int sx, int dy, int dx, int height,
    void (*bmove)(struct display *p, int sy, int sx, int dy, int dx, int height,
                  int width);
                  int width);
    void (*clear)(struct vc_data *conp, struct display *p, int sy, int sx,
    void (*clear)(struct vc_data *conp, struct display *p, int sy, int sx,
                  int height, int width);
                  int height, int width);
    void (*putc)(struct vc_data *conp, struct display *p, int c, int y, int x);
    void (*putc)(struct vc_data *conp, struct display *p, int c, int y, int x);
    void (*putcs)(struct vc_data *conp, struct display *p, const char *s,
    void (*putcs)(struct vc_data *conp, struct display *p, const char *s,
                  int count, int y, int x);
                  int count, int y, int x);
    void (*rev_char)(struct display *p, int x, int y);
    void (*rev_char)(struct display *p, int x, int y);
};
};
 
 
 
 
#ifdef CONFIG_FBCON_MONO
#ifdef CONFIG_FBCON_MONO
struct display_switch dispsw_mono = {
struct display_switch dispsw_mono = {
   bmove_mono, clear_mono, putc_mono, putcs_mono, rev_char_mono
   bmove_mono, clear_mono, putc_mono, putcs_mono, rev_char_mono
};
};
#else /* CONFIG_FBCON_MONO */
#else /* CONFIG_FBCON_MONO */
struct display_switch dispsw_mono = {
struct display_switch dispsw_mono = {
   NULL, NULL, NULL, NULL, NULL
   NULL, NULL, NULL, NULL, NULL
};
};
#endif
#endif
 
 
#ifdef CONFIG_FBCON_ILBM
#ifdef CONFIG_FBCON_ILBM
struct display_switch dispsw_ilbm = {
struct display_switch dispsw_ilbm = {
   bmove_ilbm, clear_ilbm, putc_ilbm, putcs_ilbm, rev_char_ilbm
   bmove_ilbm, clear_ilbm, putc_ilbm, putcs_ilbm, rev_char_ilbm
};
};
#endif /* CONFIG_FBCON_ILBM */
#endif /* CONFIG_FBCON_ILBM */
 
 
#ifdef CONFIG_FBCON_PLANES
#ifdef CONFIG_FBCON_PLANES
struct display_switch dispsw_plan = {
struct display_switch dispsw_plan = {
   bmove_plan, clear_plan, putc_plan, putcs_plan, rev_char_plan
   bmove_plan, clear_plan, putc_plan, putcs_plan, rev_char_plan
};
};
#endif /* CONFIG_FBCON_PLANES */
#endif /* CONFIG_FBCON_PLANES */
 
 
#ifdef CONFIG_FBCON_2PLANE
#ifdef CONFIG_FBCON_2PLANE
struct display_switch dispsw_2_plane = {
struct display_switch dispsw_2_plane = {
   bmove_2_plane, clear_2_plane, putc_2_plane, putcs_2_plane, rev_char_2_plane
   bmove_2_plane, clear_2_plane, putc_2_plane, putcs_2_plane, rev_char_2_plane
};
};
#endif /* CONFIG_FBCON_2PLANE */
#endif /* CONFIG_FBCON_2PLANE */
 
 
#ifdef CONFIG_FBCON_4PLANE
#ifdef CONFIG_FBCON_4PLANE
struct display_switch dispsw_4_plane = {
struct display_switch dispsw_4_plane = {
   bmove_4_plane, clear_4_plane, putc_4_plane, putcs_4_plane, rev_char_4_plane
   bmove_4_plane, clear_4_plane, putc_4_plane, putcs_4_plane, rev_char_4_plane
};
};
#endif /* CONFIG_FBCON_4PLANE */
#endif /* CONFIG_FBCON_4PLANE */
 
 
#ifdef CONFIG_FBCON_8PLANE
#ifdef CONFIG_FBCON_8PLANE
struct display_switch dispsw_8_plane = {
struct display_switch dispsw_8_plane = {
   bmove_8_plane, clear_8_plane, putc_8_plane, putcs_8_plane, rev_char_8_plane
   bmove_8_plane, clear_8_plane, putc_8_plane, putcs_8_plane, rev_char_8_plane
};
};
#endif /* CONFIG_FBCON_8PLANE */
#endif /* CONFIG_FBCON_8PLANE */
 
 
#ifdef CONFIG_FBCON_8PACKED
#ifdef CONFIG_FBCON_8PACKED
struct display_switch dispsw_8_packed = {
struct display_switch dispsw_8_packed = {
   bmove_8_packed, clear_8_packed, putc_8_packed, putcs_8_packed, rev_char_8_packed
   bmove_8_packed, clear_8_packed, putc_8_packed, putcs_8_packed, rev_char_8_packed
};
};
#endif /* CONFIG_FBCON_8PACKED */
#endif /* CONFIG_FBCON_8PACKED */
 
 
#ifdef CONFIG_FBCON_8PACKED_NOTALIGNED
#ifdef CONFIG_FBCON_8PACKED_NOTALIGNED
struct display_switch dispsw_8_packed = {
struct display_switch dispsw_8_packed = {
   bmove_8_packed, clear_8_packed, putc_8_packed, putcs_8_packed, rev_char_8_packed
   bmove_8_packed, clear_8_packed, putc_8_packed, putcs_8_packed, rev_char_8_packed
};
};
#endif /* CONFIG_FBCON_8PACKED_NOTALIGNED */
#endif /* CONFIG_FBCON_8PACKED_NOTALIGNED */
 
 
#ifdef CONFIG_FBCON_16PACKED
#ifdef CONFIG_FBCON_16PACKED
struct display_switch dispsw_16_packed = {
struct display_switch dispsw_16_packed = {
   bmove_16_packed, clear_16_packed, putc_16_packed, putcs_16_packed,
   bmove_16_packed, clear_16_packed, putc_16_packed, putcs_16_packed,
   rev_char_16_packed
   rev_char_16_packed
};
};
#endif /* CONFIG_FBCON_16PACKED */
#endif /* CONFIG_FBCON_16PACKED */
 
 
#ifdef CONFIG_FBCON_CYBER
#ifdef CONFIG_FBCON_CYBER
struct display_switch dispsw_cyber = {
struct display_switch dispsw_cyber = {
   bmove_cyber, clear_cyber, putc_cyber, putcs_cyber, rev_char_cyber
   bmove_cyber, clear_cyber, putc_cyber, putcs_cyber, rev_char_cyber
};
};
#endif /* CONFIG_FBCON_CYBER */
#endif /* CONFIG_FBCON_CYBER */
 
 
 
 
static u_long fbcon_startup(u_long kmem_start, char **display_desc)
static u_long fbcon_startup(u_long kmem_start, char **display_desc)
{
{
   int irqres = 0;
   int irqres = 0;
 
 
   fb_info = crt_fb_init(&kmem_start);
   fb_info = crt_fb_init(&kmem_start);
   disp = fb_info->disp;
   disp = fb_info->disp;
   *display_desc = fb_info->modename;
   *display_desc = fb_info->modename;
   fb_info->changevar = &fbcon_changevar;
   fb_info->changevar = &fbcon_changevar;
 
 
#ifdef CONFIG_AMIGA
#ifdef CONFIG_AMIGA
   if (MACH_IS_AMIGA) {
   if (MACH_IS_AMIGA) {
      cursor_blink_rate = AMIGA_CURSOR_BLINK_RATE;
      cursor_blink_rate = AMIGA_CURSOR_BLINK_RATE;
      irqres = add_isr(IRQ_AMIGA_VERTB, fbcon_vbl_handler, 0, NULL,
      irqres = add_isr(IRQ_AMIGA_VERTB, fbcon_vbl_handler, 0, NULL,
                       "console/cursor");
                       "console/cursor");
   }
   }
#endif /* CONFIG_AMIGA */
#endif /* CONFIG_AMIGA */
#ifdef CONFIG_ATARI
#ifdef CONFIG_ATARI
   if (MACH_IS_ATARI) {
   if (MACH_IS_ATARI) {
      cursor_blink_rate = ATARI_CURSOR_BLINK_RATE;
      cursor_blink_rate = ATARI_CURSOR_BLINK_RATE;
      irqres = add_isr(IRQ_AUTO_4, fbcon_vbl_handler, IRQ_TYPE_PRIO, NULL,
      irqres = add_isr(IRQ_AUTO_4, fbcon_vbl_handler, IRQ_TYPE_PRIO, NULL,
                       "console/cursor");
                       "console/cursor");
   }
   }
#endif /* CONFIG_ATARI */
#endif /* CONFIG_ATARI */
 
 
#if defined(CONFIG_AMIGA) || defined(CONFIG_ATARI)
#if defined(CONFIG_AMIGA) || defined(CONFIG_ATARI)
   if (!irqres)
   if (!irqres)
      panic("fbcon_startup: Couldn't add vblank interrupt");
      panic("fbcon_startup: Couldn't add vblank interrupt");
#endif
#endif
 
 
   return(kmem_start);
   return(kmem_start);
}
}
 
 
 
 
static void fbcon_init(struct vc_data *conp)
static void fbcon_init(struct vc_data *conp)
{
{
   int unit = conp->vc_num;
   int unit = conp->vc_num;
 
 
   if (unit)
   if (unit)
      disp[unit] = disp[0];
      disp[unit] = disp[0];
   disp[unit].conp = conp;
   disp[unit].conp = conp;
   fbcon_setup(unit, 1, 0);
   fbcon_setup(unit, 1, 0);
}
}
 
 
 
 
static int fbcon_deinit(struct vc_data *conp)
static int fbcon_deinit(struct vc_data *conp)
{
{
   disp[conp->vc_num].conp = 0;
   disp[conp->vc_num].conp = 0;
   return(0);
   return(0);
}
}
 
 
 
 
static int fbcon_changevar(int con)
static int fbcon_changevar(int con)
{
{
   fbcon_setup(con, 1, 1);
   fbcon_setup(con, 1, 1);
   return(0);
   return(0);
}
}
 
 
 
 
static void fbcon_setup(int con, int setcol, int cls)
static void fbcon_setup(int con, int setcol, int cls)
{
{
   struct display *p = &disp[con];
   struct display *p = &disp[con];
   struct vc_data *conp = p->conp;
   struct vc_data *conp = p->conp;
 
 
#ifdef CONFIG_SERIAL_ECHO
#ifdef CONFIG_SERIAL_ECHO
   void rs_console_init(void);
   void rs_console_init(void);
   rs_console_init();
   rs_console_init();
#endif
#endif
 
 
   p->var.xoffset = p->var.yoffset = p->yscroll = 0;  /* reset wrap/pan */
   p->var.xoffset = p->var.yoffset = p->yscroll = 0;  /* reset wrap/pan */
 
 
   if (!fb_info->fontname[0] ||
   if (!fb_info->fontname[0] ||
       !findsoftfont(fb_info->fontname, &p->fontwidth, &p->fontheight,
       !findsoftfont(fb_info->fontname, &p->fontwidth, &p->fontheight,
                     &p->fontdata))
                     &p->fontdata))
           getdefaultfont(p->var.xres, p->var.yres, NULL, &p->fontwidth,
           getdefaultfont(p->var.xres, p->var.yres, NULL, &p->fontwidth,
                          &p->fontheight, &p->fontdata);
                          &p->fontheight, &p->fontdata);
 
 
   if (divides(p->ywrapstep, p->fontheight) && divides(p->fontheight, p->var.yres_virtual))
   if (divides(p->ywrapstep, p->fontheight) && divides(p->fontheight, p->var.yres_virtual))
      p->scrollmode = SCROLL_YWRAP;
      p->scrollmode = SCROLL_YWRAP;
   else if (divides(p->ypanstep, p->fontheight) &&
   else if (divides(p->ypanstep, p->fontheight) &&
            p->var.yres_virtual >= p->var.yres+p->fontheight)
            p->var.yres_virtual >= p->var.yres+p->fontheight)
      p->scrollmode = SCROLL_YPAN;
      p->scrollmode = SCROLL_YPAN;
   else if ((p->var.yres_virtual == 512*1024))
   else if ((p->var.yres_virtual == 512*1024))
      p->scrollmode = SCROLL_YWRAP_NOTALIGNED;
      p->scrollmode = SCROLL_YWRAP_NOTALIGNED;
   else
   else
      p->scrollmode = SCROLL_YMOVE;
      p->scrollmode = SCROLL_YMOVE;
 
 
   conp->vc_cols = p->var.xres/p->fontwidth;
   conp->vc_cols = p->var.xres/p->fontwidth;
   conp->vc_rows = p->var.yres/p->fontheight;
   conp->vc_rows = p->var.yres/p->fontheight;
   p->vrows = p->var.yres_virtual/p->fontheight;
   p->vrows = p->var.yres_virtual/p->fontheight;
   conp->vc_can_do_color = p->var.bits_per_pixel != 1;
   conp->vc_can_do_color = p->var.bits_per_pixel != 1;
 
 
#ifdef CONFIG_FBCON_MONO
#ifdef CONFIG_FBCON_MONO
   if (p->var.bits_per_pixel == 1) {
   if (p->var.bits_per_pixel == 1) {
      if (p->line_length)
      if (p->line_length)
         p->next_line = p->line_length;
         p->next_line = p->line_length;
      else
      else
         p->next_line = p->var.xres_virtual/8;
         p->next_line = p->var.xres_virtual/8;
      p->next_plane = 0;
      p->next_plane = 0;
      p->dispsw = &dispsw_mono;
      p->dispsw = &dispsw_mono;
   } else
   } else
#endif /* CONFIG_FBCON_MONO */
#endif /* CONFIG_FBCON_MONO */
#ifdef CONFIG_FBCON_IPLAN2
#ifdef CONFIG_FBCON_IPLAN2
   if (p->type == FB_TYPE_INTERLEAVED_PLANES && p->type_aux == 2) {
   if (p->type == FB_TYPE_INTERLEAVED_PLANES && p->type_aux == 2) {
      p->next_line = p->var.xres_virtual*p->var.bits_per_pixel>>3;
      p->next_line = p->var.xres_virtual*p->var.bits_per_pixel>>3;
      p->next_plane = 0;
      p->next_plane = 0;
#ifdef CONFIG_FBCON_2PLANE
#ifdef CONFIG_FBCON_2PLANE
      if (p->var.bits_per_pixel == 2)
      if (p->var.bits_per_pixel == 2)
         p->dispsw = &dispsw_2_plane;
         p->dispsw = &dispsw_2_plane;
      else
      else
#endif /* CONFIG_FBCON_2PLANE */
#endif /* CONFIG_FBCON_2PLANE */
#ifdef CONFIG_FBCON_4PLANE
#ifdef CONFIG_FBCON_4PLANE
      if (p->var.bits_per_pixel == 4)
      if (p->var.bits_per_pixel == 4)
         p->dispsw = &dispsw_4_plane;
         p->dispsw = &dispsw_4_plane;
      else
      else
#endif /* CONFIG_FBCON_4PLANE */
#endif /* CONFIG_FBCON_4PLANE */
#ifdef CONFIG_FBCON_8PLANE
#ifdef CONFIG_FBCON_8PLANE
      if (p->var.bits_per_pixel == 8)
      if (p->var.bits_per_pixel == 8)
         p->dispsw = &dispsw_8_plane;
         p->dispsw = &dispsw_8_plane;
      else
      else
#endif /* CONFIG_FBCON_8PLANE */
#endif /* CONFIG_FBCON_8PLANE */
      goto fail;
      goto fail;
   } else
   } else
#endif /* CONFIG_FBCON_IPLAN2 */
#endif /* CONFIG_FBCON_IPLAN2 */
#ifdef CONFIG_FBCON_ILBM
#ifdef CONFIG_FBCON_ILBM
   if (p->type == FB_TYPE_INTERLEAVED_PLANES && p->type_aux != 2) {
   if (p->type == FB_TYPE_INTERLEAVED_PLANES && p->type_aux != 2) {
      if (p->line_length) {
      if (p->line_length) {
         p->next_line = p->line_length*p->var.bits_per_pixel;
         p->next_line = p->line_length*p->var.bits_per_pixel;
         p->next_plane = p->line_length;
         p->next_plane = p->line_length;
      } else {
      } else {
         p->next_line = p->type_aux;
         p->next_line = p->type_aux;
         p->next_plane = p->type_aux/p->var.bits_per_pixel;
         p->next_plane = p->type_aux/p->var.bits_per_pixel;
      }
      }
      p->dispsw = &dispsw_ilbm;
      p->dispsw = &dispsw_ilbm;
   } else
   } else
#endif /* CONFIG_FBCON_ILBM */
#endif /* CONFIG_FBCON_ILBM */
#ifdef CONFIG_FBCON_PLANES
#ifdef CONFIG_FBCON_PLANES
   if (p->type == FB_TYPE_PLANES) {
   if (p->type == FB_TYPE_PLANES) {
      if (p->line_length)
      if (p->line_length)
         p->next_line = p->line_length;
         p->next_line = p->line_length;
      else
      else
         p->next_line = p->var.xres_virtual>>3;
         p->next_line = p->var.xres_virtual>>3;
      p->next_plane = p->var.yres_virtual*p->next_line;
      p->next_plane = p->var.yres_virtual*p->next_line;
      p->dispsw = &dispsw_plan;
      p->dispsw = &dispsw_plan;
   } else
   } else
#endif /* CONFIG_FBCON_PLANES */
#endif /* CONFIG_FBCON_PLANES */
#ifdef CONFIG_FBCON_PACKED
#ifdef CONFIG_FBCON_PACKED
   if (p->type == FB_TYPE_PACKED_PIXELS) {
   if (p->type == FB_TYPE_PACKED_PIXELS) {
      p->next_line = p->var.xres_virtual*p->var.bits_per_pixel>>3;
      p->next_line = p->var.xres_virtual*p->var.bits_per_pixel>>3;
      p->next_plane = 0;
      p->next_plane = 0;
#ifdef CONFIG_FBCON_CYBER
#ifdef CONFIG_FBCON_CYBER
      if (p->var.accel == FB_ACCEL_CYBERVISION)
      if (p->var.accel == FB_ACCEL_CYBERVISION)
         p->dispsw = &dispsw_cyber;
         p->dispsw = &dispsw_cyber;
      else
      else
#endif /* CONFIG_FBCON_CYBER */
#endif /* CONFIG_FBCON_CYBER */
#ifdef CONFIG_FBCON_8PACKED
#ifdef CONFIG_FBCON_8PACKED
      if (p->var.bits_per_pixel == 8)
      if (p->var.bits_per_pixel == 8)
         p->dispsw = &dispsw_8_packed;
         p->dispsw = &dispsw_8_packed;
      else
      else
#endif /* CONFIG_FBCON_8PACKED */
#endif /* CONFIG_FBCON_8PACKED */
#ifdef CONFIG_FBCON_8PACKED_NOTALIGNED
#ifdef CONFIG_FBCON_8PACKED_NOTALIGNED
      if (p->var.bits_per_pixel == 8)
      if (p->var.bits_per_pixel == 8)
         p->dispsw = &dispsw_8_packed;
         p->dispsw = &dispsw_8_packed;
      else
      else
#endif /* CONFIG_FBCON_8PACKED_NOTALIGNED */
#endif /* CONFIG_FBCON_8PACKED_NOTALIGNED */
#ifdef CONFIG_FBCON_16PACKED
#ifdef CONFIG_FBCON_16PACKED
      if (p->var.bits_per_pixel == 16)
      if (p->var.bits_per_pixel == 16)
         p->dispsw = &dispsw_16_packed;
         p->dispsw = &dispsw_16_packed;
      else
      else
#endif /* CONFIG_FBCON_16PACKED */
#endif /* CONFIG_FBCON_16PACKED */
#ifdef CONFIG_FBCON_24PACKED
#ifdef CONFIG_FBCON_24PACKED
      if (p->var.bits_per_pixel == 24)
      if (p->var.bits_per_pixel == 24)
         p->dispsw = &dispsw_24_packed;
         p->dispsw = &dispsw_24_packed;
      else
      else
#endif /* CONFIG_FBCON_24PACKED */
#endif /* CONFIG_FBCON_24PACKED */
#ifdef CONFIG_FBCON_32PACKED
#ifdef CONFIG_FBCON_32PACKED
      if (p->var.bits_per_pixel == 32)
      if (p->var.bits_per_pixel == 32)
         p->dispsw = &dispsw_32_packed;
         p->dispsw = &dispsw_32_packed;
      else
      else
#endif /* CONFIG_FBCON_32PACKED */
#endif /* CONFIG_FBCON_32PACKED */
      goto fail;
      goto fail;
   } else
   } else
#endif /* CONFIG_FBCON_PACKED */
#endif /* CONFIG_FBCON_PACKED */
   {
   {
fail:
fail:
#ifdef CONFIG_FBCON_MONO
#ifdef CONFIG_FBCON_MONO
      printk("fbcon_setup: type %d (aux %d) not supported, trying mono\n",
      printk("fbcon_setup: type %d (aux %d) not supported, trying mono\n",
             p->type, p->type_aux);
             p->type, p->type_aux);
      if (p->line_length)
      if (p->line_length)
         p->next_line = p->line_length;
         p->next_line = p->line_length;
      else
      else
         p->next_line = p->var.xres_virtual/8;
         p->next_line = p->var.xres_virtual/8;
      p->next_plane = 0;
      p->next_plane = 0;
      p->var.bits_per_pixel = 1;
      p->var.bits_per_pixel = 1;
      p->dispsw = &dispsw_mono;
      p->dispsw = &dispsw_mono;
#else /* CONFIG_FBCON_MONO */
#else /* CONFIG_FBCON_MONO */
      panic("fbcon_setup: no default driver");
      panic("fbcon_setup: no default driver");
#endif /* CONFIG_FBCON_MONO */
#endif /* CONFIG_FBCON_MONO */
   }
   }
 
 
   if ((p->dispsw != &dispsw_mono) && (p->fontwidth != 8))
   if ((p->dispsw != &dispsw_mono) && (p->fontwidth != 8))
      panic("fbcon_setup: No support for fontwidth != 8 on non-monochrome targets");
      panic("fbcon_setup: No support for fontwidth != 8 on non-monochrome targets");
 
 
   if ((p->dispsw == &dispsw_mono) && (p->fontwidth != 8) && (p->fontwidth != 4) )
   if ((p->dispsw == &dispsw_mono) && (p->fontwidth != 8) && (p->fontwidth != 4) )
      panic("fbcon_setup: No support for fontwidth != 8/4 on monochrome targets");
      panic("fbcon_setup: No support for fontwidth != 8/4 on monochrome targets");
 
 
   if (setcol) {
   if (setcol) {
      p->fgcol = p->var.bits_per_pixel > 2 ? 7 : (1<<p->var.bits_per_pixel)-1;
      p->fgcol = p->var.bits_per_pixel > 2 ? 7 : (1<<p->var.bits_per_pixel)-1;
      p->bgcol = 0;
      p->bgcol = 0;
   }
   }
 
 
   if (cls)
   if (cls)
      vc_resize_con(conp->vc_rows, conp->vc_cols, con);
      vc_resize_con(conp->vc_rows, conp->vc_cols, con);
}
}
 
 
 
 
/* ================================================================= */
/* ================================================================= */
/*                      Utility Assembler Functions                  */
/*                      Utility Assembler Functions                  */
/* ================================================================= */
/* ================================================================= */
 
 
 
 
/* ====================================================================== */
/* ====================================================================== */
 
 
/* Those of a delicate disposition might like to skip the next couple of
/* Those of a delicate disposition might like to skip the next couple of
 * pages.
 * pages.
 *
 *
 * These functions are drop in replacements for memmove and
 * These functions are drop in replacements for memmove and
 * memset(_, 0, _). However their five instances add at least a kilobyte
 * memset(_, 0, _). However their five instances add at least a kilobyte
 * to the object file. You have been warned.
 * to the object file. You have been warned.
 *
 *
 * Not a great fan of assembler for the sake of it, but I think
 * Not a great fan of assembler for the sake of it, but I think
 * that these routines are at least 10 times faster than their C
 * that these routines are at least 10 times faster than their C
 * equivalents for large blits, and that's important to the lowest level of
 * equivalents for large blits, and that's important to the lowest level of
 * a graphics driver. Question is whether some scheme with the blitter
 * a graphics driver. Question is whether some scheme with the blitter
 * would be faster. I suspect not for simple text system - not much
 * would be faster. I suspect not for simple text system - not much
 * asynchrony.
 * asynchrony.
 *
 *
 * Code is very simple, just gruesome expansion. Basic strategy is to
 * Code is very simple, just gruesome expansion. Basic strategy is to
 * increase data moved/cleared at each step to 16 bytes to reduce
 * increase data moved/cleared at each step to 16 bytes to reduce
 * instruction per data move overhead. movem might be faster still
 * instruction per data move overhead. movem might be faster still
 * For more than 15 bytes, we try to align the write direction on a
 * For more than 15 bytes, we try to align the write direction on a
 * longword boundary to get maximum speed. This is even more gruesome.
 * longword boundary to get maximum speed. This is even more gruesome.
 * Unaligned read/write used requires 68020+ - think this is a problem?
 * Unaligned read/write used requires 68020+ - think this is a problem?
 *
 *
 * Sorry!
 * Sorry!
 */
 */
 
 
 
 
/* ++roman: I've optimized Robert's original versions in some minor
/* ++roman: I've optimized Robert's original versions in some minor
 * aspects, e.g. moveq instead of movel, let gcc choose the registers,
 * aspects, e.g. moveq instead of movel, let gcc choose the registers,
 * use movem in some places...
 * use movem in some places...
 * For other modes than 1 plane, lots of more such assembler functions
 * For other modes than 1 plane, lots of more such assembler functions
 * were needed (e.g. the ones using movep or expanding color values).
 * were needed (e.g. the ones using movep or expanding color values).
 */
 */
 
 
/* ++andreas: more optimizations:
/* ++andreas: more optimizations:
   subl #65536,d0 replaced by clrw d0; subql #1,d0 for dbcc
   subl #65536,d0 replaced by clrw d0; subql #1,d0 for dbcc
   addal is faster than addaw
   addal is faster than addaw
   movep is rather expensive compared to ordinary move's
   movep is rather expensive compared to ordinary move's
   some functions rewritten in C for clarity, no speed loss */
   some functions rewritten in C for clarity, no speed loss */
 
 
static __inline__ void *mymemclear_small(void *s, size_t count)
static __inline__ void *mymemclear_small(void *s, size_t count)
{
{
   unsigned char *sb = (unsigned char *)s;
   unsigned char *sb = (unsigned char *)s;
 
 
   while (count--)
   while (count--)
        *(sb++) = 0;
        *(sb++) = 0;
 
 
   return(0);
   return(0);
}
}
 
 
 
 
static __inline__ void *mymemclear(void *s, size_t count)
static __inline__ void *mymemclear(void *s, size_t count)
{
{
   unsigned char *sb = (unsigned char *)s;
   unsigned char *sb = (unsigned char *)s;
 
 
   while (count--)
   while (count--)
        *(sb++) = 0;
        *(sb++) = 0;
 
 
   return(0);
   return(0);
}
}
 
 
 
 
static __inline__ void *mymemset(void *s, size_t count)
static __inline__ void *mymemset(void *s, size_t count)
{
{
   unsigned char *sb = (unsigned char *)s;
   unsigned char *sb = (unsigned char *)s;
 
 
   while (count--)
   while (count--)
        *(sb++) = 0;
        *(sb++) = 0;
 
 
   return(0);
   return(0);
}
}
 
 
 
 
static __inline__ void *mymemmove(void *d, void *s, size_t count)
static __inline__ void *mymemmove(void *d, void *s, size_t count)
{
{
   unsigned char *db = (unsigned char *)d;
   unsigned char *db = (unsigned char *)d;
   unsigned char *sb = (unsigned char *)s;
   unsigned char *sb = (unsigned char *)s;
 
 
   while (count--)
   while (count--)
        *(db++) = *(sb++);
        *(db++) = *(sb++);
 
 
   return(0);
   return(0);
}
}
 
 
 
 
static __inline__ void *mymemmove_notaligned(void *d, void *s, size_t count)
static __inline__ void *mymemmove_notaligned(void *d, void *s, size_t count)
{
{
   unsigned long dst = (unsigned long)d, src = (unsigned long)s;
   unsigned long dst = (unsigned long)d, src = (unsigned long)s;
   unsigned char *db = (unsigned char *)d;
   unsigned char *db = (unsigned char *)d;
   unsigned char *sb = (unsigned char *)s;
   unsigned char *sb = (unsigned char *)s;
 
 
   while (count--) {
   while (count--) {
        *db = *sb;
        *db = *sb;
        db = (unsigned char *)CRT_WRAP(dst, ++dst);
        db = (unsigned char *)CRT_WRAP(dst, ++dst);
        sb = (unsigned char *)CRT_WRAP(src, ++src);
        sb = (unsigned char *)CRT_WRAP(src, ++src);
    }
    }
 
 
   return(0);
   return(0);
}
}
 
 
 
 
/* ++andreas: Simple and fast version of memmove, assumes size is
/* ++andreas: Simple and fast version of memmove, assumes size is
   divisible by 16, suitable for moving the whole screen bitplane */
   divisible by 16, suitable for moving the whole screen bitplane */
static __inline__ void fast_memmove(char *dst, char *src, size_t size)
static __inline__ void fast_memmove(char *dst, char *src, size_t size)
{
{
   unsigned long tmp;
   unsigned long tmp;
 
 
   __asm__ __volatile__
   __asm__ __volatile__
     ("1:"
     ("1:"
      "  l.sfgui  %2,0\n"
      "  l.sfgui  %2,0\n"
      "  l.bnf    1f\n"
      "  l.bnf    1f\n"
      "  l.addi   %2,%2,-16\n"
      "  l.addi   %2,%2,-16\n"
      "  l.lwz    %3,0(%0)\n"
      "  l.lwz    %3,0(%0)\n"
      "  l.sw     0(%1)%3\n"
      "  l.sw     0(%1)%3\n"
      "  l.lwz    %3,4(%0)\n"
      "  l.lwz    %3,4(%0)\n"
      "  l.sw     4(%1)%3\n"
      "  l.sw     4(%1)%3\n"
      "  l.lwz    %3,8(%0)\n"
      "  l.lwz    %3,8(%0)\n"
      "  l.sw     8(%1)%3\n"
      "  l.sw     8(%1)%3\n"
      "  l.lwz    %3,12(%0)\n"
      "  l.lwz    %3,12(%0)\n"
      "  l.j      1b\n"
      "  l.j      1b\n"
      "  l.sw     12(%1)%3\n"
      "  l.sw     12(%1)%3\n"
      "1:"
      "1:"
      : "=r" (src), "=r" (dst), "=r" (size), "=r" (tmp)
      : "=r" (src), "=r" (dst), "=r" (size), "=r" (tmp)
      : "r" (src), "r" (dst), "r" (size), "r" (tmp)
      : "r" (src), "r" (dst), "r" (size), "r" (tmp)
      : "memory");
      : "memory");
}
}
 
 
 
 
/* Sets the bytes in the visible column at d, height h, to the value
/* Sets the bytes in the visible column at d, height h, to the value
 * val for a 4 plane screen. The the bis of the color in 'color' are
 * val for a 4 plane screen. The the bis of the color in 'color' are
 * moved (8 times) to the respective bytes. This means:
 * moved (8 times) to the respective bytes. This means:
 *
 *
 * for(h times; d += bpr)
 * for(h times; d += bpr)
 *   *d     = (color & 1) ? 0xff : 0;
 *   *d     = (color & 1) ? 0xff : 0;
 *   *(d+2) = (color & 2) ? 0xff : 0;
 *   *(d+2) = (color & 2) ? 0xff : 0;
 *   *(d+4) = (color & 4) ? 0xff : 0;
 *   *(d+4) = (color & 4) ? 0xff : 0;
 *   *(d+6) = (color & 8) ? 0xff : 0;
 *   *(d+6) = (color & 8) ? 0xff : 0;
 */
 */
 
 
static __inline__ void memclear_4p_col(void *d, size_t h, u_long val, int bpr)
static __inline__ void memclear_4p_col(void *d, size_t h, u_long val, int bpr)
{
{
#if 0
#if 0
        __asm__ __volatile__
        __asm__ __volatile__
                ("1: movepl %4,%0@(0)\n\t"
                ("1: movepl %4,%0@(0)\n\t"
                  "addal  %5,%0\n\t"
                  "addal  %5,%0\n\t"
                  "dbra   %1,1b"
                  "dbra   %1,1b"
                  : "=a" (d), "=d" (h)
                  : "=a" (d), "=d" (h)
                  : "0" (d), "1" (h - 1), "d" (val), "r" (bpr)
                  : "0" (d), "1" (h - 1), "d" (val), "r" (bpr)
                );
                );
#endif
#endif
}
}
 
 
/* Sets a 4 plane region from 'd', length 'count' bytes, to the color
/* Sets a 4 plane region from 'd', length 'count' bytes, to the color
 * in val1/val2. 'd' has to be an even address and count must be divisible
 * in val1/val2. 'd' has to be an even address and count must be divisible
 * by 8, because only whole words and all planes are accessed. I.e.:
 * by 8, because only whole words and all planes are accessed. I.e.:
 *
 *
 * for(count/8 times)
 * for(count/8 times)
 *   *d     = *(d+1) = (color & 1) ? 0xff : 0;
 *   *d     = *(d+1) = (color & 1) ? 0xff : 0;
 *   *(d+2) = *(d+3) = (color & 2) ? 0xff : 0;
 *   *(d+2) = *(d+3) = (color & 2) ? 0xff : 0;
 *   *(d+4) = *(d+5) = (color & 4) ? 0xff : 0;
 *   *(d+4) = *(d+5) = (color & 4) ? 0xff : 0;
 *   *(d+6) = *(d+7) = (color & 8) ? 0xff : 0;
 *   *(d+6) = *(d+7) = (color & 8) ? 0xff : 0;
 */
 */
 
 
static __inline__ void memset_even_4p(void *d, size_t count, u_long val1,
static __inline__ void memset_even_4p(void *d, size_t count, u_long val1,
                                      u_long val2)
                                      u_long val2)
{
{
  u_long *dd = d;
  u_long *dd = d;
 
 
  count /= 8;
  count /= 8;
  while (count--)
  while (count--)
    {
    {
      *dd++ = val1;
      *dd++ = val1;
      *dd++ = val2;
      *dd++ = val2;
    }
    }
}
}
 
 
/* Copies a 4 plane column from 's', height 'h', to 'd'. */
/* Copies a 4 plane column from 's', height 'h', to 'd'. */
 
 
static __inline__ void memmove_4p_col (void *d, void *s, int h, int bpr)
static __inline__ void memmove_4p_col (void *d, void *s, int h, int bpr)
{
{
  u_char *dd = d, *ss = s;
  u_char *dd = d, *ss = s;
 
 
  while (h--)
  while (h--)
    {
    {
      dd[0] = ss[0];
      dd[0] = ss[0];
      dd[2] = ss[2];
      dd[2] = ss[2];
      dd[4] = ss[4];
      dd[4] = ss[4];
      dd[6] = ss[6];
      dd[6] = ss[6];
      dd += bpr;
      dd += bpr;
      ss += bpr;
      ss += bpr;
    }
    }
}
}
 
 
 
 
/* This expands a 4 bit color into a long for movepl (4 plane) operations. */
/* This expands a 4 bit color into a long for movepl (4 plane) operations. */
 
 
static __inline__ u_long expand4l(u_char c)
static __inline__ u_long expand4l(u_char c)
{
{
#if 0
#if 0
        u_long  rv;
        u_long  rv;
 
 
        __asm__ __volatile__
        __asm__ __volatile__
                ("lsrb   #1,%2\n\t"
                ("lsrb   #1,%2\n\t"
                  "scs   %0\n\t"
                  "scs   %0\n\t"
                  "lsll  #8,%0\n\t"
                  "lsll  #8,%0\n\t"
                  "lsrb  #1,%2\n\t"
                  "lsrb  #1,%2\n\t"
                  "scs   %0\n\t"
                  "scs   %0\n\t"
                  "lsll  #8,%0\n\t"
                  "lsll  #8,%0\n\t"
                  "lsrb  #1,%2\n\t"
                  "lsrb  #1,%2\n\t"
                  "scs   %0\n\t"
                  "scs   %0\n\t"
                  "lsll  #8,%0\n\t"
                  "lsll  #8,%0\n\t"
                  "lsrb  #1,%2\n\t"
                  "lsrb  #1,%2\n\t"
                  "scs   %0\n\t"
                  "scs   %0\n\t"
                  : "=&d" (rv), "=d" (c)
                  : "=&d" (rv), "=d" (c)
                  : "1" (c)
                  : "1" (c)
                );
                );
        return(rv);
        return(rv);
#endif
#endif
        return 0;
        return 0;
}
}
 
 
/* This expands a 4 bit color into two longs for two movel operations
/* This expands a 4 bit color into two longs for two movel operations
 * (4 planes).
 * (4 planes).
 */
 */
 
 
static __inline__ void expand4dl(u_char c, u_long *ret1, u_long *ret2)
static __inline__ void expand4dl(u_char c, u_long *ret1, u_long *ret2)
{
{
#if 0
#if 0
        u_long  rv1, rv2;
        u_long  rv1, rv2;
 
 
        __asm__ __volatile__
        __asm__ __volatile__
                ("lsrb   #1,%3\n\t"
                ("lsrb   #1,%3\n\t"
                  "scs   %0\n\t"
                  "scs   %0\n\t"
                  "extw  %0\n\t"
                  "extw  %0\n\t"
                  "swap  %0\n\t"
                  "swap  %0\n\t"
                  "lsrb  #1,%3\n\t"
                  "lsrb  #1,%3\n\t"
                  "scs   %0\n\t"
                  "scs   %0\n\t"
                  "extw  %0\n\t"
                  "extw  %0\n\t"
                  "lsrb  #1,%3\n\t"
                  "lsrb  #1,%3\n\t"
                  "scs   %1\n\t"
                  "scs   %1\n\t"
                  "extw  %1\n\t"
                  "extw  %1\n\t"
                  "swap  %1\n\t"
                  "swap  %1\n\t"
                  "lsrb  #1,%3\n\t"
                  "lsrb  #1,%3\n\t"
                  "scs   %1\n\t"
                  "scs   %1\n\t"
                  "extw  %1"
                  "extw  %1"
                  : "=&d" (rv1), "=&d" (rv2), "=d" (c)
                  : "=&d" (rv1), "=&d" (rv2), "=d" (c)
                  : "2" (c)
                  : "2" (c)
                );
                );
        *ret1 = rv1;
        *ret1 = rv1;
        *ret2 = rv2;
        *ret2 = rv2;
#endif
#endif
}
}
 
 
 
 
/* This duplicates a byte 4 times into a long. */
/* This duplicates a byte 4 times into a long. */
 
 
static __inline__ u_long dup4l(u_char c)
static __inline__ u_long dup4l(u_char c)
{
{
#if 0
#if 0
        ushort  tmp;
        ushort  tmp;
        ulong   rv;
        ulong   rv;
 
 
        __asm__ __volatile__
        __asm__ __volatile__
                ("moveb  %2,%0\n\t"
                ("moveb  %2,%0\n\t"
                  "lslw   #8,%0\n\t"
                  "lslw   #8,%0\n\t"
                  "moveb  %2,%0\n\t"
                  "moveb  %2,%0\n\t"
                  "movew  %0,%1\n\t"
                  "movew  %0,%1\n\t"
                  "swap   %0\n\t"
                  "swap   %0\n\t"
                  "movew  %1,%0"
                  "movew  %1,%0"
                  : "=&d" (rv), "=d" (tmp)
                  : "=&d" (rv), "=d" (tmp)
                  : "d" (c)
                  : "d" (c)
                );
                );
 
 
        return(rv);
        return(rv);
#endif
#endif
        return 0;
        return 0;
}
}
 
 
 
 
/* Sets the bytes in the visible column at d, height h, to the value
/* Sets the bytes in the visible column at d, height h, to the value
 * val1,val2 for a 8 plane screen. The the bis of the color in 'color' are
 * val1,val2 for a 8 plane screen. The the bis of the color in 'color' are
 * moved (8 times) to the respective bytes. This means:
 * moved (8 times) to the respective bytes. This means:
 *
 *
 * for(h times; d += bpr)
 * for(h times; d += bpr)
 *   *d      = (color & 1) ? 0xff : 0;
 *   *d      = (color & 1) ? 0xff : 0;
 *   *(d+2)  = (color & 2) ? 0xff : 0;
 *   *(d+2)  = (color & 2) ? 0xff : 0;
 *   *(d+4)  = (color & 4) ? 0xff : 0;
 *   *(d+4)  = (color & 4) ? 0xff : 0;
 *   *(d+6)  = (color & 8) ? 0xff : 0;
 *   *(d+6)  = (color & 8) ? 0xff : 0;
 *   *(d+8)  = (color & 16) ? 0xff : 0;
 *   *(d+8)  = (color & 16) ? 0xff : 0;
 *   *(d+10) = (color & 32) ? 0xff : 0;
 *   *(d+10) = (color & 32) ? 0xff : 0;
 *   *(d+12) = (color & 64) ? 0xff : 0;
 *   *(d+12) = (color & 64) ? 0xff : 0;
 *   *(d+14) = (color & 128) ? 0xff : 0;
 *   *(d+14) = (color & 128) ? 0xff : 0;
 */
 */
 
 
static __inline__ void memclear_8p_col(void *d, size_t h, u_long val1,
static __inline__ void memclear_8p_col(void *d, size_t h, u_long val1,
                                       u_long val2, int bpr)
                                       u_long val2, int bpr)
{
{
#if 0
#if 0
        __asm__ __volatile__
        __asm__ __volatile__
                ("1: movepl %4,%0@(0)\n\t"
                ("1: movepl %4,%0@(0)\n\t"
              "movepl %5,%0@(8)\n\t"
              "movepl %5,%0@(8)\n\t"
                  "addal  %6,%0\n\t"
                  "addal  %6,%0\n\t"
                  "dbra   %1,1b"
                  "dbra   %1,1b"
                  : "=a" (d), "=d" (h)
                  : "=a" (d), "=d" (h)
                  : "0" (d), "1" (h - 1), "d" (val1), "d" (val2), "r" (bpr)
                  : "0" (d), "1" (h - 1), "d" (val1), "d" (val2), "r" (bpr)
                );
                );
#endif
#endif
}
}
 
 
/* Sets a 8 plane region from 'd', length 'count' bytes, to the color
/* Sets a 8 plane region from 'd', length 'count' bytes, to the color
 * val1..val4. 'd' has to be an even address and count must be divisible
 * val1..val4. 'd' has to be an even address and count must be divisible
 * by 16, because only whole words and all planes are accessed. I.e.:
 * by 16, because only whole words and all planes are accessed. I.e.:
 *
 *
 * for(count/16 times)
 * for(count/16 times)
 *   *d      = *(d+1)  = (color & 1) ? 0xff : 0;
 *   *d      = *(d+1)  = (color & 1) ? 0xff : 0;
 *   *(d+2)  = *(d+3)  = (color & 2) ? 0xff : 0;
 *   *(d+2)  = *(d+3)  = (color & 2) ? 0xff : 0;
 *   *(d+4)  = *(d+5)  = (color & 4) ? 0xff : 0;
 *   *(d+4)  = *(d+5)  = (color & 4) ? 0xff : 0;
 *   *(d+6)  = *(d+7)  = (color & 8) ? 0xff : 0;
 *   *(d+6)  = *(d+7)  = (color & 8) ? 0xff : 0;
 *   *(d+8)  = *(d+9)  = (color & 16) ? 0xff : 0;
 *   *(d+8)  = *(d+9)  = (color & 16) ? 0xff : 0;
 *   *(d+10) = *(d+11) = (color & 32) ? 0xff : 0;
 *   *(d+10) = *(d+11) = (color & 32) ? 0xff : 0;
 *   *(d+12) = *(d+13) = (color & 64) ? 0xff : 0;
 *   *(d+12) = *(d+13) = (color & 64) ? 0xff : 0;
 *   *(d+14) = *(d+15) = (color & 128) ? 0xff : 0;
 *   *(d+14) = *(d+15) = (color & 128) ? 0xff : 0;
 */
 */
 
 
static __inline__ void memset_even_8p(void *d, size_t count, u_long val1,
static __inline__ void memset_even_8p(void *d, size_t count, u_long val1,
                                      u_long val2, u_long val3, u_long val4)
                                      u_long val2, u_long val3, u_long val4)
{
{
  u_long *dd = d;
  u_long *dd = d;
 
 
  count /= 16;
  count /= 16;
  while (count--)
  while (count--)
    {
    {
      *dd++ = val1;
      *dd++ = val1;
      *dd++ = val2;
      *dd++ = val2;
      *dd++ = val3;
      *dd++ = val3;
      *dd++ = val4;
      *dd++ = val4;
    }
    }
}
}
 
 
/* Copies a 8 plane column from 's', height 'h', to 'd'. */
/* Copies a 8 plane column from 's', height 'h', to 'd'. */
 
 
static __inline__ void memmove_8p_col (void *d, void *s, int h, int bpr)
static __inline__ void memmove_8p_col (void *d, void *s, int h, int bpr)
{
{
  u_char *dd = d, *ss = s;
  u_char *dd = d, *ss = s;
 
 
  while (h--)
  while (h--)
    {
    {
      dd[0] = ss[0];
      dd[0] = ss[0];
      dd[2] = ss[2];
      dd[2] = ss[2];
      dd[4] = ss[4];
      dd[4] = ss[4];
      dd[6] = ss[6];
      dd[6] = ss[6];
      dd[8] = ss[8];
      dd[8] = ss[8];
      dd[10] = ss[10];
      dd[10] = ss[10];
      dd[12] = ss[12];
      dd[12] = ss[12];
      dd[14] = ss[14];
      dd[14] = ss[14];
      dd += bpr;
      dd += bpr;
      ss += bpr;
      ss += bpr;
    }
    }
}
}
 
 
 
 
/* This expands a 8 bit color into two longs for two movepl (8 plane)
/* This expands a 8 bit color into two longs for two movepl (8 plane)
 * operations.
 * operations.
 */
 */
 
 
static __inline__ void expand8dl(u_char c, u_long *ret1, u_long *ret2)
static __inline__ void expand8dl(u_char c, u_long *ret1, u_long *ret2)
{
{
#if 0
#if 0
        u_long  rv1, rv2;
        u_long  rv1, rv2;
 
 
        __asm__ __volatile__
        __asm__ __volatile__
                ("lsrb   #1,%3\n\t"
                ("lsrb   #1,%3\n\t"
                  "scs   %0\n\t"
                  "scs   %0\n\t"
                  "lsll  #8,%0\n\t"
                  "lsll  #8,%0\n\t"
                  "lsrb  #1,%3\n\t"
                  "lsrb  #1,%3\n\t"
                  "scs   %0\n\t"
                  "scs   %0\n\t"
                  "lsll  #8,%0\n\t"
                  "lsll  #8,%0\n\t"
                  "lsrb  #1,%3\n\t"
                  "lsrb  #1,%3\n\t"
                  "scs   %0\n\t"
                  "scs   %0\n\t"
                  "lsll  #8,%0\n\t"
                  "lsll  #8,%0\n\t"
                  "lsrb  #1,%3\n\t"
                  "lsrb  #1,%3\n\t"
                  "scs   %0\n\t"
                  "scs   %0\n\t"
                  "lsrb  #1,%3\n\t"
                  "lsrb  #1,%3\n\t"
                  "scs   %1\n\t"
                  "scs   %1\n\t"
                  "lsll  #8,%1\n\t"
                  "lsll  #8,%1\n\t"
                  "lsrb  #1,%3\n\t"
                  "lsrb  #1,%3\n\t"
                  "scs   %1\n\t"
                  "scs   %1\n\t"
                  "lsll  #8,%1\n\t"
                  "lsll  #8,%1\n\t"
                  "lsrb  #1,%3\n\t"
                  "lsrb  #1,%3\n\t"
                  "scs   %1\n\t"
                  "scs   %1\n\t"
                  "lsll  #8,%1\n\t"
                  "lsll  #8,%1\n\t"
                  "lsrb  #1,%3\n\t"
                  "lsrb  #1,%3\n\t"
                  "scs   %1"
                  "scs   %1"
                  : "=&d" (rv1), "=&d" (rv2),"=d" (c)
                  : "=&d" (rv1), "=&d" (rv2),"=d" (c)
                  : "2" (c)
                  : "2" (c)
                );
                );
 
 
        *ret1 = rv1;
        *ret1 = rv1;
        *ret2 = rv2;
        *ret2 = rv2;
#endif
#endif
}
}
 
 
/* This expands a 8 bit color into four longs for four movel operations
/* This expands a 8 bit color into four longs for four movel operations
 * (8 planes).
 * (8 planes).
 */
 */
 
 
/* ++andreas: use macro to avoid taking address of return values */
/* ++andreas: use macro to avoid taking address of return values */
#if 0
#if 0
#define expand8ql(c, rv1, rv2, rv3, rv4) \
#define expand8ql(c, rv1, rv2, rv3, rv4) \
do {    u_char tmp = c;                                         \
do {    u_char tmp = c;                                         \
        __asm__ __volatile__                                    \
        __asm__ __volatile__                                    \
                ("lsrb   #1,%5\n\t"                             \
                ("lsrb   #1,%5\n\t"                             \
                  "scs   %0\n\t"                                \
                  "scs   %0\n\t"                                \
                  "extw  %0\n\t"                                \
                  "extw  %0\n\t"                                \
                  "swap  %0\n\t"                                \
                  "swap  %0\n\t"                                \
                  "lsrb  #1,%5\n\t"                             \
                  "lsrb  #1,%5\n\t"                             \
                  "scs   %0\n\t"                                \
                  "scs   %0\n\t"                                \
                  "extw  %0\n\t"                                \
                  "extw  %0\n\t"                                \
                  "lsrb  #1,%5\n\t"                             \
                  "lsrb  #1,%5\n\t"                             \
                  "scs   %1\n\t"                                \
                  "scs   %1\n\t"                                \
                  "extw  %1\n\t"                                \
                  "extw  %1\n\t"                                \
                  "swap  %1\n\t"                                \
                  "swap  %1\n\t"                                \
                  "lsrb  #1,%5\n\t"                             \
                  "lsrb  #1,%5\n\t"                             \
                  "scs   %1\n\t"                                \
                  "scs   %1\n\t"                                \
                  "extw  %1\n\t"                                \
                  "extw  %1\n\t"                                \
                  "lsrb  #1,%5\n\t"                             \
                  "lsrb  #1,%5\n\t"                             \
                  "scs   %2\n\t"                                \
                  "scs   %2\n\t"                                \
                  "extw  %2\n\t"                                \
                  "extw  %2\n\t"                                \
                  "swap  %2\n\t"                                \
                  "swap  %2\n\t"                                \
                  "lsrb  #1,%5\n\t"                             \
                  "lsrb  #1,%5\n\t"                             \
                  "scs   %2\n\t"                                \
                  "scs   %2\n\t"                                \
                  "extw  %2\n\t"                                \
                  "extw  %2\n\t"                                \
                  "lsrb  #1,%5\n\t"                             \
                  "lsrb  #1,%5\n\t"                             \
                  "scs   %3\n\t"                                \
                  "scs   %3\n\t"                                \
                  "extw  %3\n\t"                                \
                  "extw  %3\n\t"                                \
                  "swap  %3\n\t"                                \
                  "swap  %3\n\t"                                \
                  "lsrb  #1,%5\n\t"                             \
                  "lsrb  #1,%5\n\t"                             \
                  "scs   %3\n\t"                                \
                  "scs   %3\n\t"                                \
                  "extw  %3"                                    \
                  "extw  %3"                                    \
                  : "=&d" (rv1), "=&d" (rv2), "=&d" (rv3),      \
                  : "=&d" (rv1), "=&d" (rv2), "=&d" (rv3),      \
                    "=&d" (rv4), "=d" (tmp)                     \
                    "=&d" (rv4), "=d" (tmp)                     \
                  : "4" (tmp)                                   \
                  : "4" (tmp)                                   \
                );                                              \
                );                                              \
} while (0)
} while (0)
#endif
#endif
 
 
 
 
/* Sets the bytes in the visible column at d, height h, to the value
/* Sets the bytes in the visible column at d, height h, to the value
 * val for a 2 plane screen. The the bis of the color in 'color' are
 * val for a 2 plane screen. The the bis of the color in 'color' are
 * moved (8 times) to the respective bytes. This means:
 * moved (8 times) to the respective bytes. This means:
 *
 *
 * for(h times; d += bpr)
 * for(h times; d += bpr)
 *   *d     = (color & 1) ? 0xff : 0;
 *   *d     = (color & 1) ? 0xff : 0;
 *   *(d+2) = (color & 2) ? 0xff : 0;
 *   *(d+2) = (color & 2) ? 0xff : 0;
 */
 */
 
 
static __inline__ void memclear_2p_col(void *d, size_t h, u_short val, int bpr)
static __inline__ void memclear_2p_col(void *d, size_t h, u_short val, int bpr)
{
{
#if 0
#if 0
        __asm__ __volatile__
        __asm__ __volatile__
                ("1: movepw %4,%0@(0)\n\t"
                ("1: movepw %4,%0@(0)\n\t"
                  "addal  %5,%0\n\t"
                  "addal  %5,%0\n\t"
                  "dbra   %1,1b"
                  "dbra   %1,1b"
                  : "=a" (d), "=d" (h)
                  : "=a" (d), "=d" (h)
                  : "0" (d), "1" (h - 1), "d" (val), "r" (bpr)
                  : "0" (d), "1" (h - 1), "d" (val), "r" (bpr)
                );
                );
#endif
#endif
}
}
 
 
/* Sets a 2 plane region from 'd', length 'count' bytes, to the color
/* Sets a 2 plane region from 'd', length 'count' bytes, to the color
 * in val1. 'd' has to be an even address and count must be divisible
 * in val1. 'd' has to be an even address and count must be divisible
 * by 8, because only whole words and all planes are accessed. I.e.:
 * by 8, because only whole words and all planes are accessed. I.e.:
 *
 *
 * for(count/4 times)
 * for(count/4 times)
 *   *d     = *(d+1) = (color & 1) ? 0xff : 0;
 *   *d     = *(d+1) = (color & 1) ? 0xff : 0;
 *   *(d+2) = *(d+3) = (color & 2) ? 0xff : 0;
 *   *(d+2) = *(d+3) = (color & 2) ? 0xff : 0;
 */
 */
 
 
static __inline__ void memset_even_2p(void *d, size_t count, u_long val)
static __inline__ void memset_even_2p(void *d, size_t count, u_long val)
{
{
  u_long *dd = d;
  u_long *dd = d;
 
 
  count /= 4;
  count /= 4;
  while (count--)
  while (count--)
    *dd++ = val;
    *dd++ = val;
}
}
 
 
/* Copies a 2 plane column from 's', height 'h', to 'd'. */
/* Copies a 2 plane column from 's', height 'h', to 'd'. */
 
 
static __inline__ void memmove_2p_col (void *d, void *s, int h, int bpr)
static __inline__ void memmove_2p_col (void *d, void *s, int h, int bpr)
{
{
  u_char *dd = d, *ss = s;
  u_char *dd = d, *ss = s;
 
 
  while (h--)
  while (h--)
    {
    {
      dd[0] = ss[0];
      dd[0] = ss[0];
      dd[2] = ss[2];
      dd[2] = ss[2];
      dd += bpr;
      dd += bpr;
      ss += bpr;
      ss += bpr;
    }
    }
}
}
 
 
 
 
/* This expands a 2 bit color into a short for movepw (2 plane) operations. */
/* This expands a 2 bit color into a short for movepw (2 plane) operations. */
 
 
static __inline__ u_short expand2w(u_char c)
static __inline__ u_short expand2w(u_char c)
{
{
#if 0
#if 0
        u_short rv;
        u_short rv;
 
 
        __asm__ __volatile__
        __asm__ __volatile__
                ("lsrb   #1,%2\n\t"
                ("lsrb   #1,%2\n\t"
                  "scs   %0\n\t"
                  "scs   %0\n\t"
                  "lsll  #8,%0\n\t"
                  "lsll  #8,%0\n\t"
                  "lsrb  #1,%2\n\t"
                  "lsrb  #1,%2\n\t"
                  "scs   %0\n\t"
                  "scs   %0\n\t"
                  : "=&d" (rv), "=d" (c)
                  : "=&d" (rv), "=d" (c)
                  : "1" (c)
                  : "1" (c)
                );
                );
        return(rv);
        return(rv);
#endif
#endif
        return 0;
        return 0;
}
}
 
 
/* This expands a 2 bit color into one long for a movel operation
/* This expands a 2 bit color into one long for a movel operation
 * (2 planes).
 * (2 planes).
 */
 */
 
 
static __inline__ u_long expand2l(u_char c)
static __inline__ u_long expand2l(u_char c)
{
{
#if 0
#if 0
        u_long  rv;
        u_long  rv;
 
 
        __asm__ __volatile__
        __asm__ __volatile__
                ("lsrb   #1,%2\n\t"
                ("lsrb   #1,%2\n\t"
                  "scs   %0\n\t"
                  "scs   %0\n\t"
                  "extw  %0\n\t"
                  "extw  %0\n\t"
                  "swap  %0\n\t"
                  "swap  %0\n\t"
                  "lsrb  #1,%2\n\t"
                  "lsrb  #1,%2\n\t"
                  "scs   %0\n\t"
                  "scs   %0\n\t"
                  "extw  %0\n\t"
                  "extw  %0\n\t"
                  : "=&d" (rv), "=d" (c)
                  : "=&d" (rv), "=d" (c)
                  : "1" (c)
                  : "1" (c)
                );
                );
 
 
        return rv;
        return rv;
#endif
#endif
        return 0;
        return 0;
}
}
 
 
 
 
/* This duplicates a byte 2 times into a short. */
/* This duplicates a byte 2 times into a short. */
 
 
static __inline__ u_short dup2w(u_char c)
static __inline__ u_short dup2w(u_char c)
{
{
#if 0
#if 0
    ushort  rv;
    ushort  rv;
 
 
    __asm__ __volatile__
    __asm__ __volatile__
        ( "moveb  %1,%0\n\t"
        ( "moveb  %1,%0\n\t"
          "lslw   #8,%0\n\t"
          "lslw   #8,%0\n\t"
          "moveb  %1,%0\n\t"
          "moveb  %1,%0\n\t"
          : "=&d" (rv)
          : "=&d" (rv)
          : "d" (c)
          : "d" (c)
        );
        );
 
 
    return( rv );
    return( rv );
#endif
#endif
    return 0;
    return 0;
}
}
 
 
 
 
/* ====================================================================== */
/* ====================================================================== */
 
 
/* fbcon_XXX routines - interface used by the world
/* fbcon_XXX routines - interface used by the world
 *
 *
 * This system is now divided into two levels because of complications
 * This system is now divided into two levels because of complications
 * caused by hardware scrolling. Top level functions:
 * caused by hardware scrolling. Top level functions:
 *
 *
 *    fbcon_bmove(), fbcon_clear(), fbcon_putc()
 *    fbcon_bmove(), fbcon_clear(), fbcon_putc()
 *
 *
 * handles y values in range [0, scr_height-1] that correspond to real
 * handles y values in range [0, scr_height-1] that correspond to real
 * screen positions. y_wrap shift means that first line of bitmap may be
 * screen positions. y_wrap shift means that first line of bitmap may be
 * anywhere on this display. These functions convert lineoffsets to
 * anywhere on this display. These functions convert lineoffsets to
 * bitmap offsets and deal with the wrap-around case by splitting blits.
 * bitmap offsets and deal with the wrap-around case by splitting blits.
 *
 *
 *    fbcon_bmove_physical_8()   -- These functions fast implementations
 *    fbcon_bmove_physical_8()   -- These functions fast implementations
 *    fbcon_clear_physical_8()   -- of original fbcon_XXX fns.
 *    fbcon_clear_physical_8()   -- of original fbcon_XXX fns.
 *    fbcon_putc_physical_8()    -- (fontwidth != 8) may be added later
 *    fbcon_putc_physical_8()    -- (fontwidth != 8) may be added later
 *
 *
 * WARNING:
 * WARNING:
 *
 *
 * At the moment fbcon_putc() cannot blit across vertical wrap boundary
 * At the moment fbcon_putc() cannot blit across vertical wrap boundary
 * Implies should only really hardware scroll in rows. Only reason for
 * Implies should only really hardware scroll in rows. Only reason for
 * restriction is simplicity & efficiency at the moment.
 * restriction is simplicity & efficiency at the moment.
 */
 */
 
 
static __inline__ int real_y(struct display *p, int y)
static __inline__ int real_y(struct display *p, int y)
{
{
   int rows = p->vrows;
   int rows = p->vrows;
 
 
   y += p->yscroll;
   y += p->yscroll;
   return(y < rows ? y : y-rows);
   return(y < rows ? y : y-rows);
}
}
 
 
 
 
static int fbcon_clear(struct vc_data *conp, int sy, int sx, int height,
static int fbcon_clear(struct vc_data *conp, int sy, int sx, int height,
                       int width)
                       int width)
{
{
   int unit = conp->vc_num;
   int unit = conp->vc_num;
   struct display *p = &disp[unit];
   struct display *p = &disp[unit];
   u_int y_break;
   u_int y_break;
 
 
   if (!p->can_soft_blank && console_blanked)
   if (!p->can_soft_blank && console_blanked)
      return(0);
      return(0);
 
 
   if ((sy <= p->cursor_y) && (p->cursor_y < sy+height) &&
   if ((sy <= p->cursor_y) && (p->cursor_y < sy+height) &&
       (sx <= p->cursor_x) && (p->cursor_x < sx+width))
       (sx <= p->cursor_x) && (p->cursor_x < sx+width))
      CURSOR_UNDRAWN();
      CURSOR_UNDRAWN();
 
 
   /* Split blits that cross physical y_wrap boundary */
   /* Split blits that cross physical y_wrap boundary */
 
 
   y_break = p->vrows-p->yscroll;
   y_break = p->vrows-p->yscroll;
   if (sy < y_break && sy+height-1 >= y_break) {
   if (sy < y_break && sy+height-1 >= y_break) {
      u_int b = y_break-sy;
      u_int b = y_break-sy;
      p->dispsw->clear(conp, p, real_y(p, sy), sx, b, width);
      p->dispsw->clear(conp, p, real_y(p, sy), sx, b, width);
      p->dispsw->clear(conp, p, real_y(p, sy+b), sx, height-b, width);
      p->dispsw->clear(conp, p, real_y(p, sy+b), sx, height-b, width);
   } else
   } else
      p->dispsw->clear(conp, p, real_y(p, sy), sx, height, width);
      p->dispsw->clear(conp, p, real_y(p, sy), sx, height, width);
 
 
   return(0);
   return(0);
}
}
 
 
 
 
static int fbcon_putc(struct vc_data *conp, int c, int y, int x)
static int fbcon_putc(struct vc_data *conp, int c, int y, int x)
{
{
   int unit = conp->vc_num;
   int unit = conp->vc_num;
   struct display *p = &disp[unit];
   struct display *p = &disp[unit];
 
 
#ifdef CONFIG_SERIAL_ECHO
#ifdef CONFIG_SERIAL_ECHO
   extern void putc(char);
   extern void putc(char);
   putc(c);
   putc(c);
#endif
#endif
   if (!p->can_soft_blank && console_blanked)
   if (!p->can_soft_blank && console_blanked)
      return(0);
      return(0);
 
 
   if ((p->cursor_x == x) && (p->cursor_y == y))
   if ((p->cursor_x == x) && (p->cursor_y == y))
       CURSOR_UNDRAWN();
       CURSOR_UNDRAWN();
 
 
   p->dispsw->putc(conp, p, c, real_y(p, y), x);
   p->dispsw->putc(conp, p, c, real_y(p, y), x);
 
 
   return(0);
   return(0);
}
}
 
 
 
 
static int fbcon_putcs(struct vc_data *conp, const char *s, int count, int y,
static int fbcon_putcs(struct vc_data *conp, const char *s, int count, int y,
                       int x)
                       int x)
{
{
   int unit = conp->vc_num;
   int unit = conp->vc_num;
   struct display *p = &disp[unit];
   struct display *p = &disp[unit];
 
 
#ifdef CONFIG_SERIAL_ECHO
#ifdef CONFIG_SERIAL_ECHO
   void rs_console_print(const char *p);
   void rs_console_print(const char *p);
   rs_console_print(s);
   rs_console_print(s);
#endif
#endif
 
 
   if (!p->can_soft_blank && console_blanked)
   if (!p->can_soft_blank && console_blanked)
      return(0);
      return(0);
 
 
   if ((p->cursor_y == y) && (x <= p->cursor_x) && (p->cursor_x < x+count))
   if ((p->cursor_y == y) && (x <= p->cursor_x) && (p->cursor_x < x+count))
      CURSOR_UNDRAWN();
      CURSOR_UNDRAWN();
 
 
   p->dispsw->putcs(conp, p, s, count, real_y(p, y), x);
   p->dispsw->putcs(conp, p, s, count, real_y(p, y), x);
 
 
   return(0);
   return(0);
}
}
 
 
 
 
static int fbcon_cursor(struct vc_data *conp, int mode)
static int fbcon_cursor(struct vc_data *conp, int mode)
{
{
   int unit = conp->vc_num;
   int unit = conp->vc_num;
   struct display *p = &disp[unit];
   struct display *p = &disp[unit];
 
 
   if (CURSOR_UNDRAWN ())
   if (CURSOR_UNDRAWN ())
      p->dispsw->rev_char(p, p->cursor_x, real_y(p, p->cursor_y));
      p->dispsw->rev_char(p, p->cursor_x, real_y(p, p->cursor_y));
   p->cursor_x = conp->vc_x;
   p->cursor_x = conp->vc_x;
   p->cursor_y = conp->vc_y;
   p->cursor_y = conp->vc_y;
 
 
   switch (mode) {
   switch (mode) {
      case CM_ERASE:
      case CM_ERASE:
         cursor_on = 0;
         cursor_on = 0;
         break;
         break;
 
 
      case CM_MOVE:
      case CM_MOVE:
      case CM_DRAW:
      case CM_DRAW:
         vbl_cursor_cnt = CURSOR_DRAW_DELAY;
         vbl_cursor_cnt = CURSOR_DRAW_DELAY;
         cursor_on = 1;
         cursor_on = 1;
         break;
         break;
   }
   }
 
 
   return(0);
   return(0);
}
}
 
 
 
 
static void fbcon_vbl_handler(int irq, struct pt_regs *fp, void *dummy)
static void fbcon_vbl_handler(int irq, struct pt_regs *fp, void *dummy)
{
{
   struct display *p;
   struct display *p;
 
 
   if (!cursor_on)
   if (!cursor_on)
      return;
      return;
 
 
   if (vbl_cursor_cnt && --vbl_cursor_cnt == 0) {
   if (vbl_cursor_cnt && --vbl_cursor_cnt == 0) {
      /* Here no check is possible for console changing. The console
      /* Here no check is possible for console changing. The console
       * switching code should set vbl_cursor_cnt to an appropriate value.
       * switching code should set vbl_cursor_cnt to an appropriate value.
       */
       */
      p = &disp[fg_console];
      p = &disp[fg_console];
      p->dispsw->rev_char(p, p->cursor_x, real_y(p, p->cursor_y));
      p->dispsw->rev_char(p, p->cursor_x, real_y(p, p->cursor_y));
      cursor_drawn ^= 1;
      cursor_drawn ^= 1;
      vbl_cursor_cnt = cursor_blink_rate;
      vbl_cursor_cnt = cursor_blink_rate;
   }
   }
}
}
 
 
static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
{
{
   int unit = conp->vc_num;
   int unit = conp->vc_num;
   struct display *p = &disp[unit];
   struct display *p = &disp[unit];
 
 
   if (!p->can_soft_blank && console_blanked)
   if (!p->can_soft_blank && console_blanked)
      return(0);
      return(0);
 
 
   fbcon_cursor(conp, CM_ERASE);
   fbcon_cursor(conp, CM_ERASE);
 
 
   /*
   /*
    * ++Geert: Only use ywrap/ypan if the console is in text mode
    * ++Geert: Only use ywrap/ypan if the console is in text mode
    */
    */
 
 
   switch (dir) {
   switch (dir) {
      case SM_UP:
      case SM_UP:
         if (t == 0 && b == conp->vc_rows &&
         if (t == 0 && b == conp->vc_rows &&
             vt_cons[unit]->vc_mode == KD_TEXT) {
             vt_cons[unit]->vc_mode == KD_TEXT) {
            if (count > conp->vc_rows)             /* Maximum realistic size */
            if (count > conp->vc_rows)             /* Maximum realistic size */
               count = conp->vc_rows;
               count = conp->vc_rows;
            switch (p->scrollmode) {
            switch (p->scrollmode) {
               case SCROLL_YWRAP:
               case SCROLL_YWRAP:
                  p->yscroll += count;
                  p->yscroll += count;
                  if (p->yscroll >= p->vrows) /* Deal with wrap */
                  if (p->yscroll >= p->vrows) /* Deal with wrap */
                     p->yscroll -= p->vrows;
                     p->yscroll -= p->vrows;
                  p->var.xoffset = 0;
                  p->var.xoffset = 0;
                  p->var.yoffset = p->yscroll*p->fontheight;
                  p->var.yoffset = p->yscroll*p->fontheight;
                  p->var.vmode |= FB_VMODE_YWRAP;
                  p->var.vmode |= FB_VMODE_YWRAP;
                  fb_info->updatevar(unit);
                  fb_info->updatevar(unit);
                  break;
                  break;
 
 
               case SCROLL_YPAN:
               case SCROLL_YPAN:
                  p->yscroll += count;
                  p->yscroll += count;
                  if (p->yscroll+conp->vc_rows > p->vrows) {
                  if (p->yscroll+conp->vc_rows > p->vrows) {
                     p->dispsw->bmove(p, p->yscroll, 0, 0, 0, b-count,
                     p->dispsw->bmove(p, p->yscroll, 0, 0, 0, b-count,
                                      conp->vc_cols);
                                      conp->vc_cols);
                     p->yscroll = 0;
                     p->yscroll = 0;
                  }
                  }
                  p->var.xoffset = 0;
                  p->var.xoffset = 0;
                  p->var.yoffset = p->yscroll*p->fontheight;
                  p->var.yoffset = p->yscroll*p->fontheight;
                  p->var.vmode &= ~FB_VMODE_YWRAP;
                  p->var.vmode &= ~FB_VMODE_YWRAP;
                  fb_info->updatevar(unit);
                  fb_info->updatevar(unit);
                  break;
                  break;
 
 
               case SCROLL_YWRAP_NOTALIGNED:
               case SCROLL_YWRAP_NOTALIGNED:
                  p->var.xoffset = 0;
                  p->var.xoffset = 0;
                  p->var.yoffset = (p->var.yoffset + count*p->fontheight*p->var.xres) & (CRT_WRAP_BOUNDARY - 1);
                  p->var.yoffset = (p->var.yoffset + count*p->fontheight*p->var.xres) & (CRT_WRAP_BOUNDARY - 1);
                  p->var.vmode = SCROLL_YWRAP_NOTALIGNED;
                  p->var.vmode = SCROLL_YWRAP_NOTALIGNED;
                  fb_info->updatevar(unit);
                  fb_info->updatevar(unit);
                  break;
                  break;
 
 
               case SCROLL_YMOVE:
               case SCROLL_YMOVE:
                  p->dispsw->bmove(p, count, 0, 0, 0, b-count, conp->vc_cols);
                  p->dispsw->bmove(p, count, 0, 0, 0, b-count, conp->vc_cols);
                  break;
                  break;
            }
            }
         } else
         } else
            fbcon_bmove(conp, t+count, 0, t, 0, b-t-count, conp->vc_cols);
            fbcon_bmove(conp, t+count, 0, t, 0, b-t-count, conp->vc_cols);
         fbcon_clear(conp, b-count, 0, count, conp->vc_cols);
         fbcon_clear(conp, b-count, 0, count, conp->vc_cols);
         break;
         break;
 
 
      case SM_DOWN:
      case SM_DOWN:
         if (t == 0 && b == conp->vc_rows &&
         if (t == 0 && b == conp->vc_rows &&
             vt_cons[unit]->vc_mode == KD_TEXT) {
             vt_cons[unit]->vc_mode == KD_TEXT) {
            if (count > conp->vc_rows)             /* Maximum realistic size */
            if (count > conp->vc_rows)             /* Maximum realistic size */
               count = conp->vc_rows;
               count = conp->vc_rows;
            switch (p->scrollmode) {
            switch (p->scrollmode) {
               case SCROLL_YWRAP:
               case SCROLL_YWRAP:
                  p->yscroll -= count;
                  p->yscroll -= count;
                  if (p->yscroll < 0)              /* Deal with wrap */
                  if (p->yscroll < 0)              /* Deal with wrap */
                     p->yscroll += p->vrows;
                     p->yscroll += p->vrows;
                  p->var.xoffset = 0;
                  p->var.xoffset = 0;
                  p->var.yoffset = p->yscroll*p->fontheight;
                  p->var.yoffset = p->yscroll*p->fontheight;
                  p->var.vmode |= FB_VMODE_YWRAP;
                  p->var.vmode |= FB_VMODE_YWRAP;
                  fb_info->updatevar(unit);
                  fb_info->updatevar(unit);
                  break;
                  break;
 
 
               case SCROLL_YPAN:
               case SCROLL_YPAN:
                  p->yscroll -= count;
                  p->yscroll -= count;
                  if (p->yscroll < 0) {
                  if (p->yscroll < 0) {
                     p->yscroll = p->vrows-conp->vc_rows;
                     p->yscroll = p->vrows-conp->vc_rows;
                     p->dispsw->bmove(p, 0, 0, p->yscroll+count, 0, b-count,
                     p->dispsw->bmove(p, 0, 0, p->yscroll+count, 0, b-count,
                                      conp->vc_cols);
                                      conp->vc_cols);
                  }
                  }
                  p->var.xoffset = 0;
                  p->var.xoffset = 0;
                  p->var.yoffset = p->yscroll*p->fontheight;
                  p->var.yoffset = p->yscroll*p->fontheight;
                  p->var.vmode &= ~FB_VMODE_YWRAP;
                  p->var.vmode &= ~FB_VMODE_YWRAP;
                  fb_info->updatevar(unit);
                  fb_info->updatevar(unit);
                  break;
                  break;
 
 
               case SCROLL_YWRAP_NOTALIGNED:
               case SCROLL_YWRAP_NOTALIGNED:
                  p->var.xoffset = 0;
                  p->var.xoffset = 0;
                  p->var.yoffset = (p->var.yoffset - count*p->fontheight*p->var.xres) & (CRT_WRAP_BOUNDARY - 1);
                  p->var.yoffset = (p->var.yoffset - count*p->fontheight*p->var.xres) & (CRT_WRAP_BOUNDARY - 1);
                  p->var.vmode = SCROLL_YWRAP_NOTALIGNED;
                  p->var.vmode = SCROLL_YWRAP_NOTALIGNED;
                  fb_info->updatevar(unit);
                  fb_info->updatevar(unit);
                  break;
                  break;
 
 
               case SCROLL_YMOVE:
               case SCROLL_YMOVE:
                  p->dispsw->bmove(p, 0, 0, count, 0, b-count, conp->vc_cols);
                  p->dispsw->bmove(p, 0, 0, count, 0, b-count, conp->vc_cols);
                  break;
                  break;
            }
            }
         } else
         } else
            fbcon_bmove(conp, t, 0, t+count, 0, b-t-count, conp->vc_cols);
            fbcon_bmove(conp, t, 0, t+count, 0, b-t-count, conp->vc_cols);
 
 
         /* Fixed bmove() should end Arno's frustration with copying?
         /* Fixed bmove() should end Arno's frustration with copying?
          * Confucius says:
          * Confucius says:
          *    Man who copies in wrong direction, end up with trashed data
          *    Man who copies in wrong direction, end up with trashed data
          */
          */
         fbcon_clear(conp, t, 0, count, conp->vc_cols);
         fbcon_clear(conp, t, 0, count, conp->vc_cols);
         break;
         break;
 
 
      case SM_LEFT:
      case SM_LEFT:
         fbcon_bmove(conp, 0, t+count, 0, t, conp->vc_rows, b-t-count);
         fbcon_bmove(conp, 0, t+count, 0, t, conp->vc_rows, b-t-count);
         fbcon_clear(conp, 0, b-count, conp->vc_rows, count);
         fbcon_clear(conp, 0, b-count, conp->vc_rows, count);
         break;
         break;
 
 
      case SM_RIGHT:
      case SM_RIGHT:
         fbcon_bmove(conp, 0, t, 0, t+count, conp->vc_rows, b-t-count);
         fbcon_bmove(conp, 0, t, 0, t+count, conp->vc_rows, b-t-count);
         fbcon_clear(conp, 0, t, conp->vc_rows, count);
         fbcon_clear(conp, 0, t, conp->vc_rows, count);
         break;
         break;
   }
   }
 
 
   return(0);
   return(0);
}
}
 
 
static int fbcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
static int fbcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
                       int height, int width)
                       int height, int width)
{
{
   int unit = conp->vc_num;
   int unit = conp->vc_num;
   struct display *p = &disp[unit];
   struct display *p = &disp[unit];
 
 
   if (!p->can_soft_blank && console_blanked)
   if (!p->can_soft_blank && console_blanked)
      return(0);
      return(0);
 
 
   if (((sy <= p->cursor_y) && (p->cursor_y < sy+height) &&
   if (((sy <= p->cursor_y) && (p->cursor_y < sy+height) &&
        (sx <= p->cursor_x) && (p->cursor_x < sx+width)) ||
        (sx <= p->cursor_x) && (p->cursor_x < sx+width)) ||
       ((dy <= p->cursor_y) && (p->cursor_y < dy+height) &&
       ((dy <= p->cursor_y) && (p->cursor_y < dy+height) &&
        (dx <= p->cursor_x) && (p->cursor_x < dx+width)))
        (dx <= p->cursor_x) && (p->cursor_x < dx+width)))
      fbcon_cursor(conp, CM_ERASE);
      fbcon_cursor(conp, CM_ERASE);
 
 
   /* Split blits that cross physical y_wrap case.
   /* Split blits that cross physical y_wrap case.
    * Pathological case involves 4 blits, better to use recursive
    * Pathological case involves 4 blits, better to use recursive
    * code rather than unrolled case
    * code rather than unrolled case
    *
    *
    * Recursive invocations don't need to erase the cursor over and
    * Recursive invocations don't need to erase the cursor over and
    * over again, so we use fbcon_bmove_rec()
    * over again, so we use fbcon_bmove_rec()
    */
    */
   fbcon_bmove_rec(p, sy, sx, dy, dx, height, width, p->vrows-p->yscroll);
   fbcon_bmove_rec(p, sy, sx, dy, dx, height, width, p->vrows-p->yscroll);
 
 
   return(0);
   return(0);
}
}
 
 
 
 
static void fbcon_bmove_rec(struct display *p, int sy, int sx, int dy, int dx,
static void fbcon_bmove_rec(struct display *p, int sy, int sx, int dy, int dx,
                            int height, int width, u_int y_break)
                            int height, int width, u_int y_break)
{
{
   u_int b;
   u_int b;
 
 
   if (sy < y_break && sy+height > y_break) {
   if (sy < y_break && sy+height > y_break) {
      b = y_break-sy;
      b = y_break-sy;
      if (dy < sy) {       /* Avoid trashing self */
      if (dy < sy) {       /* Avoid trashing self */
         fbcon_bmove_rec(p, sy, sx, dy, dx, b, width, y_break);
         fbcon_bmove_rec(p, sy, sx, dy, dx, b, width, y_break);
         fbcon_bmove_rec(p, sy+b, sx, dy+b, dx, height-b, width, y_break);
         fbcon_bmove_rec(p, sy+b, sx, dy+b, dx, height-b, width, y_break);
      } else {
      } else {
         fbcon_bmove_rec(p, sy+b, sx, dy+b, dx, height-b, width, y_break);
         fbcon_bmove_rec(p, sy+b, sx, dy+b, dx, height-b, width, y_break);
         fbcon_bmove_rec(p, sy, sx, dy, dx, b, width, y_break);
         fbcon_bmove_rec(p, sy, sx, dy, dx, b, width, y_break);
      }
      }
      return;
      return;
   }
   }
 
 
   if (dy < y_break && dy+height > y_break) {
   if (dy < y_break && dy+height > y_break) {
      b = y_break-dy;
      b = y_break-dy;
      if (dy < sy) {       /* Avoid trashing self */
      if (dy < sy) {       /* Avoid trashing self */
         fbcon_bmove_rec(p, sy, sx, dy, dx, b, width, y_break);
         fbcon_bmove_rec(p, sy, sx, dy, dx, b, width, y_break);
         fbcon_bmove_rec(p, sy+b, sx, dy+b, dx, height-b, width, y_break);
         fbcon_bmove_rec(p, sy+b, sx, dy+b, dx, height-b, width, y_break);
      } else {
      } else {
         fbcon_bmove_rec(p, sy+b, sx, dy+b, dx, height-b, width, y_break);
         fbcon_bmove_rec(p, sy+b, sx, dy+b, dx, height-b, width, y_break);
         fbcon_bmove_rec(p, sy, sx, dy, dx, b, width, y_break);
         fbcon_bmove_rec(p, sy, sx, dy, dx, b, width, y_break);
      }
      }
      return;
      return;
   }
   }
   p->dispsw->bmove(p, real_y(p, sy), sx, real_y(p, dy), dx, height, width);
   p->dispsw->bmove(p, real_y(p, sy), sx, real_y(p, dy), dx, height, width);
}
}
 
 
 
 
static int fbcon_switch(struct vc_data *conp)
static int fbcon_switch(struct vc_data *conp)
{
{
   if (fb_info && fb_info->switch_con)
   if (fb_info && fb_info->switch_con)
      (*fb_info->switch_con)(conp->vc_num);
      (*fb_info->switch_con)(conp->vc_num);
   return(0);
   return(0);
}
}
 
 
 
 
static int fbcon_blank(int blank)
static int fbcon_blank(int blank)
{
{
   struct display *p = &disp[fg_console];
   struct display *p = &disp[fg_console];
 
 
   fbcon_cursor(p->conp, blank ? CM_ERASE : CM_DRAW);
   fbcon_cursor(p->conp, blank ? CM_ERASE : CM_DRAW);
 
 
   if (!p->can_soft_blank) {
   if (!p->can_soft_blank) {
      if (blank) {
      if (blank) {
         if (p->visual == FB_VISUAL_MONO01)
         if (p->visual == FB_VISUAL_MONO01)
             mymemset(p->screen_base, p->var.xres_virtual*p->var.yres_virtual*
             mymemset(p->screen_base, p->var.xres_virtual*p->var.yres_virtual*
                                      p->var.bits_per_pixel>>3);
                                      p->var.bits_per_pixel>>3);
          else
          else
             mymemclear(p->screen_base, p->var.xres_virtual*p->var.yres_virtual*
             mymemclear(p->screen_base, p->var.xres_virtual*p->var.yres_virtual*
                                        p->var.bits_per_pixel>>3);
                                        p->var.bits_per_pixel>>3);
         return(0);
         return(0);
      } else {
      } else {
         /* Tell console.c that it has to restore the screen itself */
         /* Tell console.c that it has to restore the screen itself */
         return(1);
         return(1);
      }
      }
   }
   }
   (*fb_info->blank)(blank);
   (*fb_info->blank)(blank);
   return(0);
   return(0);
}
}
 
 
 
 
static int fbcon_get_font(struct vc_data *conp, int *w, int *h, char *data)
static int fbcon_get_font(struct vc_data *conp, int *w, int *h, char *data)
{
{
        int unit = conp->vc_num;
        int unit = conp->vc_num;
        struct display *p = &disp[unit];
        struct display *p = &disp[unit];
        int i, size, alloc;
        int i, size, alloc;
 
 
        size = (p->fontwidth+7)/8 * p->fontheight * 256;
        size = (p->fontwidth+7)/8 * p->fontheight * 256;
        alloc = (*w+7)/8 * *h * 256;
        alloc = (*w+7)/8 * *h * 256;
        *w = p->fontwidth;
        *w = p->fontwidth;
        *h = p->fontheight;
        *h = p->fontheight;
 
 
        if (alloc < size)
        if (alloc < size)
                /* allocation length not sufficient */
                /* allocation length not sufficient */
                return( -ENAMETOOLONG );
                return( -ENAMETOOLONG );
 
 
        if ((i = verify_area( VERIFY_WRITE, (void *)data, size )))
        if ((i = verify_area( VERIFY_WRITE, (void *)data, size )))
                return i;
                return i;
 
 
        memcpy_tofs( data, p->fontdata, size );
        memcpy_tofs( data, p->fontdata, size );
        return( 0 );
        return( 0 );
}
}
 
 
 
 
#define REFCOUNT(fd)    (((int *)(fd))[-1])
#define REFCOUNT(fd)    (((int *)(fd))[-1])
 
 
static int fbcon_set_font(struct vc_data *conp, int w, int h, char *data)
static int fbcon_set_font(struct vc_data *conp, int w, int h, char *data)
{
{
        int unit = conp->vc_num;
        int unit = conp->vc_num;
        struct display *p = &disp[unit];
        struct display *p = &disp[unit];
        int i, size, userspace = 1, resize;
        int i, size, userspace = 1, resize;
        char *old_data = NULL, *new_data;
        char *old_data = NULL, *new_data;
 
 
        if (w < 0)
        if (w < 0)
                w = p->fontwidth;
                w = p->fontwidth;
        if (h < 0)
        if (h < 0)
                h = p->fontheight;
                h = p->fontheight;
 
 
        printk("Set_font, w=%d, h=%d, data=%s\n", w, h, data);
        printk("Set_font, w=%d, h=%d, data=%s\n", w, h, data);
 
 
        if (w == 0) {
        if (w == 0) {
                /* engage predefined font, name in 'data' */
                /* engage predefined font, name in 'data' */
                char name[MAX_FONT_NAME+1];
                char name[MAX_FONT_NAME+1];
 
 
                if ((i = verify_area( VERIFY_READ, (void *)data, MAX_FONT_NAME )))
                if ((i = verify_area( VERIFY_READ, (void *)data, MAX_FONT_NAME )))
                        return i;
                        return i;
                memcpy_fromfs( name, data, MAX_FONT_NAME );
                memcpy_fromfs( name, data, MAX_FONT_NAME );
                name[sizeof(name)-1] = 0;
                name[sizeof(name)-1] = 0;
 
 
                if (!findsoftfont( name, &w, &h, (u_char **)&data ))
                if (!findsoftfont( name, &w, &h, (u_char **)&data ))
                        return( -ENOENT );
                        return( -ENOENT );
                userspace = 0;
                userspace = 0;
        }
        }
        else if (w == 1) {
        else if (w == 1) {
                /* copy font from some other console in 'h'*/
                /* copy font from some other console in 'h'*/
                struct display *op;
                struct display *op;
 
 
                if (h < 0 || !vc_cons_allocated( h ))
                if (h < 0 || !vc_cons_allocated( h ))
                        return( -ENOTTY );
                        return( -ENOTTY );
                if (h == unit)
                if (h == unit)
                        return( 0 ); /* nothing to do */
                        return( 0 ); /* nothing to do */
                op = &disp[h];
                op = &disp[h];
                if (op->fontdata == p->fontdata)
                if (op->fontdata == p->fontdata)
                        return( 0 ); /* already the same font... */
                        return( 0 ); /* already the same font... */
 
 
                resize = (op->fontwidth != p->fontwidth) ||
                resize = (op->fontwidth != p->fontwidth) ||
                             (op->fontheight != p->fontheight);
                             (op->fontheight != p->fontheight);
                if (p->userfont)
                if (p->userfont)
                        old_data = p->fontdata;
                        old_data = p->fontdata;
                p->fontdata = op->fontdata;
                p->fontdata = op->fontdata;
                w = p->fontwidth = op->fontwidth;
                w = p->fontwidth = op->fontwidth;
                h = p->fontheight = op->fontheight;
                h = p->fontheight = op->fontheight;
                if ((p->userfont = op->userfont))
                if ((p->userfont = op->userfont))
                        REFCOUNT(p->fontdata)++; /* increment usage counter */
                        REFCOUNT(p->fontdata)++; /* increment usage counter */
                goto activate;
                goto activate;
        }
        }
 
 
        if ((p->dispsw != &dispsw_mono) && (w != 8))
        if ((p->dispsw != &dispsw_mono) && (w != 8))
                /* Currently only fontwidth == 8 supported */
                /* Currently only fontwidth == 8 supported */
                return( -ENXIO );
                return( -ENXIO );
        if ((p->dispsw == &dispsw_mono) && (w != 8) && (w != 4))
        if ((p->dispsw == &dispsw_mono) && (w != 8) && (w != 4))
                return( -ENXIO );
                return( -ENXIO );
 
 
        resize = (w != p->fontwidth) || (h != p->fontheight);
        resize = (w != p->fontwidth) || (h != p->fontheight);
        size = (w+7)/8 * h * 256;
        size = (w+7)/8 * h * 256;
 
 
        if (p->userfont)
        if (p->userfont)
                old_data = p->fontdata;
                old_data = p->fontdata;
 
 
        if (userspace) {
        if (userspace) {
                if ((i = verify_area( VERIFY_READ, (void *)data, size )))
                if ((i = verify_area( VERIFY_READ, (void *)data, size )))
                        return i;
                        return i;
                if (!(new_data = kmalloc( sizeof(int)+size, GFP_USER )))
                if (!(new_data = kmalloc( sizeof(int)+size, GFP_USER )))
                        return( -ENOMEM );
                        return( -ENOMEM );
                new_data += sizeof(int);
                new_data += sizeof(int);
                REFCOUNT(new_data) = 1; /* usage counter */
                REFCOUNT(new_data) = 1; /* usage counter */
                memcpy_fromfs( new_data, data, size );
                memcpy_fromfs( new_data, data, size );
                p->fontdata = new_data;
                p->fontdata = new_data;
                p->userfont = 1;
                p->userfont = 1;
        }
        }
        else {
        else {
                p->fontdata = data;
                p->fontdata = data;
                p->userfont = 0;
                p->userfont = 0;
        }
        }
        p->fontwidth = w;
        p->fontwidth = w;
        p->fontheight = h;
        p->fontheight = h;
 
 
  activate:
  activate:
        if (resize) {
        if (resize) {
                p->var.xoffset = p->var.yoffset = p->yscroll = 0;  /* reset wrap/pan */
                p->var.xoffset = p->var.yoffset = p->yscroll = 0;  /* reset wrap/pan */
                if (divides(p->ywrapstep, p->fontheight))
                if (divides(p->ywrapstep, p->fontheight))
                        p->scrollmode = SCROLL_YWRAP;
                        p->scrollmode = SCROLL_YWRAP;
                else if (divides(p->ypanstep, p->fontheight) &&
                else if (divides(p->ypanstep, p->fontheight) &&
                                 p->var.yres_virtual >= p->var.yres+p->fontheight)
                                 p->var.yres_virtual >= p->var.yres+p->fontheight)
                        p->scrollmode = SCROLL_YPAN;
                        p->scrollmode = SCROLL_YPAN;
                else if ((p->var.yres_virtual == 512*1024))
                else if ((p->var.yres_virtual == 512*1024))
                        p->scrollmode = SCROLL_YWRAP_NOTALIGNED;
                        p->scrollmode = SCROLL_YWRAP_NOTALIGNED;
                else
                else
                        p->scrollmode = SCROLL_YMOVE;
                        p->scrollmode = SCROLL_YMOVE;
 
 
                vc_resize_con( p->var.yres/h, p->var.xres/w, unit );
                vc_resize_con( p->var.yres/h, p->var.xres/w, unit );
        }
        }
        else if (unit == fg_console)
        else if (unit == fg_console)
                update_screen( unit );
                update_screen( unit );
 
 
        if (old_data) {
        if (old_data) {
                if (--REFCOUNT(old_data) == 0) {
                if (--REFCOUNT(old_data) == 0) {
                        kfree( old_data - sizeof(int) );
                        kfree( old_data - sizeof(int) );
                }
                }
        }
        }
 
 
        return( 0 );
        return( 0 );
}
}
 
 
 
 
/* ====================================================================== */
/* ====================================================================== */
 
 
/*
/*
 *    Low Level Operations for the various display memory organizations.
 *    Low Level Operations for the various display memory organizations.
 *
 *
 *    Currently only the following organizations are supported here:
 *    Currently only the following organizations are supported here:
 *
 *
 *      - Monochrome
 *      - Monochrome
 *      - Color Interleaved Planes à la Amiga
 *      - Color Interleaved Planes à la Amiga
 *      - Color Normal Planes
 *      - Color Normal Planes
 *      - Color Interleaved Planes à la Atari (2, 4 and 8 planes)
 *      - Color Interleaved Planes à la Atari (2, 4 and 8 planes)
 *      - Color Packed Pixels (8 and 16 bpp)
 *      - Color Packed Pixels (8 and 16 bpp)
 *      - Cybervision Color Packed Pixels (accelerated)
 *      - Cybervision Color Packed Pixels (accelerated)
 */
 */
 
 
#ifdef CONFIG_FBCON_MONO
#ifdef CONFIG_FBCON_MONO
 
 
   /*
   /*
    *    Monochrome
    *    Monochrome
    */
    */
 
 
 
 
static u_char mask4[2] = {0xF0, 0x0F};
static u_char mask4[2] = {0xF0, 0x0F};
 
 
static void bmove_mono(struct display *p, int sy, int sx, int dy, int dx,
static void bmove_mono(struct display *p, int sy, int sx, int dy, int dx,
                       int height, int width)
                       int height, int width)
{
{
   u_char *src, *dest;
   u_char *src, *dest;
   u_int rows;
   u_int rows;
 
 
   if (p->fontwidth == 8) {
   if (p->fontwidth == 8) {
   if (sx == 0 && sy == 0 && width == p->next_line) {
   if (sx == 0 && sy == 0 && width == p->next_line) {
      src = p->screen_base;
      src = p->screen_base;
      dest = p->screen_base+dy*p->fontheight*width;
      dest = p->screen_base+dy*p->fontheight*width;
      mymemmove(dest, src, height*p->fontheight*width);
      mymemmove(dest, src, height*p->fontheight*width);
   } else if (dy <= sy) {
   } else if (dy <= sy) {
      src = p->screen_base+sy*p->fontheight*p->next_line+sx;
      src = p->screen_base+sy*p->fontheight*p->next_line+sx;
      dest = p->screen_base+dy*p->fontheight*p->next_line+dx;
      dest = p->screen_base+dy*p->fontheight*p->next_line+dx;
      for (rows = height*p->fontheight; rows--;) {
      for (rows = height*p->fontheight; rows--;) {
         mymemmove(dest, src, width);
         mymemmove(dest, src, width);
         src += p->next_line;
         src += p->next_line;
         dest += p->next_line;
         dest += p->next_line;
      }
      }
   } else {
   } else {
      src = p->screen_base+((sy+height)*p->fontheight-1)*p->next_line+sx;
      src = p->screen_base+((sy+height)*p->fontheight-1)*p->next_line+sx;
      dest = p->screen_base+((dy+height)*p->fontheight-1)*p->next_line+dx;
      dest = p->screen_base+((dy+height)*p->fontheight-1)*p->next_line+dx;
      for (rows = height*p->fontheight; rows--;) {
      for (rows = height*p->fontheight; rows--;) {
         mymemmove(dest, src, width);
         mymemmove(dest, src, width);
         src -= p->next_line;
         src -= p->next_line;
         dest -= p->next_line;
         dest -= p->next_line;
      }
      }
   }
   }
   } else { /* fw == 4 */
   } else { /* fw == 4 */
   if ((sx == 0) && (sy == 0) && (width == (p->next_line*2))) {
   if ((sx == 0) && (sy == 0) && (width == (p->next_line*2))) {
      src = p->screen_base;
      src = p->screen_base;
      dest = p->screen_base+dy*p->fontheight*p->next_line;
      dest = p->screen_base+dy*p->fontheight*p->next_line;
      mymemmove(dest, src, height*p->fontheight*p->next_line);
      mymemmove(dest, src, height*p->fontheight*p->next_line);
   } else if ((dy <= sy) && ((width & 1) == 0) && ((sx & 1) == 0) && ((dy & 1) == 0)) {
   } else if ((dy <= sy) && ((width & 1) == 0) && ((sx & 1) == 0) && ((dy & 1) == 0)) {
      src = p->screen_base+sy*p->fontheight*p->next_line+(sx>>1);
      src = p->screen_base+sy*p->fontheight*p->next_line+(sx>>1);
      dest = p->screen_base+dy*p->fontheight*p->next_line+(dx>>1);
      dest = p->screen_base+dy*p->fontheight*p->next_line+(dx>>1);
      for (rows = height*p->fontheight; rows--;) {
      for (rows = height*p->fontheight; rows--;) {
         mymemmove(dest, src, width);
         mymemmove(dest, src, width);
         src += p->next_line;
         src += p->next_line;
         dest += p->next_line;
         dest += p->next_line;
      }
      }
   } else {
   } else {
     int x,y,ry;
     int x,y,ry;
     for(x=0;x<width;x++)
     for(x=0;x<width;x++)
       for(y=0;y<height;y++)
       for(y=0;y<height;y++)
         for(ry=0;ry<p->fontheight;ry++) {
         for(ry=0;ry<p->fontheight;ry++) {
           u_char * src = p->screen_base+((sy+y)*p->fontheight+ry)*p->next_line+((sx+x)>>1);
           u_char * src = p->screen_base+((sy+y)*p->fontheight+ry)*p->next_line+((sx+x)>>1);
           u_char * dest = p->screen_base+((dy+y)*p->fontheight+ry)*p->next_line+((dx+x)>>1);
           u_char * dest = p->screen_base+((dy+y)*p->fontheight+ry)*p->next_line+((dx+x)>>1);
           int rs = (sx+x) & 1;
           int rs = (sx+x) & 1;
           int rd = (dx+x) & 1;
           int rd = (dx+x) & 1;
           if (rs == rd)
           if (rs == rd)
                *dest = (*dest & ~mask4[rd]) | (*src & mask4[rs]);
                *dest = (*dest & ~mask4[rd]) | (*src & mask4[rs]);
           else if (rs == 0)
           else if (rs == 0)
                *dest = (*dest & ~mask4[rd]) | ((*src & mask4[rs]) >> 4);
                *dest = (*dest & ~mask4[rd]) | ((*src & mask4[rs]) >> 4);
           else if (rs == 1)
           else if (rs == 1)
                *dest = (*dest & ~mask4[rd]) | ((*src & mask4[rs]) << 4);
                *dest = (*dest & ~mask4[rd]) | ((*src & mask4[rs]) << 4);
         }
         }
   }
   }
   }
   }
 
 
}
}
 
 
 
 
static void clear_mono(struct vc_data *conp, struct display *p, int sy, int sx,
static void clear_mono(struct vc_data *conp, struct display *p, int sy, int sx,
                       int height, int width)
                       int height, int width)
{
{
   u_char *dest;
   u_char *dest;
   u_int rows;
   u_int rows;
 
 
   dest = p->screen_base+sy*p->fontheight*p->next_line+sx;
   dest = p->screen_base+sy*p->fontheight*p->next_line+sx;
 
 
   if (p->fontwidth == 8) {
   if (p->fontwidth == 8) {
   if (sx == 0 && width == p->next_line)
   if (sx == 0 && width == p->next_line)
      if (attr_reverse(p,conp))
      if (attr_reverse(p,conp))
         mymemset(dest, height*p->fontheight*width);
         mymemset(dest, height*p->fontheight*width);
      else
      else
         mymemclear(dest, height*p->fontheight*width);
         mymemclear(dest, height*p->fontheight*width);
   else
   else
      for (rows = height*p->fontheight; rows--; dest += p->next_line)
      for (rows = height*p->fontheight; rows--; dest += p->next_line)
         if (attr_reverse(p,conp))
         if (attr_reverse(p,conp))
            mymemset(dest, width);
            mymemset(dest, width);
         else
         else
            mymemclear_small(dest, width);
            mymemclear_small(dest, width);
   } else { /* fw == 4 */
   } else { /* fw == 4 */
 
 
     if ((sx == 0) && (width == (p->next_line*2)))
     if ((sx == 0) && (width == (p->next_line*2)))
        if (attr_reverse(p,conp))
        if (attr_reverse(p,conp))
           mymemset(dest, height*p->fontheight*p->next_line);
           mymemset(dest, height*p->fontheight*p->next_line);
        else
        else
           mymemclear(dest, height*p->fontheight*p->next_line);
           mymemclear(dest, height*p->fontheight*p->next_line);
     else
     else
     {
     {
     int x,y,ry;
     int x,y,ry;
     for(x=sx;x<sx+width;x++)
     for(x=sx;x<sx+width;x++)
       for(y=sy;y<sy+height;y++)
       for(y=sy;y<sy+height;y++)
         for(ry=0;ry<p->fontheight;ry++)
         for(ry=0;ry<p->fontheight;ry++)
           *(p->screen_base+(y*p->fontheight+ry)*p->next_line+(x>>1)) &= mask4[x & 1 ^ 1];
           *(p->screen_base+(y*p->fontheight+ry)*p->next_line+(x>>1)) &= mask4[x & 1 ^ 1];
     }
     }
  }
  }
}
}
 
 
 
 
static void putc_mono(struct vc_data *conp, struct display *p, int c, int y,
static void putc_mono(struct vc_data *conp, struct display *p, int c, int y,
                      int x)
                      int x)
{
{
   u_char *dest, *cdat;
   u_char *dest, *cdat;
   u_int rows, bold, reverse, underline;
   u_int rows, bold, reverse, underline;
   u_char d;
   u_char d;
 
 
   c &= 0xff;
   c &= 0xff;
 
 
   if (p->fontwidth == 8) {
   if (p->fontwidth == 8) {
 
 
   dest = p->screen_base+y*p->fontheight*p->next_line+x;
   dest = p->screen_base+y*p->fontheight*p->next_line+x;
   cdat = p->fontdata+c*p->fontheight;
   cdat = p->fontdata+c*p->fontheight;
   bold = attr_bold(p,conp);
   bold = attr_bold(p,conp);
   reverse = attr_reverse(p,conp);
   reverse = attr_reverse(p,conp);
   underline = attr_underline(p,conp);
   underline = attr_underline(p,conp);
 
 
   for (rows = p->fontheight; rows--; dest += p->next_line) {
   for (rows = p->fontheight; rows--; dest += p->next_line) {
      d = *cdat++;
      d = *cdat++;
      if (underline && !rows)
      if (underline && !rows)
         d = 0xff;
         d = 0xff;
      else if (bold)
      else if (bold)
         d |= d>>1;
         d |= d>>1;
      if (reverse)
      if (reverse)
         d = ~d;
         d = ~d;
      *dest = d;
      *dest = d;
   }
   }
   } else { /* fontwidth == 4 */
   } else { /* fontwidth == 4 */
   int r = x & 1;
   int r = x & 1;
   dest = p->screen_base+y*p->fontheight*p->next_line+(x>>1);
   dest = p->screen_base+y*p->fontheight*p->next_line+(x>>1);
 
 
   cdat = p->fontdata+c*p->fontheight;
   cdat = p->fontdata+c*p->fontheight;
   bold = attr_bold(p,conp);
   bold = attr_bold(p,conp);
   reverse = attr_reverse(p,conp);
   reverse = attr_reverse(p,conp);
   underline = attr_underline(p,conp);
   underline = attr_underline(p,conp);
 
 
   for (rows = p->fontheight; rows--; dest += p->next_line) {
   for (rows = p->fontheight; rows--; dest += p->next_line) {
      d = *cdat++;
      d = *cdat++;
      if (underline && !rows)
      if (underline && !rows)
         d = 0xff;
         d = 0xff;
      else if (bold)
      else if (bold)
         d |= d>>1;
         d |= d>>1;
      if (reverse)
      if (reverse)
         d = ~d;
         d = ~d;
      *dest = (*dest & ~mask4[r]) | (d & mask4[r]);
      *dest = (*dest & ~mask4[r]) | (d & mask4[r]);
   }
   }
   }
   }
}
}
 
 
 
 
static void putcs_mono(struct vc_data *conp, struct display *p, const char *s,
static void putcs_mono(struct vc_data *conp, struct display *p, const char *s,
                       int count, int y, int x)
                       int count, int y, int x)
{
{
   u_char *dest, *dest0, *cdat;
   u_char *dest, *dest0, *cdat;
   u_int rows, bold, reverse, underline;
   u_int rows, bold, reverse, underline;
   u_char c, d;
   u_char c, d;
 
 
   if (p->fontwidth==8) {
   if (p->fontwidth==8) {
 
 
   dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
   dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
   bold = attr_bold(p,conp);
   bold = attr_bold(p,conp);
   reverse = attr_reverse(p,conp);
   reverse = attr_reverse(p,conp);
   underline = attr_underline(p,conp);
   underline = attr_underline(p,conp);
 
 
   while (count--) {
   while (count--) {
      c = *s++;
      c = *s++;
      dest = dest0++;
      dest = dest0++;
      cdat = p->fontdata+c*p->fontheight;
      cdat = p->fontdata+c*p->fontheight;
      for (rows = p->fontheight; rows--; dest += p->next_line) {
      for (rows = p->fontheight; rows--; dest += p->next_line) {
         d = *cdat++;
         d = *cdat++;
         if (underline && !rows)
         if (underline && !rows)
            d = 0xff;
            d = 0xff;
         else if (bold)
         else if (bold)
            d |= d>>1;
            d |= d>>1;
         if (reverse)
         if (reverse)
            d = ~d;
            d = ~d;
         *dest = d;
         *dest = d;
      }
      }
   }
   }
 
 
   } else {     /* fontwidth == 4 */
   } else {     /* fontwidth == 4 */
 
 
   int r = x & 1;
   int r = x & 1;
   dest0 = p->screen_base+y*p->fontheight*p->next_line+(x>>1);
   dest0 = p->screen_base+y*p->fontheight*p->next_line+(x>>1);
   bold = attr_bold(p,conp);
   bold = attr_bold(p,conp);
   reverse = attr_reverse(p,conp);
   reverse = attr_reverse(p,conp);
   underline = attr_underline(p,conp);
   underline = attr_underline(p,conp);
 
 
   while (count--) {
   while (count--) {
      c = *s++;
      c = *s++;
      dest = dest0;
      dest = dest0;
      cdat = p->fontdata+c*p->fontheight;
      cdat = p->fontdata+c*p->fontheight;
      for (rows = p->fontheight; rows--; dest += p->next_line) {
      for (rows = p->fontheight; rows--; dest += p->next_line) {
         d = *cdat++;
         d = *cdat++;
         if (underline && !rows)
         if (underline && !rows)
            d = 0xff;
            d = 0xff;
         else if (bold)
         else if (bold)
            d |= d>>1;
            d |= d>>1;
         if (reverse)
         if (reverse)
            d = ~d;
            d = ~d;
         *dest = (*dest & ~mask4[r]) | (d & mask4[r]);
         *dest = (*dest & ~mask4[r]) | (d & mask4[r]);
      }
      }
      r ^= 1;
      r ^= 1;
      if (!r)
      if (!r)
        dest0++;
        dest0++;
   }
   }
 
 
   }
   }
}
}
 
 
 
 
static void rev_char_mono(struct display *p, int x, int y)
static void rev_char_mono(struct display *p, int x, int y)
{
{
   u_char *dest;
   u_char *dest;
   u_int rows;
   u_int rows;
 
 
   if (p->fontwidth == 8) {
   if (p->fontwidth == 8) {
     dest = p->screen_base+y*p->fontheight*p->next_line+x;
     dest = p->screen_base+y*p->fontheight*p->next_line+x;
     for (rows = p->fontheight; rows--; dest += p->next_line)
     for (rows = p->fontheight; rows--; dest += p->next_line)
        *dest = ~*dest;
        *dest = ~*dest;
   } else { /* fw == 4 */
   } else { /* fw == 4 */
     dest = p->screen_base+y*p->fontheight*p->next_line+(x>>1);
     dest = p->screen_base+y*p->fontheight*p->next_line+(x>>1);
     for (rows = p->fontheight; rows--; dest += p->next_line)
     for (rows = p->fontheight; rows--; dest += p->next_line)
        *dest ^= mask4[x&1];
        *dest ^= mask4[x&1];
   }
   }
}
}
 
 
#endif /* CONFIG_FBCON_MONO */
#endif /* CONFIG_FBCON_MONO */
 
 
 
 
/* ====================================================================== */
/* ====================================================================== */
 
 
#ifdef CONFIG_FBCON_ILBM
#ifdef CONFIG_FBCON_ILBM
 
 
   /*
   /*
    *    Color Interleaved Planes
    *    Color Interleaved Planes
    *
    *
    *    This code heavily relies on the fact that
    *    This code heavily relies on the fact that
    *
    *
    *       next_line == interleave == next_plane*bits_per_pixel
    *       next_line == interleave == next_plane*bits_per_pixel
    *
    *
    *    But maybe it can be merged with the code for normal bitplanes without
    *    But maybe it can be merged with the code for normal bitplanes without
    *    much performance loss?
    *    much performance loss?
    */
    */
 
 
static void bmove_ilbm(struct display *p, int sy, int sx, int dy, int dx,
static void bmove_ilbm(struct display *p, int sy, int sx, int dy, int dx,
                       int height, int width)
                       int height, int width)
{
{
   if (sx == 0 && sy == 0 && width == p->next_plane)
   if (sx == 0 && sy == 0 && width == p->next_plane)
      mymemmove(p->screen_base+dy*p->fontheight*p->next_line, p->screen_base,
      mymemmove(p->screen_base+dy*p->fontheight*p->next_line, p->screen_base,
                height*p->fontheight*p->next_line);
                height*p->fontheight*p->next_line);
   else {
   else {
      u_char *src, *dest;
      u_char *src, *dest;
      u_int i;
      u_int i;
 
 
      if (dy <= sy) {
      if (dy <= sy) {
         src = p->screen_base+sy*p->fontheight*p->next_line+sx;
         src = p->screen_base+sy*p->fontheight*p->next_line+sx;
         dest = p->screen_base+dy*p->fontheight*p->next_line+dx;
         dest = p->screen_base+dy*p->fontheight*p->next_line+dx;
         for (i = p->var.bits_per_pixel*height*p->fontheight; i--;) {
         for (i = p->var.bits_per_pixel*height*p->fontheight; i--;) {
            mymemmove(dest, src, width);
            mymemmove(dest, src, width);
            src += p->next_plane;
            src += p->next_plane;
            dest += p->next_plane;
            dest += p->next_plane;
         }
         }
      } else {
      } else {
         src = p->screen_base+(sy+height)*p->fontheight*p->next_line+sx;
         src = p->screen_base+(sy+height)*p->fontheight*p->next_line+sx;
         dest = p->screen_base+(dy+height)*p->fontheight*p->next_line+dx;
         dest = p->screen_base+(dy+height)*p->fontheight*p->next_line+dx;
         for (i = p->var.bits_per_pixel*height*p->fontheight; i--;) {
         for (i = p->var.bits_per_pixel*height*p->fontheight; i--;) {
            src -= p->next_plane;
            src -= p->next_plane;
            dest -= p->next_plane;
            dest -= p->next_plane;
            mymemmove(dest, src, width);
            mymemmove(dest, src, width);
         }
         }
      }
      }
   }
   }
}
}
 
 
 
 
static void clear_ilbm(struct vc_data *conp, struct display *p, int sy, int sx,
static void clear_ilbm(struct vc_data *conp, struct display *p, int sy, int sx,
                       int height, int width)
                       int height, int width)
{
{
   u_char *dest;
   u_char *dest;
   u_int i, rows;
   u_int i, rows;
   int bg, bg0;
   int bg, bg0;
 
 
   dest = p->screen_base+sy*p->fontheight*p->next_line+sx;
   dest = p->screen_base+sy*p->fontheight*p->next_line+sx;
 
 
   bg0 = attr_bgcol_ec(p,conp);
   bg0 = attr_bgcol_ec(p,conp);
   for (rows = height*p->fontheight; rows--;) {
   for (rows = height*p->fontheight; rows--;) {
      bg = bg0;
      bg = bg0;
      for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) {
      for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) {
         if (bg & 1)
         if (bg & 1)
            mymemset(dest, width);
            mymemset(dest, width);
         else
         else
            mymemclear(dest, width);
            mymemclear(dest, width);
         bg >>= 1;
         bg >>= 1;
      }
      }
   }
   }
}
}
 
 
 
 
static void putc_ilbm(struct vc_data *conp, struct display *p, int c, int y,
static void putc_ilbm(struct vc_data *conp, struct display *p, int c, int y,
                      int x)
                      int x)
{
{
   u_char *dest, *cdat;
   u_char *dest, *cdat;
   u_int rows, i;
   u_int rows, i;
   u_char d;
   u_char d;
   int fg0, bg0, fg, bg;
   int fg0, bg0, fg, bg;
 
 
   c &= 0xff;
   c &= 0xff;
 
 
   dest = p->screen_base+y*p->fontheight*p->next_line+x;
   dest = p->screen_base+y*p->fontheight*p->next_line+x;
   cdat = p->fontdata+c*p->fontheight;
   cdat = p->fontdata+c*p->fontheight;
   fg0 = attr_fgcol(p,conp);
   fg0 = attr_fgcol(p,conp);
   bg0 = attr_bgcol(p,conp);
   bg0 = attr_bgcol(p,conp);
 
 
   for (rows = p->fontheight; rows--;) {
   for (rows = p->fontheight; rows--;) {
      d = *cdat++;
      d = *cdat++;
      fg = fg0;
      fg = fg0;
      bg = bg0;
      bg = bg0;
      for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) {
      for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) {
         if (bg & 1)
         if (bg & 1)
            if (fg & 1)
            if (fg & 1)
               *dest = 0xff;
               *dest = 0xff;
            else
            else
               *dest = ~d;
               *dest = ~d;
         else
         else
            if (fg & 1)
            if (fg & 1)
               *dest = d;
               *dest = d;
            else
            else
               *dest = 0x00;
               *dest = 0x00;
         bg >>= 1;
         bg >>= 1;
         fg >>= 1;
         fg >>= 1;
      }
      }
   }
   }
}
}
 
 
 
 
/*
/*
 *    I split the console character loop in two parts:
 *    I split the console character loop in two parts:
 *
 *
 *      - slow version: this blits one character at a time
 *      - slow version: this blits one character at a time
 *
 *
 *      - fast version: this blits 4 characters at a time at a longword aligned
 *      - fast version: this blits 4 characters at a time at a longword aligned
 *                      address, to reduce the number of expensive Chip RAM
 *                      address, to reduce the number of expensive Chip RAM
 *                      accesses.
 *                      accesses.
 *
 *
 *    Experiments on my A4000/040 revealed that this makes a console switch on a
 *    Experiments on my A4000/040 revealed that this makes a console switch on a
 *    640x400 screen with 256 colors about 3 times faster.
 *    640x400 screen with 256 colors about 3 times faster.
 *
 *
 *                                                                Geert
 *                                                                Geert
 */
 */
 
 
static void putcs_ilbm(struct vc_data *conp, struct display *p, const char *s,
static void putcs_ilbm(struct vc_data *conp, struct display *p, const char *s,
                       int count, int y, int x)
                       int count, int y, int x)
{
{
   u_char *dest0, *dest, *cdat1, *cdat2, *cdat3, *cdat4;
   u_char *dest0, *dest, *cdat1, *cdat2, *cdat3, *cdat4;
   u_int rows, i;
   u_int rows, i;
   u_char c1, c2, c3, c4;
   u_char c1, c2, c3, c4;
   u_long d;
   u_long d;
   int fg0, bg0, fg, bg;
   int fg0, bg0, fg, bg;
 
 
   dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
   dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
   fg0 = attr_fgcol(p,conp);
   fg0 = attr_fgcol(p,conp);
   bg0 = attr_bgcol(p,conp);
   bg0 = attr_bgcol(p,conp);
 
 
   while (count--)
   while (count--)
      if (x&3 || count < 3) {   /* Slow version */
      if (x&3 || count < 3) {   /* Slow version */
         c1 = *s++;
         c1 = *s++;
         dest = dest0++;
         dest = dest0++;
         x++;
         x++;
 
 
         cdat1 = p->fontdata+c1*p->fontheight;
         cdat1 = p->fontdata+c1*p->fontheight;
         for (rows = p->fontheight; rows--;) {
         for (rows = p->fontheight; rows--;) {
            d = *cdat1++;
            d = *cdat1++;
            fg = fg0;
            fg = fg0;
            bg = bg0;
            bg = bg0;
            for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) {
            for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) {
               if (bg & 1)
               if (bg & 1)
                  if (fg & 1)
                  if (fg & 1)
                     *dest = 0xff;
                     *dest = 0xff;
                  else
                  else
                     *dest = ~d;
                     *dest = ~d;
               else
               else
                  if (fg & 1)
                  if (fg & 1)
                     *dest = d;
                     *dest = d;
                  else
                  else
                     *dest = 0x00;
                     *dest = 0x00;
               bg >>= 1;
               bg >>= 1;
               fg >>= 1;
               fg >>= 1;
            }
            }
         }
         }
      } else {                      /* Fast version */
      } else {                      /* Fast version */
         c1 = s[0];
         c1 = s[0];
         c2 = s[1];
         c2 = s[1];
         c3 = s[2];
         c3 = s[2];
         c4 = s[3];
         c4 = s[3];
 
 
         dest = dest0;
         dest = dest0;
         cdat1 = p->fontdata+c1*p->fontheight;
         cdat1 = p->fontdata+c1*p->fontheight;
         cdat2 = p->fontdata+c2*p->fontheight;
         cdat2 = p->fontdata+c2*p->fontheight;
         cdat3 = p->fontdata+c3*p->fontheight;
         cdat3 = p->fontdata+c3*p->fontheight;
         cdat4 = p->fontdata+c4*p->fontheight;
         cdat4 = p->fontdata+c4*p->fontheight;
         for (rows = p->fontheight; rows--;) {
         for (rows = p->fontheight; rows--;) {
            d = *cdat1++<<24 | *cdat2++<<16 | *cdat3++<<8 | *cdat4++;
            d = *cdat1++<<24 | *cdat2++<<16 | *cdat3++<<8 | *cdat4++;
            fg = fg0;
            fg = fg0;
            bg = bg0;
            bg = bg0;
            for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) {
            for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) {
               if (bg & 1)
               if (bg & 1)
                  if (fg & 1)
                  if (fg & 1)
                     *(u_long *)dest = 0xffffffff;
                     *(u_long *)dest = 0xffffffff;
                  else
                  else
                     *(u_long *)dest = ~d;
                     *(u_long *)dest = ~d;
               else
               else
                  if (fg & 1)
                  if (fg & 1)
                     *(u_long *)dest = d;
                     *(u_long *)dest = d;
                  else
                  else
                     *(u_long *)dest = 0x00000000;
                     *(u_long *)dest = 0x00000000;
               bg >>= 1;
               bg >>= 1;
               fg >>= 1;
               fg >>= 1;
            }
            }
         }
         }
         s += 4;
         s += 4;
         dest0 += 4;
         dest0 += 4;
         x += 4;
         x += 4;
         count -= 3;
         count -= 3;
      }
      }
}
}
 
 
 
 
static void rev_char_ilbm(struct display *p, int x, int y)
static void rev_char_ilbm(struct display *p, int x, int y)
{
{
   u_char *dest, *dest0;
   u_char *dest, *dest0;
   u_int rows, i;
   u_int rows, i;
   int mask;
   int mask;
 
 
   dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
   dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
   mask = p->fgcol ^ p->bgcol;
   mask = p->fgcol ^ p->bgcol;
 
 
   /*
   /*
    *    This should really obey the individual character's
    *    This should really obey the individual character's
    *    background and foreground colors instead of simply
    *    background and foreground colors instead of simply
    *    inverting.
    *    inverting.
    */
    */
 
 
   for (i = p->var.bits_per_pixel; i--; dest0 += p->next_plane) {
   for (i = p->var.bits_per_pixel; i--; dest0 += p->next_plane) {
      if (mask & 1) {
      if (mask & 1) {
         dest = dest0;
         dest = dest0;
         for (rows = p->fontheight; rows--; dest += p->next_line)
         for (rows = p->fontheight; rows--; dest += p->next_line)
            *dest = ~*dest;
            *dest = ~*dest;
      }
      }
      mask >>= 1;
      mask >>= 1;
   }
   }
}
}
 
 
#endif /* CONFIG_FBCON_ILBM */
#endif /* CONFIG_FBCON_ILBM */
 
 
 
 
/* ====================================================================== */
/* ====================================================================== */
 
 
#ifdef CONFIG_FBCON_PLANES
#ifdef CONFIG_FBCON_PLANES
 
 
   /*
   /*
    *    Color Planes
    *    Color Planes
    */
    */
 
 
static void bmove_plan(struct display *p, int sy, int sx, int dy, int dx,
static void bmove_plan(struct display *p, int sy, int sx, int dy, int dx,
                       int height, int width)
                       int height, int width)
{
{
   u_char *src, *dest, *src0, *dest0;
   u_char *src, *dest, *src0, *dest0;
   u_int i, rows;
   u_int i, rows;
 
 
   if (sx == 0 && sy == 0 && width == p->next_line) {
   if (sx == 0 && sy == 0 && width == p->next_line) {
      src = p->screen_base;
      src = p->screen_base;
      dest = p->screen_base+dy*p->fontheight*width;
      dest = p->screen_base+dy*p->fontheight*width;
      for (i = p->var.bits_per_pixel; i--;) {
      for (i = p->var.bits_per_pixel; i--;) {
         mymemmove(dest, src, height*p->fontheight*width);
         mymemmove(dest, src, height*p->fontheight*width);
         src += p->next_plane;
         src += p->next_plane;
         dest += p->next_plane;
         dest += p->next_plane;
      }
      }
   } else if (dy <= sy) {
   } else if (dy <= sy) {
      src0 = p->screen_base+sy*p->fontheight*p->next_line+sx;
      src0 = p->screen_base+sy*p->fontheight*p->next_line+sx;
      dest0 = p->screen_base+dy*p->fontheight*p->next_line+dx;
      dest0 = p->screen_base+dy*p->fontheight*p->next_line+dx;
      for (i = p->var.bits_per_pixel; i--;) {
      for (i = p->var.bits_per_pixel; i--;) {
         src = src0;
         src = src0;
         dest = dest0;
         dest = dest0;
         for (rows = height*p->fontheight; rows--;) {
         for (rows = height*p->fontheight; rows--;) {
            mymemmove(dest, src, width);
            mymemmove(dest, src, width);
            src += p->next_line;
            src += p->next_line;
            dest += p->next_line;
            dest += p->next_line;
         }
         }
         src0 += p->next_plane;
         src0 += p->next_plane;
         dest0 += p->next_plane;
         dest0 += p->next_plane;
      }
      }
   } else {
   } else {
      src0 = p->screen_base+(sy+height)*p->fontheight*p->next_line+sx;
      src0 = p->screen_base+(sy+height)*p->fontheight*p->next_line+sx;
      dest0 = p->screen_base+(dy+height)*p->fontheight*p->next_line+dx;
      dest0 = p->screen_base+(dy+height)*p->fontheight*p->next_line+dx;
      for (i = p->var.bits_per_pixel; i--;) {
      for (i = p->var.bits_per_pixel; i--;) {
         src = src0;
         src = src0;
         dest = dest0;
         dest = dest0;
         for (rows = height*p->fontheight; rows--;) {
         for (rows = height*p->fontheight; rows--;) {
            src -= p->next_line;
            src -= p->next_line;
            dest -= p->next_line;
            dest -= p->next_line;
            mymemmove(dest, src, width);
            mymemmove(dest, src, width);
         }
         }
         src0 += p->next_plane;
         src0 += p->next_plane;
         dest0 += p->next_plane;
         dest0 += p->next_plane;
      }
      }
   }
   }
}
}
 
 
 
 
static void clear_plan(struct vc_data *conp, struct display *p, int sy, int sx,
static void clear_plan(struct vc_data *conp, struct display *p, int sy, int sx,
                       int height, int width)
                       int height, int width)
{
{
   u_char *dest, *dest0;
   u_char *dest, *dest0;
   u_int i, rows;
   u_int i, rows;
   int bg;
   int bg;
 
 
   dest0 = p->screen_base+sy*p->fontheight*p->next_line+sx;
   dest0 = p->screen_base+sy*p->fontheight*p->next_line+sx;
 
 
   bg = attr_bgcol_ec(p,conp);
   bg = attr_bgcol_ec(p,conp);
   for (i = p->var.bits_per_pixel; i--; dest0 += p->next_plane) {
   for (i = p->var.bits_per_pixel; i--; dest0 += p->next_plane) {
      dest = dest0;
      dest = dest0;
      for (rows = height*p->fontheight; rows--; dest += p->next_line)
      for (rows = height*p->fontheight; rows--; dest += p->next_line)
         if (bg & 1)
         if (bg & 1)
            mymemset(dest, width);
            mymemset(dest, width);
         else
         else
            mymemclear(dest, width);
            mymemclear(dest, width);
      bg >>= 1;
      bg >>= 1;
   }
   }
}
}
 
 
 
 
static void putc_plan(struct vc_data *conp, struct display *p, int c, int y,
static void putc_plan(struct vc_data *conp, struct display *p, int c, int y,
                      int x)
                      int x)
{
{
   u_char *dest, *dest0, *cdat, *cdat0;
   u_char *dest, *dest0, *cdat, *cdat0;
   u_int rows, i;
   u_int rows, i;
   u_char d;
   u_char d;
   int fg, bg;
   int fg, bg;
 
 
   c &= 0xff;
   c &= 0xff;
 
 
   dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
   dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
   cdat0 = p->fontdata+c*p->fontheight;
   cdat0 = p->fontdata+c*p->fontheight;
   fg = attr_fgcol(p,conp);
   fg = attr_fgcol(p,conp);
   bg = attr_bgcol(p,conp);
   bg = attr_bgcol(p,conp);
 
 
   for (i = p->var.bits_per_pixel; i--; dest0 += p->next_plane) {
   for (i = p->var.bits_per_pixel; i--; dest0 += p->next_plane) {
      dest = dest0;
      dest = dest0;
      cdat = cdat0;
      cdat = cdat0;
      for (rows = p->fontheight; rows--; dest += p->next_line) {
      for (rows = p->fontheight; rows--; dest += p->next_line) {
         d = *cdat++;
         d = *cdat++;
         if (bg & 1)
         if (bg & 1)
            if (fg & 1)
            if (fg & 1)
               *dest = 0xff;
               *dest = 0xff;
            else
            else
               *dest = ~d;
               *dest = ~d;
         else
         else
            if (fg & 1)
            if (fg & 1)
               *dest = d;
               *dest = d;
            else
            else
               *dest = 0x00;
               *dest = 0x00;
      }
      }
      bg >>= 1;
      bg >>= 1;
      fg >>= 1;
      fg >>= 1;
   }
   }
}
}
 
 
 
 
/*
/*
 *    I split the console character loop in two parts
 *    I split the console character loop in two parts
 *    (cfr. fbcon_putcs_ilbm())
 *    (cfr. fbcon_putcs_ilbm())
 */
 */
 
 
static void putcs_plan(struct vc_data *conp, struct display *p, const char *s,
static void putcs_plan(struct vc_data *conp, struct display *p, const char *s,
                       int count, int y, int x)
                       int count, int y, int x)
{
{
   u_char *dest, *dest0, *dest1;
   u_char *dest, *dest0, *dest1;
   u_char *cdat1, *cdat2, *cdat3, *cdat4, *cdat10, *cdat20, *cdat30, *cdat40;
   u_char *cdat1, *cdat2, *cdat3, *cdat4, *cdat10, *cdat20, *cdat30, *cdat40;
   u_int rows, i;
   u_int rows, i;
   u_char c1, c2, c3, c4;
   u_char c1, c2, c3, c4;
   u_long d;
   u_long d;
   int fg0, bg0, fg, bg;
   int fg0, bg0, fg, bg;
 
 
   dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
   dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
   fg0 = attr_fgcol(p,conp);
   fg0 = attr_fgcol(p,conp);
   bg0 = attr_bgcol(p,conp);
   bg0 = attr_bgcol(p,conp);
 
 
   while (count--)
   while (count--)
      if (x&3 || count < 3) {   /* Slow version */
      if (x&3 || count < 3) {   /* Slow version */
         c1 = *s++;
         c1 = *s++;
         dest1 = dest0++;
         dest1 = dest0++;
         x++;
         x++;
 
 
         cdat10 = p->fontdata+c1*p->fontheight;
         cdat10 = p->fontdata+c1*p->fontheight;
         fg = fg0;
         fg = fg0;
         bg = bg0;
         bg = bg0;
 
 
         for (i = p->var.bits_per_pixel; i--; dest1 += p->next_plane) {
         for (i = p->var.bits_per_pixel; i--; dest1 += p->next_plane) {
            dest = dest1;
            dest = dest1;
            cdat1 = cdat10;
            cdat1 = cdat10;
            for (rows = p->fontheight; rows--; dest += p->next_line) {
            for (rows = p->fontheight; rows--; dest += p->next_line) {
               d = *cdat1++;
               d = *cdat1++;
               if (bg & 1)
               if (bg & 1)
                  if (fg & 1)
                  if (fg & 1)
                     *dest = 0xff;
                     *dest = 0xff;
                  else
                  else
                     *dest = ~d;
                     *dest = ~d;
               else
               else
                  if (fg & 1)
                  if (fg & 1)
                     *dest = d;
                     *dest = d;
                  else
                  else
                     *dest = 0x00;
                     *dest = 0x00;
            }
            }
            bg >>= 1;
            bg >>= 1;
            fg >>= 1;
            fg >>= 1;
         }
         }
      } else {                      /* Fast version */
      } else {                      /* Fast version */
         c1 = s[0];
         c1 = s[0];
         c2 = s[1];
         c2 = s[1];
         c3 = s[2];
         c3 = s[2];
         c4 = s[3];
         c4 = s[3];
 
 
         dest1 = dest0;
         dest1 = dest0;
         cdat10 = p->fontdata+c1*p->fontheight;
         cdat10 = p->fontdata+c1*p->fontheight;
         cdat20 = p->fontdata+c2*p->fontheight;
         cdat20 = p->fontdata+c2*p->fontheight;
         cdat30 = p->fontdata+c3*p->fontheight;
         cdat30 = p->fontdata+c3*p->fontheight;
         cdat40 = p->fontdata+c4*p->fontheight;
         cdat40 = p->fontdata+c4*p->fontheight;
         fg = fg0;
         fg = fg0;
         bg = bg0;
         bg = bg0;
 
 
         for (i = p->var.bits_per_pixel; i--; dest1 += p->next_plane) {
         for (i = p->var.bits_per_pixel; i--; dest1 += p->next_plane) {
            dest = dest1;
            dest = dest1;
            cdat1 = cdat10;
            cdat1 = cdat10;
            cdat2 = cdat20;
            cdat2 = cdat20;
            cdat3 = cdat30;
            cdat3 = cdat30;
            cdat4 = cdat40;
            cdat4 = cdat40;
            for (rows = p->fontheight; rows--; dest += p->next_line) {
            for (rows = p->fontheight; rows--; dest += p->next_line) {
               d = *cdat1++<<24 | *cdat2++<<16 | *cdat3++<<8 | *cdat4++;
               d = *cdat1++<<24 | *cdat2++<<16 | *cdat3++<<8 | *cdat4++;
               if (bg & 1)
               if (bg & 1)
                  if (fg & 1)
                  if (fg & 1)
                     *(u_long *)dest = 0xffffffff;
                     *(u_long *)dest = 0xffffffff;
                  else
                  else
                     *(u_long *)dest = ~d;
                     *(u_long *)dest = ~d;
               else
               else
                  if (fg & 1)
                  if (fg & 1)
                     *(u_long *)dest = d;
                     *(u_long *)dest = d;
                  else
                  else
                     *(u_long *)dest = 0x00000000;
                     *(u_long *)dest = 0x00000000;
            }
            }
            bg >>= 1;
            bg >>= 1;
            fg >>= 1;
            fg >>= 1;
         }
         }
         s += 4;
         s += 4;
         dest0 += 4;
         dest0 += 4;
         x += 4;
         x += 4;
         count -= 3;
         count -= 3;
      }
      }
}
}
 
 
 
 
static void rev_char_plan(struct display *p, int x, int y)
static void rev_char_plan(struct display *p, int x, int y)
{
{
   u_char *dest, *dest0;
   u_char *dest, *dest0;
   u_int rows, i;
   u_int rows, i;
   int mask;
   int mask;
 
 
   dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
   dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
   mask = p->fgcol ^ p->bgcol;
   mask = p->fgcol ^ p->bgcol;
 
 
   /*
   /*
    *    This should really obey the individual character's
    *    This should really obey the individual character's
    *    background and foreground colors instead of simply
    *    background and foreground colors instead of simply
    *    inverting.
    *    inverting.
    */
    */
 
 
   for (i = p->var.bits_per_pixel; i--; dest0 += p->next_plane) {
   for (i = p->var.bits_per_pixel; i--; dest0 += p->next_plane) {
      if (mask & 1) {
      if (mask & 1) {
         dest = dest0;
         dest = dest0;
         for (rows = p->fontheight; rows--; dest += p->next_line)
         for (rows = p->fontheight; rows--; dest += p->next_line)
            *dest = ~*dest;
            *dest = ~*dest;
      }
      }
      mask >>= 1;
      mask >>= 1;
   }
   }
}
}
 
 
#endif /* CONFIG_FBCON_PLANES */
#endif /* CONFIG_FBCON_PLANES */
 
 
 
 
/* ====================================================================== */
/* ====================================================================== */
 
 
#ifdef CONFIG_FBCON_2PLANE
#ifdef CONFIG_FBCON_2PLANE
 
 
   /*
   /*
    *    2 Planes (2-bytes interleave)
    *    2 Planes (2-bytes interleave)
    */
    */
 
 
/* Increment/decrement 2 plane addresses */
/* Increment/decrement 2 plane addresses */
 
 
#define INC_2P(p)       do { if (!((long)(++(p)) & 1)) (p) += 2; } while(0)
#define INC_2P(p)       do { if (!((long)(++(p)) & 1)) (p) += 2; } while(0)
#define DEC_2P(p)       do { if ((long)(--(p)) & 1) (p) -= 2; } while(0)
#define DEC_2P(p)       do { if ((long)(--(p)) & 1) (p) -= 2; } while(0)
 
 
/* Convert a standard 4 bit color to our 2 bit color assignment:
/* Convert a standard 4 bit color to our 2 bit color assignment:
 * If at least two RGB channels are active, the low bit is turned on;
 * If at least two RGB channels are active, the low bit is turned on;
 * The intensity bit (b3) is shifted into b1.
 * The intensity bit (b3) is shifted into b1.
 */
 */
 
 
#define COLOR_2P(c)     (((c & 7) >= 3 && (c & 7) != 4) | (c & 8) >> 2)
#define COLOR_2P(c)     (((c & 7) >= 3 && (c & 7) != 4) | (c & 8) >> 2)
 
 
 
 
static void bmove_2_plane(struct display *p, int sy, int sx, int dy, int dx,
static void bmove_2_plane(struct display *p, int sy, int sx, int dy, int dx,
                          int height, int width)
                          int height, int width)
{
{
        /* bmove() has to distinguish two major cases: If both, source and
        /* bmove() has to distinguish two major cases: If both, source and
         * destination, start at even addresses or both are at odd
         * destination, start at even addresses or both are at odd
         * addresses, just the first odd and last even column (if present)
         * addresses, just the first odd and last even column (if present)
         * require special treatment (memmove_col()). The rest between
         * require special treatment (memmove_col()). The rest between
         * then can be copied by normal operations, because all adjacent
         * then can be copied by normal operations, because all adjacent
         * bytes are affected and are to be stored in the same order.
         * bytes are affected and are to be stored in the same order.
         *   The pathological case is when the move should go from an odd
         *   The pathological case is when the move should go from an odd
         * address to an even or vice versa. Since the bytes in the plane
         * address to an even or vice versa. Since the bytes in the plane
         * words must be assembled in new order, it seems wisest to make
         * words must be assembled in new order, it seems wisest to make
         * all movements by memmove_col().
         * all movements by memmove_col().
         */
         */
 
 
    if (sx == 0 && dx == 0 && width == p->next_line/2) {
    if (sx == 0 && dx == 0 && width == p->next_line/2) {
                /* Special (but often used) case: Moving whole lines can be
                /* Special (but often used) case: Moving whole lines can be
                 * done with memmove()
                 * done with memmove()
                 */
                 */
                mymemmove(p->screen_base + dy * p->next_line * p->fontheight,
                mymemmove(p->screen_base + dy * p->next_line * p->fontheight,
                                   p->screen_base + sy * p->next_line * p->fontheight,
                                   p->screen_base + sy * p->next_line * p->fontheight,
                                   p->next_line * height * p->fontheight);
                                   p->next_line * height * p->fontheight);
    } else {
    } else {
        int rows, cols;
        int rows, cols;
        u_char *src;
        u_char *src;
        u_char *dst;
        u_char *dst;
        int bytes = p->next_line;
        int bytes = p->next_line;
        int linesize = bytes * p->fontheight;
        int linesize = bytes * p->fontheight;
                       u_int colsize  = height * p->fontheight;
                       u_int colsize  = height * p->fontheight;
                       u_int upwards  = (dy < sy) || (dy == sy && dx < sx);
                       u_int upwards  = (dy < sy) || (dy == sy && dx < sx);
 
 
                if ((sx & 1) == (dx & 1)) {
                if ((sx & 1) == (dx & 1)) {
                        /* odd->odd or even->even */
                        /* odd->odd or even->even */
 
 
                        if (upwards) {
                        if (upwards) {
 
 
                                src = p->screen_base + sy * linesize + (sx>>1)*4 + (sx & 1);
                                src = p->screen_base + sy * linesize + (sx>>1)*4 + (sx & 1);
                                dst = p->screen_base + dy * linesize + (dx>>1)*4 + (dx & 1);
                                dst = p->screen_base + dy * linesize + (dx>>1)*4 + (dx & 1);
 
 
                                if (sx & 1) {
                                if (sx & 1) {
                                        memmove_2p_col(dst, src, colsize, bytes);
                                        memmove_2p_col(dst, src, colsize, bytes);
                                        src += 3;
                                        src += 3;
                                        dst += 3;
                                        dst += 3;
                                        --width;
                                        --width;
                                }
                                }
 
 
                                if (width > 1) {
                                if (width > 1) {
                                        for(rows = colsize; rows > 0; --rows) {
                                        for(rows = colsize; rows > 0; --rows) {
                                                mymemmove(dst, src, (width>>1)*4);
                                                mymemmove(dst, src, (width>>1)*4);
                                                src += bytes;
                                                src += bytes;
                                                dst += bytes;
                                                dst += bytes;
                                        }
                                        }
                                }
                                }
 
 
                                if (width & 1) {
                                if (width & 1) {
                                        src -= colsize * bytes;
                                        src -= colsize * bytes;
                                        dst -= colsize * bytes;
                                        dst -= colsize * bytes;
                                        memmove_2p_col(dst + (width>>1)*4, src + (width>>1)*4,
                                        memmove_2p_col(dst + (width>>1)*4, src + (width>>1)*4,
                                                                        colsize, bytes);
                                                                        colsize, bytes);
                                }
                                }
                        }
                        }
                        else {
                        else {
 
 
                                if (!((sx+width-1) & 1)) {
                                if (!((sx+width-1) & 1)) {
                                        src = p->screen_base + sy * linesize + ((sx+width-1)>>1)*4;
                                        src = p->screen_base + sy * linesize + ((sx+width-1)>>1)*4;
                                        dst = p->screen_base + dy * linesize + ((dx+width-1)>>1)*4;
                                        dst = p->screen_base + dy * linesize + ((dx+width-1)>>1)*4;
                                        memmove_2p_col(dst, src, colsize, bytes);
                                        memmove_2p_col(dst, src, colsize, bytes);
                                        --width;
                                        --width;
                                }
                                }
 
 
                                src = p->screen_base + sy * linesize + (sx>>1)*4 + (sx & 1);
                                src = p->screen_base + sy * linesize + (sx>>1)*4 + (sx & 1);
                                dst = p->screen_base + dy * linesize + (dx>>1)*4 + (dx & 1);
                                dst = p->screen_base + dy * linesize + (dx>>1)*4 + (dx & 1);
 
 
                                if (width > 1) {
                                if (width > 1) {
                                        src += colsize * bytes + (sx & 1)*3;
                                        src += colsize * bytes + (sx & 1)*3;
                                        dst += colsize * bytes + (sx & 1)*3;
                                        dst += colsize * bytes + (sx & 1)*3;
                                        for(rows = colsize; rows > 0; --rows) {
                                        for(rows = colsize; rows > 0; --rows) {
                                                src -= bytes;
                                                src -= bytes;
                                                dst -= bytes;
                                                dst -= bytes;
                                                mymemmove(dst, src, (width>>1)*4);
                                                mymemmove(dst, src, (width>>1)*4);
                                        }
                                        }
                                }
                                }
 
 
                                if (width & 1) {
                                if (width & 1) {
                                        memmove_2p_col(dst-3, src-3, colsize, bytes);
                                        memmove_2p_col(dst-3, src-3, colsize, bytes);
                                }
                                }
 
 
                        }
                        }
                }
                }
                else {
                else {
                        /* odd->even or even->odd */
                        /* odd->even or even->odd */
 
 
                        if (upwards) {
                        if (upwards) {
                                src = p->screen_base + sy * linesize + (sx>>1)*4 + (sx & 1);
                                src = p->screen_base + sy * linesize + (sx>>1)*4 + (sx & 1);
                                dst = p->screen_base + dy * linesize + (dx>>1)*4 + (dx & 1);
                                dst = p->screen_base + dy * linesize + (dx>>1)*4 + (dx & 1);
                                for(cols = width; cols > 0; --cols) {
                                for(cols = width; cols > 0; --cols) {
                                        memmove_2p_col(dst, src, colsize, bytes);
                                        memmove_2p_col(dst, src, colsize, bytes);
                                        INC_2P(src);
                                        INC_2P(src);
                                        INC_2P(dst);
                                        INC_2P(dst);
                                }
                                }
                        }
                        }
                        else {
                        else {
                                sx += width-1;
                                sx += width-1;
                                dx += width-1;
                                dx += width-1;
                                src = p->screen_base + sy * linesize + (sx>>1)*4 + (sx & 1);
                                src = p->screen_base + sy * linesize + (sx>>1)*4 + (sx & 1);
                                dst = p->screen_base + dy * linesize + (dx>>1)*4 + (dx & 1);
                                dst = p->screen_base + dy * linesize + (dx>>1)*4 + (dx & 1);
                                for(cols = width; cols > 0; --cols) {
                                for(cols = width; cols > 0; --cols) {
                                        memmove_2p_col(dst, src, colsize, bytes);
                                        memmove_2p_col(dst, src, colsize, bytes);
                                        DEC_2P(src);
                                        DEC_2P(src);
                                        DEC_2P(dst);
                                        DEC_2P(dst);
                                }
                                }
                        }
                        }
                }
                }
 
 
 
 
    }
    }
}
}
 
 
 
 
static void clear_2_plane(struct vc_data *conp, struct display *p, int sy,
static void clear_2_plane(struct vc_data *conp, struct display *p, int sy,
                          int sx, int height, int width)
                          int sx, int height, int width)
{
{
    ulong offset;
    ulong offset;
    u_char *start;
    u_char *start;
    int rows;
    int rows;
    int bytes = p->next_line;
    int bytes = p->next_line;
    int lines = height * p->fontheight;
    int lines = height * p->fontheight;
    ulong  size;
    ulong  size;
        u_long          cval;
        u_long          cval;
        u_short                 pcval;
        u_short                 pcval;
 
 
    cval = expand2l (COLOR_2P (attr_bgcol_ec(p,conp)));
    cval = expand2l (COLOR_2P (attr_bgcol_ec(p,conp)));
 
 
    if (sx == 0 && width == bytes/2) {
    if (sx == 0 && width == bytes/2) {
 
 
        offset = sy * bytes * p->fontheight;
        offset = sy * bytes * p->fontheight;
        size   = lines * bytes;
        size   = lines * bytes;
                memset_even_2p(p->screen_base+offset, size, cval);
                memset_even_2p(p->screen_base+offset, size, cval);
 
 
    } else {
    } else {
 
 
        offset = (sy * bytes * p->fontheight) + (sx>>1)*4 + (sx & 1);
        offset = (sy * bytes * p->fontheight) + (sx>>1)*4 + (sx & 1);
                start = p->screen_base + offset;
                start = p->screen_base + offset;
                pcval = expand2w(COLOR_2P(attr_bgcol_ec(p,conp)));
                pcval = expand2w(COLOR_2P(attr_bgcol_ec(p,conp)));
 
 
                /* Clears are split if the region starts at an odd column or
                /* Clears are split if the region starts at an odd column or
                 * end at an even column. These extra columns are spread
                 * end at an even column. These extra columns are spread
                 * across the interleaved planes. All in between can be
                 * across the interleaved planes. All in between can be
                 * cleared by normal mymemclear_small(), because both bytes of
                 * cleared by normal mymemclear_small(), because both bytes of
                 * the single plane words are affected.
                 * the single plane words are affected.
                 */
                 */
 
 
                if (sx & 1) {
                if (sx & 1) {
                        memclear_2p_col(start, lines, pcval, bytes);
                        memclear_2p_col(start, lines, pcval, bytes);
                        start += 3;
                        start += 3;
                        width--;
                        width--;
                }
                }
 
 
                if (width & 1) {
                if (width & 1) {
                        memclear_2p_col(start + (width>>1)*4, lines, pcval, bytes);
                        memclear_2p_col(start + (width>>1)*4, lines, pcval, bytes);
                        width--;
                        width--;
                }
                }
 
 
                if (width) {
                if (width) {
                        for(rows = lines; rows-- ; start += bytes)
                        for(rows = lines; rows-- ; start += bytes)
                                memset_even_2p(start, width*2, cval);
                                memset_even_2p(start, width*2, cval);
                }
                }
    }
    }
}
}
 
 
 
 
static void putc_2_plane(struct vc_data *conp, struct display *p, int c, int y,
static void putc_2_plane(struct vc_data *conp, struct display *p, int c, int y,
                         int x)
                         int x)
{
{
   u_char   *dest;
   u_char   *dest;
    u_char   *cdat;
    u_char   *cdat;
    int rows;
    int rows;
    int bytes = p->next_line;
    int bytes = p->next_line;
        ulong                     eorx, fgx, bgx, fdx;
        ulong                     eorx, fgx, bgx, fdx;
 
 
        c &= 0xff;
        c &= 0xff;
 
 
    dest  = p->screen_base + y * p->fontheight * bytes + (x>>1)*4 + (x & 1);
    dest  = p->screen_base + y * p->fontheight * bytes + (x>>1)*4 + (x & 1);
    cdat  = p->fontdata + (c * p->fontheight);
    cdat  = p->fontdata + (c * p->fontheight);
 
 
        fgx   = expand2w(COLOR_2P(attr_fgcol(p,conp)));
        fgx   = expand2w(COLOR_2P(attr_fgcol(p,conp)));
        bgx   = expand2w(COLOR_2P(attr_bgcol(p,conp)));
        bgx   = expand2w(COLOR_2P(attr_bgcol(p,conp)));
        eorx  = fgx ^ bgx;
        eorx  = fgx ^ bgx;
 
 
    for(rows = p->fontheight ; rows-- ; dest += bytes) {
    for(rows = p->fontheight ; rows-- ; dest += bytes) {
                fdx = dup2w(*cdat++);
                fdx = dup2w(*cdat++);
                __asm__ __volatile__ ("movepw %1,%0@(0)" : /* no outputs */
                __asm__ __volatile__ ("movepw %1,%0@(0)" : /* no outputs */
                                                           : "a" (dest), "d" ((fdx & eorx) ^ bgx));
                                                           : "a" (dest), "d" ((fdx & eorx) ^ bgx));
        }
        }
}
}
 
 
 
 
static void putcs_2_plane(struct vc_data *conp, struct display *p,
static void putcs_2_plane(struct vc_data *conp, struct display *p,
                          const char *s, int count, int y, int x)
                          const char *s, int count, int y, int x)
{
{
        u_char   *dest, *dest0;
        u_char   *dest, *dest0;
    u_char   *cdat, c;
    u_char   *cdat, c;
    int rows;
    int rows;
    int bytes;
    int bytes;
        ulong                     eorx, fgx, bgx, fdx;
        ulong                     eorx, fgx, bgx, fdx;
 
 
    bytes = p->next_line;
    bytes = p->next_line;
    dest0 = p->screen_base + y * p->fontheight * bytes + (x>>1)*4 + (x & 1);
    dest0 = p->screen_base + y * p->fontheight * bytes + (x>>1)*4 + (x & 1);
        fgx   = expand2w(COLOR_2P(attr_fgcol(p,conp)));
        fgx   = expand2w(COLOR_2P(attr_fgcol(p,conp)));
        bgx   = expand2w(COLOR_2P(attr_bgcol(p,conp)));
        bgx   = expand2w(COLOR_2P(attr_bgcol(p,conp)));
        eorx  = fgx ^ bgx;
        eorx  = fgx ^ bgx;
 
 
        while (count--) {
        while (count--) {
 
 
                c = *s++;
                c = *s++;
                cdat  = p->fontdata + (c * p->fontheight);
                cdat  = p->fontdata + (c * p->fontheight);
 
 
                for(rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
                for(rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
                        fdx = dup2w(*cdat++);
                        fdx = dup2w(*cdat++);
                        __asm__ __volatile__ ("movepw %1,%0@(0)" : /* no outputs */
                        __asm__ __volatile__ ("movepw %1,%0@(0)" : /* no outputs */
                                                                   : "a" (dest), "d" ((fdx & eorx) ^ bgx));
                                                                   : "a" (dest), "d" ((fdx & eorx) ^ bgx));
                }
                }
                INC_2P(dest0);
                INC_2P(dest0);
        }
        }
}
}
 
 
 
 
static void rev_char_2_plane(struct display *p, int x, int y)
static void rev_char_2_plane(struct display *p, int x, int y)
{
{
   u_char *dest;
   u_char *dest;
   int j;
   int j;
   int bytes;
   int bytes;
 
 
   dest = p->screen_base + y * p->fontheight * p->next_line + (x>>1)*4 + (x & 1);
   dest = p->screen_base + y * p->fontheight * p->next_line + (x>>1)*4 + (x & 1);
   j = p->fontheight;
   j = p->fontheight;
   bytes = p->next_line;
   bytes = p->next_line;
   while (j--)
   while (j--)
     {
     {
      /* This should really obey the individual character's
      /* This should really obey the individual character's
       * background and foreground colors instead of simply
       * background and foreground colors instead of simply
       * inverting.
       * inverting.
       */
       */
       dest[0] = ~dest[0];
       dest[0] = ~dest[0];
       dest[2] = ~dest[2];
       dest[2] = ~dest[2];
       dest += bytes;
       dest += bytes;
     }
     }
}
}
#endif /* CONFIG_FBCON_2PLANE */
#endif /* CONFIG_FBCON_2PLANE */
 
 
 
 
/* ====================================================================== */
/* ====================================================================== */
 
 
#ifdef CONFIG_FBCON_4PLANE
#ifdef CONFIG_FBCON_4PLANE
 
 
   /*
   /*
    *    4 Planes (2-bytes interleave)
    *    4 Planes (2-bytes interleave)
    */
    */
 
 
/* Increment/decrement 4 plane addresses */
/* Increment/decrement 4 plane addresses */
 
 
#define INC_4P(p)       do { if (!((long)(++(p)) & 1)) (p) += 6; } while(0)
#define INC_4P(p)       do { if (!((long)(++(p)) & 1)) (p) += 6; } while(0)
#define DEC_4P(p)       do { if ((long)(--(p)) & 1) (p) -= 6; } while(0)
#define DEC_4P(p)       do { if ((long)(--(p)) & 1) (p) -= 6; } while(0)
 
 
 
 
static void bmove_4_plane(struct display *p, int sy, int sx, int dy, int dx,
static void bmove_4_plane(struct display *p, int sy, int sx, int dy, int dx,
                          int height, int width)
                          int height, int width)
{
{
        /* bmove() has to distinguish two major cases: If both, source and
        /* bmove() has to distinguish two major cases: If both, source and
         * destination, start at even addresses or both are at odd
         * destination, start at even addresses or both are at odd
         * addresses, just the first odd and last even column (if present)
         * addresses, just the first odd and last even column (if present)
         * require special treatment (memmove_col()). The rest between
         * require special treatment (memmove_col()). The rest between
         * then can be copied by normal operations, because all adjacent
         * then can be copied by normal operations, because all adjacent
         * bytes are affected and are to be stored in the same order.
         * bytes are affected and are to be stored in the same order.
         *   The pathological case is when the move should go from an odd
         *   The pathological case is when the move should go from an odd
         * address to an even or vice versa. Since the bytes in the plane
         * address to an even or vice versa. Since the bytes in the plane
         * words must be assembled in new order, it seems wisest to make
         * words must be assembled in new order, it seems wisest to make
         * all movements by memmove_col().
         * all movements by memmove_col().
         */
         */
 
 
    if (sx == 0 && dx == 0 && width == p->next_line/4) {
    if (sx == 0 && dx == 0 && width == p->next_line/4) {
                /* Special (but often used) case: Moving whole lines can be
                /* Special (but often used) case: Moving whole lines can be
                 * done with memmove()
                 * done with memmove()
                 */
                 */
                mymemmove(p->screen_base + dy * p->next_line * p->fontheight,
                mymemmove(p->screen_base + dy * p->next_line * p->fontheight,
                                   p->screen_base + sy * p->next_line * p->fontheight,
                                   p->screen_base + sy * p->next_line * p->fontheight,
                                   p->next_line * height * p->fontheight);
                                   p->next_line * height * p->fontheight);
    } else {
    } else {
        int rows, cols;
        int rows, cols;
        u_char *src;
        u_char *src;
        u_char *dst;
        u_char *dst;
        int bytes = p->next_line;
        int bytes = p->next_line;
        int linesize = bytes * p->fontheight;
        int linesize = bytes * p->fontheight;
                       u_int colsize  = height * p->fontheight;
                       u_int colsize  = height * p->fontheight;
                       u_int upwards  = (dy < sy) || (dy == sy && dx < sx);
                       u_int upwards  = (dy < sy) || (dy == sy && dx < sx);
 
 
                if ((sx & 1) == (dx & 1)) {
                if ((sx & 1) == (dx & 1)) {
                        /* odd->odd or even->even */
                        /* odd->odd or even->even */
 
 
                        if (upwards) {
                        if (upwards) {
 
 
                                src = p->screen_base + sy * linesize + (sx>>1)*8 + (sx & 1);
                                src = p->screen_base + sy * linesize + (sx>>1)*8 + (sx & 1);
                                dst = p->screen_base + dy * linesize + (dx>>1)*8 + (dx & 1);
                                dst = p->screen_base + dy * linesize + (dx>>1)*8 + (dx & 1);
 
 
                                if (sx & 1) {
                                if (sx & 1) {
                                        memmove_4p_col(dst, src, colsize, bytes);
                                        memmove_4p_col(dst, src, colsize, bytes);
                                        src += 7;
                                        src += 7;
                                        dst += 7;
                                        dst += 7;
                                        --width;
                                        --width;
                                }
                                }
 
 
                                if (width > 1) {
                                if (width > 1) {
                                        for(rows = colsize; rows > 0; --rows) {
                                        for(rows = colsize; rows > 0; --rows) {
                                                mymemmove(dst, src, (width>>1)*8);
                                                mymemmove(dst, src, (width>>1)*8);
                                                src += bytes;
                                                src += bytes;
                                                dst += bytes;
                                                dst += bytes;
                                        }
                                        }
                                }
                                }
 
 
                                if (width & 1) {
                                if (width & 1) {
                                        src -= colsize * bytes;
                                        src -= colsize * bytes;
                                        dst -= colsize * bytes;
                                        dst -= colsize * bytes;
                                        memmove_4p_col(dst + (width>>1)*8, src + (width>>1)*8,
                                        memmove_4p_col(dst + (width>>1)*8, src + (width>>1)*8,
                                                                        colsize, bytes);
                                                                        colsize, bytes);
                                }
                                }
                        }
                        }
                        else {
                        else {
 
 
                                if (!((sx+width-1) & 1)) {
                                if (!((sx+width-1) & 1)) {
                                        src = p->screen_base + sy * linesize + ((sx+width-1)>>1)*8;
                                        src = p->screen_base + sy * linesize + ((sx+width-1)>>1)*8;
                                        dst = p->screen_base + dy * linesize + ((dx+width-1)>>1)*8;
                                        dst = p->screen_base + dy * linesize + ((dx+width-1)>>1)*8;
                                        memmove_4p_col(dst, src, colsize, bytes);
                                        memmove_4p_col(dst, src, colsize, bytes);
                                        --width;
                                        --width;
                                }
                                }
 
 
                                src = p->screen_base + sy * linesize + (sx>>1)*8 + (sx & 1);
                                src = p->screen_base + sy * linesize + (sx>>1)*8 + (sx & 1);
                                dst = p->screen_base + dy * linesize + (dx>>1)*8 + (dx & 1);
                                dst = p->screen_base + dy * linesize + (dx>>1)*8 + (dx & 1);
 
 
                                if (width > 1) {
                                if (width > 1) {
                                        src += colsize * bytes + (sx & 1)*7;
                                        src += colsize * bytes + (sx & 1)*7;
                                        dst += colsize * bytes + (sx & 1)*7;
                                        dst += colsize * bytes + (sx & 1)*7;
                                        for(rows = colsize; rows > 0; --rows) {
                                        for(rows = colsize; rows > 0; --rows) {
                                                src -= bytes;
                                                src -= bytes;
                                                dst -= bytes;
                                                dst -= bytes;
                                                mymemmove(dst, src, (width>>1)*8);
                                                mymemmove(dst, src, (width>>1)*8);
                                        }
                                        }
                                }
                                }
 
 
                                if (width & 1) {
                                if (width & 1) {
                                        memmove_4p_col(dst-7, src-7, colsize, bytes);
                                        memmove_4p_col(dst-7, src-7, colsize, bytes);
                                }
                                }
 
 
                        }
                        }
                }
                }
                else {
                else {
                        /* odd->even or even->odd */
                        /* odd->even or even->odd */
 
 
                        if (upwards) {
                        if (upwards) {
                                src = p->screen_base + sy * linesize + (sx>>1)*8 + (sx & 1);
                                src = p->screen_base + sy * linesize + (sx>>1)*8 + (sx & 1);
                                dst = p->screen_base + dy * linesize + (dx>>1)*8 + (dx & 1);
                                dst = p->screen_base + dy * linesize + (dx>>1)*8 + (dx & 1);
                                for(cols = width; cols > 0; --cols) {
                                for(cols = width; cols > 0; --cols) {
                                        memmove_4p_col(dst, src, colsize, bytes);
                                        memmove_4p_col(dst, src, colsize, bytes);
                                        INC_4P(src);
                                        INC_4P(src);
                                        INC_4P(dst);
                                        INC_4P(dst);
                                }
                                }
                        }
                        }
                        else {
                        else {
                                sx += width-1;
                                sx += width-1;
                                dx += width-1;
                                dx += width-1;
                                src = p->screen_base + sy * linesize + (sx>>1)*8 + (sx & 1);
                                src = p->screen_base + sy * linesize + (sx>>1)*8 + (sx & 1);
                                dst = p->screen_base + dy * linesize + (dx>>1)*8 + (dx & 1);
                                dst = p->screen_base + dy * linesize + (dx>>1)*8 + (dx & 1);
                                for(cols = width; cols > 0; --cols) {
                                for(cols = width; cols > 0; --cols) {
                                        memmove_4p_col(dst, src, colsize, bytes);
                                        memmove_4p_col(dst, src, colsize, bytes);
                                        DEC_4P(src);
                                        DEC_4P(src);
                                        DEC_4P(dst);
                                        DEC_4P(dst);
                                }
                                }
                        }
                        }
                }
                }
 
 
 
 
    }
    }
}
}
 
 
 
 
static void clear_4_plane(struct vc_data *conp, struct display *p, int sy,
static void clear_4_plane(struct vc_data *conp, struct display *p, int sy,
                          int sx, int height, int width)
                          int sx, int height, int width)
{
{
    ulong offset;
    ulong offset;
    u_char *start;
    u_char *start;
    int rows;
    int rows;
    int bytes = p->next_line;
    int bytes = p->next_line;
    int lines = height * p->fontheight;
    int lines = height * p->fontheight;
    ulong  size;
    ulong  size;
        u_long          cval1, cval2, pcval;
        u_long          cval1, cval2, pcval;
 
 
        expand4dl(attr_bgcol_ec(p,conp), &cval1, &cval2);
        expand4dl(attr_bgcol_ec(p,conp), &cval1, &cval2);
 
 
    if (sx == 0 && width == bytes/4) {
    if (sx == 0 && width == bytes/4) {
 
 
        offset = sy * bytes * p->fontheight;
        offset = sy * bytes * p->fontheight;
        size   = lines * bytes;
        size   = lines * bytes;
                memset_even_4p(p->screen_base+offset, size, cval1, cval2);
                memset_even_4p(p->screen_base+offset, size, cval1, cval2);
 
 
    } else {
    } else {
 
 
        offset = (sy * bytes * p->fontheight) + (sx>>1)*8 + (sx & 1);
        offset = (sy * bytes * p->fontheight) + (sx>>1)*8 + (sx & 1);
                start = p->screen_base + offset;
                start = p->screen_base + offset;
                pcval = expand4l(attr_bgcol_ec(p,conp));
                pcval = expand4l(attr_bgcol_ec(p,conp));
 
 
                /* Clears are split if the region starts at an odd column or
                /* Clears are split if the region starts at an odd column or
                 * end at an even column. These extra columns are spread
                 * end at an even column. These extra columns are spread
                 * across the interleaved planes. All in between can be
                 * across the interleaved planes. All in between can be
                 * cleared by normal mymemclear_small(), because both bytes of
                 * cleared by normal mymemclear_small(), because both bytes of
                 * the single plane words are affected.
                 * the single plane words are affected.
                 */
                 */
 
 
                if (sx & 1) {
                if (sx & 1) {
                        memclear_4p_col(start, lines, pcval, bytes);
                        memclear_4p_col(start, lines, pcval, bytes);
                        start += 7;
                        start += 7;
                        width--;
                        width--;
                }
                }
 
 
                if (width & 1) {
                if (width & 1) {
                        memclear_4p_col(start + (width>>1)*8, lines, pcval, bytes);
                        memclear_4p_col(start + (width>>1)*8, lines, pcval, bytes);
                        width--;
                        width--;
                }
                }
 
 
                if (width) {
                if (width) {
                        for(rows = lines; rows-- ; start += bytes)
                        for(rows = lines; rows-- ; start += bytes)
                                memset_even_4p(start, width*4, cval1, cval2);
                                memset_even_4p(start, width*4, cval1, cval2);
                }
                }
    }
    }
}
}
 
 
 
 
static void putc_4_plane(struct vc_data *conp, struct display *p, int c, int y,
static void putc_4_plane(struct vc_data *conp, struct display *p, int c, int y,
                         int x)
                         int x)
{
{
        u_char   *dest;
        u_char   *dest;
    u_char   *cdat;
    u_char   *cdat;
    int rows;
    int rows;
    int bytes = p->next_line;
    int bytes = p->next_line;
        ulong                     eorx, fgx, bgx, fdx;
        ulong                     eorx, fgx, bgx, fdx;
 
 
        c &= 0xff;
        c &= 0xff;
 
 
    dest  = p->screen_base + y * p->fontheight * bytes + (x>>1)*8 + (x & 1);
    dest  = p->screen_base + y * p->fontheight * bytes + (x>>1)*8 + (x & 1);
    cdat  = p->fontdata + (c * p->fontheight);
    cdat  = p->fontdata + (c * p->fontheight);
 
 
        fgx   = expand4l(attr_fgcol(p,conp));
        fgx   = expand4l(attr_fgcol(p,conp));
        bgx   = expand4l(attr_bgcol(p,conp));
        bgx   = expand4l(attr_bgcol(p,conp));
        eorx  = fgx ^ bgx;
        eorx  = fgx ^ bgx;
 
 
    for(rows = p->fontheight ; rows-- ; dest += bytes) {
    for(rows = p->fontheight ; rows-- ; dest += bytes) {
                fdx = dup4l(*cdat++);
                fdx = dup4l(*cdat++);
                __asm__ __volatile__ ("movepl %1,%0@(0)" : /* no outputs */
                __asm__ __volatile__ ("movepl %1,%0@(0)" : /* no outputs */
                                                           : "a" (dest), "d" ((fdx & eorx) ^ bgx));
                                                           : "a" (dest), "d" ((fdx & eorx) ^ bgx));
        }
        }
}
}
 
 
 
 
static void putcs_4_plane(struct vc_data *conp, struct display *p,
static void putcs_4_plane(struct vc_data *conp, struct display *p,
                          const char *s, int count, int y, int x)
                          const char *s, int count, int y, int x)
{
{
        u_char   *dest, *dest0;
        u_char   *dest, *dest0;
    u_char   *cdat, c;
    u_char   *cdat, c;
    int rows;
    int rows;
    int bytes;
    int bytes;
        ulong                     eorx, fgx, bgx, fdx;
        ulong                     eorx, fgx, bgx, fdx;
 
 
    bytes = p->next_line;
    bytes = p->next_line;
    dest0 = p->screen_base + y * p->fontheight * bytes + (x>>1)*8 + (x & 1);
    dest0 = p->screen_base + y * p->fontheight * bytes + (x>>1)*8 + (x & 1);
        fgx   = expand4l(attr_fgcol(p,conp));
        fgx   = expand4l(attr_fgcol(p,conp));
        bgx   = expand4l(attr_bgcol(p,conp));
        bgx   = expand4l(attr_bgcol(p,conp));
        eorx  = fgx ^ bgx;
        eorx  = fgx ^ bgx;
 
 
        while (count--) {
        while (count--) {
 
 
                /* I think, unrolling the loops like in the 1 plane case isn't
                /* I think, unrolling the loops like in the 1 plane case isn't
                 * practicable here, because the body is much longer for 4
                 * practicable here, because the body is much longer for 4
                 * planes (mostly the dup4l()). I guess, unrolling this would
                 * planes (mostly the dup4l()). I guess, unrolling this would
                 * need more than 256 bytes and so exceed the instruction
                 * need more than 256 bytes and so exceed the instruction
                 * cache :-(
                 * cache :-(
                 */
                 */
 
 
                c = *s++;
                c = *s++;
                cdat  = p->fontdata + (c * p->fontheight);
                cdat  = p->fontdata + (c * p->fontheight);
 
 
                for(rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
                for(rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
                        fdx = dup4l(*cdat++);
                        fdx = dup4l(*cdat++);
                        __asm__ __volatile__ ("movepl %1,%0@(0)" : /* no outputs */
                        __asm__ __volatile__ ("movepl %1,%0@(0)" : /* no outputs */
                                                                   : "a" (dest), "d" ((fdx & eorx) ^ bgx));
                                                                   : "a" (dest), "d" ((fdx & eorx) ^ bgx));
                }
                }
                INC_4P(dest0);
                INC_4P(dest0);
        }
        }
}
}
 
 
 
 
static void rev_char_4_plane(struct display *p, int x, int y)
static void rev_char_4_plane(struct display *p, int x, int y)
{
{
   u_char *dest;
   u_char *dest;
   int j;
   int j;
   int bytes;
   int bytes;
 
 
   dest = p->screen_base + y * p->fontheight * p->next_line + (x>>1)*8 + (x & 1);
   dest = p->screen_base + y * p->fontheight * p->next_line + (x>>1)*8 + (x & 1);
   j = p->fontheight;
   j = p->fontheight;
   bytes = p->next_line;
   bytes = p->next_line;
 
 
   while (j--)
   while (j--)
     {
     {
      /* This should really obey the individual character's
      /* This should really obey the individual character's
       * background and foreground colors instead of simply
       * background and foreground colors instead of simply
       * inverting.
       * inverting.
       */
       */
       dest[0] = ~dest[0];
       dest[0] = ~dest[0];
       dest[2] = ~dest[2];
       dest[2] = ~dest[2];
       dest[4] = ~dest[4];
       dest[4] = ~dest[4];
       dest[6] = ~dest[6];
       dest[6] = ~dest[6];
       dest += bytes;
       dest += bytes;
     }
     }
}
}
#endif /* CONFIG_FBCON_4PLANE */
#endif /* CONFIG_FBCON_4PLANE */
 
 
 
 
/* ====================================================================== */
/* ====================================================================== */
 
 
#ifdef CONFIG_FBCON_8PLANE
#ifdef CONFIG_FBCON_8PLANE
 
 
   /*
   /*
    *    8 Planes (2-bytes interleave)
    *    8 Planes (2-bytes interleave)
    */
    */
 
 
/* In 8 plane mode, 256 colors would be possible, but only the first
/* In 8 plane mode, 256 colors would be possible, but only the first
 * 16 are used by the console code (the upper 4 bits are
 * 16 are used by the console code (the upper 4 bits are
 * background/unused). For that, the following functions mask off the
 * background/unused). For that, the following functions mask off the
 * higher 4 bits of each color.
 * higher 4 bits of each color.
 */
 */
 
 
/* Increment/decrement 8 plane addresses */
/* Increment/decrement 8 plane addresses */
 
 
#define INC_8P(p)       do { if (!((long)(++(p)) & 1)) (p) += 14; } while(0)
#define INC_8P(p)       do { if (!((long)(++(p)) & 1)) (p) += 14; } while(0)
#define DEC_8P(p)       do { if ((long)(--(p)) & 1) (p) -= 14; } while(0)
#define DEC_8P(p)       do { if ((long)(--(p)) & 1) (p) -= 14; } while(0)
 
 
 
 
static void bmove_8_plane(struct display *p, int sy, int sx, int dy, int dx,
static void bmove_8_plane(struct display *p, int sy, int sx, int dy, int dx,
                          int height, int width)
                          int height, int width)
{
{
        /* bmove() has to distinguish two major cases: If both, source and
        /* bmove() has to distinguish two major cases: If both, source and
         * destination, start at even addresses or both are at odd
         * destination, start at even addresses or both are at odd
         * addresses, just the first odd and last even column (if present)
         * addresses, just the first odd and last even column (if present)
         * require special treatment (memmove_col()). The rest between
         * require special treatment (memmove_col()). The rest between
         * then can be copied by normal operations, because all adjacent
         * then can be copied by normal operations, because all adjacent
         * bytes are affected and are to be stored in the same order.
         * bytes are affected and are to be stored in the same order.
         *   The pathological case is when the move should go from an odd
         *   The pathological case is when the move should go from an odd
         * address to an even or vice versa. Since the bytes in the plane
         * address to an even or vice versa. Since the bytes in the plane
         * words must be assembled in new order, it seems wisest to make
         * words must be assembled in new order, it seems wisest to make
         * all movements by memmove_col().
         * all movements by memmove_col().
         */
         */
 
 
    if (sx == 0 && dx == 0 && width == p->next_line/8) {
    if (sx == 0 && dx == 0 && width == p->next_line/8) {
                /* Special (but often used) case: Moving whole lines can be
                /* Special (but often used) case: Moving whole lines can be
                 * done with memmove()
                 * done with memmove()
                 */
                 */
      fast_memmove (p->screen_base + dy * p->next_line * p->fontheight,
      fast_memmove (p->screen_base + dy * p->next_line * p->fontheight,
                    p->screen_base + sy * p->next_line * p->fontheight,
                    p->screen_base + sy * p->next_line * p->fontheight,
                    p->next_line * height * p->fontheight);
                    p->next_line * height * p->fontheight);
    } else {
    } else {
        int rows, cols;
        int rows, cols;
        u_char *src;
        u_char *src;
        u_char *dst;
        u_char *dst;
        int bytes = p->next_line;
        int bytes = p->next_line;
        int linesize = bytes * p->fontheight;
        int linesize = bytes * p->fontheight;
                       u_int colsize  = height * p->fontheight;
                       u_int colsize  = height * p->fontheight;
                       u_int upwards  = (dy < sy) || (dy == sy && dx < sx);
                       u_int upwards  = (dy < sy) || (dy == sy && dx < sx);
 
 
                if ((sx & 1) == (dx & 1)) {
                if ((sx & 1) == (dx & 1)) {
                        /* odd->odd or even->even */
                        /* odd->odd or even->even */
 
 
                        if (upwards) {
                        if (upwards) {
 
 
                                src = p->screen_base + sy * linesize + (sx>>1)*16 + (sx & 1);
                                src = p->screen_base + sy * linesize + (sx>>1)*16 + (sx & 1);
                                dst = p->screen_base + dy * linesize + (dx>>1)*16 + (dx & 1);
                                dst = p->screen_base + dy * linesize + (dx>>1)*16 + (dx & 1);
 
 
                                if (sx & 1) {
                                if (sx & 1) {
                                        memmove_8p_col(dst, src, colsize, bytes);
                                        memmove_8p_col(dst, src, colsize, bytes);
                                        src += 15;
                                        src += 15;
                                        dst += 15;
                                        dst += 15;
                                        --width;
                                        --width;
                                }
                                }
 
 
                                if (width > 1) {
                                if (width > 1) {
                                        for(rows = colsize; rows > 0; --rows) {
                                        for(rows = colsize; rows > 0; --rows) {
                                                fast_memmove (dst, src, (width >> 1) * 16);
                                                fast_memmove (dst, src, (width >> 1) * 16);
                                                src += bytes;
                                                src += bytes;
                                                dst += bytes;
                                                dst += bytes;
                                        }
                                        }
                                }
                                }
 
 
                                if (width & 1) {
                                if (width & 1) {
                                        src -= colsize * bytes;
                                        src -= colsize * bytes;
                                        dst -= colsize * bytes;
                                        dst -= colsize * bytes;
                                        memmove_8p_col(dst + (width>>1)*16, src + (width>>1)*16,
                                        memmove_8p_col(dst + (width>>1)*16, src + (width>>1)*16,
                                                                        colsize, bytes);
                                                                        colsize, bytes);
                                }
                                }
                        }
                        }
                        else {
                        else {
 
 
                                if (!((sx+width-1) & 1)) {
                                if (!((sx+width-1) & 1)) {
                                        src = p->screen_base + sy * linesize + ((sx+width-1)>>1)*16;
                                        src = p->screen_base + sy * linesize + ((sx+width-1)>>1)*16;
                                        dst = p->screen_base + dy * linesize + ((dx+width-1)>>1)*16;
                                        dst = p->screen_base + dy * linesize + ((dx+width-1)>>1)*16;
                                        memmove_8p_col(dst, src, colsize, bytes);
                                        memmove_8p_col(dst, src, colsize, bytes);
                                        --width;
                                        --width;
                                }
                                }
 
 
                                src = p->screen_base + sy * linesize + (sx>>1)*16 + (sx & 1);
                                src = p->screen_base + sy * linesize + (sx>>1)*16 + (sx & 1);
                                dst = p->screen_base + dy * linesize + (dx>>1)*16 + (dx & 1);
                                dst = p->screen_base + dy * linesize + (dx>>1)*16 + (dx & 1);
 
 
                                if (width > 1) {
                                if (width > 1) {
                                        src += colsize * bytes + (sx & 1)*15;
                                        src += colsize * bytes + (sx & 1)*15;
                                        dst += colsize * bytes + (sx & 1)*15;
                                        dst += colsize * bytes + (sx & 1)*15;
                                        for(rows = colsize; rows > 0; --rows) {
                                        for(rows = colsize; rows > 0; --rows) {
                                                src -= bytes;
                                                src -= bytes;
                                                dst -= bytes;
                                                dst -= bytes;
                                                fast_memmove (dst, src, (width>>1)*16);
                                                fast_memmove (dst, src, (width>>1)*16);
                                        }
                                        }
                                }
                                }
 
 
                                if (width & 1) {
                                if (width & 1) {
                                        memmove_8p_col(dst-15, src-15, colsize, bytes);
                                        memmove_8p_col(dst-15, src-15, colsize, bytes);
                                }
                                }
 
 
                        }
                        }
                }
                }
                else {
                else {
                        /* odd->even or even->odd */
                        /* odd->even or even->odd */
 
 
                        if (upwards) {
                        if (upwards) {
                                src = p->screen_base + sy * linesize + (sx>>1)*16 + (sx & 1);
                                src = p->screen_base + sy * linesize + (sx>>1)*16 + (sx & 1);
                                dst = p->screen_base + dy * linesize + (dx>>1)*16 + (dx & 1);
                                dst = p->screen_base + dy * linesize + (dx>>1)*16 + (dx & 1);
                                for(cols = width; cols > 0; --cols) {
                                for(cols = width; cols > 0; --cols) {
                                        memmove_8p_col(dst, src, colsize, bytes);
                                        memmove_8p_col(dst, src, colsize, bytes);
                                        INC_8P(src);
                                        INC_8P(src);
                                        INC_8P(dst);
                                        INC_8P(dst);
                                }
                                }
                        }
                        }
                        else {
                        else {
                                sx += width-1;
                                sx += width-1;
                                dx += width-1;
                                dx += width-1;
                                src = p->screen_base + sy * linesize + (sx>>1)*16 + (sx & 1);
                                src = p->screen_base + sy * linesize + (sx>>1)*16 + (sx & 1);
                                dst = p->screen_base + dy * linesize + (dx>>1)*16 + (dx & 1);
                                dst = p->screen_base + dy * linesize + (dx>>1)*16 + (dx & 1);
                                for(cols = width; cols > 0; --cols) {
                                for(cols = width; cols > 0; --cols) {
                                        memmove_8p_col(dst, src, colsize, bytes);
                                        memmove_8p_col(dst, src, colsize, bytes);
                                        DEC_8P(src);
                                        DEC_8P(src);
                                        DEC_8P(dst);
                                        DEC_8P(dst);
                                }
                                }
                        }
                        }
                }
                }
 
 
 
 
    }
    }
}
}
 
 
 
 
static void clear_8_plane(struct vc_data *conp, struct display *p, int sy,
static void clear_8_plane(struct vc_data *conp, struct display *p, int sy,
                          int sx, int height, int width)
                          int sx, int height, int width)
{
{
    ulong offset;
    ulong offset;
    u_char *start;
    u_char *start;
    int rows;
    int rows;
    int bytes = p->next_line;
    int bytes = p->next_line;
    int lines = height * p->fontheight;
    int lines = height * p->fontheight;
    ulong  size;
    ulong  size;
        u_long          cval1, cval2, cval3, cval4, pcval1, pcval2;
        u_long          cval1, cval2, cval3, cval4, pcval1, pcval2;
 
 
        expand8ql(attr_bgcol_ec(p,conp), cval1, cval2, cval3, cval4);
        expand8ql(attr_bgcol_ec(p,conp), cval1, cval2, cval3, cval4);
 
 
    if (sx == 0 && width == bytes/8) {
    if (sx == 0 && width == bytes/8) {
 
 
        offset = sy * bytes * p->fontheight;
        offset = sy * bytes * p->fontheight;
        size   = lines * bytes;
        size   = lines * bytes;
                memset_even_8p(p->screen_base+offset, size, cval1, cval2, cval3, cval4);
                memset_even_8p(p->screen_base+offset, size, cval1, cval2, cval3, cval4);
 
 
    } else {
    } else {
 
 
        offset = (sy * bytes * p->fontheight) + (sx>>1)*16 + (sx & 1);
        offset = (sy * bytes * p->fontheight) + (sx>>1)*16 + (sx & 1);
                start = p->screen_base + offset;
                start = p->screen_base + offset;
                expand8dl(attr_bgcol_ec(p,conp), &pcval1, &pcval2);
                expand8dl(attr_bgcol_ec(p,conp), &pcval1, &pcval2);
 
 
                /* Clears are split if the region starts at an odd column or
                /* Clears are split if the region starts at an odd column or
                 * end at an even column. These extra columns are spread
                 * end at an even column. These extra columns are spread
                 * across the interleaved planes. All in between can be
                 * across the interleaved planes. All in between can be
                 * cleared by normal mymemclear_small(), because both bytes of
                 * cleared by normal mymemclear_small(), because both bytes of
                 * the single plane words are affected.
                 * the single plane words are affected.
                 */
                 */
 
 
                if (sx & 1) {
                if (sx & 1) {
                        memclear_8p_col(start, lines, pcval1, pcval2, bytes);
                        memclear_8p_col(start, lines, pcval1, pcval2, bytes);
                        start += 7;
                        start += 7;
                        width--;
                        width--;
                }
                }
 
 
                if (width & 1) {
                if (width & 1) {
                        memclear_8p_col(start + (width>>1)*16, lines, pcval1,
                        memclear_8p_col(start + (width>>1)*16, lines, pcval1,
                                                         pcval2, bytes);
                                                         pcval2, bytes);
                        width--;
                        width--;
                }
                }
 
 
                if (width) {
                if (width) {
                        for(rows = lines; rows-- ; start += bytes)
                        for(rows = lines; rows-- ; start += bytes)
                                memset_even_8p(start, width*8, cval1, cval2, cval3, cval4);
                                memset_even_8p(start, width*8, cval1, cval2, cval3, cval4);
                }
                }
    }
    }
}
}
 
 
 
 
static void putc_8_plane(struct vc_data *conp, struct display *p, int c, int y,
static void putc_8_plane(struct vc_data *conp, struct display *p, int c, int y,
                         int x)
                         int x)
{
{
        u_char   *dest;
        u_char   *dest;
    u_char   *cdat;
    u_char   *cdat;
    int rows;
    int rows;
    int bytes = p->next_line;
    int bytes = p->next_line;
        ulong                     eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx;
        ulong                     eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx;
 
 
        c &= 0xff;
        c &= 0xff;
 
 
    dest  = p->screen_base + y * p->fontheight * bytes + (x>>1)*16 + (x & 1);
    dest  = p->screen_base + y * p->fontheight * bytes + (x>>1)*16 + (x & 1);
    cdat  = p->fontdata + (c * p->fontheight);
    cdat  = p->fontdata + (c * p->fontheight);
 
 
        expand8dl(attr_fgcol(p,conp), &fgx1, &fgx2);
        expand8dl(attr_fgcol(p,conp), &fgx1, &fgx2);
        expand8dl(attr_bgcol(p,conp), &bgx1, &bgx2);
        expand8dl(attr_bgcol(p,conp), &bgx1, &bgx2);
        eorx1  = fgx1 ^ bgx1; eorx2  = fgx2 ^ bgx2;
        eorx1  = fgx1 ^ bgx1; eorx2  = fgx2 ^ bgx2;
 
 
    for(rows = p->fontheight ; rows-- ; dest += bytes) {
    for(rows = p->fontheight ; rows-- ; dest += bytes) {
                fdx = dup4l(*cdat++);
                fdx = dup4l(*cdat++);
                __asm__ __volatile__
                __asm__ __volatile__
                        ("movepl %1,%0@(0)\n\t"
                        ("movepl %1,%0@(0)\n\t"
                          "movepl %2,%0@(8)"
                          "movepl %2,%0@(8)"
                          : /* no outputs */
                          : /* no outputs */
                          : "a" (dest), "d" ((fdx & eorx1) ^ bgx1),
                          : "a" (dest), "d" ((fdx & eorx1) ^ bgx1),
                            "d" ((fdx & eorx2) ^ bgx2)
                            "d" ((fdx & eorx2) ^ bgx2)
                        );
                        );
        }
        }
}
}
 
 
 
 
static void putcs_8_plane(struct vc_data *conp, struct display *p,
static void putcs_8_plane(struct vc_data *conp, struct display *p,
                          const char *s, int count, int y, int x)
                          const char *s, int count, int y, int x)
{
{
        u_char   *dest, *dest0;
        u_char   *dest, *dest0;
    u_char   *cdat, c;
    u_char   *cdat, c;
    int rows;
    int rows;
    int bytes;
    int bytes;
        ulong                     eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx;
        ulong                     eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx;
 
 
    bytes = p->next_line;
    bytes = p->next_line;
    dest0 = p->screen_base + y * p->fontheight * bytes + (x>>1)*16 + (x & 1);
    dest0 = p->screen_base + y * p->fontheight * bytes + (x>>1)*16 + (x & 1);
 
 
        expand8dl(attr_fgcol(p,conp), &fgx1, &fgx2);
        expand8dl(attr_fgcol(p,conp), &fgx1, &fgx2);
        expand8dl(attr_bgcol(p,conp), &bgx1, &bgx2);
        expand8dl(attr_bgcol(p,conp), &bgx1, &bgx2);
        eorx1  = fgx1 ^ bgx1; eorx2  = fgx2 ^ bgx2;
        eorx1  = fgx1 ^ bgx1; eorx2  = fgx2 ^ bgx2;
 
 
        while (count--) {
        while (count--) {
 
 
                /* I think, unrolling the loops like in the 1 plane case isn't
                /* I think, unrolling the loops like in the 1 plane case isn't
                 * practicable here, because the body is much longer for 4
                 * practicable here, because the body is much longer for 4
                 * planes (mostly the dup4l()). I guess, unrolling this would
                 * planes (mostly the dup4l()). I guess, unrolling this would
                 * need more than 256 bytes and so exceed the instruction
                 * need more than 256 bytes and so exceed the instruction
                 * cache :-(
                 * cache :-(
                 */
                 */
 
 
                c = *s++;
                c = *s++;
                cdat  = p->fontdata + (c * p->fontheight);
                cdat  = p->fontdata + (c * p->fontheight);
 
 
                for(rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
                for(rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
                        fdx = dup4l(*cdat++);
                        fdx = dup4l(*cdat++);
                        __asm__ __volatile__
                        __asm__ __volatile__
                                ("movepl %1,%0@(0)\n\t"
                                ("movepl %1,%0@(0)\n\t"
                                  "movepl %2,%0@(8)"
                                  "movepl %2,%0@(8)"
                                  : /* no outputs */
                                  : /* no outputs */
                                  : "a" (dest), "d" ((fdx & eorx1) ^ bgx1),
                                  : "a" (dest), "d" ((fdx & eorx1) ^ bgx1),
                                  "d" ((fdx & eorx2) ^ bgx2)
                                  "d" ((fdx & eorx2) ^ bgx2)
                                );
                                );
                }
                }
                INC_8P(dest0);
                INC_8P(dest0);
        }
        }
}
}
 
 
 
 
static void rev_char_8_plane(struct display *p, int x, int y)
static void rev_char_8_plane(struct display *p, int x, int y)
{
{
   u_char *dest;
   u_char *dest;
   int j;
   int j;
   int bytes;
   int bytes;
 
 
   dest = p->screen_base + y * p->fontheight * p->next_line + (x>>1)*16 + (x & 1);
   dest = p->screen_base + y * p->fontheight * p->next_line + (x>>1)*16 + (x & 1);
   j = p->fontheight;
   j = p->fontheight;
   bytes = p->next_line;
   bytes = p->next_line;
 
 
   while (j--)
   while (j--)
     {
     {
      /* This should really obey the individual character's
      /* This should really obey the individual character's
       * background and foreground colors instead of simply
       * background and foreground colors instead of simply
       * inverting. For 8 plane mode, only the lower 4 bits of the
       * inverting. For 8 plane mode, only the lower 4 bits of the
       * color are inverted, because only that color registers have
       * color are inverted, because only that color registers have
       * been set up.
       * been set up.
       */
       */
       dest[0] = ~dest[0];
       dest[0] = ~dest[0];
       dest[2] = ~dest[2];
       dest[2] = ~dest[2];
       dest[4] = ~dest[4];
       dest[4] = ~dest[4];
       dest[6] = ~dest[6];
       dest[6] = ~dest[6];
       dest += bytes;
       dest += bytes;
     }
     }
}
}
#endif /* CONFIG_FBCON_8PLANE */
#endif /* CONFIG_FBCON_8PLANE */
 
 
 
 
/* ====================================================================== */
/* ====================================================================== */
 
 
#ifdef CONFIG_FBCON_8PACKED
#ifdef CONFIG_FBCON_8PACKED
 
 
   /*
   /*
    *    8 bpp Packed Pixels
    *    8 bpp Packed Pixels
    */
    */
 
 
static u_long nibbletab_8_packed[]={
static u_long nibbletab_8_packed[]={
0x00000000,0x000000ff,0x0000ff00,0x0000ffff,
0x00000000,0x000000ff,0x0000ff00,0x0000ffff,
0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff,
0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff,
0xff000000,0xff0000ff,0xff00ff00,0xff00ffff,
0xff000000,0xff0000ff,0xff00ff00,0xff00ffff,
0xffff0000,0xffff00ff,0xffffff00,0xffffffff};
0xffff0000,0xffff00ff,0xffffff00,0xffffffff};
 
 
static void bmove_8_packed(struct display *p, int sy, int sx, int dy, int dx,
static void bmove_8_packed(struct display *p, int sy, int sx, int dy, int dx,
                           int height, int width)
                           int height, int width)
{
{
        int bytes = p->next_line, linesize = bytes * p->fontheight, rows;
        int bytes = p->next_line, linesize = bytes * p->fontheight, rows;
        u_char *src,*dst;
        u_char *src,*dst;
 
 
        if (sx == 0 && dx == 0 && width * 8 == bytes) {
        if (sx == 0 && dx == 0 && width * 8 == bytes) {
                mymemmove(p->screen_base + dy * linesize,
                mymemmove(p->screen_base + dy * linesize,
                          p->screen_base + sy * linesize,
                          p->screen_base + sy * linesize,
                          height * linesize);
                          height * linesize);
        }
        }
        else {
        else {
                if (dy < sy || (dy == sy && dx < sx)) {
                if (dy < sy || (dy == sy && dx < sx)) {
                        src = p->screen_base + sy * linesize + sx * 8;
                        src = p->screen_base + sy * linesize + sx * 8;
                        dst = p->screen_base + dy * linesize + dx * 8;
                        dst = p->screen_base + dy * linesize + dx * 8;
                        for (rows = height * p->fontheight ; rows-- ;) {
                        for (rows = height * p->fontheight ; rows-- ;) {
                                mymemmove(dst, src, width * 8);
                                mymemmove(dst, src, width * 8);
                                src += bytes;
                                src += bytes;
                                dst += bytes;
                                dst += bytes;
                        }
                        }
                }
                }
                else {
                else {
                        src = p->screen_base + (sy+height) * linesize + sx * 8
                        src = p->screen_base + (sy+height) * linesize + sx * 8
                                - bytes;
                                - bytes;
                        dst = p->screen_base + (dy+height) * linesize + dx * 8
                        dst = p->screen_base + (dy+height) * linesize + dx * 8
                                - bytes;
                                - bytes;
                        for (rows = height * p->fontheight ; rows-- ;) {
                        for (rows = height * p->fontheight ; rows-- ;) {
                                mymemmove(dst, src, width * 8);
                                mymemmove(dst, src, width * 8);
                                src -= bytes;
                                src -= bytes;
                                dst -= bytes;
                                dst -= bytes;
                        }
                        }
                }
                }
        }
        }
}
}
 
 
 
 
static void clear_8_packed(struct vc_data *conp, struct display *p, int sy,
static void clear_8_packed(struct vc_data *conp, struct display *p, int sy,
                           int sx, int height, int width)
                           int sx, int height, int width)
{
{
        u_char *dest0,*dest;
        u_char *dest0,*dest;
        int bytes=p->next_line,lines=height * p->fontheight, rows, i;
        int bytes=p->next_line,lines=height * p->fontheight, rows, i;
        u_long bgx;
        u_long bgx;
 
 
        dest = p->screen_base + sy * p->fontheight * bytes + sx * 8;
        dest = p->screen_base + sy * p->fontheight * bytes + sx * 8;
 
 
        bgx=attr_bgcol_ec(p,conp);
        bgx=attr_bgcol_ec(p,conp);
        bgx |= (bgx << 8);
        bgx |= (bgx << 8);
        bgx |= (bgx << 16);
        bgx |= (bgx << 16);
 
 
        if (sx == 0 && width * 8 == bytes) {
        if (sx == 0 && width * 8 == bytes) {
                for (i = 0 ; i < lines * width ; i++) {
                for (i = 0 ; i < lines * width ; i++) {
                        ((u_long *)dest)[0]=bgx;
                        ((u_long *)dest)[0]=bgx;
                        ((u_long *)dest)[1]=bgx;
                        ((u_long *)dest)[1]=bgx;
                        dest+=8;
                        dest+=8;
                }
                }
        } else {
        } else {
                dest0=dest;
                dest0=dest;
                for (rows = lines; rows-- ; dest0 += bytes) {
                for (rows = lines; rows-- ; dest0 += bytes) {
                        dest=dest0;
                        dest=dest0;
                        for (i = 0 ; i < width ; i++) {
                        for (i = 0 ; i < width ; i++) {
                                ((u_long *)dest)[0]=bgx;
                                ((u_long *)dest)[0]=bgx;
                                ((u_long *)dest)[1]=bgx;
                                ((u_long *)dest)[1]=bgx;
                                dest+=8;
                                dest+=8;
                        }
                        }
                }
                }
        }
        }
}
}
 
 
 
 
static void putc_8_packed(struct vc_data *conp, struct display *p, int c, int y,
static void putc_8_packed(struct vc_data *conp, struct display *p, int c, int y,
                          int x)
                          int x)
{
{
        u_char *dest,*cdat;
        u_char *dest,*cdat;
        int bytes=p->next_line,rows;
        int bytes=p->next_line,rows;
        ulong eorx,fgx,bgx;
        ulong eorx,fgx,bgx;
 
 
        c &= 0xff;
        c &= 0xff;
 
 
        dest = p->screen_base + y * p->fontheight * bytes + x * 8;
        dest = p->screen_base + y * p->fontheight * bytes + x * 8;
        cdat = p->fontdata + c * p->fontheight;
        cdat = p->fontdata + c * p->fontheight;
 
 
        fgx=attr_fgcol(p,conp);
        fgx=attr_fgcol(p,conp);
        bgx=attr_bgcol(p,conp);
        bgx=attr_bgcol(p,conp);
        fgx |= (fgx << 8);
        fgx |= (fgx << 8);
        fgx |= (fgx << 16);
        fgx |= (fgx << 16);
        bgx |= (bgx << 8);
        bgx |= (bgx << 8);
        bgx |= (bgx << 16);
        bgx |= (bgx << 16);
        eorx = fgx ^ bgx;
        eorx = fgx ^ bgx;
 
 
        for (rows = p->fontheight ; rows-- ; dest += bytes) {
        for (rows = p->fontheight ; rows-- ; dest += bytes) {
                ((u_long *)dest)[0]=
                ((u_long *)dest)[0]=
                        (nibbletab_8_packed[*cdat >> 4] & eorx) ^ bgx;
                        (nibbletab_8_packed[*cdat >> 4] & eorx) ^ bgx;
                ((u_long *)dest)[1]=
                ((u_long *)dest)[1]=
                        (nibbletab_8_packed[*cdat++ & 0xf] & eorx) ^ bgx;
                        (nibbletab_8_packed[*cdat++ & 0xf] & eorx) ^ bgx;
        }
        }
/*
/*
        for (rows = p->fontheight ; rows-- ; dest += bytes) {
        for (rows = p->fontheight ; rows-- ; dest += bytes) {
                ((u_long *)dest)[0]=
                ((u_long *)dest)[0]=
                        nibbletab_8_packed[*cdat >> 4];
                        nibbletab_8_packed[*cdat >> 4];
                ((u_long *)dest)[1]=
                ((u_long *)dest)[1]=
                        nibbletab_8_packed[*cdat++ & 0xf];
                        nibbletab_8_packed[*cdat++ & 0xf];
        }
        }
*/
*/
}
}
 
 
 
 
static void putcs_8_packed(struct vc_data *conp, struct display *p,
static void putcs_8_packed(struct vc_data *conp, struct display *p,
                           const char *s, int count, int y, int x)
                           const char *s, int count, int y, int x)
{
{
        u_char *cdat, c, *dest, *dest0;
        u_char *cdat, c, *dest, *dest0;
        int rows,bytes=p->next_line;
        int rows,bytes=p->next_line;
        u_long eorx, fgx, bgx;
        u_long eorx, fgx, bgx;
 
 
        dest0 = p->screen_base + y * p->fontheight * bytes + x * 8;
        dest0 = p->screen_base + y * p->fontheight * bytes + x * 8;
        fgx=attr_fgcol(p,conp);
        fgx=attr_fgcol(p,conp);
        bgx=attr_bgcol(p,conp);
        bgx=attr_bgcol(p,conp);
        fgx |= (fgx << 8);
        fgx |= (fgx << 8);
        fgx |= (fgx << 16);
        fgx |= (fgx << 16);
        bgx |= (bgx << 8);
        bgx |= (bgx << 8);
        bgx |= (bgx << 16);
        bgx |= (bgx << 16);
        eorx = fgx ^ bgx;
        eorx = fgx ^ bgx;
        while (count--) {
        while (count--) {
                c = *s++;
                c = *s++;
                cdat = p->fontdata + c * p->fontheight;
                cdat = p->fontdata + c * p->fontheight;
 
 
                for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
                for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
                        ((u_long *)dest)[0]=
                        ((u_long *)dest)[0]=
                        (nibbletab_8_packed[*cdat >> 4] & eorx) ^ bgx;
                        (nibbletab_8_packed[*cdat >> 4] & eorx) ^ bgx;
                        ((u_long *)dest)[1]=
                        ((u_long *)dest)[1]=
                        (nibbletab_8_packed[*cdat++ & 0xf] & eorx) ^ bgx;
                        (nibbletab_8_packed[*cdat++ & 0xf] & eorx) ^ bgx;
                }
                }
                dest0+=8;
                dest0+=8;
        }
        }
}
}
 
 
 
 
static void rev_char_8_packed(struct display *p, int x, int y)
static void rev_char_8_packed(struct display *p, int x, int y)
{
{
        u_char *dest;
        u_char *dest;
        int bytes=p->next_line, rows;
        int bytes=p->next_line, rows;
 
 
        dest = p->screen_base + y * p->fontheight * bytes + x * 8;
        dest = p->screen_base + y * p->fontheight * bytes + x * 8;
        for (rows = p->fontheight ; rows-- ; dest += bytes) {
        for (rows = p->fontheight ; rows-- ; dest += bytes) {
                ((u_long *)dest)[0] ^= 0x0f0f0f0f;
                ((u_long *)dest)[0] ^= 0x0f0f0f0f;
                ((u_long *)dest)[1] ^= 0x0f0f0f0f;
                ((u_long *)dest)[1] ^= 0x0f0f0f0f;
        }
        }
}
}
 
 
#endif /* CONFIG_FBCON_8PACKED */
#endif /* CONFIG_FBCON_8PACKED */
 
 
/* ====================================================================== */
/* ====================================================================== */
 
 
#ifdef CONFIG_FBCON_8PACKED_NOTALIGNED
#ifdef CONFIG_FBCON_8PACKED_NOTALIGNED
 
 
   /*
   /*
    *    8 bpp Packed Pixels
    *    8 bpp Packed Pixels
    */
    */
 
 
static u_long nibbletab_8_packed[]={
static u_long nibbletab_8_packed[]={
0x00000000,0x000000ff,0x0000ff00,0x0000ffff,
0x00000000,0x000000ff,0x0000ff00,0x0000ffff,
0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff,
0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff,
0xff000000,0xff0000ff,0xff00ff00,0xff00ffff,
0xff000000,0xff0000ff,0xff00ff00,0xff00ffff,
0xffff0000,0xffff00ff,0xffffff00,0xffffffff};
0xffff0000,0xffff00ff,0xffffff00,0xffffffff};
 
 
static void bmove_8_packed(struct display *p, int sy, int sx, int dy, int dx,
static void bmove_8_packed(struct display *p, int sy, int sx, int dy, int dx,
                           int height, int width)
                           int height, int width)
{
{
        int bytes = p->next_line, linesize = bytes * p->fontheight, rows;
        int bytes = p->next_line, linesize = bytes * p->fontheight, rows;
        u_char *src,*dst;
        u_char *src,*dst;
 
 
        if (sx == 0 && dx == 0 && width * 8 == bytes) {
        if (sx == 0 && dx == 0 && width * 8 == bytes) {
                mymemmove_notaligned(p->screen_base + p->var.yoffset + dy * linesize,
                mymemmove_notaligned(p->screen_base + p->var.yoffset + dy * linesize,
                          p->screen_base + p->var.yoffset + sy * linesize,
                          p->screen_base + p->var.yoffset + sy * linesize,
                          height * linesize);
                          height * linesize);
        }
        }
        else {
        else {
                if (dy < sy || (dy == sy && dx < sx)) {
                if (dy < sy || (dy == sy && dx < sx)) {
                        src = p->screen_base + p->var.yoffset + sy * linesize + sx * 8;
                        src = p->screen_base + p->var.yoffset + sy * linesize + sx * 8;
                        dst = p->screen_base + p->var.yoffset + dy * linesize + dx * 8;
                        dst = p->screen_base + p->var.yoffset + dy * linesize + dx * 8;
                        for (rows = height * p->fontheight ; rows-- ;) {
                        for (rows = height * p->fontheight ; rows-- ;) {
                                mymemmove_notaligned(dst, src, width * 8);
                                mymemmove_notaligned(dst, src, width * 8);
                                src += bytes;
                                src += bytes;
                                dst += bytes;
                                dst += bytes;
                        }
                        }
                }
                }
                else {
                else {
                        src = p->screen_base + p->var.yoffset + (sy+height) * linesize + sx * 8
                        src = p->screen_base + p->var.yoffset + (sy+height) * linesize + sx * 8
                                - bytes;
                                - bytes;
                        dst = p->screen_base + p->var.yoffset + (dy+height) * linesize + dx * 8
                        dst = p->screen_base + p->var.yoffset + (dy+height) * linesize + dx * 8
                                - bytes;
                                - bytes;
                        for (rows = height * p->fontheight ; rows-- ;) {
                        for (rows = height * p->fontheight ; rows-- ;) {
                                mymemmove_notaligned(dst, src, width * 8);
                                mymemmove_notaligned(dst, src, width * 8);
                                src -= bytes;
                                src -= bytes;
                                dst -= bytes;
                                dst -= bytes;
                        }
                        }
                }
                }
        }
        }
}
}
 
 
 
 
static void clear_8_packed(struct vc_data *conp, struct display *p, int sy,
static void clear_8_packed(struct vc_data *conp, struct display *p, int sy,
                           int sx, int height, int width)
                           int sx, int height, int width)
{
{
        u_long dest0,dest;
        u_long dest0,dest;
        int bytes=p->next_line,lines=height * p->fontheight, rows, i;
        int bytes=p->next_line,lines=height * p->fontheight, rows, i;
        u_long bgx;
        u_long bgx;
        u_long fb_base = (u_long)p->screen_base;
        u_long fb_base = (u_long)p->screen_base;
 
 
        dest = fb_base + p->var.yoffset + sy * p->fontheight * bytes + sx * 8;
        dest = fb_base + p->var.yoffset + sy * p->fontheight * bytes + sx * 8;
 
 
        bgx=attr_bgcol_ec(p,conp);
        bgx=attr_bgcol_ec(p,conp);
        bgx |= (bgx << 8);
        bgx |= (bgx << 8);
        bgx |= (bgx << 16);
        bgx |= (bgx << 16);
 
 
        if (sx == 0 && width * 8 == bytes) {
        if (sx == 0 && width * 8 == bytes) {
                for (i = 0 ; i < lines * width ; i++) {
                for (i = 0 ; i < lines * width ; i++) {
                        *((u_long *)CRT_WRAP(fb_base, dest)) = bgx;
                        *((u_long *)CRT_WRAP(fb_base, dest)) = bgx;
                        *((u_long *)CRT_WRAP(fb_base, dest + 4)) = bgx;
                        *((u_long *)CRT_WRAP(fb_base, dest + 4)) = bgx;
                        dest+=8;
                        dest+=8;
                }
                }
        } else {
        } else {
                dest0=dest;
                dest0=dest;
                for (rows = lines; rows-- ; dest0 += bytes) {
                for (rows = lines; rows-- ; dest0 += bytes) {
                        dest=dest0;
                        dest=dest0;
                        for (i = 0 ; i < width ; i++) {
                        for (i = 0 ; i < width ; i++) {
                                *((u_long *)CRT_WRAP(fb_base, dest0)) = bgx;
                                *((u_long *)CRT_WRAP(fb_base, dest0)) = bgx;
                                *((u_long *)CRT_WRAP(fb_base, dest0 + 4)) = bgx;
                                *((u_long *)CRT_WRAP(fb_base, dest0 + 4)) = bgx;
                                dest+=8;
                                dest+=8;
                        }
                        }
                }
                }
        }
        }
}
}
 
 
 
 
static void putc_8_packed(struct vc_data *conp, struct display *p, int c, int y,
static void putc_8_packed(struct vc_data *conp, struct display *p, int c, int y,
                          int x)
                          int x)
{
{
        u_long dest;
        u_long dest;
        u_char *cdat;
        u_char *cdat;
        int bytes=p->next_line,rows;
        int bytes=p->next_line,rows;
        ulong eorx,fgx,bgx;
        ulong eorx,fgx,bgx;
        u_long fb_base = (u_long)p->screen_base;
        u_long fb_base = (u_long)p->screen_base;
 
 
        c &= 0xff;
        c &= 0xff;
 
 
        dest = fb_base + p->var.yoffset + y * p->fontheight * bytes + x * 8;
        dest = fb_base + p->var.yoffset + y * p->fontheight * bytes + x * 8;
        cdat = p->fontdata + c * p->fontheight;
        cdat = p->fontdata + c * p->fontheight;
 
 
        fgx=attr_fgcol(p,conp);
        fgx=attr_fgcol(p,conp);
        bgx=attr_bgcol(p,conp);
        bgx=attr_bgcol(p,conp);
        fgx |= (fgx << 8);
        fgx |= (fgx << 8);
        fgx |= (fgx << 16);
        fgx |= (fgx << 16);
        bgx |= (bgx << 8);
        bgx |= (bgx << 8);
        bgx |= (bgx << 16);
        bgx |= (bgx << 16);
        eorx = fgx ^ bgx;
        eorx = fgx ^ bgx;
 
 
        for (rows = p->fontheight ; rows-- ; dest += bytes) {
        for (rows = p->fontheight ; rows-- ; dest += bytes) {
                *((u_long *)CRT_WRAP(fb_base, dest)) =
                *((u_long *)CRT_WRAP(fb_base, dest)) =
                        (nibbletab_8_packed[*cdat >> 4] & eorx) ^ bgx;
                        (nibbletab_8_packed[*cdat >> 4] & eorx) ^ bgx;
                *((u_long *)CRT_WRAP(fb_base, dest + 4)) =
                *((u_long *)CRT_WRAP(fb_base, dest + 4)) =
                        (nibbletab_8_packed[*cdat++ & 0xf] & eorx) ^ bgx;
                        (nibbletab_8_packed[*cdat++ & 0xf] & eorx) ^ bgx;
        }
        }
}
}
 
 
 
 
static void putcs_8_packed(struct vc_data *conp, struct display *p,
static void putcs_8_packed(struct vc_data *conp, struct display *p,
                           const char *s, int count, int y, int x)
                           const char *s, int count, int y, int x)
{
{
        u_long dest, dest0;
        u_long dest, dest0;
        u_char *cdat, c;
        u_char *cdat, c;
        int rows,bytes=p->next_line;
        int rows,bytes=p->next_line;
        u_long eorx, fgx, bgx;
        u_long eorx, fgx, bgx;
        u_long fb_base = (u_long)p->screen_base;
        u_long fb_base = (u_long)p->screen_base;
 
 
 
 
        dest0 = fb_base + p->var.yoffset + y * p->fontheight * bytes + x * 8;
        dest0 = fb_base + p->var.yoffset + y * p->fontheight * bytes + x * 8;
        fgx=attr_fgcol(p,conp);
        fgx=attr_fgcol(p,conp);
        bgx=attr_bgcol(p,conp);
        bgx=attr_bgcol(p,conp);
        fgx |= (fgx << 8);
        fgx |= (fgx << 8);
        fgx |= (fgx << 16);
        fgx |= (fgx << 16);
        bgx |= (bgx << 8);
        bgx |= (bgx << 8);
        bgx |= (bgx << 16);
        bgx |= (bgx << 16);
        eorx = fgx ^ bgx;
        eorx = fgx ^ bgx;
        while (count--) {
        while (count--) {
                c = *s++;
                c = *s++;
                cdat = p->fontdata + c * p->fontheight;
                cdat = p->fontdata + c * p->fontheight;
 
 
                for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
                for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
                        *((u_long *)CRT_WRAP(fb_base, dest)) =
                        *((u_long *)CRT_WRAP(fb_base, dest)) =
                        (nibbletab_8_packed[*cdat >> 4] & eorx) ^ bgx;
                        (nibbletab_8_packed[*cdat >> 4] & eorx) ^ bgx;
                        *((u_long *)CRT_WRAP(fb_base, dest + 4)) =
                        *((u_long *)CRT_WRAP(fb_base, dest + 4)) =
                        (nibbletab_8_packed[*cdat++ & 0xf] & eorx) ^ bgx;
                        (nibbletab_8_packed[*cdat++ & 0xf] & eorx) ^ bgx;
                }
                }
                dest0+=8;
                dest0+=8;
        }
        }
}
}
 
 
 
 
static void rev_char_8_packed(struct display *p, int x, int y)
static void rev_char_8_packed(struct display *p, int x, int y)
{
{
        u_long dest;
        u_long dest;
        int bytes=p->next_line, rows;
        int bytes=p->next_line, rows;
        u_long fb_base = (u_long)p->screen_base;
        u_long fb_base = (u_long)p->screen_base;
 
 
 
 
        dest = fb_base + p->var.yoffset + y * p->fontheight * bytes + x * 8;
        dest = fb_base + p->var.yoffset + y * p->fontheight * bytes + x * 8;
        for (rows = p->fontheight ; rows-- ; dest += bytes) {
        for (rows = p->fontheight ; rows-- ; dest += bytes) {
                *((u_long *)CRT_WRAP(fb_base, dest)) ^= 0x0f0f0f0f;
                *((u_long *)CRT_WRAP(fb_base, dest)) ^= 0x0f0f0f0f;
                *((u_long *)CRT_WRAP(fb_base, dest + 4)) ^= 0x0f0f0f0f;
                *((u_long *)CRT_WRAP(fb_base, dest + 4)) ^= 0x0f0f0f0f;
        }
        }
}
}
 
 
#endif /* CONFIG_FBCON_8PACKED_NOTALIGNED */
#endif /* CONFIG_FBCON_8PACKED_NOTALIGNED */
 
 
 
 
/* ====================================================================== */
/* ====================================================================== */
 
 
#ifdef CONFIG_FBCON_16PACKED
#ifdef CONFIG_FBCON_16PACKED
 
 
   /*
   /*
    *    16 bpp Packed Pixels
    *    16 bpp Packed Pixels
    */
    */
 
 
u_short packed16_cmap[16];
u_short packed16_cmap[16];
 
 
static u_long tab_16_packed[]={
static u_long tab_16_packed[]={
0x00000000,0x0000ffff,0xffff0000,0xffffffff};
0x00000000,0x0000ffff,0xffff0000,0xffffffff};
 
 
static void bmove_16_packed(struct display *p, int sy, int sx, int dy, int dx,
static void bmove_16_packed(struct display *p, int sy, int sx, int dy, int dx,
                            int height, int width)
                            int height, int width)
{
{
        int bytes = p->next_line, linesize = bytes * p->fontheight, rows;
        int bytes = p->next_line, linesize = bytes * p->fontheight, rows;
        u_char *src,*dst;
        u_char *src,*dst;
 
 
        if (sx == 0 && dx == 0 && width * 16 == bytes) {
        if (sx == 0 && dx == 0 && width * 16 == bytes) {
                mymemmove(p->screen_base + dy * linesize,
                mymemmove(p->screen_base + dy * linesize,
                          p->screen_base + sy * linesize,
                          p->screen_base + sy * linesize,
                          height * linesize);
                          height * linesize);
        }
        }
        else {
        else {
                if (dy < sy || (dy == sy && dx < sx)) {
                if (dy < sy || (dy == sy && dx < sx)) {
                        src = p->screen_base + sy * linesize + sx * 16;
                        src = p->screen_base + sy * linesize + sx * 16;
                        dst = p->screen_base + dy * linesize + dx * 16;
                        dst = p->screen_base + dy * linesize + dx * 16;
                        for (rows = height * p->fontheight ; rows-- ;) {
                        for (rows = height * p->fontheight ; rows-- ;) {
                                mymemmove(dst, src, width * 16);
                                mymemmove(dst, src, width * 16);
                                src += bytes;
                                src += bytes;
                                dst += bytes;
                                dst += bytes;
                        }
                        }
                }
                }
                else {
                else {
                        src = p->screen_base + (sy+height) * linesize + sx * 16
                        src = p->screen_base + (sy+height) * linesize + sx * 16
                                - bytes;
                                - bytes;
                        dst = p->screen_base + (dy+height) * linesize + dx * 16
                        dst = p->screen_base + (dy+height) * linesize + dx * 16
                                - bytes;
                                - bytes;
                        for (rows = height * p->fontheight ; rows-- ;) {
                        for (rows = height * p->fontheight ; rows-- ;) {
                                mymemmove(dst, src, width * 16);
                                mymemmove(dst, src, width * 16);
                                src -= bytes;
                                src -= bytes;
                                dst -= bytes;
                                dst -= bytes;
                        }
                        }
                }
                }
        }
        }
}
}
 
 
 
 
static void clear_16_packed(struct vc_data *conp, struct display *p, int sy,
static void clear_16_packed(struct vc_data *conp, struct display *p, int sy,
                            int sx, int height, int width)
                            int sx, int height, int width)
{
{
        u_char *dest0,*dest;
        u_char *dest0,*dest;
        int bytes=p->next_line,lines=height * p->fontheight, rows, i;
        int bytes=p->next_line,lines=height * p->fontheight, rows, i;
        u_long bgx;
        u_long bgx;
 
 
        dest = p->screen_base + sy * p->fontheight * bytes + sx * 16;
        dest = p->screen_base + sy * p->fontheight * bytes + sx * 16;
 
 
        bgx = attr_bgcol_ec(p,conp);
        bgx = attr_bgcol_ec(p,conp);
        bgx = packed16_cmap[bgx];
        bgx = packed16_cmap[bgx];
        bgx |= (bgx << 16);
        bgx |= (bgx << 16);
 
 
        if (sx == 0 && width * 16 == bytes) {
        if (sx == 0 && width * 16 == bytes) {
                for (i = 0 ; i < lines * width ; i++) {
                for (i = 0 ; i < lines * width ; i++) {
                        ((u_long *)dest)[0]=bgx;
                        ((u_long *)dest)[0]=bgx;
                        ((u_long *)dest)[1]=bgx;
                        ((u_long *)dest)[1]=bgx;
                        ((u_long *)dest)[2]=bgx;
                        ((u_long *)dest)[2]=bgx;
                        ((u_long *)dest)[3]=bgx;
                        ((u_long *)dest)[3]=bgx;
                        dest+=16;
                        dest+=16;
                }
                }
        } else {
        } else {
                dest0=dest;
                dest0=dest;
                for (rows = lines; rows-- ; dest0 += bytes) {
                for (rows = lines; rows-- ; dest0 += bytes) {
                        dest=dest0;
                        dest=dest0;
                        for (i = 0 ; i < width ; i++) {
                        for (i = 0 ; i < width ; i++) {
                                ((u_long *)dest)[0]=bgx;
                                ((u_long *)dest)[0]=bgx;
                                ((u_long *)dest)[1]=bgx;
                                ((u_long *)dest)[1]=bgx;
                                ((u_long *)dest)[2]=bgx;
                                ((u_long *)dest)[2]=bgx;
                                ((u_long *)dest)[3]=bgx;
                                ((u_long *)dest)[3]=bgx;
                                dest+=16;
                                dest+=16;
                        }
                        }
                }
                }
        }
        }
}
}
 
 
 
 
static void putc_16_packed(struct vc_data *conp, struct display *p, int c,
static void putc_16_packed(struct vc_data *conp, struct display *p, int c,
                           int y, int x)
                           int y, int x)
{
{
        u_char *dest,*cdat;
        u_char *dest,*cdat;
        int bytes=p->next_line,rows;
        int bytes=p->next_line,rows;
        ulong eorx,fgx,bgx;
        ulong eorx,fgx,bgx;
 
 
        c &= 0xff;
        c &= 0xff;
 
 
        dest = p->screen_base + y * p->fontheight * bytes + x * 16;
        dest = p->screen_base + y * p->fontheight * bytes + x * 16;
        cdat = p->fontdata + c * p->fontheight;
        cdat = p->fontdata + c * p->fontheight;
 
 
        fgx = attr_fgcol(p,conp);
        fgx = attr_fgcol(p,conp);
        fgx = packed16_cmap[fgx];
        fgx = packed16_cmap[fgx];
        bgx = attr_bgcol(p,conp);
        bgx = attr_bgcol(p,conp);
        bgx = packed16_cmap[bgx];
        bgx = packed16_cmap[bgx];
        fgx |= (fgx << 16);
        fgx |= (fgx << 16);
        bgx |= (bgx << 16);
        bgx |= (bgx << 16);
        eorx = fgx ^ bgx;
        eorx = fgx ^ bgx;
 
 
        for (rows = p->fontheight ; rows-- ; dest += bytes) {
        for (rows = p->fontheight ; rows-- ; dest += bytes) {
                ((u_long *)dest)[0]=
                ((u_long *)dest)[0]=
                        (tab_16_packed[*cdat >> 6] & eorx) ^ bgx;
                        (tab_16_packed[*cdat >> 6] & eorx) ^ bgx;
                ((u_long *)dest)[1]=
                ((u_long *)dest)[1]=
                        (tab_16_packed[*cdat >> 4 & 0x3] & eorx) ^ bgx;
                        (tab_16_packed[*cdat >> 4 & 0x3] & eorx) ^ bgx;
                ((u_long *)dest)[2]=
                ((u_long *)dest)[2]=
                        (tab_16_packed[*cdat >> 2 & 0x3] & eorx) ^ bgx;
                        (tab_16_packed[*cdat >> 2 & 0x3] & eorx) ^ bgx;
                ((u_long *)dest)[3]=
                ((u_long *)dest)[3]=
                        (tab_16_packed[*cdat++ & 0x3] & eorx) ^ bgx;
                        (tab_16_packed[*cdat++ & 0x3] & eorx) ^ bgx;
        }
        }
}
}
 
 
 
 
/* TODO */
/* TODO */
static void putcs_16_packed(struct vc_data *conp, struct display *p,
static void putcs_16_packed(struct vc_data *conp, struct display *p,
                            const char *s, int count, int y, int x)
                            const char *s, int count, int y, int x)
{
{
        u_char *cdat, c, *dest, *dest0;
        u_char *cdat, c, *dest, *dest0;
        int rows,bytes=p->next_line;
        int rows,bytes=p->next_line;
        u_long eorx, fgx, bgx;
        u_long eorx, fgx, bgx;
 
 
        dest0 = p->screen_base + y * p->fontheight * bytes + x * 16;
        dest0 = p->screen_base + y * p->fontheight * bytes + x * 16;
        fgx = attr_fgcol(p,conp);
        fgx = attr_fgcol(p,conp);
        fgx = packed16_cmap[fgx];
        fgx = packed16_cmap[fgx];
        bgx = attr_bgcol(p,conp);
        bgx = attr_bgcol(p,conp);
        bgx = packed16_cmap[bgx];
        bgx = packed16_cmap[bgx];
        fgx |= (fgx << 16);
        fgx |= (fgx << 16);
        bgx |= (bgx << 16);
        bgx |= (bgx << 16);
        eorx = fgx ^ bgx;
        eorx = fgx ^ bgx;
        while (count--) {
        while (count--) {
                c = *s++;
                c = *s++;
                cdat = p->fontdata + c * p->fontheight;
                cdat = p->fontdata + c * p->fontheight;
 
 
                for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
                for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
                        ((u_long *)dest)[0]=
                        ((u_long *)dest)[0]=
                                (tab_16_packed[*cdat >> 6] & eorx) ^ bgx;
                                (tab_16_packed[*cdat >> 6] & eorx) ^ bgx;
                        ((u_long *)dest)[1]=
                        ((u_long *)dest)[1]=
                                (tab_16_packed[*cdat >> 4 & 0x3] & eorx) ^ bgx;
                                (tab_16_packed[*cdat >> 4 & 0x3] & eorx) ^ bgx;
                        ((u_long *)dest)[2]=
                        ((u_long *)dest)[2]=
                                (tab_16_packed[*cdat >> 2 & 0x3] & eorx) ^ bgx;
                                (tab_16_packed[*cdat >> 2 & 0x3] & eorx) ^ bgx;
                        ((u_long *)dest)[3]=
                        ((u_long *)dest)[3]=
                                (tab_16_packed[*cdat++ & 0x3] & eorx) ^ bgx;
                                (tab_16_packed[*cdat++ & 0x3] & eorx) ^ bgx;
                }
                }
                dest0+=16;
                dest0+=16;
        }
        }
}
}
 
 
 
 
static void rev_char_16_packed(struct display *p, int x, int y)
static void rev_char_16_packed(struct display *p, int x, int y)
{
{
        u_char *dest;
        u_char *dest;
        int bytes=p->next_line, rows;
        int bytes=p->next_line, rows;
 
 
        dest = p->screen_base + y * p->fontheight * bytes + x * 16;
        dest = p->screen_base + y * p->fontheight * bytes + x * 16;
        for (rows = p->fontheight ; rows-- ; dest += bytes) {
        for (rows = p->fontheight ; rows-- ; dest += bytes) {
                ((u_long *)dest)[0] ^= 0xffffffff;
                ((u_long *)dest)[0] ^= 0xffffffff;
                ((u_long *)dest)[1] ^= 0xffffffff;
                ((u_long *)dest)[1] ^= 0xffffffff;
                ((u_long *)dest)[2] ^= 0xffffffff;
                ((u_long *)dest)[2] ^= 0xffffffff;
                ((u_long *)dest)[3] ^= 0xffffffff;
                ((u_long *)dest)[3] ^= 0xffffffff;
        }
        }
}
}
 
 
#endif /* CONFIG_FBCON_16PACKED */
#endif /* CONFIG_FBCON_16PACKED */
 
 
 
 
/* ====================================================================== */
/* ====================================================================== */
 
 
#ifdef CONFIG_FBCON_CYBER
#ifdef CONFIG_FBCON_CYBER
 
 
   /*
   /*
    *    Cybervision (accelerated)
    *    Cybervision (accelerated)
    */
    */
 
 
static void bmove_cyber(struct display *p, int sy, int sx, int dy, int dx,
static void bmove_cyber(struct display *p, int sy, int sx, int dy, int dx,
                        int height, int width)
                        int height, int width)
{
{
        sx *= 8; dx *= 8; width *= 8;
        sx *= 8; dx *= 8; width *= 8;
        Cyber_BitBLT((u_short)sx, (u_short)(sy*p->fontheight), (u_short)dx,
        Cyber_BitBLT((u_short)sx, (u_short)(sy*p->fontheight), (u_short)dx,
                (u_short)(dy*p->fontheight), (u_short)width,
                (u_short)(dy*p->fontheight), (u_short)width,
                (u_short)(height*p->fontheight), (u_short)S3_NEW);
                (u_short)(height*p->fontheight), (u_short)S3_NEW);
}
}
 
 
 
 
static void clear_cyber(struct vc_data *conp, struct display *p, int sy, int sx,
static void clear_cyber(struct vc_data *conp, struct display *p, int sy, int sx,
                        int height, int width)
                        int height, int width)
{
{
   u_char bg;
   u_char bg;
 
 
        sx *= 8; width *= 8;
        sx *= 8; width *= 8;
        bg = attr_bgcol_ec(p,conp);
        bg = attr_bgcol_ec(p,conp);
   Cyber_RectFill((u_short)sx, (u_short)(sy*p->fontheight), (u_short)width,
   Cyber_RectFill((u_short)sx, (u_short)(sy*p->fontheight), (u_short)width,
                  (u_short)(height*p->fontheight), (u_short)S3_NEW,
                  (u_short)(height*p->fontheight), (u_short)S3_NEW,
                  (u_short)bg);
                  (u_short)bg);
}
}
 
 
 
 
static void putc_cyber(struct vc_data *conp, struct display *p, int c, int y,
static void putc_cyber(struct vc_data *conp, struct display *p, int c, int y,
                       int x)
                       int x)
{
{
        u_char *dest, *cdat;
        u_char *dest, *cdat;
        u_long tmp;
        u_long tmp;
        u_int rows, reverse, underline;
        u_int rows, reverse, underline;
        u_char d;
        u_char d;
   u_char fg, bg;
   u_char fg, bg;
 
 
   c &= 0xff;
   c &= 0xff;
 
 
        dest = p->screen_base+y*p->fontheight*p->next_line+8*x;
        dest = p->screen_base+y*p->fontheight*p->next_line+8*x;
        cdat = p->fontdata+(c*p->fontheight);
        cdat = p->fontdata+(c*p->fontheight);
   fg = disp->fgcol;
   fg = disp->fgcol;
   bg = disp->bgcol;
   bg = disp->bgcol;
        reverse = conp->vc_reverse;
        reverse = conp->vc_reverse;
        underline = conp->vc_underline;
        underline = conp->vc_underline;
 
 
   Cyber_WaitBlit();
   Cyber_WaitBlit();
        for (rows = p->fontheight; rows--; dest += p->next_line) {
        for (rows = p->fontheight; rows--; dest += p->next_line) {
                d = *cdat++;
                d = *cdat++;
 
 
                if (underline && !rows)
                if (underline && !rows)
                        d = 0xff;
                        d = 0xff;
                if (reverse)
                if (reverse)
                        d = ~d;
                        d = ~d;
 
 
      tmp =  ((d & 0x80) ? fg : bg) << 24;
      tmp =  ((d & 0x80) ? fg : bg) << 24;
      tmp |= ((d & 0x40) ? fg : bg) << 16;
      tmp |= ((d & 0x40) ? fg : bg) << 16;
      tmp |= ((d & 0x20) ? fg : bg) << 8;
      tmp |= ((d & 0x20) ? fg : bg) << 8;
      tmp |= ((d & 0x10) ? fg : bg);
      tmp |= ((d & 0x10) ? fg : bg);
      *((u_long*) dest) = tmp;
      *((u_long*) dest) = tmp;
      tmp =  ((d & 0x8) ? fg : bg) << 24;
      tmp =  ((d & 0x8) ? fg : bg) << 24;
      tmp |= ((d & 0x4) ? fg : bg) << 16;
      tmp |= ((d & 0x4) ? fg : bg) << 16;
      tmp |= ((d & 0x2) ? fg : bg) << 8;
      tmp |= ((d & 0x2) ? fg : bg) << 8;
      tmp |= ((d & 0x1) ? fg : bg);
      tmp |= ((d & 0x1) ? fg : bg);
      *((u_long*) dest + 1) = tmp;
      *((u_long*) dest + 1) = tmp;
        }
        }
}
}
 
 
 
 
static void putcs_cyber(struct vc_data *conp, struct display *p, const char *s,
static void putcs_cyber(struct vc_data *conp, struct display *p, const char *s,
                        int count, int y, int x)
                        int count, int y, int x)
{
{
        u_char *dest, *dest0, *cdat;
        u_char *dest, *dest0, *cdat;
   u_long tmp;
   u_long tmp;
        u_int rows, reverse, underline;
        u_int rows, reverse, underline;
        u_char c, d;
        u_char c, d;
   u_char fg, bg;
   u_char fg, bg;
 
 
        dest0 = p->screen_base+y*p->fontheight*p->next_line+8*x;
        dest0 = p->screen_base+y*p->fontheight*p->next_line+8*x;
   fg = disp->fgcol;
   fg = disp->fgcol;
   bg = disp->bgcol;
   bg = disp->bgcol;
        reverse = conp->vc_reverse;
        reverse = conp->vc_reverse;
        underline = conp->vc_underline;
        underline = conp->vc_underline;
 
 
   Cyber_WaitBlit();
   Cyber_WaitBlit();
        while (count--) {
        while (count--) {
                c = *s++;
                c = *s++;
                dest = dest0;
                dest = dest0;
      dest0 += 8;
      dest0 += 8;
                cdat = p->fontdata+(c*p->fontheight);
                cdat = p->fontdata+(c*p->fontheight);
                for (rows = p->fontheight; rows--; dest += p->next_line) {
                for (rows = p->fontheight; rows--; dest += p->next_line) {
                        d = *cdat++;
                        d = *cdat++;
 
 
                        if (underline && !rows)
                        if (underline && !rows)
                                d = 0xff;
                                d = 0xff;
                        if (reverse)
                        if (reverse)
                                d = ~d;
                                d = ~d;
 
 
         tmp =  ((d & 0x80) ? fg : bg) << 24;
         tmp =  ((d & 0x80) ? fg : bg) << 24;
         tmp |= ((d & 0x40) ? fg : bg) << 16;
         tmp |= ((d & 0x40) ? fg : bg) << 16;
         tmp |= ((d & 0x20) ? fg : bg) << 8;
         tmp |= ((d & 0x20) ? fg : bg) << 8;
         tmp |= ((d & 0x10) ? fg : bg);
         tmp |= ((d & 0x10) ? fg : bg);
         *((u_long*) dest) = tmp;
         *((u_long*) dest) = tmp;
         tmp =  ((d & 0x8) ? fg : bg) << 24;
         tmp =  ((d & 0x8) ? fg : bg) << 24;
         tmp |= ((d & 0x4) ? fg : bg) << 16;
         tmp |= ((d & 0x4) ? fg : bg) << 16;
         tmp |= ((d & 0x2) ? fg : bg) << 8;
         tmp |= ((d & 0x2) ? fg : bg) << 8;
         tmp |= ((d & 0x1) ? fg : bg);
         tmp |= ((d & 0x1) ? fg : bg);
         *((u_long*) dest + 1) = tmp;
         *((u_long*) dest + 1) = tmp;
                }
                }
        }
        }
}
}
 
 
 
 
static void rev_char_cyber(struct display *p, int x, int y)
static void rev_char_cyber(struct display *p, int x, int y)
{
{
        u_char *dest;
        u_char *dest;
        u_int rows;
        u_int rows;
   u_char fg, bg;
   u_char fg, bg;
 
 
   fg = disp->fgcol;
   fg = disp->fgcol;
   bg = disp->bgcol;
   bg = disp->bgcol;
 
 
        dest = p->screen_base+y*p->fontheight*p->next_line+8*x;
        dest = p->screen_base+y*p->fontheight*p->next_line+8*x;
   Cyber_WaitBlit();
   Cyber_WaitBlit();
        for (rows = p->fontheight; rows--; dest += p->next_line) {
        for (rows = p->fontheight; rows--; dest += p->next_line) {
                *dest = (*dest == fg) ? bg : fg;
                *dest = (*dest == fg) ? bg : fg;
      *(dest+1) = (*(dest + 1) == fg) ? bg : fg;
      *(dest+1) = (*(dest + 1) == fg) ? bg : fg;
      *(dest+2) = (*(dest + 2) == fg) ? bg : fg;
      *(dest+2) = (*(dest + 2) == fg) ? bg : fg;
      *(dest+3) = (*(dest + 3) == fg) ? bg : fg;
      *(dest+3) = (*(dest + 3) == fg) ? bg : fg;
      *(dest+4) = (*(dest + 4) == fg) ? bg : fg;
      *(dest+4) = (*(dest + 4) == fg) ? bg : fg;
      *(dest+5) = (*(dest + 5) == fg) ? bg : fg;
      *(dest+5) = (*(dest + 5) == fg) ? bg : fg;
      *(dest+6) = (*(dest + 6) == fg) ? bg : fg;
      *(dest+6) = (*(dest + 6) == fg) ? bg : fg;
      *(dest+7) = (*(dest + 7) == fg) ? bg : fg;
      *(dest+7) = (*(dest + 7) == fg) ? bg : fg;
        }
        }
}
}
 
 
#endif /* CONFIG_FBCON_CYBER */
#endif /* CONFIG_FBCON_CYBER */
 
 
 
 
/* ====================================================================== */
/* ====================================================================== */
 
 
   /*
   /*
    *    The console `switch' structure for the frame buffer based console
    *    The console `switch' structure for the frame buffer based console
    */
    */
 
 
struct consw fb_con = {
struct consw fb_con = {
   fbcon_startup, fbcon_init, fbcon_deinit, fbcon_clear, fbcon_putc,
   fbcon_startup, fbcon_init, fbcon_deinit, fbcon_clear, fbcon_putc,
   fbcon_putcs, fbcon_cursor, fbcon_scroll, fbcon_bmove, fbcon_switch,
   fbcon_putcs, fbcon_cursor, fbcon_scroll, fbcon_bmove, fbcon_switch,
   fbcon_blank, fbcon_get_font, fbcon_set_font
   fbcon_blank, fbcon_get_font, fbcon_set_font
};
};
 
 
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.