/*
 * linux/arch/m68k/console/fbcon.c -- Low level frame buffer based console
 *                                    driver
 *
 *    Copyright (C) 1995 Geert Uytterhoeven
 *
 *
 * This file is based on the original Amiga console driver (amicon.c):
 *
 *    Copyright (C) 1993 Hamish Macdonald
 *                       Greg Harp
 *    Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk]
 *
 *          with work by William Rucklidge (wjr@cs.cornell.edu)
 *                       Geert Uytterhoeven
 *                       Jes Sorensen (jds@kom.auc.dk)
 *                       Martin Apel
 *
 * and on the original Atari console driver (atacon.c):
 *
 *    Copyright (C) 1993 Bjoern Brauel
 *                       Roman Hodek
 *
 *          with work by Guenther Kelleter
 *                       Martin Schaller
 *                       Andreas Schwab
 *
 *
 * 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
 * for more details.
 */

/*
 * To do:
 *  - Implement 16 plane mode.
 *  - Add support for 16/24/32 bit packed pixels
 *  - Hardware cursor
 */


#include <linux/types.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/tty.h>
#include <linux/console.h>
#include <linux/string.h>
#include <linux/config.h>
#include <linux/kd.h>
#include <linux/malloc.h>

#include <asm/bootinfo.h>
#include <asm/irq.h>
#ifdef CONFIG_AMIGA
#include <asm/amigahw.h>
#include <asm/amigaints.h>
#endif /* CONFIG_AMIGA */
#ifdef CONFIG_ATARI
#include <asm/atariints.h>
#endif
#ifdef CONFIG_FB_CYBER
#include "../amiga/s3blit.h"
#endif /* CONFIG_FB_CYBER */
#include <linux/fb.h>
#include <asm/font.h>
#include <asm/machdep.h>

#include <asm/system.h>

#include "../../../drivers/char/vt_kern.h"   /* vt_cons and vc_resize_con() */


/* Import console_blanked from console.c */

extern int console_blanked;


   /*
    *    The following symbols select what modes are supported. They should
    *    be settable by the user ("make config") later.
    */

/* Clear all definitions */

#undef CONFIG_FBCON_MONO
#undef CONFIG_FBCON_ILBM
#undef CONFIG_FBCON_PLANES
#undef CONFIG_FBCON_2PLANE
#undef CONFIG_FBCON_4PLANE
#undef CONFIG_FBCON_8PLANE
#undef CONFIG_FBCON_8PACKED
#undef CONFIG_FBCON_16PACKED
#undef CONFIG_FBCON_24PACKED
#undef CONFIG_FBCON_32PACKED
#undef CONFIG_FBCON_CYBER


/* Monochrome is default */

#define CONFIG_FBCON_MONO

/* Amiga support */

#ifdef CONFIG_AMIGA
#ifndef CONFIG_FBCON_ILBM
#define CONFIG_FBCON_ILBM
#endif
#ifndef CONFIG_FBCON_PLANES
#define CONFIG_FBCON_PLANES
#endif

/* Cybervision Graphics Board */

#ifdef CONFIG_FB_CYBER
#ifndef CONFIG_FBCON_CYBER
#define CONFIG_FBCON_CYBER
#endif
#endif /* CONFIG_FB_CYBER */

#endif /* CONFIG_AMIGA */

/* Atari support */

#ifdef CONFIG_ATARI
#ifndef CONFIG_FBCON_2PLANE
#define CONFIG_FBCON_2PLANE
#endif
#ifndef CONFIG_FBCON_4PLANE
#define CONFIG_FBCON_4PLANE
#endif
#ifndef CONFIG_FBCON_8PLANE
#define CONFIG_FBCON_8PLANE
#endif
#ifndef CONFIG_FBCON_8PACKED
#define CONFIG_FBCON_8PACKED
#endif
#ifndef CONFIG_FBCON_16PACKED
#define CONFIG_FBCON_16PACKED
#endif
#endif /* CONFIG_ATARI */


/* Extra definitions to make the code more readable */

#if defined(CONFIG_FBCON_2PLANE) || defined(CONFIG_FBCON_4PLANE) || \
    defined(CONFIG_FBCON_8PLANE)
#define CONFIG_FBCON_IPLAN2
#else
#undef CONFIG_FBCON_IPLAN2
#endif

#if defined(CONFIG_FBCON_CYBER) || defined(CONFIG_FBCON_8PACKED) || \
    defined(CONFIG_FBCON_16PACKED) || defined(CONFIG_FBCON_24PACKED) || \
    defined(CONFIG_FBCON_32PACKED)
#define CONFIG_FBCON_PACKED
#else
#undef CONFIG_FBCON_PACKED
#endif


struct fb_info *fb_info;
struct display *disp;


/* ++Geert: Sorry, no hardware cursor support at the moment;
   use Atari alike software cursor */

static int cursor_drawn = 0;

#define CURSOR_DRAW_DELAY           (2)

/* # VBL ints between cursor state changes */
#define AMIGA_CURSOR_BLINK_RATE   (20)
#define ATARI_CURSOR_BLINK_RATE   (42)

static int vbl_cursor_cnt = 0;
static int cursor_on = 0;
static int cursor_blink_rate;

static __inline__ int CURSOR_UNDRAWN(void)
{
  return 0;
}

   /*
    *    Attribute Decoding
    */

/* Color */
#define attr_fgcol(p,conp)    \
	(((conp)->vc_attr >> ((p)->inverse ? 4 : 0)) & 0x0f)
#define attr_bgcol(p,conp)    \
	(((conp)->vc_attr >> ((p)->inverse ? 0 : 4)) & 0x0f)
#define	attr_bgcol_ec(p,conp) \
	(((conp)->vc_video_erase_char >> ((p)->inverse ? 8 : 12)) & 0x0f)

/* Monochrome */
#define attr_bold(p,conp)     \
	(((conp)->vc_attr & 3) == 2)
#define attr_reverse(p,conp)  \
	(((conp)->vc_attr & 8) ^ ((p)->inverse ? 8 : 0))
#define attr_underline(p,conp) \
	(((conp)->vc_attr) & 4)


   /*
    *    Scroll Method
    */

#define SCROLL_YWRAP          (0)
#define SCROLL_YPAN           (1)
#define SCROLL_YMOVE          (2)

#define divides(a, b)         ((!(a) || (b)%(a)) ? 0 : 1)


   /*
    *    Interface used by the world
    */

static u_long fbcon_startup(u_long kmem_start, char **display_desc);
static void fbcon_init(struct vc_data *conp);
static int fbcon_deinit(struct vc_data *conp);
static int fbcon_changevar(int con);
static int fbcon_clear(struct vc_data *conp, int sy, int sx, int height,
                       int width);
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,
                       int x);
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_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
                       int height, int width);
static int fbcon_switch(struct vc_data *conp);
static int fbcon_blank(int blank);


   /*
    *    Internal routines
    */

static void fbcon_setup(int con, int setcol, int cls);
static __inline__ void *mymemclear_small(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 *mymemmove(void *d, void *s, size_t count);
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 memset_even_4p(void *d, size_t count, u_long val1,
                                      u_long val2);
static __inline__ void memmove_4p_col(void *d, void *s, int h, int bpr);
static __inline__ u_long expand4l(u_char c);
static __inline__ void expand4dl(u_char c, u_long *ret1, u_long *ret2);
static __inline__ u_long dup4l(u_char c);
static __inline__ void memclear_8p_col(void *d, size_t h, u_long val1,
                                       u_long val2, int bpr);
static __inline__ void memset_even_8p(void *d, size_t count, u_long val1,
                                      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 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 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__ u_short expand2w(u_char c);
static __inline__ u_long expand2l(u_char c);
static __inline__ u_short dup2w(u_char c);
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_bmove_rec(struct display *p, int sy, int sx, int dy, int dx,
                            int height, int width, u_int y_break);


   /*
    *    Monochrome
    */

#ifdef CONFIG_FBCON_MONO
static void bmove_mono(struct display *p, int sy, int sx, int dy, int dx,
                       int height, int width);
static void clear_mono(struct vc_data *conp, struct display *p, int sy, int sx,
                       int height, int width);
static void putc_mono(struct vc_data *conp, struct display *p, int c, int y,
                      int x);
static void putcs_mono(struct vc_data *conp, struct display *p, const char *s,
                       int count, int y, int x);
static void rev_char_mono(struct display *p, int x, int y);
#endif /* CONFIG_FBCON_MONO */


   /*
    *    Color Interleaved Planes
    */

#ifdef CONFIG_FBCON_ILBM
static void bmove_ilbm(struct display *p, int sy, int sx, int dy, int dx,
                       int height, int width);
static void clear_ilbm(struct vc_data *conp, struct display *p, int sy, int sx,
                       int height, int width);
static void putc_ilbm(struct vc_data *conp, struct display *p, int c, int y,
                      int x);
static void putcs_ilbm(struct vc_data *conp, struct display *p, const char *s,
                       int count, int y, int x);
static void rev_char_ilbm(struct display *p, int x, int y);
#endif /* CONFIG_FBCON_ILBM */


   /*
    *    Color Planes
    */

#ifdef CONFIG_FBCON_PLANES
static void bmove_plan(struct display *p, int sy, int sx, int dy, int dx,
                       int height, int width);
static void clear_plan(struct vc_data *conp, struct display *p, int sy, int sx,
                       int height, int width);
static void putc_plan(struct vc_data *conp, struct display *p, int c, int y,
                      int x);
static void putcs_plan(struct vc_data *conp, struct display *p, const char *s,
                       int count, int y, int x);
static void rev_char_plan(struct display *p, int x, int y);
#endif /* CONFIG_FBCON_PLANES */


   /*
    *    2 Planes (2-bytes interleave)
    */

#ifdef CONFIG_FBCON_2PLANE
static void bmove_2_plane(struct display *p, int sy, int sx, int dy, int dx,
                          int height, int width);
static void clear_2_plane(struct vc_data *conp, struct display *p, int sy,
                          int sx, int height, int width);
static void putc_2_plane(struct vc_data *conp, struct display *p, int c, int y,
                         int x);
static void putcs_2_plane(struct vc_data *conp, struct display *p,
                          const char *s, int count, int y, int x);
static void rev_char_2_plane(struct display *display, int x, int y);
#endif /* CONFIG_FBCON_2PLANE */


   /*
    *    4 Planes (2-bytes interleave)
    */

#ifdef CONFIG_FBCON_4PLANE
static void bmove_4_plane(struct display *p, int sy, int sx, int dy, int dx,
                          int height, int width);
static void clear_4_plane(struct vc_data *conp, struct display *p, int sy,
                          int sx, int height, int width);
static void putc_4_plane(struct vc_data *conp, struct display *p, int c, int y,
                         int x);
static void putcs_4_plane(struct vc_data *conp, struct display *p,
                          const char *s, int count, int y, int x);
static void rev_char_4_plane(struct display *p, int x, int y);
#endif /* CONFIG_FBCON_4PLANE */


   /*
    *    8 Planes (2-bytes interleave)
    */

#ifdef CONFIG_FBCON_8PLANE
static void bmove_8_plane(struct display *p, int sy, int sx, int dy, int dx,
                          int height, int width);
static void clear_8_plane(struct vc_data *conp, struct display *p, int sy,
                          int sx, int height, int width);
static void putc_8_plane(struct vc_data *conp, struct display *p, int c, int y,
                         int x);
static void putcs_8_plane(struct vc_data *conp, struct display *p,
                          const char *s, int count, int y, int x);
static void rev_char_8_plane(struct display *display, int x, int y);
#endif /* CONFIG_FBCON_8PLANE */


   /*
    *    8 bpp Packed Pixels
    */

#ifdef CONFIG_FBCON_8PACKED
static void bmove_8_packed(struct display *p, int sy, int sx, int dy, int dx,
                           int height, int width);
static void clear_8_packed(struct vc_data *conp, struct display *p, int sy,
                           int sx, int height, int width);
static void putc_8_packed(struct vc_data *conp, struct display *p, int c, int y,
                          int x);
static void putcs_8_packed(struct vc_data *conp, struct display *p,
                           const char *s, int count, int y, int x);
static void rev_char_8_packed(struct display *p, int x, int y);
#endif /* CONFIG_FBCON_8PACKED */


   /*
    *    16 bpp Packed Pixels
    */

#ifdef CONFIG_FBCON_16PACKED
static void bmove_16_packed(struct display *p, int sy, int sx, int dy, int dx,
                            int height, int width);
static void clear_16_packed(struct vc_data *conp, struct display *p, int sy,
                            int sx, int height, int width);
static void putc_16_packed(struct vc_data *conp, struct display *p, int c,
                           int y, int x);
static void putcs_16_packed(struct vc_data *conp, struct display *p,
                            const char *s, int count, int y, int x);
static void rev_char_16_packed(struct display *p, int x, int y);
#endif */ CONFIG_FBCON_8PACKED */


   /*
    *    Cybervision (accelerated)
    */

#ifdef CONFIG_FBCON_CYBER
static void bmove_cyber(struct display *p, int sy, int sx, int dy, int dx,
                        int height, int width);
static void clear_cyber(struct vc_data *conp, struct display *p, int sy, int sx,
                        int height, int width);
static void putc_cyber(struct vc_data *conp, struct display *p, int c, int y,
                       int x);
static void putcs_cyber(struct vc_data *conp, struct display *p, const char *s,
                        int count, int y, int x);
static void rev_char_cyber(struct display *p, int x, int y);

extern void Cyber_WaitQueue(u_short fifo);
extern void Cyber_WaitBlit(void);
extern void Cyber_BitBLT(u_short curx, u_short cury, u_short destx,
                         u_short desty, u_short width, u_short height,
                         u_short mode);
extern void Cyber_RectFill(u_short x, u_short y, u_short width, u_short height,
                           u_short mode, u_short color);
extern void Cyber_MoveCursor(u_short x, u_short y);
#endif /* CONFIG_FBCON_CYBER */


   /*
    *    `switch' for the Low Level Operations
    */

struct display_switch {
    void (*bmove)(struct display *p, int sy, int sx, int dy, int dx, int height,
                  int width);
    void (*clear)(struct vc_data *conp, struct display *p, int sy, int sx,
                  int height, int width);
    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,
                  int count, int y, int x);
    void (*rev_char)(struct display *p, int x, int y);
};


#ifdef CONFIG_FBCON_MONO
struct display_switch dispsw_mono = {
   bmove_mono, clear_mono, putc_mono, putcs_mono, rev_char_mono
};
#endif /* CONFIG_FBCON_MONO */

#ifdef CONFIG_FBCON_ILBM
struct display_switch dispsw_ilbm = {
   bmove_ilbm, clear_ilbm, putc_ilbm, putcs_ilbm, rev_char_ilbm
};
#endif /* CONFIG_FBCON_ILBM */

#ifdef CONFIG_FBCON_PLANES
struct display_switch dispsw_plan = {
   bmove_plan, clear_plan, putc_plan, putcs_plan, rev_char_plan
};
#endif /* CONFIG_FBCON_PLANES */

#ifdef CONFIG_FBCON_2PLANE
struct display_switch dispsw_2_plane = {
   bmove_2_plane, clear_2_plane, putc_2_plane, putcs_2_plane, rev_char_2_plane
};
#endif /* CONFIG_FBCON_2PLANE */

#ifdef CONFIG_FBCON_4PLANE
struct display_switch dispsw_4_plane = {
   bmove_4_plane, clear_4_plane, putc_4_plane, putcs_4_plane, rev_char_4_plane
};
#endif /* CONFIG_FBCON_4PLANE */

#ifdef CONFIG_FBCON_8PLANE
struct display_switch dispsw_8_plane = {
   bmove_8_plane, clear_8_plane, putc_8_plane, putcs_8_plane, rev_char_8_plane
};
#endif /* CONFIG_FBCON_8PLANE */

#ifdef CONFIG_FBCON_8PACKED
struct display_switch dispsw_8_packed = {
   bmove_8_packed, clear_8_packed, putc_8_packed, putcs_8_packed, rev_char_8_packed
};
#endif /* CONFIG_FBCON_8PACKED */

#ifdef CONFIG_FBCON_16PACKED
struct display_switch dispsw_16_packed = {
   bmove_16_packed, clear_16_packed, putc_16_packed, putcs_16_packed,
   rev_char_16_packed
};
#endif /* CONFIG_FBCON_16PACKED */

#ifdef CONFIG_FBCON_CYBER
struct display_switch dispsw_cyber = {
   bmove_cyber, clear_cyber, putc_cyber, putcs_cyber, rev_char_cyber
};
#endif /* CONFIG_FBCON_CYBER */


static u_long fbcon_startup(u_long kmem_start, char **display_desc)
{
  return 0;
}


static void fbcon_init(struct vc_data *conp)
{
}


static int fbcon_deinit(struct vc_data *conp)
{
  return 0;
}


static int fbcon_changevar(int con)
{
  return 0;
}


static void fbcon_setup(int con, int setcol, int cls)
{
}


/* ================================================================= */
/*                      Utility Assembler Functions                  */
/* ================================================================= */


/* ====================================================================== */

/* Those of a delicate disposition might like to skip the next couple of
 * pages.
 *
 * These functions are drop in replacements for memmove and
 * memset(_, 0, _). However their five instances add at least a kilobyte
 * to the object file. You have been warned.
 *
 * 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
 * equivalents for large blits, and that's important to the lowest level of
 * a graphics driver. Question is whether some scheme with the blitter
 * would be faster. I suspect not for simple text system - not much
 * asynchrony.
 *
 * Code is very simple, just gruesome expansion. Basic strategy is to
 * increase data moved/cleared at each step to 16 bytes to reduce
 * instruction per data move overhead. movem might be faster still
 * 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.
 * Unaligned read/write used requires 68020+ - think this is a problem?
 *
 * Sorry!
 */


/* ++roman: I've optimized Robert's original versions in some minor
 * aspects, e.g. moveq instead of movel, let gcc choose the registers,
 * use movem in some places...
 * For other modes than 1 plane, lots of more such assembler functions
 * were needed (e.g. the ones using movep or expanding color values).
 */

/* ++andreas: more optimizations:
   subl #65536,d0 replaced by clrw d0; subql #1,d0 for dbcc
   addal is faster than addaw
   movep is rather expensive compared to ordinary move's
   some functions rewritten in C for clarity, no speed loss */

static __inline__ void *mymemclear_small(void *s, size_t count)
{
  return NULL;
}


static __inline__ void *mymemclear(void *s, size_t count)
{
  return NULL;
}


static __inline__ void *mymemset(void *s, size_t count)
{
  return NULL;
}


static __inline__ void *mymemmove(void *d, void *s, size_t count)
{
  return NULL;
}


/* ++andreas: Simple and fast version of memmove, assumes size is
   divisible by 16, suitable for moving the whole screen bitplane */
static __inline__ void fast_memmove(char *dst, char *src, size_t size)
{
}


/* 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
 * moved (8 times) to the respective bytes. This means:
 *
 * for(h times; d += bpr)
 *   *d     = (color & 1) ? 0xff : 0;
 *   *(d+2) = (color & 2) ? 0xff : 0;
 *   *(d+4) = (color & 4) ? 0xff : 0;
 *   *(d+6) = (color & 8) ? 0xff : 0;
 */

static __inline__ void memclear_4p_col(void *d, size_t h, u_long val, int bpr)
{
}

/* 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
 * by 8, because only whole words and all planes are accessed. I.e.:
 *
 * for(count/8 times)
 *   *d     = *(d+1) = (color & 1) ? 0xff : 0;
 *   *(d+2) = *(d+3) = (color & 2) ? 0xff : 0;
 *   *(d+4) = *(d+5) = (color & 4) ? 0xff : 0;
 *   *(d+6) = *(d+7) = (color & 8) ? 0xff : 0;
 */

static __inline__ void memset_even_4p(void *d, size_t count, u_long val1,
                                      u_long val2)
{
}

/* 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)
{
}


/* This expands a 4 bit color into a long for movepl (4 plane) operations. */

static __inline__ u_long expand4l(u_char c)
{
  return 0;
}

/* This expands a 4 bit color into two longs for two movel operations
 * (4 planes).
 */

static __inline__ void expand4dl(u_char c, u_long *ret1, u_long *ret2)
{
}


/* This duplicates a byte 4 times into a long. */

static __inline__ u_long dup4l(u_char c)
{
  return 0;
}


/* 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
 * moved (8 times) to the respective bytes. This means:
 *
 * for(h times; d += bpr)
 *   *d      = (color & 1) ? 0xff : 0;
 *   *(d+2)  = (color & 2) ? 0xff : 0;
 *   *(d+4)  = (color & 4) ? 0xff : 0;
 *   *(d+6)  = (color & 8) ? 0xff : 0;
 *   *(d+8)  = (color & 16) ? 0xff : 0;
 *   *(d+10) = (color & 32) ? 0xff : 0;
 *   *(d+12) = (color & 64) ? 0xff : 0;
 *   *(d+14) = (color & 128) ? 0xff : 0;
 */

static __inline__ void memclear_8p_col(void *d, size_t h, u_long val1,
                                       u_long val2, int bpr)
{
}

/* 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
 * by 16, because only whole words and all planes are accessed. I.e.:
 *
 * for(count/16 times)
 *   *d      = *(d+1)  = (color & 1) ? 0xff : 0;
 *   *(d+2)  = *(d+3)  = (color & 2) ? 0xff : 0;
 *   *(d+4)  = *(d+5)  = (color & 4) ? 0xff : 0;
 *   *(d+6)  = *(d+7)  = (color & 8) ? 0xff : 0;
 *   *(d+8)  = *(d+9)  = (color & 16) ? 0xff : 0;
 *   *(d+10) = *(d+11) = (color & 32) ? 0xff : 0;
 *   *(d+12) = *(d+13) = (color & 64) ? 0xff : 0;
 *   *(d+14) = *(d+15) = (color & 128) ? 0xff : 0;
 */

static __inline__ void memset_even_8p(void *d, size_t count, u_long val1,
                                      u_long val2, u_long val3, u_long val4)
{
}

/* 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)
{
}


/* This expands a 8 bit color into two longs for two movepl (8 plane)
 * operations.
 */

static __inline__ void expand8dl(u_char c, u_long *ret1, u_long *ret2)
{
}

/* This expands a 8 bit color into four longs for four movel operations
 * (8 planes).
 */

/* ++andreas: use macro to avoid taking address of return values */
#define expand8ql(c, rv1, rv2, rv3, rv4)


/* 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
 * moved (8 times) to the respective bytes. This means:
 *
 * for(h times; d += bpr)
 *   *d     = (color & 1) ? 0xff : 0;
 *   *(d+2) = (color & 2) ? 0xff : 0;
 */

static __inline__ void memclear_2p_col(void *d, size_t h, u_short val, int bpr)
{
}

/* 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
 * by 8, because only whole words and all planes are accessed. I.e.:
 *
 * for(count/4 times)
 *   *d     = *(d+1) = (color & 1) ? 0xff : 0;
 *   *(d+2) = *(d+3) = (color & 2) ? 0xff : 0;
 */

static __inline__ void memset_even_2p(void *d, size_t count, u_long val)
{
}

/* 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)
{
}


/* This expands a 2 bit color into a short for movepw (2 plane) operations. */

static __inline__ u_short expand2w(u_char c)
{
  return 0;
}

/* This expands a 2 bit color into one long for a movel operation
 * (2 planes).
 */

static __inline__ u_long expand2l(u_char c)
{
  return 0;
}


/* This duplicates a byte 2 times into a short. */

static __inline__ u_short dup2w(u_char c)
{
  return 0;
}


/* ====================================================================== */

/* fbcon_XXX routines - interface used by the world
 *
 * This system is now divided into two levels because of complications
 * caused by hardware scrolling. Top level functions:
 *
 *    fbcon_bmove(), fbcon_clear(), fbcon_putc()
 *
 * 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
 * anywhere on this display. These functions convert lineoffsets to
 * bitmap offsets and deal with the wrap-around case by splitting blits.
 *
 *    fbcon_bmove_physical_8()   -- These functions fast implementations
 *    fbcon_clear_physical_8()   -- of original fbcon_XXX fns.
 *    fbcon_putc_physical_8()    -- (fontwidth != 8) may be added later
 *
 * WARNING:
 *
 * At the moment fbcon_putc() cannot blit across vertical wrap boundary
 * Implies should only really hardware scroll in rows. Only reason for
 * restriction is simplicity & efficiency at the moment.
 */

static __inline__ int real_y(struct display *p, int y)
{
  return 0;
}


static int fbcon_clear(struct vc_data *conp, int sy, int sx, int height,
                       int width)
{
  return 0;
}


static int fbcon_putc(struct vc_data *conp, int c, int y, int x)
{
  return 0;
}


static int fbcon_putcs(struct vc_data *conp, const char *s, int count, int y,
                       int x)
{
  return 0;
}


static int fbcon_cursor(struct vc_data *conp, int mode)
{
  return 0;
}


static void fbcon_vbl_handler(int irq, struct pt_regs *fp, void *dummy)
{
}


static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
{
  return 0;
}


static int fbcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
                       int height, int width)
{
  return 0;
}


static void fbcon_bmove_rec(struct display *p, int sy, int sx, int dy, int dx,
                            int height, int width, u_int y_break)
{
}


static int fbcon_switch(struct vc_data *conp)
{
  return 0;
}


static int fbcon_blank(int blank)
{
  return 0;
}


static int fbcon_get_font(struct vc_data *conp, int *w, int *h, char *data)
{
  return 0;
}


#define REFCOUNT(fd)	(((int *)(fd))[-1])

static int fbcon_set_font(struct vc_data *conp, int w, int h, char *data)
{
  return 0;
}


/* ====================================================================== */

/*
 *    Low Level Operations for the various display memory organizations.
 *
 *    Currently only the following organizations are supported here:
 *
 *      - Monochrome
 *      - Color Interleaved Planes à la Amiga
 *      - Color Normal Planes
 *      - Color Interleaved Planes à la Atari (2, 4 and 8 planes)
 *      - Color Packed Pixels (8 and 16 bpp)
 *      - Cybervision Color Packed Pixels (accelerated)
 */

#ifdef CONFIG_FBCON_MONO

   /*
    *    Monochrome
    */

static void bmove_mono(struct display *p, int sy, int sx, int dy, int dx,
                       int height, int width)
{
}


static void clear_mono(struct vc_data *conp, struct display *p, int sy, int sx,
                       int height, int width)
{
   u_char *dest;
   u_int rows;

   dest = p->screen_base+sy*p->fontheight*p->next_line+sx;

   if (sx == 0 && width == p->next_line)
      if (attr_reverse(p,conp))
         mymemset(dest, height*p->fontheight*width);
      else
         mymemclear(dest, height*p->fontheight*width);
   else
      for (rows = height*p->fontheight; rows--; dest += p->next_line)
         if (attr_reverse(p,conp))
            mymemset(dest, width);
         else
            mymemclear_small(dest, width);
}


static void putc_mono(struct vc_data *conp, struct display *p, int c, int y,
                      int x)
{
}


static void putcs_mono(struct vc_data *conp, struct display *p, const char *s,
                       int count, int y, int x)
{
}


static void rev_char_mono(struct display *p, int x, int y)
{
}

#endif /* CONFIG_FBCON_MONO */


/* ====================================================================== */

#ifdef CONFIG_FBCON_ILBM

   /*
    *    Color Interleaved Planes
    *
    *    This code heavily relies on the fact that
    *
    *       next_line == interleave == next_plane*bits_per_pixel
    *
    *    But maybe it can be merged with the code for normal bitplanes without
    *    much performance loss?
    */

static void bmove_ilbm(struct display *p, int sy, int sx, int dy, int dx,
                       int height, int width)
{
}


static void clear_ilbm(struct vc_data *conp, struct display *p, int sy, int sx,
                       int height, int width)
{
}


static void putc_ilbm(struct vc_data *conp, struct display *p, int c, int y,
                      int x)
{
}


/*
 *    I split the console character loop in two parts:
 *
 *      - slow version: this blits one character at a time
 *
 *      - fast version: this blits 4 characters at a time at a longword aligned
 *                      address, to reduce the number of expensive Chip RAM
 *                      accesses.
 *
 *    Experiments on my A4000/040 revealed that this makes a console switch on a
 *    640x400 screen with 256 colors about 3 times faster.
 *
 *                                                                Geert
 */

static void putcs_ilbm(struct vc_data *conp, struct display *p, const char *s,
                       int count, int y, int x)
{
}


static void rev_char_ilbm(struct display *p, int x, int y)
{
}

#endif /* CONFIG_FBCON_ILBM */


/* ====================================================================== */

#ifdef CONFIG_FBCON_PLANES

   /*
    *    Color Planes
    */

static void bmove_plan(struct display *p, int sy, int sx, int dy, int dx,
                       int height, int width)
{
}


static void clear_plan(struct vc_data *conp, struct display *p, int sy, int sx,
                       int height, int width)
{
}


static void putc_plan(struct vc_data *conp, struct display *p, int c, int y,
                      int x)
{
}


/*
 *    I split the console character loop in two parts
 *    (cfr. fbcon_putcs_ilbm())
 */

static void putcs_plan(struct vc_data *conp, struct display *p, const char *s,
                       int count, int y, int x)
{
}


static void rev_char_plan(struct display *p, int x, int y)
{
}

#endif /* CONFIG_FBCON_PLANES */


/* ====================================================================== */

#ifdef CONFIG_FBCON_2PLANE

   /*
    *    2 Planes (2-bytes interleave)
    */

/* Increment/decrement 2 plane addresses */

#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)

/* 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;
 * The intensity bit (b3) is shifted into b1.
 */

#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,
                          int height, int width)
{
}


static void clear_2_plane(struct vc_data *conp, struct display *p, int sy,
                          int sx, int height, int width)
{
}


static void putc_2_plane(struct vc_data *conp, struct display *p, int c, int y,
                         int x)
{
}


static void putcs_2_plane(struct vc_data *conp, struct display *p,
                          const char *s, int count, int y, int x)
{
}


static void rev_char_2_plane(struct display *p, int x, int y)
{
}
#endif /* CONFIG_FBCON_2PLANE */


/* ====================================================================== */

#ifdef CONFIG_FBCON_4PLANE

   /*
    *    4 Planes (2-bytes interleave)
    */

/* Increment/decrement 4 plane addresses */

#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)


static void bmove_4_plane(struct display *p, int sy, int sx, int dy, int dx,
                          int height, int width)
{
}


static void clear_4_plane(struct vc_data *conp, struct display *p, int sy,
                          int sx, int height, int width)
{
}


static void putc_4_plane(struct vc_data *conp, struct display *p, int c, int y,
                         int x)
{
}


static void putcs_4_plane(struct vc_data *conp, struct display *p,
                          const char *s, int count, int y, int x)
{
}


static void rev_char_4_plane(struct display *p, int x, int y)
{
}
#endif /* CONFIG_FBCON_4PLANE */


/* ====================================================================== */

#ifdef CONFIG_FBCON_8PLANE

   /*
    *    8 Planes (2-bytes interleave)
    */

/* 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
 * background/unused). For that, the following functions mask off the
 * higher 4 bits of each color.
 */

/* Increment/decrement 8 plane addresses */

#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)


static void bmove_8_plane(struct display *p, int sy, int sx, int dy, int dx,
                          int height, int width)
{
}


static void clear_8_plane(struct vc_data *conp, struct display *p, int sy,
                          int sx, int height, int width)
{
}


static void putc_8_plane(struct vc_data *conp, struct display *p, int c, int y,
                         int x)
{
}


static void putcs_8_plane(struct vc_data *conp, struct display *p,
                          const char *s, int count, int y, int x)
{
}


static void rev_char_8_plane(struct display *p, int x, int y)
{
}
#endif /* CONFIG_FBCON_8PLANE */


/* ====================================================================== */

#ifdef CONFIG_FBCON_8PACKED

   /*
    *    8 bpp Packed Pixels
    */

static u_long nibbletab_8_packed[]={
0x00000000,0x000000ff,0x0000ff00,0x0000ffff,
0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff,
0xff000000,0xff0000ff,0xff00ff00,0xff00ffff,
0xffff0000,0xffff00ff,0xffffff00,0xffffffff};

static void bmove_8_packed(struct display *p, int sy, int sx, int dy, int dx,
                           int height, int width)
{
}


static void clear_8_packed(struct vc_data *conp, struct display *p, int sy,
                           int sx, int height, int width)
{
}


static void putc_8_packed(struct vc_data *conp, struct display *p, int c, int y,
                          int x)
{
}


static void putcs_8_packed(struct vc_data *conp, struct display *p,
                           const char *s, int count, int y, int x)
}


static void rev_char_8_packed(struct display *p, int x, int y)
{
}

#endif /* CONFIG_FBCON_8PACKED */


/* ====================================================================== */

#ifdef CONFIG_FBCON_16PACKED

   /*
    *    16 bpp Packed Pixels
    */

u_short packed16_cmap[16];

static u_long tab_16_packed[]={
0x00000000,0x0000ffff,0xffff0000,0xffffffff};

static void bmove_16_packed(struct display *p, int sy, int sx, int dy, int dx,
                            int height, int width)
{
}


static void clear_16_packed(struct vc_data *conp, struct display *p, int sy,
                            int sx, int height, int width)
{
}


static void putc_16_packed(struct vc_data *conp, struct display *p, int c,
                           int y, int x)
{
}


/* TODO */
static void putcs_16_packed(struct vc_data *conp, struct display *p,
                            const char *s, int count, int y, int x)
{
}


static void rev_char_16_packed(struct display *p, int x, int y)
{
}

#endif /* CONFIG_FBCON_16PACKED */


/* ====================================================================== */

#ifdef CONFIG_FBCON_CYBER

   /*
    *    Cybervision (accelerated)
    */

static void bmove_cyber(struct display *p, int sy, int sx, int dy, int dx,
                        int height, int width)
{
}


static void clear_cyber(struct vc_data *conp, struct display *p, int sy, int sx,
                        int height, int width)
{
}


static void putc_cyber(struct vc_data *conp, struct display *p, int c, int y,
                       int x)
{
}


static void putcs_cyber(struct vc_data *conp, struct display *p, const char *s,
                        int count, int y, int x)
{
}


static void rev_char_cyber(struct display *p, int x, int y)
{
}

#endif /* CONFIG_FBCON_CYBER */


/* ====================================================================== */

   /*
    *    The console `switch' structure for the frame buffer based console
    */

struct consw fb_con = {
   fbcon_startup, fbcon_init, fbcon_deinit, fbcon_clear, fbcon_putc,
   fbcon_putcs, fbcon_cursor, fbcon_scroll, fbcon_bmove, fbcon_switch,
   fbcon_blank, fbcon_get_font, fbcon_set_font
};
