linux/drivers/video/fbdev/core/fbcon.c

/*
 *  linux/drivers/video/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 [[email protected]]
 *
 *	      with work by William Rucklidge ([email protected])
 *			   Geert Uytterhoeven
 *			   Jes Sorensen ([email protected])
 *			   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
 *
 *  Hardware cursor support added by Emmanuel Marty ([email protected])
 *  Smart redraw scrolling, arbitrary font width support, 512char font support
 *  and software scrollback added by
 *                         Jakub Jelinek ([email protected])
 *
 *  Random hacking by Martin Mares <[email protected]>
 *
 *	2001 - Documented with DocBook
 *	- Brad Douglas <[email protected]>
 *
 *  The low level operations for the various display memory organizations are
 *  now in separate source files.
 *
 *  Currently the following organizations are supported:
 *
 *    o afb			Amiga bitplanes
 *    o cfb{2,4,8,16,24,32}	Packed pixels
 *    o ilbm			Amiga interleaved bitplanes
 *    o iplan2p[248]		Atari interleaved bitplanes
 *    o mfb			Monochrome
 *    o vga			VGA characters/attributes
 *
 *  To do:
 *
 *    - Implement 16 plane mode (iplan2p16)
 *
 *
 *  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.
 */

#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/delay.h>	/* MSch: for IRQ probe */
#include <linux/console.h>
#include <linux/string.h>
#include <linux/kd.h>
#include <linux/panic.h>
#include <linux/printk.h>
#include <linux/slab.h>
#include <linux/fb.h>
#include <linux/fbcon.h>
#include <linux/vt_kern.h>
#include <linux/selection.h>
#include <linux/font.h>
#include <linux/smp.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/crc32.h> /* For counting font checksums */
#include <linux/uaccess.h>
#include <asm/irq.h>

#include "fbcon.h"
#include "fb_internal.h"

/*
 * FIXME: Locking
 *
 * - fbcon state itself is protected by the console_lock, and the code does a
 *   pretty good job at making sure that lock is held everywhere it's needed.
 *
 * - fbcon doesn't bother with fb_lock/unlock at all. This is buggy, since it
 *   means concurrent access to the same fbdev from both fbcon and userspace
 *   will blow up. To fix this all fbcon calls from fbmem.c need to be moved out
 *   of fb_lock/unlock protected sections, since otherwise we'll recurse and
 *   deadlock eventually. Aside: Due to these deadlock issues the fbdev code in
 *   fbmem.c cannot use locking asserts, and there's lots of callers which get
 *   the rules wrong, e.g. fbsysfs.c entirely missed fb_lock/unlock calls too.
 */

enum {};

static struct fbcon_display fb_display[MAX_NR_CONSOLES];

static struct fb_info *fbcon_registered_fb[FB_MAX];
static int fbcon_num_registered_fb;

#define fbcon_for_each_registered_fb(i)

static signed char con2fb_map[MAX_NR_CONSOLES];
static signed char con2fb_map_boot[MAX_NR_CONSOLES];

static struct fb_info *fbcon_info_from_console(int console)
{}

static int logo_lines;
/* logo_shown is an index to vc_cons when >= 0; otherwise follows FBCON_LOGO
   enums.  */
static int logo_shown =;
/* console mappings */
static unsigned int first_fb_vc;
static unsigned int last_fb_vc =;
static int fbcon_is_default =;
static int primary_device =;
static int fbcon_has_console_bind;

#ifdef CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY
static int map_override;

static inline void fbcon_map_override(void)
{}
#else
static inline void fbcon_map_override(void)
{
}
#endif /* CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY */

#ifdef CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER
static bool deferred_takeover =;
#else
#define deferred_takeover
#endif

/* font data */
static char fontname[40];

/* current fb_info */
static int info_idx =;

/* console rotation */
static int initial_rotation =;
static int fbcon_has_sysfs;
static int margin_color;

static const struct consw fb_con;

#define advance_row(p, delta)

static int fbcon_cursor_noblink;

#define divides(a, b)

/*
 *  Interface used by the world
 */

static void fbcon_clear_margins(struct vc_data *vc, int bottom_only);
static void fbcon_set_palette(struct vc_data *vc, const unsigned char *table);

/*
 *  Internal routines
 */
static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
			   int unit);
static void fbcon_redraw_move(struct vc_data *vc, struct fbcon_display *p,
			      int line, int count, int dy);
static void fbcon_modechanged(struct fb_info *info);
static void fbcon_set_all_vcs(struct fb_info *info);

static struct device *fbcon_device;

#ifdef CONFIG_FRAMEBUFFER_CONSOLE_ROTATION
static inline void fbcon_set_rotation(struct fb_info *info)
{}

static void fbcon_rotate(struct fb_info *info, u32 rotate)
{}

static void fbcon_rotate_all(struct fb_info *info, u32 rotate)
{}
#else
static inline void fbcon_set_rotation(struct fb_info *info)
{
	struct fbcon_ops *ops = info->fbcon_par;

	ops->rotate = FB_ROTATE_UR;
}

static void fbcon_rotate(struct fb_info *info, u32 rotate)
{
	return;
}

static void fbcon_rotate_all(struct fb_info *info, u32 rotate)
{
	return;
}
#endif /* CONFIG_FRAMEBUFFER_CONSOLE_ROTATION */

static int fbcon_get_rotate(struct fb_info *info)
{}

static bool fbcon_skip_panic(struct fb_info *info)
{}

static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info)
{}

static int get_color(struct vc_data *vc, struct fb_info *info,
	      u16 c, int is_fg)
{}

static void fb_flashcursor(struct work_struct *work)
{}

static void fbcon_add_cursor_work(struct fb_info *info)
{}

static void fbcon_del_cursor_work(struct fb_info *info)
{}

#ifndef MODULE
static int __init fb_console_setup(char *this_opt)
{}

__setup();
#endif

static int search_fb_in_map(int idx)
{}

static int search_for_mapped_con(void)
{}

static int do_fbcon_takeover(int show_logo)
{}

#ifdef MODULE
static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
			       int cols, int rows, int new_cols, int new_rows)
{
	logo_shown = FBCON_LOGO_DONTSHOW;
}
#else
static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
			       int cols, int rows, int new_cols, int new_rows)
{}
#endif /* MODULE */

#ifdef CONFIG_FB_TILEBLITTING
static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
{}

static int fbcon_invalid_charcount(struct fb_info *info, unsigned charcount)
{}
#else
static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
{
	struct fbcon_ops *ops = info->fbcon_par;

	info->flags &= ~FBINFO_MISC_TILEBLITTING;
	ops->p = &fb_display[vc->vc_num];
	fbcon_set_rotation(info);
	fbcon_set_bitops(ops);
}

static int fbcon_invalid_charcount(struct fb_info *info, unsigned charcount)
{
	return 0;
}

#endif /* CONFIG_MISC_TILEBLITTING */

static void fbcon_release(struct fb_info *info)
{}

static int fbcon_open(struct fb_info *info)
{}

static int con2fb_acquire_newinfo(struct vc_data *vc, struct fb_info *info,
				  int unit)
{}

static void con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo,
				   struct fb_info *newinfo)
{}

static void con2fb_init_display(struct vc_data *vc, struct fb_info *info,
				int unit, int show_logo)
{}

/**
 *	set_con2fb_map - map console to frame buffer device
 *	@unit: virtual console number to map
 *	@newidx: frame buffer index to map virtual console to
 *      @user: user request
 *
 *	Maps a virtual console @unit to a frame buffer device
 *	@newidx.
 *
 *	This should be called with the console lock held.
 */
static int set_con2fb_map(int unit, int newidx, int user)
{}

/*
 *  Low Level Operations
 */
/* NOTE: fbcon cannot be __init: it may be called from do_take_over_console later */
static int var_to_display(struct fbcon_display *disp,
			  struct fb_var_screeninfo *var,
			  struct fb_info *info)
{}

static void display_to_var(struct fb_var_screeninfo *var,
			   struct fbcon_display *disp)
{}

static const char *fbcon_startup(void)
{}

static void fbcon_init(struct vc_data *vc, bool init)
{}

static void fbcon_free_font(struct fbcon_display *p)
{}

static void set_vc_hi_font(struct vc_data *vc, bool set);

static void fbcon_release_all(void)
{}

static void fbcon_deinit(struct vc_data *vc)
{}

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

/*  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(), fbcon_clear_margins()
 *
 *  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()	    -- (font width != 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 void __fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx,
			  unsigned int height, unsigned int width)
{}

static void fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx,
			unsigned int width)
{}

static void fbcon_putcs(struct vc_data *vc, const u16 *s, unsigned int count,
			unsigned int ypos, unsigned int xpos)
{}

static void fbcon_clear_margins(struct vc_data *vc, int bottom_only)
{}

static void fbcon_cursor(struct vc_data *vc, bool enable)
{}

static int scrollback_phys_max =;
static int scrollback_max =;
static int scrollback_current =;

static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
			   int unit)
{}

static __inline__ void ywrap_up(struct vc_data *vc, int count)
{}

static __inline__ void ywrap_down(struct vc_data *vc, int count)
{}

static __inline__ void ypan_up(struct vc_data *vc, int count)
{}

static __inline__ void ypan_up_redraw(struct vc_data *vc, int t, int count)
{}

static __inline__ void ypan_down(struct vc_data *vc, int count)
{}

static __inline__ void ypan_down_redraw(struct vc_data *vc, int t, int count)
{}

static void fbcon_redraw_move(struct vc_data *vc, struct fbcon_display *p,
			      int line, int count, int dy)
{}

static void fbcon_redraw_blit(struct vc_data *vc, struct fb_info *info,
			struct fbcon_display *p, int line, int count, int ycount)
{}

static void fbcon_redraw(struct vc_data *vc, int line, int count, int offset)
{}

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

static void fbcon_bmove(struct vc_data *vc, int sy, int sx, int dy, int dx,
			int height, int width)
{}

static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
		enum con_scroll dir, unsigned int count)
{}


static void updatescrollmode_accel(struct fbcon_display *p,
					struct fb_info *info,
					struct vc_data *vc)
{}

static void updatescrollmode(struct fbcon_display *p,
					struct fb_info *info,
					struct vc_data *vc)
{}

#define PITCH(w)
#define CALC_FONTSZ(h, p, c)

static int fbcon_resize(struct vc_data *vc, unsigned int width,
			unsigned int height, bool from_user)
{}

static bool fbcon_switch(struct vc_data *vc)
{}

static void fbcon_generic_blank(struct vc_data *vc, struct fb_info *info,
				int blank)
{}

static bool fbcon_blank(struct vc_data *vc, enum vesa_blank_mode blank,
			bool mode_switch)
{}

static void fbcon_debug_enter(struct vc_data *vc)
{}

static void fbcon_debug_leave(struct vc_data *vc)
{}

static int fbcon_get_font(struct vc_data *vc, struct console_font *font, unsigned int vpitch)
{}

/* set/clear vc_hi_font_mask and update vc attrs accordingly */
static void set_vc_hi_font(struct vc_data *vc, bool set)
{}

static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount,
			     const u8 * data, int userfont)
{}

/*
 *  User asked to set font; we are guaranteed that charcount does not exceed 512
 *  but lets not assume that, since charcount of 512 is small for unicode support.
 */

static int fbcon_set_font(struct vc_data *vc, const struct console_font *font,
			  unsigned int vpitch, unsigned int flags)
{}

static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font,
			      const char *name)
{}

static u16 palette_red[16];
static u16 palette_green[16];
static u16 palette_blue[16];

static struct fb_cmap palette_cmap =;

static void fbcon_set_palette(struct vc_data *vc, const unsigned char *table)
{}

/* As we might be inside of softback, we may work with non-contiguous buffer,
   that's why we have to use a separate routine. */
static void fbcon_invert_region(struct vc_data *vc, u16 * p, int cnt)
{}

void fbcon_suspended(struct fb_info *info)
{}

void fbcon_resumed(struct fb_info *info)
{}

static void fbcon_modechanged(struct fb_info *info)
{}

static void fbcon_set_all_vcs(struct fb_info *info)
{}


void fbcon_update_vcs(struct fb_info *info, bool all)
{}
EXPORT_SYMBOL();

/* let fbcon check if it supports a new screen resolution */
int fbcon_modechange_possible(struct fb_info *info, struct fb_var_screeninfo *var)
{}
EXPORT_SYMBOL_GPL();

int fbcon_mode_deleted(struct fb_info *info,
		       struct fb_videomode *mode)
{}

#ifdef CONFIG_VT_HW_CONSOLE_BINDING
static void fbcon_unbind(void)
{}
#else
static inline void fbcon_unbind(void) {}
#endif /* CONFIG_VT_HW_CONSOLE_BINDING */

void fbcon_fb_unbind(struct fb_info *info)
{}

void fbcon_fb_unregistered(struct fb_info *info)
{}

void fbcon_remap_all(struct fb_info *info)
{}

#ifdef CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY
static void fbcon_select_primary(struct fb_info *info)
{}
#else
static inline void fbcon_select_primary(struct fb_info *info)
{
	return;
}
#endif /* CONFIG_FRAMEBUFFER_DETECT_PRIMARY */

static bool lockless_register_fb;
module_param_named_unsafe(lockless_register_fb, lockless_register_fb, bool, 0400);
MODULE_PARM_DESC();

/* called with console_lock held */
static int do_fb_registered(struct fb_info *info)
{}

int fbcon_fb_registered(struct fb_info *info)
{}

void fbcon_fb_blanked(struct fb_info *info, int blank)
{}

void fbcon_new_modelist(struct fb_info *info)
{}

void fbcon_get_requirement(struct fb_info *info,
			   struct fb_blit_caps *caps)
{}

int fbcon_set_con2fb_map_ioctl(void __user *argp)
{}

int fbcon_get_con2fb_map_ioctl(void __user *argp)
{}

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

static const struct consw fb_con =;

static ssize_t store_rotate(struct device *device,
			    struct device_attribute *attr, const char *buf,
			    size_t count)
{}

static ssize_t store_rotate_all(struct device *device,
				struct device_attribute *attr,const char *buf,
				size_t count)
{}

static ssize_t show_rotate(struct device *device,
			   struct device_attribute *attr,char *buf)
{}

static ssize_t show_cursor_blink(struct device *device,
				 struct device_attribute *attr, char *buf)
{}

static ssize_t store_cursor_blink(struct device *device,
				  struct device_attribute *attr,
				  const char *buf, size_t count)
{}

static struct device_attribute device_attrs[] =;

static int fbcon_init_device(void)
{}

#ifdef CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER
static void fbcon_register_existing_fbs(struct work_struct *work)
{}

static struct notifier_block fbcon_output_nb;
static DECLARE_WORK(fbcon_deferred_takeover_work, fbcon_register_existing_fbs);

static int fbcon_output_notifier(struct notifier_block *nb,
				 unsigned long action, void *data)
{}
#endif

static void fbcon_start(void)
{}

void __init fb_console_init(void)
{}

#ifdef MODULE

static void __exit fbcon_deinit_device(void)
{
	int i;

	if (fbcon_has_sysfs) {
		for (i = 0; i < ARRAY_SIZE(device_attrs); i++)
			device_remove_file(fbcon_device, &device_attrs[i]);

		fbcon_has_sysfs = 0;
	}
}

void __exit fb_console_exit(void)
{
#ifdef CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER
	console_lock();
	if (deferred_takeover)
		dummycon_unregister_output_notifier(&fbcon_output_nb);
	console_unlock();

	cancel_work_sync(&fbcon_deferred_takeover_work);
#endif

	console_lock();
	fbcon_deinit_device();
	device_destroy(fb_class, MKDEV(0, 0));

	do_unregister_con_driver(&fb_con);
	console_unlock();
}
#endif