Commit 0733e4dd authored by James Simmons's avatar James Simmons

The last of the console code inside the frmaebuffer layer. I also moved all...

The last of the console code inside the frmaebuffer layer. I also moved all the graphics related code into the drivers/video directory.
parent 32705156
......@@ -670,7 +670,7 @@ CLEAN_FILES += \
vmlinux System.map \
drivers/char/consolemap_deftbl.c drivers/video/console/promcon_tbl.c \
drivers/char/conmakehash \
drivers/char/drm/*-mod.c \
drivers/video/drm/*-mod.c \
drivers/char/defkeymap.c drivers/char/qtronixmap.c \
drivers/pci/devlist.h drivers/pci/classlist.h drivers/pci/gen-devlist \
drivers/zorro/devlist.h drivers/zorro/gen-devlist \
......
......@@ -184,9 +184,6 @@ if [ "$CONFIG_FTAPE" != "n" ]; then
fi
endmenu
source drivers/char/agp/Config.in
source drivers/char/drm/Config.in
if [ "$CONFIG_HOTPLUG" = "y" -a "$CONFIG_PCMCIA" != "n" ]; then
source drivers/char/pcmcia/Config.in
fi
......
......@@ -100,8 +100,6 @@ obj-$(CONFIG_SH_WDT) += shwdt.o
obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o
obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
obj-$(CONFIG_MWAVE) += mwave/
obj-$(CONFIG_AGP) += agp/
obj-$(CONFIG_DRM) += drm/
obj-$(CONFIG_PCMCIA) += pcmcia/
include $(TOPDIR)/Rules.make
......
......@@ -5,6 +5,9 @@
mainmenu_option next_comment
comment 'Graphics support'
source drivers/video/agp/Config.in
source drivers/video/drm/Config.in
bool 'Support for frame buffer devices ' CONFIG_FB
if [ "$CONFIG_FB" = "y" ]; then
......
......@@ -9,6 +9,9 @@ export-objs := fbmem.o fbcmap.o fbmon.o modedb.o fbgen.o cyber2000fb.o
# Each configuration option enables a list of files.
obj-$(CONFIG_AGP) += agp/
obj-$(CONFIG_DRM) += drm/
# Add fbmon.o back into obj-$(CONFIG_FB) in 2.5.x
obj-$(CONFIG_FB) += fbmem.o fbcmap.o modedb.o fbgen.o
# Only include macmodes.o if we have FB support and are PPC
......
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
......@@ -78,7 +78,6 @@ anakinfb_init(void)
fb_info.fbops = &anakinfb_ops;
fb_info.var = anakinfb_var;
fb_info.fix = anakinfb_fix;
strcpy(fb_info.fontname, "VGA8x16");
if (!(request_mem_region(VGA_START, VGA_SIZE, "vga")))
return -ENOMEM;
if (fb_info.screen_base = ioremap(VGA_START, VGA_SIZE)) {
......
......@@ -214,7 +214,6 @@ static struct fb_ops atyfb_ops = {
.fb_rasterimg = atyfb_rasterimg,
};
static char fontname[40] __initdata = { 0 };
static char curblink __initdata = 1;
static char noaccel __initdata = 0;
static u32 default_vram __initdata = 0;
......@@ -1822,7 +1821,6 @@ static int __init aty_init(struct fb_info *info, const char *name)
info->node = NODEV;
info->fbops = &atyfb_ops;
info->pseudo_palette = pseudo_palette;
strcpy(info->fontname, fontname);
info->flags = FBINFO_FLAG_DEFAULT;
#ifdef CONFIG_PMAC_BACKLIGHT
......@@ -2415,17 +2413,7 @@ int __init atyfb_setup(char *options)
return 0;
while ((this_opt = strsep(&options, ",")) != NULL) {
if (!strncmp(this_opt, "font:", 5)) {
char *p;
int i;
p = this_opt + 5;
for (i = 0; i < sizeof(fontname) - 1; i++)
if (!*p || *p == ' ' || *p == ',')
break;
memcpy(fontname, this_opt + 5, i);
fontname[i] = 0;
} else if (!strncmp(this_opt, "noblink", 7)) {
if (!strncmp(this_opt, "noblink", 7)) {
curblink = 0;
} else if (!strncmp(this_opt, "noaccel", 7)) {
noaccel = 1;
......
......@@ -26,7 +26,6 @@
#include <linux/slab.h>
#include <asm/types.h>
#include <asm/io.h>
#include <video/fbcon.h>
#if BITS_PER_LONG == 32
#define FB_READ fb_readl
......@@ -36,6 +35,384 @@
#define FB_WRITE fb_writeq
#endif
/*
* Oh no Assembly code !!!! Expect more to come as the code gets better.
* Ideally the assembly code shoudl be split off into its own seperate file
*/
/* 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).
*/
#if defined(__mc68000__)
/*
* ++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 *fb_memmove(void *d, const void *s, size_t count)
{
if (d < s) {
if (count < 16) {
__asm__ __volatile__(
"lsrl #1,%2 ; jcc 1f ; moveb %1@+,%0@+\n\t"
"1: lsrl #1,%2 ; jcc 1f ; movew %1@+,%0@+\n\t"
"1: lsrl #1,%2 ; jcc 1f ; movel %1@+,%0@+\n\t"
"1: lsrl #1,%2 ; jcc 1f ; movel %1@+,%0@+ ; movel %1@+,%0@+\n\t"
"1:"
: "=a" (d), "=a" (s), "=d" (count)
: "0" (d), "1" (s), "2" (count)
);
} else {
long tmp;
__asm__ __volatile__(
"movel %0,%3\n\t"
"lsrl #1,%3 ; jcc 1f ; moveb %1@+,%0@+ ; subqw #1,%2\n\t"
"lsrl #1,%3 ; jcs 2f\n\t" /* %0 increased=>bit 2 switched*/
"movew %1@+,%0@+ ; subqw #2,%2 ; jra 2f\n\t"
"1: lsrl #1,%3 ; jcc 2f\n\t"
"movew %1@+,%0@+ ; subqw #2,%2\n\t"
"2: movew %2,%-; lsrl #2,%2 ; jeq 6f\n\t"
"lsrl #1,%2 ; jcc 3f ; movel %1@+,%0@+\n\t"
"3: lsrl #1,%2 ; jcc 4f ; movel %1@+,%0@+ ; movel %1@+,%0@+\n\t"
"4: subql #1,%2 ; jcs 6f\n\t"
"5: movel %1@+,%0@+;movel %1@+,%0@+\n\t"
"movel %1@+,%0@+;movel %1@+,%0@+\n\t"
"dbra %2,5b ; clrw %2; subql #1,%2; jcc 5b\n\t"
"6: movew %+,%2; btst #1,%2 ; jeq 7f ; movew %1@+,%0@+\n\t"
"7: ; btst #0,%2 ; jeq 8f ; moveb %1@+,%0@+\n\t"
"8:"
: "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
: "0" (d), "1" (s), "2" (count)
);
}
} else {
if (count < 16) {
__asm__ __volatile__(
"lsrl #1,%2 ; jcc 1f ; moveb %1@-,%0@-\n\t"
"1: lsrl #1,%2 ; jcc 1f ; movew %1@-,%0@-\n\t"
"1: lsrl #1,%2 ; jcc 1f ; movel %1@-,%0@-\n\t"
"1: lsrl #1,%2 ; jcc 1f ; movel %1@-,%0@- ; movel %1@-,%0@-\n\t"
"1:"
: "=a" (d), "=a" (s), "=d" (count)
: "0" ((char *) d + count), "1" ((char *) s + count), "2" (count)
);
} else {
long tmp;
__asm__ __volatile__(
"movel %0,%3\n\t"
"lsrl #1,%3 ; jcc 1f ; moveb %1@-,%0@- ; subqw #1,%2\n\t"
"lsrl #1,%3 ; jcs 2f\n\t" /* %0 increased=>bit 2 switched*/
"movew %1@-,%0@- ; subqw #2,%2 ; jra 2f\n\t"
"1: lsrl #1,%3 ; jcc 2f\n\t"
"movew %1@-,%0@- ; subqw #2,%2\n\t"
"2: movew %2,%-; lsrl #2,%2 ; jeq 6f\n\t"
"lsrl #1,%2 ; jcc 3f ; movel %1@-,%0@-\n\t"
"3: lsrl #1,%2 ; jcc 4f ; movel %1@-,%0@- ; movel %1@-,%0@-\n\t"
"4: subql #1,%2 ; jcs 6f\n\t"
"5: movel %1@-,%0@-;movel %1@-,%0@-\n\t"
"movel %1@-,%0@-;movel %1@-,%0@-\n\t"
"dbra %2,5b ; clrw %2; subql #1,%2; jcc 5b\n\t"
"6: movew %+,%2; btst #1,%2 ; jeq 7f ; movew %1@-,%0@-\n\t"
"7: ; btst #0,%2 ; jeq 8f ; moveb %1@-,%0@-\n\t"
"8:"
: "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
: "0" ((char *) d + count), "1" ((char *) s + count), "2" (count)
);
}
}
return(0);
}
/* ++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, const char *src, size_t size)
{
if (!size)
return;
if (dst < src)
__asm__ __volatile__
("1:"
" moveml %0@+,%/d0/%/d1/%/a0/%/a1\n"
" moveml %/d0/%/d1/%/a0/%/a1,%1@\n"
" addql #8,%1; addql #8,%1\n"
" dbra %2,1b\n"
" clrw %2; subql #1,%2\n"
" jcc 1b"
: "=a" (src), "=a" (dst), "=d" (size)
: "0" (src), "1" (dst), "2" (size / 16 - 1)
: "d0", "d1", "a0", "a1", "memory");
else
__asm__ __volatile__
("1:"
" subql #8,%0; subql #8,%0\n"
" moveml %0@,%/d0/%/d1/%/a0/%/a1\n"
" moveml %/d0/%/d1/%/a0/%/a1,%1@-\n"
" dbra %2,1b\n"
" clrw %2; subql #1,%2\n"
" jcc 1b"
: "=a" (src), "=a" (dst), "=d" (size)
: "0" (src + size), "1" (dst + size), "2" (size / 16 - 1)
: "d0", "d1", "a0", "a1", "memory");
}
#elif defined(CONFIG_SUN4)
/* You may think that I'm crazy and that I should use generic
routines. No, I'm not: sun4's framebuffer crashes if we std
into it, so we cannot use memset. */
static __inline__ void *sun4_memset(void *s, char val, size_t count)
{
int i;
for(i=0; i<count;i++)
((char *) s) [i] = val;
return s;
}
/* To be honest, this is slow_memmove :). But sun4 is crappy, so what we can do. */
static __inline__ void fast_memmove(void *d, const void *s, size_t count)
{
int i;
if (d<s) {
for (i=0; i<count; i++)
((char *) d)[i] = ((char *) s)[i];
} else
for (i=0; i<count; i++)
((char *) d)[count-i-1] = ((char *) s)[count-i-1];
}
static __inline__ void *fb_memmove(char *dst, const char *src, size_t size)
{
fast_memmove(dst, src, size);
return dst;
}
#endif /* __mc68000__ */
#if defined(__i386__)
static __inline__ void fast_memmove(void *d, const void *s, size_t count)
{
int d0, d1, d2, d3;
if (d < s) {
__asm__ __volatile__ (
"cld\n\t"
"shrl $1,%%ecx\n\t"
"jnc 1f\n\t"
"movsb\n"
"1:\tshrl $1,%%ecx\n\t"
"jnc 2f\n\t"
"movsw\n"
"2:\trep\n\t"
"movsl"
: "=&c" (d0), "=&D" (d1), "=&S" (d2)
:"0"(count),"1"((long)d),"2"((long)s)
:"memory");
} else {
__asm__ __volatile__ (
"std\n\t"
"shrl $1,%%ecx\n\t"
"jnc 1f\n\t"
"movb 3(%%esi),%%al\n\t"
"movb %%al,3(%%edi)\n\t"
"decl %%esi\n\t"
"decl %%edi\n"
"1:\tshrl $1,%%ecx\n\t"
"jnc 2f\n\t"
"movw 2(%%esi),%%ax\n\t"
"movw %%ax,2(%%edi)\n\t"
"decl %%esi\n\t"
"decl %%edi\n\t"
"decl %%esi\n\t"
"decl %%edi\n"
"2:\trep\n\t"
"movsl\n\t"
"cld"
: "=&c" (d0), "=&D" (d1), "=&S" (d2), "=&a" (d3)
:"0"(count),"1"(count-4+(long)d),"2"(count-4+(long)s)
:"memory");
}
}
static __inline__ void *fb_memmove(char *dst, const char *src, size_t size)
{
fast_memmove(dst, src, size);
return dst;
}
#else /* !__i386__ */
/*
* Anyone who'd like to write asm functions for other CPUs?
* (Why are these functions better than those from include/asm/string.h?)
*/
static __inline__ void *fb_memmove(void *d, const void *s, size_t count)
{
unsigned long dst, src;
if (d < s) {
dst = (unsigned long) d;
src = (unsigned long) s;
if ((count < 8) || ((dst ^ src) & 3))
goto restup;
if (dst & 1) {
fb_writeb(fb_readb(src++), dst++);
count--;
}
if (dst & 2) {
fb_writew(fb_readw(src), dst);
src += 2;
dst += 2;
count -= 2;
}
while (count > 3) {
fb_writel(fb_readl(src), dst);
src += 4;
dst += 4;
count -= 4;
}
restup:
while (count--)
fb_writeb(fb_readb(src++), dst++);
} else {
dst = (unsigned long) d + count;
src = (unsigned long) s + count;
if ((count < 8) || ((dst ^ src) & 3))
goto restdown;
if (dst & 1) {
src--;
dst--;
count--;
fb_writeb(fb_readb(src), dst);
}
if (dst & 2) {
src -= 2;
dst -= 2;
count -= 2;
fb_writew(fb_readw(src), dst);
}
while (count > 3) {
src -= 4;
dst -= 4;
count -= 4;
fb_writel(fb_readl(src), dst);
}
restdown:
while (count--) {
src--;
dst--;
fb_writeb(fb_readb(src), dst);
}
}
return d;
}
static __inline__ void fast_memmove(char *d, const char *s, size_t count)
{
unsigned long dst, src;
if (d < s) {
dst = (unsigned long) d;
src = (unsigned long) s;
if ((count < 8) || ((dst ^ src) & 3))
goto restup;
if (dst & 1) {
fb_writeb(fb_readb(src++), dst++);
count--;
}
if (dst & 2) {
fb_writew(fb_readw(src), dst);
src += 2;
dst += 2;
count -= 2;
}
while (count > 3) {
fb_writel(fb_readl(src), dst);
src += 4;
dst += 4;
count -= 4;
}
restup:
while (count--)
fb_writeb(fb_readb(src++), dst++);
} else {
dst = (unsigned long) d + count;
src = (unsigned long) s + count;
if ((count < 8) || ((dst ^ src) & 3))
goto restdown;
if (dst & 1) {
src--;
dst--;
count--;
fb_writeb(fb_readb(src), dst);
}
if (dst & 2) {
src -= 2;
dst -= 2;
count -= 2;
fb_writew(fb_readw(src), dst);
}
while (count > 3) {
src -= 4;
dst -= 4;
count -= 4;
fb_writel(fb_readl(src), dst);
}
restdown:
while (count--) {
src--;
dst--;
fb_writeb(fb_readb(src), dst);
}
}
}
#endif /* !__i386__ */
void cfb_copyarea(struct fb_info *p, struct fb_copyarea *area)
{
int x2, y2, lineincr, shift, shift_right, shift_left, old_dx,
......
......@@ -27,8 +27,6 @@
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <video/fbcon.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/uaccess.h>
......@@ -368,20 +366,16 @@ int __init clps711xfb_init(void)
{
int err = -ENOMEM;
cfb = kmalloc(sizeof(*cfb) + sizeof(struct display), GFP_KERNEL);
cfb = kmalloc(sizeof(*cfb), GFP_KERNEL);
if (!cfb)
goto out;
memset(cfb, 0, sizeof(*cfb) + sizeof(struct display));
memset(cfb, 0, sizeof(*cfb));
strcpy(cfb->fix.id, "clps711x");
cfb->currcon = -1;
cfb->fbops = &clps7111fb_ops;
cfb->changevar = NULL;
cfb->switch_con = gen_switch;
cfb->updatevar = gen_update_var;
cfb->flags = FBINFO_FLAG_DEFAULT;
cfb->disp = (struct display *)(cfb + 1);
clps711x_guess_lcd_params(cfb);
......@@ -422,7 +416,6 @@ int __init clps711xfb_init(void)
clps_writeb(clps_readb(PDDR) | EDB_PD3_LCDBL, PDDR);
}
gen_set_var(&cfb->var, -1, cfb);
err = register_framebuffer(cfb);
out: return err;
......
......@@ -18,17 +18,15 @@ if [ "$CONFIG_VT" != "n" ]; then
# fi
fi
tristate 'MDA text console (dual-headed) ' CONFIG_MDA_CONSOLE
if [ "$CONFIG_FB" = "y" ]; then
define_bool CONFIG_PCI_CONSOLE y
if [ "$CONFIG_SGI_IP22" = "y" ]; then
tristate 'SGI Newport Console support' CONFIG_SGI_NEWPORT_CONSOLE
if [ "$CONFIG_SGI_NEWPORT_CONSOLE" != "y" ]; then
define_bool CONFIG_DUMMY_CONSOLE y
else
define_bool CONFIG_FONT_8x16 y
fi
fi
#if [ "$CONFIG_SGI_IP22" = "y" ]; then
# tristate 'SGI Newport Console support' CONFIG_SGI_NEWPORT_CONSOLE
# if [ "$CONFIG_SGI_NEWPORT_CONSOLE" != "y" ]; then
# define_bool CONFIG_DUMMY_CONSOLE y
# else
# define_bool CONFIG_FONT_8x16 y
#fi
if [ "$CONFIG_ARCH_PARISC" = "y" ]; then
if [ "$CONFIG_PARISC" = "y" ]; then
# bool 'IODC console' CONFIG_IODC_CONSOLE
bool 'STI console' CONFIG_STI_CONSOLE
if [ "$CONFIG_IODC_CONSOLE" = "n" ]; then
......@@ -50,6 +48,7 @@ if [ "$CONFIG_VT" != "n" ]; then
bool 'Framebuffer Console support' CONFIG_FRAMEBUFFER_CONSOLE
if [ "$CONFIG_FRAMEBUFFER_CONSOLE" = "y" ]; then
define_bool CONFIG_DUMMY_CONSOLE y
define_bool CONFIG_PCI_CONSOLE y
bool ' Advanced low level driver options' CONFIG_FBCON_ADVANCED
if [ "$CONFIG_FBCON_ADVANCED" = "y" ]; then
tristate ' Hardware acceleration support' CONFIG_FBCON_ACCEL
......
......@@ -243,6 +243,24 @@ static void cursor_timer_handler(unsigned long dev_addr)
add_timer(&cursor_timer);
}
static int __init fbconsole_setup(char *options)
{
char *this_opt;
int unit;
if (!options || !*options)
return 0;
while ((this_opt = strsep(&options, ",")) != NULL) {
if (!strncmp(this_opt, "font:", 5)) {
for (unit = 0; unit < MAX_NR_CONSOLES; unit++)
strcpy(fb_display[unit].fontname, this_opt+5);
}
}
return 0;
}
__setup("fbcon=", fbconsole_setup);
/**
* PROC_CONSOLE - find the attached tty or visible console
......@@ -653,8 +671,8 @@ static void fbcon_setup(int con, int init, int logo)
}
if (!p->fontdata) {
if (!info->fontname[0] ||
!(font = fbcon_find_font(info->fontname)))
if (!p->fontname[0] ||
!(font = fbcon_find_font(p->fontname)))
font = fbcon_get_default_font(info->var.xres, info->var.yres);
p->_fontwidth = font->width;
p->_fontheight = font->height;
......@@ -1605,7 +1623,6 @@ static int fbcon_switch(struct vc_data *conp)
return 1;
}
static int fbcon_blank(struct vc_data *conp, int blank)
{
struct display *p = &fb_display[conp->vc_num];
......@@ -1619,10 +1636,12 @@ static int fbcon_blank(struct vc_data *conp, int blank)
if (!p->can_soft_blank) {
if (blank) {
if (info->fix.visual == FB_VISUAL_MONO01) {
/*
if (info->screen_base)
fb_memset255(info->screen_base,
info->var.xres_virtual*info->var.yres_virtual*
info->var.bits_per_pixel>>3);
*/
} else {
unsigned short oldc;
u_int height;
......
......@@ -233,7 +233,6 @@ unsigned long __init dnfb_init(unsigned long mem_start)
{
int err;
fb_info.fontname[0] = 0;
fb_info.node = NODEV;
fb_info.fbops = &dn_fb_ops;
fb_info.fix = dnfb_fix;
......
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
......@@ -24,7 +24,6 @@
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/tty.h>
#include <linux/console.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#ifdef CONFIG_KMOD
......@@ -42,7 +41,10 @@
#include <asm/pgtable.h>
#include <linux/fb.h>
#ifdef CONFIG_VT
#include <linux/console.h>
#include <video/fbcon.h>
#endif
/*
* Frame buffer device initialization and setup routines
......@@ -356,11 +358,14 @@ static int num_pref_init_funcs __initdata = 0;
struct fb_info *registered_fb[FB_MAX];
int num_registered_fb;
#ifdef CONFIG_FRAMEBUFFER_CONSOLE
extern int fbcon_softback_size;
static int first_fb_vc;
static int last_fb_vc = MAX_NR_CONSOLES-1;
static int fbcon_is_default = 1;
#endif
#ifdef CONFIG_FB_OF
static int ofonly __initdata = 0;
......@@ -468,7 +473,9 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
struct fb_ops *fb = info->fbops;
struct fb_var_screeninfo var;
struct fb_fix_screeninfo fix;
#ifdef CONFIG_FRAMEBUFFER_CONSOLE
struct fb_con2fbmap con2fb;
#endif
struct fb_cmap cmap;
int i;
......@@ -481,13 +488,13 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
case FBIOPUT_VSCREENINFO:
if (copy_from_user(&var, (void *) arg, sizeof(var)))
return -EFAULT;
if (var.activate & FB_ACTIVATE_ALL) {
#ifdef CONFIG_FRAMEBUFFER_CONSOLE
if (var.activate & FB_ACTIVATE_ALL)
i = set_all_vcs(fbidx, fb, &var, info);
if (i) return i;
} else {
else
#endif
i = fb_set_var(&var, info);
if (i) return i;
}
if (i) return i;
if (copy_to_user((void *) arg, &var, sizeof(var)))
return -EFAULT;
return 0;
......@@ -511,7 +518,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
if (copy_to_user((void *) arg, &var, sizeof(var)))
return -EFAULT;
return i;
#ifdef CONFIG_VT
#ifdef CONFIG_FRAMEBUFFER_CONSOLE
case FBIOGET_CON2FBMAP:
if (copy_from_user(&con2fb, (void *)arg, sizeof(con2fb)))
return -EFAULT;
......@@ -540,7 +547,7 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
for (i = 0; i < MAX_NR_CONSOLES; i++)
set_con2fb_map(i, con2fb.framebuffer);
return 0;
#endif
#endif /* CONFIG_FRAMEBUFFER_CONSOLE */
case FBIOBLANK:
if (fb->fb_blank == NULL)
return -EINVAL;
......@@ -737,10 +744,13 @@ static devfs_handle_t devfs_handle;
int
register_framebuffer(struct fb_info *fb_info)
{
int i, j;
char name_buf[8];
static int fb_ever_opened[FB_MAX];
#ifdef CONFIG_FRAMEBUFFER_CONSOLE
static int first = 1;
int j;
#endif
char name_buf[8];
int i;
if (num_registered_fb == FB_MAX)
return -ENXIO;
......@@ -753,6 +763,7 @@ register_framebuffer(struct fb_info *fb_info)
registered_fb[i] = fb_info;
if (!fb_ever_opened[i]) {
struct module *owner = fb_info->fbops->owner;
#ifdef CONFIG_FRAMEBUFFER_CONSOLE
/*
* We assume initial frame buffer devices can be opened this
* many times
......@@ -775,6 +786,15 @@ register_framebuffer(struct fb_info *fb_info)
first = 0;
take_over_console(&fb_con, first_fb_vc, last_fb_vc, fbcon_is_default);
}
#else
if (owner) {
__MOD_INC_USE_COUNT(owner);
if (fb_info->fbops->fb_open && fb_info->fbops->fb_open(fb_info,0))
__MOD_DEC_USE_COUNT(owner);
}
fb_ever_opened[i] = 1;
}
#endif
sprintf (name_buf, "%d", i);
fb_info->devfs_handle =
devfs_register (devfs_handle, name_buf, DEVFS_FL_DEFAULT,
......@@ -801,9 +821,11 @@ unregister_framebuffer(struct fb_info *fb_info)
int i, j;
i = GET_FB_IDX(fb_info->node);
#ifdef CONFIG_FRAMEBUFFER_CONSOLE
for (j = 0; j < MAX_NR_CONSOLES; j++)
if (con2fb_map[j] == i)
return -EBUSY;
#endif
if (!registered_fb[i])
return -EINVAL;
devfs_unregister (fb_info->devfs_handle);
......@@ -873,7 +895,8 @@ int __init video_setup(char *options)
if (!options || !*options)
return 0;
#ifdef CONFIG_FRAMEBUFFER_CONSOLE
if (!strncmp(options, "scrollback:", 11)) {
options += 11;
if (*options) {
......@@ -910,6 +933,7 @@ int __init video_setup(char *options)
last_fb_vc = simple_strtoul(options, &options, 10) - 1;
fbcon_is_default = 0;
}
#endif
#ifdef CONFIG_FB_OF
if (!strcmp(options, "ofonly")) {
......
......@@ -240,7 +240,6 @@ int __init g364fb_init(void)
fb_info.fix = fb_fix;
fb_info.flags = FBINFO_FLAG_DEFAULT;
fb_info.fontname[0] = '\0';
fb_alloc_cmap(&fb_info.cmap, 255, 0);
if (register_framebuffer(&fb_info) < 0)
......
......@@ -595,8 +595,6 @@ void __init macfb_setup(char *options, int *ints)
{
char *this_opt;
fb_info.fontname[0] = '\0';
if (!options || !*options)
return;
......@@ -605,8 +603,6 @@ void __init macfb_setup(char *options, int *ints)
if (! strcmp(this_opt, "inverse"))
inverse=1;
else if (!strncmp(this_opt, "font:", 5))
strcpy(fb_info.fontname, this_opt+5);
/* This means "turn on experimental CLUT code" */
else if (!strcmp(this_opt, "vidtest"))
vidtest=1;
......
......@@ -20,7 +20,6 @@
#include <linux/fb.h>
#include <linux/string.h>
#include <video/fbcon.h>
#include <video/macmodes.h>
/*
......
......@@ -34,7 +34,6 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/fb.h>
#include <video/fbcon.h>
#include "maxinefb.h"
/* bootinfo.h defines the machine type values, needed when checking */
......
......@@ -528,7 +528,6 @@ static void __init offb_init_fb(const char *name, const char *full_name,
info->screen_base = ioremap(address, fix->smem_len);
info->par = par;
info->pseudo_palette = (void *) (info + 1);
info->fontname[0] = '\0';
info->flags = FBINFO_FLAG_DEFAULT;
fb_alloc_cmap(&info->cmap, 256, 0);
......
......@@ -181,8 +181,6 @@ int __init vesafb_setup(char *options)
{
char *this_opt;
fb_info.fontname[0] = '\0';
if (!options || !*options)
return 0;
......@@ -203,8 +201,6 @@ int __init vesafb_setup(char *options)
pmi_setpal=1;
else if (! strcmp(this_opt, "mtrr"))
mtrr=1;
else if (!strncmp(this_opt, "font:", 5))
strcpy(fb_info.fontname, this_opt+5);
}
return 0;
}
......
......@@ -18,18 +18,10 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/console.h>
#include <linux/selection.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <asm/io.h>
#include <video/fbcon.h>
#include <video/fbcon-vga-planes.h>
#include <video/fbcon-vga.h>
#include <video/fbcon-cfb4.h>
#include <video/fbcon-cfb8.h>
#include "vga.h"
#define GRAPHICS_ADDR_REG 0x3ce /* Graphics address register. */
......@@ -1058,8 +1050,6 @@ static struct fb_ops vga16fb_ops = {
.fb_set_var = vga16fb_set_var,
.fb_check_var = vga16fb_check_var,
.fb_set_par = vga16fb_set_par,
.fb_get_cmap = gen_get_cmap,
.fb_set_cmap = gen_set_cmap,
.fb_setcolreg = vga16fb_setcolreg,
.fb_pan_display = vga16fb_pan_display,
.fb_blank = vga16fb_blank,
......@@ -1070,16 +1060,11 @@ int vga16fb_setup(char *options)
{
char *this_opt;
vga16fb.fontname[0] = '\0';
if (!options || !*options)
return 0;
while ((this_opt = strsep(&options, ",")) != NULL) {
if (!*this_opt) continue;
if (!strncmp(this_opt, "font:", 5))
strcpy(vga16fb.fontname, this_opt+5);
}
return 0;
}
......@@ -1109,24 +1094,14 @@ int __init vga16fb_init(void)
vga16fb_defined.green.length = i;
vga16fb_defined.blue.length = i;
/* XXX share VGA I/O region with vgacon and others */
disp.var = vga16fb_defined;
/* name should not depend on EGA/VGA */
strcpy(vga16fb.modename, "VGA16 VGA");
vga16fb.changevar = NULL;
strcpy(vga16fb_fix.id, "VGA16 VGA");
vga16fb.node = NODEV;
vga16fb.fbops = &vga16fb_ops;
vga16fb.var = vga16fb_defined;
vga16fb.fix = vga16fb_fix;
vga16fb.par = &vga16_par;
vga16fb.disp = &disp;
vga16fb.currcon = -1;
vga16fb.switch_con = gen_switch;
vga16fb.updatevar=&vga16fb_update_var;
vga16fb.flags=FBINFO_FLAG_DEFAULT;
vga16fb_set_disp(-1, &vga16fb);
if (register_framebuffer(&vga16fb) < 0) {
iounmap(vga16fb.screen_base);
......@@ -1134,8 +1109,7 @@ int __init vga16fb_init(void)
}
printk(KERN_INFO "fb%d: %s frame buffer device\n",
GET_FB_IDX(vga16fb.node), vga16fb.modename);
GET_FB_IDX(vga16fb.node), vga16fb.fix.id);
return 0;
}
......
......@@ -18,6 +18,7 @@
#define FBIOGETCMAP 0x4604
#define FBIOPUTCMAP 0x4605
#define FBIOPAN_DISPLAY 0x4606
#define FBIO_CURSOR _IOWR('F', 0x08, struct fbcursor)
/* 0x4607-0x460B are defined below */
/* #define FBIOGET_MONITORSPEC 0x460C */
/* #define FBIOPUT_MONITORSPEC 0x460D */
......@@ -258,6 +259,32 @@ struct fb_vblank {
__u32 reserved[4]; /* reserved for future compatibility */
};
/*
* hardware cursor control
*/
#define FB_CUR_SETCUR 0x01
#define FB_CUR_SETPOS 0x02
#define FB_CUR_SETHOT 0x04
#define FB_CUR_SETCMAP 0x08
#define FB_CUR_SETSHAPE 0x10
#define FB_CUR_SETALL 0x1F
struct fbcurpos {
__u16 x, y;
};
struct fbcursor {
__u16 set; /* what to set */
__u16 enable; /* cursor on/off */
struct fbcurpos pos; /* cursor position */
struct fbcurpos hot; /* cursor hot spot */
struct fb_cmap cmap; /* color map info */
struct fbcurpos size; /* cursor bit map size */
char *image; /* cursor image bits */
char *mask; /* cursor mask bits */
};
/* Internal HW accel */
#define ROP_COPY 0
#define ROP_XOR 1
......@@ -324,6 +351,8 @@ struct fb_ops {
int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
/* set the video mode according to par */
int (*fb_set_par)(struct fb_info *info);
/* cursor control */
int (*fb_cursor)(struct fb_info *info, struct fbcursor *cursor);
/* set color register */
int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp, struct fb_info *info);
......@@ -358,12 +387,12 @@ struct fb_info {
struct fb_var_screeninfo var; /* Current var */
struct fb_fix_screeninfo fix; /* Current fix */
struct fb_monspecs monspecs; /* Current Monitor specs */
struct fbcursor cursor; /* Current cursor */
struct fb_cmap cmap; /* Current cmap */
struct fb_ops *fbops;
char *screen_base; /* Virtual address */
struct vc_data *display_fg; /* Console visible on this display */
int currcon; /* Current VC. */
char fontname[40]; /* default font name */
devfs_handle_t devfs_handle; /* Devfs handle for new name */
devfs_handle_t devfs_lhandle; /* Devfs handle for compat. symlink */
void *pseudo_palette; /* Fake palette of 16 colors and
......
......@@ -73,7 +73,8 @@ struct display {
int bgcol;
u_long next_line; /* offset to one line below */
u_long next_plane; /* offset to next plane */
u_char *fontdata; /* Font associated to this display */
char fontname[40]; /* Font associated to this display */
u_char *fontdata;
unsigned short _fontheightlog;
unsigned short _fontwidthlog;
unsigned short _fontheight;
......@@ -85,10 +86,9 @@ struct display {
unsigned short charmask; /* 0xff or 0x1ff */
};
/* drivers/video/fbcon.c */
/* drivers/video/console/fbcon.c */
extern struct display fb_display[MAX_NR_CONSOLES];
extern char con2fb_map[MAX_NR_CONSOLES];
extern int PROC_CONSOLE(const struct fb_info *info);
extern void set_con2fb_map(int unit, int newidx);
extern int set_all_vcs(int fbidx, struct fb_ops *fb,
struct fb_var_screeninfo *var, struct fb_info *info);
......@@ -184,571 +184,4 @@ extern int set_all_vcs(int fbidx, struct fb_ops *fb,
extern void fbcon_redraw_clear(struct vc_data *, struct display *, int, int, int, int);
extern void fbcon_redraw_bmove(struct display *, int, int, int, int, int, int);
/* ================================================================= */
/* Utility Assembler Functions */
/* ================================================================= */
#if defined(__mc68000__)
/* ====================================================================== */
/* 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 *fb_memclear_small(void *s, size_t count)
{
if (!count)
return(0);
__asm__ __volatile__(
"lsrl #1,%1 ; jcc 1f ; moveb %2,%0@-\n\t"
"1: lsrl #1,%1 ; jcc 1f ; movew %2,%0@-\n\t"
"1: lsrl #1,%1 ; jcc 1f ; movel %2,%0@-\n\t"
"1: lsrl #1,%1 ; jcc 1f ; movel %2,%0@- ; movel %2,%0@-\n\t"
"1:"
: "=a" (s), "=d" (count)
: "d" (0), "0" ((char *)s+count), "1" (count)
);
__asm__ __volatile__(
"subql #1,%1 ; jcs 3f\n\t"
"movel %2,%%d4; movel %2,%%d5; movel %2,%%d6\n\t"
"2: moveml %2/%%d4/%%d5/%%d6,%0@-\n\t"
"dbra %1,2b\n\t"
"3:"
: "=a" (s), "=d" (count)
: "d" (0), "0" (s), "1" (count)
: "d4", "d5", "d6"
);
return(0);
}
static __inline__ void *fb_memclear(void *s, size_t count)
{
if (!count)
return(0);
if (count < 16) {
__asm__ __volatile__(
"lsrl #1,%1 ; jcc 1f ; clrb %0@+\n\t"
"1: lsrl #1,%1 ; jcc 1f ; clrw %0@+\n\t"
"1: lsrl #1,%1 ; jcc 1f ; clrl %0@+\n\t"
"1: lsrl #1,%1 ; jcc 1f ; clrl %0@+ ; clrl %0@+\n\t"
"1:"
: "=a" (s), "=d" (count)
: "0" (s), "1" (count)
);
} else {
long tmp;
__asm__ __volatile__(
"movel %1,%2\n\t"
"lsrl #1,%2 ; jcc 1f ; clrb %0@+ ; subqw #1,%1\n\t"
"lsrl #1,%2 ; jcs 2f\n\t" /* %0 increased=>bit 2 switched*/
"clrw %0@+ ; subqw #2,%1 ; jra 2f\n\t"
"1: lsrl #1,%2 ; jcc 2f\n\t"
"clrw %0@+ ; subqw #2,%1\n\t"
"2: movew %1,%2; lsrl #2,%1 ; jeq 6f\n\t"
"lsrl #1,%1 ; jcc 3f ; clrl %0@+\n\t"
"3: lsrl #1,%1 ; jcc 4f ; clrl %0@+ ; clrl %0@+\n\t"
"4: subql #1,%1 ; jcs 6f\n\t"
"5: clrl %0@+; clrl %0@+ ; clrl %0@+ ; clrl %0@+\n\t"
"dbra %1,5b ; clrw %1; subql #1,%1; jcc 5b\n\t"
"6: movew %2,%1; btst #1,%1 ; jeq 7f ; clrw %0@+\n\t"
"7: ; btst #0,%1 ; jeq 8f ; clrb %0@+\n\t"
"8:"
: "=a" (s), "=d" (count), "=d" (tmp)
: "0" (s), "1" (count)
);
}
return(0);
}
static __inline__ void *fb_memset255(void *s, size_t count)
{
if (!count)
return(0);
__asm__ __volatile__(
"lsrl #1,%1 ; jcc 1f ; moveb %2,%0@-\n\t"
"1: lsrl #1,%1 ; jcc 1f ; movew %2,%0@-\n\t"
"1: lsrl #1,%1 ; jcc 1f ; movel %2,%0@-\n\t"
"1: lsrl #1,%1 ; jcc 1f ; movel %2,%0@- ; movel %2,%0@-\n\t"
"1:"
: "=a" (s), "=d" (count)
: "d" (-1), "0" ((char *)s+count), "1" (count)
);
__asm__ __volatile__(
"subql #1,%1 ; jcs 3f\n\t"
"movel %2,%%d4; movel %2,%%d5; movel %2,%%d6\n\t"
"2: moveml %2/%%d4/%%d5/%%d6,%0@-\n\t"
"dbra %1,2b\n\t"
"3:"
: "=a" (s), "=d" (count)
: "d" (-1), "0" (s), "1" (count)
: "d4", "d5", "d6"
);
return(0);
}
static __inline__ void *fb_memmove(void *d, const void *s, size_t count)
{
if (d < s) {
if (count < 16) {
__asm__ __volatile__(
"lsrl #1,%2 ; jcc 1f ; moveb %1@+,%0@+\n\t"
"1: lsrl #1,%2 ; jcc 1f ; movew %1@+,%0@+\n\t"
"1: lsrl #1,%2 ; jcc 1f ; movel %1@+,%0@+\n\t"
"1: lsrl #1,%2 ; jcc 1f ; movel %1@+,%0@+ ; movel %1@+,%0@+\n\t"
"1:"
: "=a" (d), "=a" (s), "=d" (count)
: "0" (d), "1" (s), "2" (count)
);
} else {
long tmp;
__asm__ __volatile__(
"movel %0,%3\n\t"
"lsrl #1,%3 ; jcc 1f ; moveb %1@+,%0@+ ; subqw #1,%2\n\t"
"lsrl #1,%3 ; jcs 2f\n\t" /* %0 increased=>bit 2 switched*/
"movew %1@+,%0@+ ; subqw #2,%2 ; jra 2f\n\t"
"1: lsrl #1,%3 ; jcc 2f\n\t"
"movew %1@+,%0@+ ; subqw #2,%2\n\t"
"2: movew %2,%-; lsrl #2,%2 ; jeq 6f\n\t"
"lsrl #1,%2 ; jcc 3f ; movel %1@+,%0@+\n\t"
"3: lsrl #1,%2 ; jcc 4f ; movel %1@+,%0@+ ; movel %1@+,%0@+\n\t"
"4: subql #1,%2 ; jcs 6f\n\t"
"5: movel %1@+,%0@+;movel %1@+,%0@+\n\t"
"movel %1@+,%0@+;movel %1@+,%0@+\n\t"
"dbra %2,5b ; clrw %2; subql #1,%2; jcc 5b\n\t"
"6: movew %+,%2; btst #1,%2 ; jeq 7f ; movew %1@+,%0@+\n\t"
"7: ; btst #0,%2 ; jeq 8f ; moveb %1@+,%0@+\n\t"
"8:"
: "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
: "0" (d), "1" (s), "2" (count)
);
}
} else {
if (count < 16) {
__asm__ __volatile__(
"lsrl #1,%2 ; jcc 1f ; moveb %1@-,%0@-\n\t"
"1: lsrl #1,%2 ; jcc 1f ; movew %1@-,%0@-\n\t"
"1: lsrl #1,%2 ; jcc 1f ; movel %1@-,%0@-\n\t"
"1: lsrl #1,%2 ; jcc 1f ; movel %1@-,%0@- ; movel %1@-,%0@-\n\t"
"1:"
: "=a" (d), "=a" (s), "=d" (count)
: "0" ((char *) d + count), "1" ((char *) s + count), "2" (count)
);
} else {
long tmp;
__asm__ __volatile__(
"movel %0,%3\n\t"
"lsrl #1,%3 ; jcc 1f ; moveb %1@-,%0@- ; subqw #1,%2\n\t"
"lsrl #1,%3 ; jcs 2f\n\t" /* %0 increased=>bit 2 switched*/
"movew %1@-,%0@- ; subqw #2,%2 ; jra 2f\n\t"
"1: lsrl #1,%3 ; jcc 2f\n\t"
"movew %1@-,%0@- ; subqw #2,%2\n\t"
"2: movew %2,%-; lsrl #2,%2 ; jeq 6f\n\t"
"lsrl #1,%2 ; jcc 3f ; movel %1@-,%0@-\n\t"
"3: lsrl #1,%2 ; jcc 4f ; movel %1@-,%0@- ; movel %1@-,%0@-\n\t"
"4: subql #1,%2 ; jcs 6f\n\t"
"5: movel %1@-,%0@-;movel %1@-,%0@-\n\t"
"movel %1@-,%0@-;movel %1@-,%0@-\n\t"
"dbra %2,5b ; clrw %2; subql #1,%2; jcc 5b\n\t"
"6: movew %+,%2; btst #1,%2 ; jeq 7f ; movew %1@-,%0@-\n\t"
"7: ; btst #0,%2 ; jeq 8f ; moveb %1@-,%0@-\n\t"
"8:"
: "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
: "0" ((char *) d + count), "1" ((char *) s + count), "2" (count)
);
}
}
return(0);
}
/* ++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, const char *src, size_t size)
{
if (!size)
return;
if (dst < src)
__asm__ __volatile__
("1:"
" moveml %0@+,%/d0/%/d1/%/a0/%/a1\n"
" moveml %/d0/%/d1/%/a0/%/a1,%1@\n"
" addql #8,%1; addql #8,%1\n"
" dbra %2,1b\n"
" clrw %2; subql #1,%2\n"
" jcc 1b"
: "=a" (src), "=a" (dst), "=d" (size)
: "0" (src), "1" (dst), "2" (size / 16 - 1)
: "d0", "d1", "a0", "a1", "memory");
else
__asm__ __volatile__
("1:"
" subql #8,%0; subql #8,%0\n"
" moveml %0@,%/d0/%/d1/%/a0/%/a1\n"
" moveml %/d0/%/d1/%/a0/%/a1,%1@-\n"
" dbra %2,1b\n"
" clrw %2; subql #1,%2\n"
" jcc 1b"
: "=a" (src), "=a" (dst), "=d" (size)
: "0" (src + size), "1" (dst + size), "2" (size / 16 - 1)
: "d0", "d1", "a0", "a1", "memory");
}
#elif defined(CONFIG_SUN4)
/* You may think that I'm crazy and that I should use generic
routines. No, I'm not: sun4's framebuffer crashes if we std
into it, so we cannot use memset. */
static __inline__ void *sun4_memset(void *s, char val, size_t count)
{
int i;
for(i=0; i<count;i++)
((char *) s) [i] = val;
return s;
}
static __inline__ void *fb_memset255(void *s, size_t count)
{
return sun4_memset(s, 255, count);
}
static __inline__ void *fb_memclear(void *s, size_t count)
{
return sun4_memset(s, 0, count);
}
static __inline__ void *fb_memclear_small(void *s, size_t count)
{
return sun4_memset(s, 0, count);
}
/* To be honest, this is slow_memmove :). But sun4 is crappy, so what we can do. */
static __inline__ void fast_memmove(void *d, const void *s, size_t count)
{
int i;
if (d<s) {
for (i=0; i<count; i++)
((char *) d)[i] = ((char *) s)[i];
} else
for (i=0; i<count; i++)
((char *) d)[count-i-1] = ((char *) s)[count-i-1];
}
static __inline__ void *fb_memmove(char *dst, const char *src, size_t size)
{
fast_memmove(dst, src, size);
return dst;
}
#else
static __inline__ void *fb_memclear_small(void *s, size_t count)
{
char *xs = (char *) s;
while (count--)
fb_writeb(0, xs++);
return s;
}
static __inline__ void *fb_memclear(void *s, size_t count)
{
unsigned long xs = (unsigned long) s;
if (count < 8)
goto rest;
if (xs & 1) {
fb_writeb(0, xs++);
count--;
}
if (xs & 2) {
fb_writew(0, xs);
xs += 2;
count -= 2;
}
while (count > 3) {
fb_writel(0, xs);
xs += 4;
count -= 4;
}
rest:
while (count--)
fb_writeb(0, xs++);
return s;
}
static __inline__ void *fb_memset255(void *s, size_t count)
{
unsigned long xs = (unsigned long) s;
if (count < 8)
goto rest;
if (xs & 1) {
fb_writeb(0xff, xs++);
count--;
}
if (xs & 2) {
fb_writew(0xffff, xs);
xs += 2;
count -= 2;
}
while (count > 3) {
fb_writel(0xffffffff, xs);
xs += 4;
count -= 4;
}
rest:
while (count--)
fb_writeb(0xff, xs++);
return s;
}
#if defined(__i386__)
static __inline__ void fast_memmove(void *d, const void *s, size_t count)
{
int d0, d1, d2, d3;
if (d < s) {
__asm__ __volatile__ (
"cld\n\t"
"shrl $1,%%ecx\n\t"
"jnc 1f\n\t"
"movsb\n"
"1:\tshrl $1,%%ecx\n\t"
"jnc 2f\n\t"
"movsw\n"
"2:\trep\n\t"
"movsl"
: "=&c" (d0), "=&D" (d1), "=&S" (d2)
:"0"(count),"1"((long)d),"2"((long)s)
:"memory");
} else {
__asm__ __volatile__ (
"std\n\t"
"shrl $1,%%ecx\n\t"
"jnc 1f\n\t"
"movb 3(%%esi),%%al\n\t"
"movb %%al,3(%%edi)\n\t"
"decl %%esi\n\t"
"decl %%edi\n"
"1:\tshrl $1,%%ecx\n\t"
"jnc 2f\n\t"
"movw 2(%%esi),%%ax\n\t"
"movw %%ax,2(%%edi)\n\t"
"decl %%esi\n\t"
"decl %%edi\n\t"
"decl %%esi\n\t"
"decl %%edi\n"
"2:\trep\n\t"
"movsl\n\t"
"cld"
: "=&c" (d0), "=&D" (d1), "=&S" (d2), "=&a" (d3)
:"0"(count),"1"(count-4+(long)d),"2"(count-4+(long)s)
:"memory");
}
}
static __inline__ void *fb_memmove(char *dst, const char *src, size_t size)
{
fast_memmove(dst, src, size);
return dst;
}
#else /* !__i386__ */
/*
* Anyone who'd like to write asm functions for other CPUs?
* (Why are these functions better than those from include/asm/string.h?)
*/
static __inline__ void *fb_memmove(void *d, const void *s, size_t count)
{
unsigned long dst, src;
if (d < s) {
dst = (unsigned long) d;
src = (unsigned long) s;
if ((count < 8) || ((dst ^ src) & 3))
goto restup;
if (dst & 1) {
fb_writeb(fb_readb(src++), dst++);
count--;
}
if (dst & 2) {
fb_writew(fb_readw(src), dst);
src += 2;
dst += 2;
count -= 2;
}
while (count > 3) {
fb_writel(fb_readl(src), dst);
src += 4;
dst += 4;
count -= 4;
}
restup:
while (count--)
fb_writeb(fb_readb(src++), dst++);
} else {
dst = (unsigned long) d + count;
src = (unsigned long) s + count;
if ((count < 8) || ((dst ^ src) & 3))
goto restdown;
if (dst & 1) {
src--;
dst--;
count--;
fb_writeb(fb_readb(src), dst);
}
if (dst & 2) {
src -= 2;
dst -= 2;
count -= 2;
fb_writew(fb_readw(src), dst);
}
while (count > 3) {
src -= 4;
dst -= 4;
count -= 4;
fb_writel(fb_readl(src), dst);
}
restdown:
while (count--) {
src--;
dst--;
fb_writeb(fb_readb(src), dst);
}
}
return d;
}
static __inline__ void fast_memmove(char *d, const char *s, size_t count)
{
unsigned long dst, src;
if (d < s) {
dst = (unsigned long) d;
src = (unsigned long) s;
if ((count < 8) || ((dst ^ src) & 3))
goto restup;
if (dst & 1) {
fb_writeb(fb_readb(src++), dst++);
count--;
}
if (dst & 2) {
fb_writew(fb_readw(src), dst);
src += 2;
dst += 2;
count -= 2;
}
while (count > 3) {
fb_writel(fb_readl(src), dst);
src += 4;
dst += 4;
count -= 4;
}
restup:
while (count--)
fb_writeb(fb_readb(src++), dst++);
} else {
dst = (unsigned long) d + count;
src = (unsigned long) s + count;
if ((count < 8) || ((dst ^ src) & 3))
goto restdown;
if (dst & 1) {
src--;
dst--;
count--;
fb_writeb(fb_readb(src), dst);
}
if (dst & 2) {
src -= 2;
dst -= 2;
count -= 2;
fb_writew(fb_readw(src), dst);
}
while (count > 3) {
src -= 4;
dst -= 4;
count -= 4;
fb_writel(fb_readl(src), dst);
}
restdown:
while (count--) {
src--;
dst--;
fb_writeb(fb_readb(src), dst);
}
}
}
#endif /* !__i386__ */
#endif /* !__mc68000__ */
#endif /* _VIDEO_FBCON_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment