/shark/trunk/drivers/fb/cfbcopyarea.c |
---|
0,0 → 1,435 |
/* |
* Generic function for frame buffer with packed pixels of any depth. |
* |
* Copyright (C) June 1999 James Simmons |
* |
* 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. |
* |
* NOTES: |
* |
* This is for cfb packed pixels. Iplan and such are incorporated in the |
* drivers that need them. |
* |
* FIXME |
* The code for 24 bit is horrible. It copies byte by byte size instead of |
* longs like the other sizes. Needs to be optimized. |
* |
* Also need to add code to deal with cards endians that are different than |
* the native cpu endians. I also need to deal with MSB position in the word. |
* |
*/ |
#include <linuxcomp.h> |
#include <linux/config.h> |
#include <linux/module.h> |
#include <linux/kernel.h> |
#include <linux/string.h> |
#include <linux/fb.h> |
#include <linux/slab.h> |
#include <asm/types.h> |
#include <asm/io.h> |
#define LONG_MASK (BITS_PER_LONG - 1) |
#if BITS_PER_LONG == 32 |
#define FB_WRITEL fb_writel |
#define FB_READL fb_readl |
#define SHIFT_PER_LONG 5 |
#define BYTES_PER_LONG 4 |
#else |
#define FB_WRITEL fb_writeq |
#define FB_READL fb_readq |
#define SHIFT_PER_LONG 6 |
#define BYTES_PER_LONG 8 |
#endif |
static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src, |
int src_idx, unsigned long n) |
{ |
unsigned long first, last; |
int shift = dst_idx-src_idx, left, right; |
unsigned long d0, d1; |
int m; |
if (!n) |
return; |
shift = dst_idx-src_idx; |
first = ~0UL >> dst_idx; |
last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG)); |
if (!shift) { |
// Same alignment for source and dest |
if (dst_idx+n <= BITS_PER_LONG) { |
// Single word |
if (last) |
first &= last; |
FB_WRITEL((FB_READL(src) & first) | (FB_READL(dst) & ~first), dst); |
} else { |
// Multiple destination words |
// Leading bits |
if (first) { |
FB_WRITEL((FB_READL(src) & first) | |
(FB_READL(dst) & ~first), dst); |
dst++; |
src++; |
n -= BITS_PER_LONG-dst_idx; |
} |
// Main chunk |
n /= BITS_PER_LONG; |
while (n >= 8) { |
FB_WRITEL(FB_READL(src++), dst++); |
FB_WRITEL(FB_READL(src++), dst++); |
FB_WRITEL(FB_READL(src++), dst++); |
FB_WRITEL(FB_READL(src++), dst++); |
FB_WRITEL(FB_READL(src++), dst++); |
FB_WRITEL(FB_READL(src++), dst++); |
FB_WRITEL(FB_READL(src++), dst++); |
FB_WRITEL(FB_READL(src++), dst++); |
n -= 8; |
} |
while (n--) |
FB_WRITEL(FB_READL(src++), dst++); |
// Trailing bits |
if (last) |
FB_WRITEL((FB_READL(src) & last) | (FB_READL(dst) & ~last), dst); |
} |
} else { |
// Different alignment for source and dest |
right = shift & (BITS_PER_LONG-1); |
left = -shift & (BITS_PER_LONG-1); |
if (dst_idx+n <= BITS_PER_LONG) { |
// Single destination word |
if (last) |
first &= last; |
if (shift > 0) { |
// Single source word |
FB_WRITEL(((FB_READL(src) >> right) & first) | |
(FB_READL(dst) & ~first), dst); |
} else if (src_idx+n <= BITS_PER_LONG) { |
// Single source word |
FB_WRITEL(((FB_READL(src) << left) & first) | |
(FB_READL(dst) & ~first), dst); |
} else { |
// 2 source words |
d0 = FB_READL(src++); |
d1 = FB_READL(src); |
FB_WRITEL(((d0<<left | d1>>right) & first) | |
(FB_READL(dst) & ~first), dst); |
} |
} else { |
// Multiple destination words |
d0 = FB_READL(src++); |
// Leading bits |
if (shift > 0) { |
// Single source word |
FB_WRITEL(((d0 >> right) & first) | |
(FB_READL(dst) & ~first), dst); |
dst++; |
n -= BITS_PER_LONG-dst_idx; |
} else { |
// 2 source words |
d1 = FB_READL(src++); |
FB_WRITEL(((d0<<left | d1>>right) & first) | |
(FB_READL(dst) & ~first), dst); |
d0 = d1; |
dst++; |
n -= BITS_PER_LONG-dst_idx; |
} |
// Main chunk |
m = n % BITS_PER_LONG; |
n /= BITS_PER_LONG; |
while (n >= 4) { |
d1 = FB_READL(src++); |
FB_WRITEL(d0 << left | d1 >> right, dst++); |
d0 = d1; |
d1 = FB_READL(src++); |
FB_WRITEL(d0 << left | d1 >> right, dst++); |
d0 = d1; |
d1 = FB_READL(src++); |
FB_WRITEL(d0 << left | d1 >> right, dst++); |
d0 = d1; |
d1 = FB_READL(src++); |
FB_WRITEL(d0 << left | d1 >> right, dst++); |
d0 = d1; |
n -= 4; |
} |
while (n--) { |
d1 = FB_READL(src++); |
FB_WRITEL(d0 << left | d1 >> right, dst++); |
d0 = d1; |
} |
// Trailing bits |
if (last) { |
if (m <= right) { |
// Single source word |
FB_WRITEL(((d0 << left) & last) | |
(FB_READL(dst) & ~last), |
dst); |
} else { |
// 2 source words |
d1 = FB_READL(src); |
FB_WRITEL(((d0<<left | d1>>right) & |
last) | (FB_READL(dst) & |
~last), dst); |
} |
} |
} |
} |
} |
static void bitcpy_rev(unsigned long *dst, int dst_idx, |
const unsigned long *src, int src_idx, unsigned long n) |
{ |
unsigned long first, last; |
int shift = dst_idx-src_idx, left, right; |
unsigned long d0, d1; |
int m; |
if (!n) |
return; |
dst += (n-1)/BITS_PER_LONG; |
src += (n-1)/BITS_PER_LONG; |
if ((n-1) % BITS_PER_LONG) { |
dst_idx += (n-1) % BITS_PER_LONG; |
dst += dst_idx >> SHIFT_PER_LONG; |
dst_idx &= BITS_PER_LONG-1; |
src_idx += (n-1) % BITS_PER_LONG; |
src += src_idx >> SHIFT_PER_LONG; |
src_idx &= BITS_PER_LONG-1; |
} |
shift = dst_idx-src_idx; |
first = ~0UL << (BITS_PER_LONG-1-dst_idx); |
last = ~(~0UL << (BITS_PER_LONG-1-((dst_idx-n) % BITS_PER_LONG))); |
if (!shift) { |
// Same alignment for source and dest |
if ((unsigned long)dst_idx+1 >= n) { |
// Single word |
if (last) |
first &= last; |
FB_WRITEL((FB_READL(src) & first) | (FB_READL(dst) & ~first), dst); |
} else { |
// Multiple destination words |
// Leading bits |
if (first) { |
FB_WRITEL((FB_READL(src) & first) | (FB_READL(dst) & ~first), dst); |
dst--; |
src--; |
n -= dst_idx+1; |
} |
// Main chunk |
n /= BITS_PER_LONG; |
while (n >= 8) { |
FB_WRITEL(FB_READL(src--), dst--); |
FB_WRITEL(FB_READL(src--), dst--); |
FB_WRITEL(FB_READL(src--), dst--); |
FB_WRITEL(FB_READL(src--), dst--); |
FB_WRITEL(FB_READL(src--), dst--); |
FB_WRITEL(FB_READL(src--), dst--); |
FB_WRITEL(FB_READL(src--), dst--); |
FB_WRITEL(FB_READL(src--), dst--); |
n -= 8; |
} |
while (n--) |
FB_WRITEL(FB_READL(src--), dst--); |
// Trailing bits |
if (last) |
FB_WRITEL((FB_READL(src) & last) | (FB_READL(dst) & ~last), dst); |
} |
} else { |
// Different alignment for source and dest |
right = shift & (BITS_PER_LONG-1); |
left = -shift & (BITS_PER_LONG-1); |
if ((unsigned long)dst_idx+1 >= n) { |
// Single destination word |
if (last) |
first &= last; |
if (shift < 0) { |
// Single source word |
FB_WRITEL((FB_READL(src) << left & first) | |
(FB_READL(dst) & ~first), dst); |
} else if (1+(unsigned long)src_idx >= n) { |
// Single source word |
FB_WRITEL(((FB_READL(src) >> right) & first) | |
(FB_READL(dst) & ~first), dst); |
} else { |
// 2 source words |
d0 = FB_READL(src--); |
d1 = FB_READL(src); |
FB_WRITEL(((d0>>right | d1<<left) & first) | |
(FB_READL(dst) & ~first), dst); |
} |
} else { |
// Multiple destination words |
d0 = FB_READL(src--); |
// Leading bits |
if (shift < 0) { |
// Single source word |
FB_WRITEL(((d0 << left) & first) | |
(FB_READL(dst) & ~first), dst); |
dst--; |
n -= dst_idx+1; |
} else { |
// 2 source words |
d1 = FB_READL(src--); |
FB_WRITEL(((d0>>right | d1<<left) & first) | |
(FB_READL(dst) & ~first), dst); |
d0 = d1; |
dst--; |
n -= dst_idx+1; |
} |
// Main chunk |
m = n % BITS_PER_LONG; |
n /= BITS_PER_LONG; |
while (n >= 4) { |
d1 = FB_READL(src--); |
FB_WRITEL(d0 >> right | d1 << left, dst--); |
d0 = d1; |
d1 = FB_READL(src--); |
FB_WRITEL(d0 >> right | d1 << left, dst--); |
d0 = d1; |
d1 = FB_READL(src--); |
FB_WRITEL(d0 >> right | d1 << left, dst--); |
d0 = d1; |
d1 = FB_READL(src--); |
FB_WRITEL(d0 >> right | d1 << left, dst--); |
d0 = d1; |
n -= 4; |
} |
while (n--) { |
d1 = FB_READL(src--); |
FB_WRITEL(d0 >> right | d1 << left, dst--); |
d0 = d1; |
} |
// Trailing bits |
if (last) { |
if (m <= left) { |
// Single source word |
FB_WRITEL(((d0 >> right) & last) | |
(FB_READL(dst) & ~last), |
dst); |
} else { |
// 2 source words |
d1 = FB_READL(src); |
FB_WRITEL(((d0>>right | d1<<left) & |
last) | (FB_READL(dst) & |
~last), dst); |
} |
} |
} |
} |
} |
void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area) |
{ |
u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy; |
u32 height = area->height, width = area->width; |
int x2, y2, old_dx, old_dy, vxres, vyres; |
unsigned long next_line = p->fix.line_length; |
int dst_idx = 0, src_idx = 0, rev_copy = 0; |
unsigned long *dst = NULL, *src = NULL; |
/* We want rotation but lack hardware to do it for us. */ |
if (!p->fbops->fb_rotate && p->var.rotate) { |
} |
vxres = p->var.xres_virtual; |
vyres = p->var.yres_virtual; |
if (area->dx > vxres || area->sx > vxres || |
area->dy > vyres || area->sy > vyres) |
return; |
/* clip the destination */ |
old_dx = area->dx; |
old_dy = area->dy; |
/* |
* We could use hardware clipping but on many cards you get around |
* hardware clipping by writing to framebuffer directly. |
*/ |
x2 = area->dx + area->width; |
y2 = area->dy + area->height; |
dx = area->dx > 0 ? area->dx : 0; |
dy = area->dy > 0 ? area->dy : 0; |
x2 = x2 < vxres ? x2 : vxres; |
y2 = y2 < vyres ? y2 : vyres; |
width = x2 - dx; |
height = y2 - dy; |
/* update sx1,sy1 */ |
sx += (dx - old_dx); |
sy += (dy - old_dy); |
/* the source must be completely inside the virtual screen */ |
if (sx < 0 || sy < 0 || |
(sx + width) > vxres || |
(sy + height) > vyres) |
return; |
if ((dy == sy && dx > sx) || |
(dy > sy)) { |
dy += height; |
sy += height; |
rev_copy = 1; |
} |
dst = src = (unsigned long *)((unsigned long)p->screen_base & |
~(BYTES_PER_LONG-1)); |
dst_idx = src_idx = (unsigned long)p->screen_base & (BYTES_PER_LONG-1); |
dst_idx += dy*next_line*8 + dx*p->var.bits_per_pixel; |
src_idx += sy*next_line*8 + sx*p->var.bits_per_pixel; |
if (p->fbops->fb_sync) |
p->fbops->fb_sync(p); |
if (rev_copy) { |
while (height--) { |
dst_idx -= next_line*8; |
src_idx -= next_line*8; |
dst += dst_idx >> SHIFT_PER_LONG; |
dst_idx &= (BYTES_PER_LONG-1); |
src += src_idx >> SHIFT_PER_LONG; |
src_idx &= (BYTES_PER_LONG-1); |
bitcpy_rev(dst, dst_idx, src, src_idx, |
width*p->var.bits_per_pixel); |
} |
} else { |
while (height--) { |
dst += dst_idx >> SHIFT_PER_LONG; |
dst_idx &= (BYTES_PER_LONG-1); |
src += src_idx >> SHIFT_PER_LONG; |
src_idx &= (BYTES_PER_LONG-1); |
bitcpy(dst, dst_idx, src, src_idx, |
width*p->var.bits_per_pixel); |
dst_idx += next_line*8; |
src_idx += next_line*8; |
} |
} |
} |
EXPORT_SYMBOL(cfb_copyarea); |
MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>"); |
MODULE_DESCRIPTION("Generic software accelerated copyarea"); |
MODULE_LICENSE("GPL"); |
/shark/trunk/drivers/fb/vgastate.c |
---|
0,0 → 1,505 |
/* |
* linux/drivers/video/vgastate.c -- VGA state save/restore |
* |
* Copyright 2002 James Simmons |
* |
* Copyright history from vga16fb.c: |
* Copyright 1999 Ben Pfaff and Petr Vandrovec |
* Based on VGA info at http://www.goodnet.com/~tinara/FreeVGA/home.htm |
* Based on VESA framebuffer (c) 1998 Gerd Knorr |
* |
* 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 <linuxcomp.h> |
#include <linux/config.h> |
#include <linux/module.h> |
#include <linux/slab.h> |
#include <linux/fb.h> |
#include <linux/vmalloc.h> |
#include <video/vga.h> |
struct regstate { |
__u8 *vga_font0; |
__u8 *vga_font1; |
__u8 *vga_text; |
__u8 *vga_cmap; |
__u8 *attr; |
__u8 *crtc; |
__u8 *gfx; |
__u8 *seq; |
__u8 misc; |
}; |
static inline unsigned char vga_rcrtcs(caddr_t regbase, unsigned short iobase, |
unsigned char reg) |
{ |
vga_w(regbase, iobase + 0x4, reg); |
return vga_r(regbase, iobase + 0x5); |
} |
static inline void vga_wcrtcs(caddr_t regbase, unsigned short iobase, |
unsigned char reg, unsigned char val) |
{ |
vga_w(regbase, iobase + 0x4, reg); |
vga_w(regbase, iobase + 0x5, val); |
} |
static void save_vga_text(struct vgastate *state, caddr_t fbbase) |
{ |
struct regstate *saved = (struct regstate *) state->vidstate; |
int i; |
u8 misc, attr10, gr4, gr5, gr6, seq1, seq2, seq4; |
/* if in graphics mode, no need to save */ |
attr10 = vga_rattr(state->vgabase, 0x10); |
if (attr10 & 1) |
return; |
/* save regs */ |
misc = vga_r(state->vgabase, VGA_MIS_R); |
gr4 = vga_rgfx(state->vgabase, VGA_GFX_PLANE_READ); |
gr5 = vga_rgfx(state->vgabase, VGA_GFX_MODE); |
gr6 = vga_rgfx(state->vgabase, VGA_GFX_MISC); |
seq2 = vga_rseq(state->vgabase, VGA_SEQ_PLANE_WRITE); |
seq4 = vga_rseq(state->vgabase, VGA_SEQ_MEMORY_MODE); |
/* force graphics mode */ |
vga_w(state->vgabase, VGA_MIS_W, misc | 1); |
/* blank screen */ |
seq1 = vga_rseq(state->vgabase, VGA_SEQ_CLOCK_MODE); |
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1); |
vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 | 1 << 5); |
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3); |
/* save font at plane 2 */ |
if (state->flags & VGA_SAVE_FONT0) { |
vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x4); |
vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6); |
vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x2); |
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0); |
vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5); |
for (i = 0; i < 4 * 8192; i++) |
saved->vga_font0[i] = vga_r(fbbase, i); |
} |
/* save font at plane 3 */ |
if (state->flags & VGA_SAVE_FONT1) { |
vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x8); |
vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6); |
vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x3); |
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0); |
vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5); |
for (i = 0; i < state->memsize; i++) |
saved->vga_font1[i] = vga_r(fbbase, i); |
} |
/* save font at plane 0/1 */ |
if (state->flags & VGA_SAVE_TEXT) { |
vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x1); |
vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6); |
vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x0); |
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0); |
vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5); |
for (i = 0; i < 8192; i++) |
saved->vga_text[i] = vga_r(fbbase, i); |
vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x2); |
vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6); |
vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x1); |
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0); |
vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5); |
for (i = 0; i < 8192; i++) |
saved->vga_text[8192+i] = vga_r(fbbase + 2 * 8192, i); |
} |
/* restore regs */ |
vga_wattr(state->vgabase, 0x10, attr10); |
vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, seq2); |
vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, seq4); |
vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, gr4); |
vga_wgfx(state->vgabase, VGA_GFX_MODE, gr5); |
vga_wgfx(state->vgabase, VGA_GFX_MISC, gr6); |
vga_w(state->vgabase, VGA_MIS_W, misc); |
/* unblank screen */ |
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1); |
vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 & ~(1 << 5)); |
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3); |
vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1); |
} |
static void restore_vga_text(struct vgastate *state, caddr_t fbbase) |
{ |
struct regstate *saved = (struct regstate *) state->vidstate; |
int i; |
u8 misc, gr1, gr3, gr4, gr5, gr6, gr8; |
u8 seq1, seq2, seq4; |
/* save regs */ |
misc = vga_r(state->vgabase, VGA_MIS_R); |
gr1 = vga_rgfx(state->vgabase, VGA_GFX_SR_ENABLE); |
gr3 = vga_rgfx(state->vgabase, VGA_GFX_DATA_ROTATE); |
gr4 = vga_rgfx(state->vgabase, VGA_GFX_PLANE_READ); |
gr5 = vga_rgfx(state->vgabase, VGA_GFX_MODE); |
gr6 = vga_rgfx(state->vgabase, VGA_GFX_MISC); |
gr8 = vga_rgfx(state->vgabase, VGA_GFX_BIT_MASK); |
seq2 = vga_rseq(state->vgabase, VGA_SEQ_PLANE_WRITE); |
seq4 = vga_rseq(state->vgabase, VGA_SEQ_MEMORY_MODE); |
/* force graphics mode */ |
vga_w(state->vgabase, VGA_MIS_W, misc | 1); |
/* blank screen */ |
seq1 = vga_rseq(state->vgabase, VGA_SEQ_CLOCK_MODE); |
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1); |
vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 | 1 << 5); |
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3); |
if (state->depth == 4) { |
vga_wgfx(state->vgabase, VGA_GFX_DATA_ROTATE, 0x0); |
vga_wgfx(state->vgabase, VGA_GFX_BIT_MASK, 0xff); |
vga_wgfx(state->vgabase, VGA_GFX_SR_ENABLE, 0x00); |
} |
/* restore font at plane 2 */ |
if (state->flags & VGA_SAVE_FONT0) { |
vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x4); |
vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6); |
vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x2); |
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0); |
vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5); |
for (i = 0; i < 4 * 8192; i++) |
vga_w(fbbase, i, saved->vga_font0[i]); |
} |
/* restore font at plane 3 */ |
if (state->flags & VGA_SAVE_FONT1) { |
vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x8); |
vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6); |
vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x3); |
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0); |
vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5); |
for (i = 0; i < state->memsize; i++) |
vga_w(fbbase, i, saved->vga_font1[i]); |
} |
/* restore font at plane 0/1 */ |
if (state->flags & VGA_SAVE_TEXT) { |
vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x1); |
vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6); |
vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x0); |
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0); |
vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5); |
for (i = 0; i < 8192; i++) |
vga_w(fbbase, i, saved->vga_text[i]); |
vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, 0x2); |
vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, 0x6); |
vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, 0x1); |
vga_wgfx(state->vgabase, VGA_GFX_MODE, 0x0); |
vga_wgfx(state->vgabase, VGA_GFX_MISC, 0x5); |
for (i = 0; i < 8192; i++) |
vga_w(fbbase, i, saved->vga_text[8192+i]); |
} |
/* unblank screen */ |
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1); |
vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1 & ~(1 << 5)); |
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x3); |
/* restore regs */ |
vga_w(state->vgabase, VGA_MIS_W, misc); |
vga_wgfx(state->vgabase, VGA_GFX_SR_ENABLE, gr1); |
vga_wgfx(state->vgabase, VGA_GFX_DATA_ROTATE, gr3); |
vga_wgfx(state->vgabase, VGA_GFX_PLANE_READ, gr4); |
vga_wgfx(state->vgabase, VGA_GFX_MODE, gr5); |
vga_wgfx(state->vgabase, VGA_GFX_MISC, gr6); |
vga_wgfx(state->vgabase, VGA_GFX_BIT_MASK, gr8); |
vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, seq1); |
vga_wseq(state->vgabase, VGA_SEQ_PLANE_WRITE, seq2); |
vga_wseq(state->vgabase, VGA_SEQ_MEMORY_MODE, seq4); |
} |
static void save_vga_mode(struct vgastate *state) |
{ |
struct regstate *saved = (struct regstate *) state->vidstate; |
unsigned short iobase; |
int i; |
saved->misc = vga_r(state->vgabase, VGA_MIS_R); |
if (saved->misc & 1) |
iobase = 0x3d0; |
else |
iobase = 0x3b0; |
for (i = 0; i < state->num_crtc; i++) |
saved->crtc[i] = vga_rcrtcs(state->vgabase, iobase, i); |
vga_r(state->vgabase, iobase + 0xa); |
vga_w(state->vgabase, VGA_ATT_W, 0x00); |
for (i = 0; i < state->num_attr; i++) { |
vga_r(state->vgabase, iobase + 0xa); |
saved->attr[i] = vga_rattr(state->vgabase, i); |
} |
vga_r(state->vgabase, iobase + 0xa); |
vga_w(state->vgabase, VGA_ATT_W, 0x20); |
for (i = 0; i < state->num_gfx; i++) |
saved->gfx[i] = vga_rgfx(state->vgabase, i); |
for (i = 0; i < state->num_seq; i++) |
saved->seq[i] = vga_rseq(state->vgabase, i); |
} |
static void restore_vga_mode(struct vgastate *state) |
{ |
struct regstate *saved = (struct regstate *) state->vidstate; |
unsigned short iobase; |
int i; |
vga_w(state->vgabase, VGA_MIS_W, saved->misc); |
if (saved->misc & 1) |
iobase = 0x3d0; |
else |
iobase = 0x3b0; |
/* turn off display */ |
vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, |
saved->seq[VGA_SEQ_CLOCK_MODE] | 0x20); |
/* disable sequencer */ |
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x01); |
/* enable palette addressing */ |
vga_r(state->vgabase, iobase + 0xa); |
vga_w(state->vgabase, VGA_ATT_W, 0x00); |
for (i = 2; i < state->num_seq; i++) |
vga_wseq(state->vgabase, i, saved->seq[i]); |
/* unprotect vga regs */ |
vga_wcrtcs(state->vgabase, iobase, 17, saved->crtc[17] & ~0x80); |
for (i = 0; i < state->num_crtc; i++) |
vga_wcrtcs(state->vgabase, iobase, i, saved->crtc[i]); |
for (i = 0; i < state->num_gfx; i++) |
vga_wgfx(state->vgabase, i, saved->gfx[i]); |
for (i = 0; i < state->num_attr; i++) { |
vga_r(state->vgabase, iobase + 0xa); |
vga_wattr(state->vgabase, i, saved->attr[i]); |
} |
/* reenable sequencer */ |
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x03); |
/* turn display on */ |
vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, |
saved->seq[VGA_SEQ_CLOCK_MODE] & ~(1 << 5)); |
/* disable video/palette source */ |
vga_r(state->vgabase, iobase + 0xa); |
vga_w(state->vgabase, VGA_ATT_W, 0x20); |
} |
static void save_vga_cmap(struct vgastate *state) |
{ |
struct regstate *saved = (struct regstate *) state->vidstate; |
int i; |
vga_w(state->vgabase, VGA_PEL_MSK, 0xff); |
/* assumes DAC is readable and writable */ |
vga_w(state->vgabase, VGA_PEL_IR, 0x00); |
for (i = 0; i < 768; i++) |
saved->vga_cmap[i] = vga_r(state->vgabase, VGA_PEL_D); |
} |
static void restore_vga_cmap(struct vgastate *state) |
{ |
struct regstate *saved = (struct regstate *) state->vidstate; |
int i; |
vga_w(state->vgabase, VGA_PEL_MSK, 0xff); |
/* assumes DAC is readable and writable */ |
vga_w(state->vgabase, VGA_PEL_IW, 0x00); |
for (i = 0; i < 768; i++) |
vga_w(state->vgabase, VGA_PEL_D, saved->vga_cmap[i]); |
} |
static void vga_cleanup(struct vgastate *state) |
{ |
if (state->vidstate != NULL) { |
struct regstate *saved = (struct regstate *) state->vidstate; |
if (saved->vga_font0) |
vfree(saved->vga_font0); |
if (saved->vga_font1) |
vfree(saved->vga_font1); |
if (saved->vga_text) |
vfree(saved->vga_text); |
if (saved->vga_cmap) |
vfree(saved->vga_cmap); |
if (saved->attr) |
vfree(saved->attr); |
kfree(saved); |
state->vidstate = NULL; |
} |
} |
int save_vga(struct vgastate *state) |
{ |
struct regstate *saved; |
saved = kmalloc(sizeof(struct regstate), GFP_KERNEL); |
if (saved == NULL) |
return 1; |
memset (saved, 0, sizeof(struct regstate)); |
(struct regstate *) state->vidstate = saved; |
if (state->flags & VGA_SAVE_CMAP) { |
saved->vga_cmap = vmalloc(768); |
if (!saved->vga_cmap) { |
vga_cleanup(state); |
return 1; |
} |
save_vga_cmap(state); |
} |
if (state->flags & VGA_SAVE_MODE) { |
int total; |
if (state->num_attr < 21) |
state->num_attr = 21; |
if (state->num_crtc < 25) |
state->num_crtc = 25; |
if (state->num_gfx < 9) |
state->num_gfx = 9; |
if (state->num_seq < 5) |
state->num_seq = 5; |
total = state->num_attr + state->num_crtc + |
state->num_gfx + state->num_seq; |
saved->attr = vmalloc(total); |
if (!saved->attr) { |
vga_cleanup(state); |
return 1; |
} |
saved->crtc = saved->attr + state->num_attr; |
saved->gfx = saved->crtc + state->num_crtc; |
saved->seq = saved->gfx + state->num_gfx; |
save_vga_mode(state); |
} |
if (state->flags & VGA_SAVE_FONTS) { |
caddr_t fbbase; |
/* exit if window is less than 32K */ |
if (state->memsize && state->memsize < 4 * 8192) { |
vga_cleanup(state); |
return 1; |
} |
if (!state->memsize) |
state->memsize = 8 * 8192; |
if (!state->membase) |
state->membase = 0xA0000; |
fbbase = ioremap(state->membase, state->memsize); |
if (!fbbase) { |
vga_cleanup(state); |
iounmap(fbbase); |
return 1; |
} |
/* |
* save only first 32K used by vgacon |
*/ |
if (state->flags & VGA_SAVE_FONT0) { |
saved->vga_font0 = vmalloc(4 * 8192); |
if (!saved->vga_font0) { |
vga_cleanup(state); |
return 1; |
} |
} |
/* |
* largely unused, but if required by the caller |
* we'll just save everything. |
*/ |
if (state->flags & VGA_SAVE_FONT1) { |
saved->vga_font1 = vmalloc(state->memsize); |
if (!saved->vga_font1) { |
vga_cleanup(state); |
return 1; |
} |
} |
/* |
* Save 8K at plane0[0], and 8K at plane1[16K] |
*/ |
if (state->flags & VGA_SAVE_TEXT) { |
saved->vga_text = vmalloc(8192 * 2); |
if (!saved->vga_text) { |
vga_cleanup(state); |
return 1; |
} |
} |
save_vga_text(state, fbbase); |
iounmap(fbbase); |
} |
return 0; |
} |
int restore_vga (struct vgastate *state) |
{ |
if (state->vidstate == NULL) |
return 1; |
if (state->flags & VGA_SAVE_MODE) |
restore_vga_mode(state); |
if (state->flags & VGA_SAVE_FONTS) { |
caddr_t fbbase = ioremap(state->membase, state->memsize); |
if (!fbbase) { |
vga_cleanup(state); |
iounmap(fbbase); |
return 1; |
} |
restore_vga_text(state, fbbase); |
iounmap(fbbase); |
} |
if (state->flags & VGA_SAVE_CMAP) |
restore_vga_cmap(state); |
vga_cleanup(state); |
return 0; |
} |
#ifdef MODULE |
int init_module(void) { return 0; }; |
void cleanup_module(void) {}; |
#endif |
EXPORT_SYMBOL(save_vga); |
EXPORT_SYMBOL(restore_vga); |
MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>"); |
MODULE_DESCRIPTION("VGA State Save/Restore"); |
MODULE_LICENSE("GPL"); |
/shark/trunk/drivers/fb/cfbfillrect.c |
---|
0,0 → 1,461 |
/* |
* Generic fillrect for frame buffers with packed pixels of any depth. |
* |
* Copyright (C) 2000 James Simmons (jsimmons@linux-fbdev.org) |
* |
* 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. |
* |
* NOTES: |
* |
* The code for depths like 24 that don't have integer number of pixels per |
* long is broken and needs to be fixed. For now I turned these types of |
* mode off. |
* |
* Also need to add code to deal with cards endians that are different than |
* the native cpu endians. I also need to deal with MSB position in the word. |
* |
*/ |
#include <linuxcomp.h> |
#include <linux/config.h> |
#include <linux/module.h> |
#include <linux/string.h> |
#include <linux/fb.h> |
#include <asm/types.h> |
#if BITS_PER_LONG == 32 |
#define FB_WRITEL fb_writel |
#define FB_READL fb_readl |
#define BYTES_PER_LONG 4 |
#define SHIFT_PER_LONG 5 |
#else |
#define FB_WRITEL fb_writeq |
#define FB_READL fb_readq |
#define BYTES_PER_LONG 8 |
#define SHIFT_PER_LONG 6 |
#endif |
#define EXP1(x) 0xffffffffU*x |
#define EXP2(x) 0x55555555U*x |
#define EXP4(x) 0x11111111U*0x ## x |
typedef u32 pixel_t; |
static const u32 bpp1tab[2] = { |
EXP1(0), EXP1(1) |
}; |
static const u32 bpp2tab[4] = { |
EXP2(0), EXP2(1), EXP2(2), EXP2(3) |
}; |
static const u32 bpp4tab[16] = { |
EXP4(0), EXP4(1), EXP4(2), EXP4(3), EXP4(4), EXP4(5), EXP4(6), EXP4(7), |
EXP4(8), EXP4(9), EXP4(a), EXP4(b), EXP4(c), EXP4(d), EXP4(e), EXP4(f) |
}; |
/* |
* Compose two values, using a bitmask as decision value |
* This is equivalent to (a & mask) | (b & ~mask) |
*/ |
static inline unsigned long comp(unsigned long a, unsigned long b, |
unsigned long mask) |
{ |
return ((a ^ b) & mask) ^ b; |
} |
static inline u32 pixel_to_pat32(const struct fb_info *p, pixel_t pixel) |
{ |
u32 pat = pixel; |
switch (p->var.bits_per_pixel) { |
case 1: |
pat = bpp1tab[pat]; |
break; |
case 2: |
pat = bpp2tab[pat]; |
break; |
case 4: |
pat = bpp4tab[pat]; |
break; |
case 8: |
pat |= pat << 8; |
// Fall through |
case 16: |
pat |= pat << 16; |
// Fall through |
case 32: |
break; |
} |
return pat; |
} |
/* |
* Expand a pixel value to a generic 32/64-bit pattern and rotate it to |
* the correct start position |
*/ |
static inline unsigned long pixel_to_pat(const struct fb_info *p, |
pixel_t pixel, int left) |
{ |
unsigned long pat = pixel; |
u32 bpp = p->var.bits_per_pixel; |
int i; |
/* expand pixel value */ |
for (i = bpp; i < BITS_PER_LONG; i *= 2) |
pat |= pat << i; |
/* rotate pattern to correct start position */ |
pat = pat << left | pat >> (bpp-left); |
return pat; |
} |
/* |
* Unaligned 32-bit pattern fill using 32/64-bit memory accesses |
*/ |
void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n) |
{ |
unsigned long val = pat; |
unsigned long first, last; |
if (!n) |
return; |
#if BITS_PER_LONG == 64 |
val |= val << 32; |
#endif |
first = ~0UL >> dst_idx; |
last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG)); |
if (dst_idx+n <= BITS_PER_LONG) { |
// Single word |
if (last) |
first &= last; |
FB_WRITEL(comp(val, FB_READL(dst), first), dst); |
} else { |
// Multiple destination words |
// Leading bits |
if (first) { |
FB_WRITEL(comp(val, FB_READL(dst), first), dst); |
dst++; |
n -= BITS_PER_LONG-dst_idx; |
} |
// Main chunk |
n /= BITS_PER_LONG; |
while (n >= 8) { |
FB_WRITEL(val, dst++); |
FB_WRITEL(val, dst++); |
FB_WRITEL(val, dst++); |
FB_WRITEL(val, dst++); |
FB_WRITEL(val, dst++); |
FB_WRITEL(val, dst++); |
FB_WRITEL(val, dst++); |
FB_WRITEL(val, dst++); |
n -= 8; |
} |
while (n--) |
FB_WRITEL(val, dst++); |
// Trailing bits |
if (last) |
FB_WRITEL(comp(val, FB_READL(dst), first), dst); |
} |
} |
/* |
* Unaligned generic pattern fill using 32/64-bit memory accesses |
* The pattern must have been expanded to a full 32/64-bit value |
* Left/right are the appropriate shifts to convert to the pattern to be |
* used for the next 32/64-bit word |
*/ |
void bitfill(unsigned long *dst, int dst_idx, unsigned long pat, int left, |
int right, u32 n) |
{ |
unsigned long first, last; |
if (!n) |
return; |
first = ~0UL >> dst_idx; |
last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG)); |
if (dst_idx+n <= BITS_PER_LONG) { |
// Single word |
if (last) |
first &= last; |
FB_WRITEL(comp(pat, FB_READL(dst), first), dst); |
} else { |
// Multiple destination words |
// Leading bits |
if (first) { |
FB_WRITEL(comp(pat, FB_READL(dst), first), dst); |
dst++; |
pat = pat << left | pat >> right; |
n -= BITS_PER_LONG-dst_idx; |
} |
// Main chunk |
n /= BITS_PER_LONG; |
while (n >= 4) { |
FB_WRITEL(pat, dst++); |
pat = pat << left | pat >> right; |
FB_WRITEL(pat, dst++); |
pat = pat << left | pat >> right; |
FB_WRITEL(pat, dst++); |
pat = pat << left | pat >> right; |
FB_WRITEL(pat, dst++); |
pat = pat << left | pat >> right; |
n -= 4; |
} |
while (n--) { |
FB_WRITEL(pat, dst++); |
pat = pat << left | pat >> right; |
} |
// Trailing bits |
if (last) |
FB_WRITEL(comp(pat, FB_READL(dst), first), dst); |
} |
} |
void bitfill32_rev(unsigned long *dst, int dst_idx, u32 pat, u32 n) |
{ |
unsigned long val = pat, dat; |
unsigned long first, last; |
if (!n) |
return; |
#if BITS_PER_LONG == 64 |
val |= val << 32; |
#endif |
first = ~0UL >> dst_idx; |
last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG)); |
if (dst_idx+n <= BITS_PER_LONG) { |
// Single word |
if (last) |
first &= last; |
dat = FB_READL(dst); |
FB_WRITEL(comp(dat ^ val, dat, first), dst); |
} else { |
// Multiple destination words |
// Leading bits |
if (first) { |
dat = FB_READL(dst); |
FB_WRITEL(comp(dat ^ val, dat, first), dst); |
dst++; |
n -= BITS_PER_LONG-dst_idx; |
} |
// Main chunk |
n /= BITS_PER_LONG; |
while (n >= 8) { |
FB_WRITEL(FB_READL(dst) ^ val, dst); |
dst++; |
FB_WRITEL(FB_READL(dst) ^ val, dst); |
dst++; |
FB_WRITEL(FB_READL(dst) ^ val, dst); |
dst++; |
FB_WRITEL(FB_READL(dst) ^ val, dst); |
dst++; |
FB_WRITEL(FB_READL(dst) ^ val, dst); |
dst++; |
FB_WRITEL(FB_READL(dst) ^ val, dst); |
dst++; |
FB_WRITEL(FB_READL(dst) ^ val, dst); |
dst++; |
FB_WRITEL(FB_READL(dst) ^ val, dst); |
dst++; |
n -= 8; |
} |
while (n--) { |
FB_WRITEL(FB_READL(dst) ^ val, dst); |
dst++; |
} |
// Trailing bits |
if (last) { |
dat = FB_READL(dst); |
FB_WRITEL(comp(dat ^ val, dat, first), dst); |
} |
} |
} |
/* |
* Unaligned generic pattern fill using 32/64-bit memory accesses |
* The pattern must have been expanded to a full 32/64-bit value |
* Left/right are the appropriate shifts to convert to the pattern to be |
* used for the next 32/64-bit word |
*/ |
void bitfill_rev(unsigned long *dst, int dst_idx, unsigned long pat, int left, |
int right, u32 n) |
{ |
unsigned long first, last, dat; |
if (!n) |
return; |
first = ~0UL >> dst_idx; |
last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG)); |
if (dst_idx+n <= BITS_PER_LONG) { |
// Single word |
if (last) |
first &= last; |
dat = FB_READL(dst); |
FB_WRITEL(comp(dat ^ pat, dat, first), dst); |
} else { |
// Multiple destination words |
// Leading bits |
if (first) { |
dat = FB_READL(dst); |
FB_WRITEL(comp(dat ^ pat, dat, first), dst); |
dst++; |
pat = pat << left | pat >> right; |
n -= BITS_PER_LONG-dst_idx; |
} |
// Main chunk |
n /= BITS_PER_LONG; |
while (n >= 4) { |
FB_WRITEL(FB_READL(dst) ^ pat, dst); |
dst++; |
pat = pat << left | pat >> right; |
FB_WRITEL(FB_READL(dst) ^ pat, dst); |
dst++; |
pat = pat << left | pat >> right; |
FB_WRITEL(FB_READL(dst) ^ pat, dst); |
dst++; |
pat = pat << left | pat >> right; |
FB_WRITEL(FB_READL(dst) ^ pat, dst); |
dst++; |
pat = pat << left | pat >> right; |
n -= 4; |
} |
while (n--) { |
FB_WRITEL(FB_READL(dst) ^ pat, dst); |
dst++; |
pat = pat << left | pat >> right; |
} |
// Trailing bits |
if (last) { |
dat = FB_READL(dst); |
FB_WRITEL(comp(dat ^ pat, dat, first), dst); |
} |
} |
} |
void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) |
{ |
u32 bpp = p->var.bits_per_pixel; |
unsigned long x2, y2, vxres, vyres; |
unsigned long height, width, fg; |
unsigned long *dst; |
int dst_idx, left; |
/* We want rotation but lack hardware to do it for us. */ |
if (!p->fbops->fb_rotate && p->var.rotate) { |
} |
vxres = p->var.xres_virtual; |
vyres = p->var.yres_virtual; |
if (!rect->width || !rect->height || |
rect->dx > vxres || rect->dy > vyres) |
return; |
/* We could use hardware clipping but on many cards you get around |
* hardware clipping by writing to framebuffer directly. */ |
x2 = rect->dx + rect->width; |
y2 = rect->dy + rect->height; |
x2 = x2 < vxres ? x2 : vxres; |
y2 = y2 < vyres ? y2 : vyres; |
width = x2 - rect->dx; |
height = y2 - rect->dy; |
if (p->fix.visual == FB_VISUAL_TRUECOLOR || |
p->fix.visual == FB_VISUAL_DIRECTCOLOR ) |
fg = ((u32 *) (p->pseudo_palette))[rect->color]; |
else |
fg = rect->color; |
dst = (unsigned long *)((unsigned long)p->screen_base & |
~(BYTES_PER_LONG-1)); |
dst_idx = ((unsigned long)p->screen_base & (BYTES_PER_LONG-1))*8; |
dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp; |
/* FIXME For now we support 1-32 bpp only */ |
left = BITS_PER_LONG % bpp; |
if (p->fbops->fb_sync) |
p->fbops->fb_sync(p); |
if (!left) { |
u32 pat = pixel_to_pat32(p, fg); |
void (*fill_op32)(unsigned long *dst, int dst_idx, u32 pat, |
u32 n) = NULL; |
switch (rect->rop) { |
case ROP_XOR: |
fill_op32 = bitfill32_rev; |
break; |
case ROP_COPY: |
default: |
fill_op32 = bitfill32; |
break; |
} |
while (height--) { |
dst += dst_idx >> SHIFT_PER_LONG; |
dst_idx &= (BITS_PER_LONG-1); |
fill_op32(dst, dst_idx, pat, width*bpp); |
dst_idx += p->fix.line_length*8; |
} |
} else { |
unsigned long pat = pixel_to_pat(p, fg, (left-dst_idx) % bpp); |
int right = bpp-left; |
int r; |
void (*fill_op)(unsigned long *dst, int dst_idx, |
unsigned long pat, int left, int right, |
u32 n) = NULL; |
switch (rect->rop) { |
case ROP_XOR: |
fill_op = bitfill_rev; |
break; |
case ROP_COPY: |
default: |
fill_op = bitfill; |
break; |
} |
while (height--) { |
dst += dst_idx >> SHIFT_PER_LONG; |
dst_idx &= (BITS_PER_LONG-1); |
fill_op(dst, dst_idx, pat, left, right, |
width*bpp); |
r = (p->fix.line_length*8) % bpp; |
pat = pat << (bpp-r) | pat >> r; |
dst_idx += p->fix.line_length*8; |
} |
} |
} |
EXPORT_SYMBOL(cfb_fillrect); |
MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>"); |
MODULE_DESCRIPTION("Generic software accelerated fill rectangle"); |
MODULE_LICENSE("GPL"); |
/shark/trunk/drivers/fb/fbmem.c |
---|
387,7 → 387,7 |
#define NUM_FB_DRIVERS (sizeof(fb_drivers)/sizeof(*fb_drivers)) |
#define FBPIXMAPSIZE 8192 |
extern const char *global_mode_option; |
//extern const char *global_mode_option; |
static initcall_t pref_init_funcs[FB_MAX]; |
static int num_pref_init_funcs __initdata = 0; |
1126,8 → 1126,8 |
#elif defined(__alpha__) |
/* Caching is off in the I/O space quadrant by design. */ |
#elif defined(__i386__) || defined(__x86_64__) |
if (boot_cpu_data.x86 > 3) |
pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; |
//if (boot_cpu_data.x86 > 3) |
// pgprot_val(vma->vm_page_prot) |= _PAGE_PCD; |
#elif defined(__mips__) |
pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK; |
pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED; |
1367,7 → 1367,7 |
* If we get here no fb was specified. |
* We consider the argument to be a global video mode option. |
*/ |
global_mode_option = options; |
//global_mode_option = options; |
return 0; |
} |
/shark/trunk/drivers/fb/fbcmap.c |
---|
0,0 → 1,332 |
/* |
* linux/drivers/video/fbcmap.c -- Colormap handling for frame buffer devices |
* |
* Created 15 Jun 1997 by Geert Uytterhoeven |
* |
* 2001 - Documented with DocBook |
* - Brad Douglas <brad@neruo.com> |
* |
* 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 <linuxcomp.h> |
#include <linux/string.h> |
#include <linux/module.h> |
#include <linux/tty.h> |
#include <linux/fb.h> |
#include <linux/slab.h> |
#include <asm/uaccess.h> |
static u16 red2[] = { |
0x0000, 0xaaaa |
}; |
static u16 green2[] = { |
0x0000, 0xaaaa |
}; |
static u16 blue2[] = { |
0x0000, 0xaaaa |
}; |
static u16 red4[] = { |
0x0000, 0xaaaa, 0x5555, 0xffff |
}; |
static u16 green4[] = { |
0x0000, 0xaaaa, 0x5555, 0xffff |
}; |
static u16 blue4[] = { |
0x0000, 0xaaaa, 0x5555, 0xffff |
}; |
static u16 red8[] = { |
0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa |
}; |
static u16 green8[] = { |
0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0x5555, 0xaaaa |
}; |
static u16 blue8[] = { |
0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa |
}; |
static u16 red16[] = { |
0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa, |
0x5555, 0x5555, 0x5555, 0x5555, 0xffff, 0xffff, 0xffff, 0xffff |
}; |
static u16 green16[] = { |
0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0x5555, 0xaaaa, |
0x5555, 0x5555, 0xffff, 0xffff, 0x5555, 0x5555, 0xffff, 0xffff |
}; |
static u16 blue16[] = { |
0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, |
0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff |
}; |
static struct fb_cmap default_2_colors = { |
0, 2, red2, green2, blue2, NULL |
}; |
static struct fb_cmap default_8_colors = { |
0, 8, red8, green8, blue8, NULL |
}; |
static struct fb_cmap default_4_colors = { |
0, 4, red4, green4, blue4, NULL |
}; |
static struct fb_cmap default_16_colors = { |
0, 16, red16, green16, blue16, NULL |
}; |
/** |
* fb_alloc_cmap - allocate a colormap |
* @cmap: frame buffer colormap structure |
* @len: length of @cmap |
* @transp: boolean, 1 if there is transparency, 0 otherwise |
* |
* Allocates memory for a colormap @cmap. @len is the |
* number of entries in the palette. |
* |
* Returns -1 errno on error, or zero on success. |
* |
*/ |
int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp) |
{ |
int size = len*sizeof(u16); |
if (cmap->len != len) { |
fb_dealloc_cmap(cmap); |
if (!len) |
return 0; |
if (!(cmap->red = kmalloc(size, GFP_ATOMIC))) |
return -1; |
if (!(cmap->green = kmalloc(size, GFP_ATOMIC))) |
return -1; |
if (!(cmap->blue = kmalloc(size, GFP_ATOMIC))) |
return -1; |
if (transp) { |
if (!(cmap->transp = kmalloc(size, GFP_ATOMIC))) |
return -1; |
} else |
cmap->transp = NULL; |
} |
cmap->start = 0; |
cmap->len = len; |
fb_copy_cmap(fb_default_cmap(len), cmap, 0); |
return 0; |
} |
/** |
* fb_dealloc_cmap - deallocate a colormap |
* @cmap: frame buffer colormap structure |
* |
* Deallocates a colormap that was previously allocated with |
* fb_alloc_cmap(). |
* |
*/ |
void fb_dealloc_cmap(struct fb_cmap *cmap) |
{ |
if (cmap->red) |
kfree(cmap->red); |
if (cmap->green) |
kfree(cmap->green); |
if (cmap->blue) |
kfree(cmap->blue); |
if (cmap->transp) |
kfree(cmap->transp); |
cmap->red = cmap->green = cmap->blue = cmap->transp = NULL; |
cmap->len = 0; |
} |
/** |
* fb_copy_cmap - copy a colormap |
* @from: frame buffer colormap structure |
* @to: frame buffer colormap structure |
* @fsfromto: determine copy method |
* |
* Copy contents of colormap from @from to @to. |
* |
* @fsfromto accepts the following integer parameters: |
* 0: memcpy function |
* 1: copy_from_user() function to copy from userspace |
* 2: copy_to_user() function to copy to userspace |
* |
*/ |
int fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto) |
{ |
int tooff = 0, fromoff = 0; |
int size; |
if (to->start > from->start) |
fromoff = to->start-from->start; |
else |
tooff = from->start-to->start; |
size = to->len-tooff; |
if (size > (int) (from->len - fromoff)) |
size = from->len-fromoff; |
if (size <= 0) |
return -EINVAL; |
size *= sizeof(u16); |
switch (fsfromto) { |
case 0: |
memcpy(to->red+tooff, from->red+fromoff, size); |
memcpy(to->green+tooff, from->green+fromoff, size); |
memcpy(to->blue+tooff, from->blue+fromoff, size); |
if (from->transp && to->transp) |
memcpy(to->transp+tooff, from->transp+fromoff, size); |
break; |
case 1: |
if (copy_from_user(to->red+tooff, from->red+fromoff, size)) |
return -EFAULT; |
if (copy_from_user(to->green+tooff, from->green+fromoff, size)) |
return -EFAULT; |
if (copy_from_user(to->blue+tooff, from->blue+fromoff, size)) |
return -EFAULT; |
if (from->transp && to->transp) |
if (copy_from_user(to->transp+tooff, from->transp+fromoff, size)) |
return -EFAULT; |
break; |
case 2: |
if (copy_to_user(to->red+tooff, from->red+fromoff, size)) |
return -EFAULT; |
if (copy_to_user(to->green+tooff, from->green+fromoff, size)) |
return -EFAULT; |
if (copy_to_user(to->blue+tooff, from->blue+fromoff, size)) |
return -EFAULT; |
if (from->transp && to->transp) |
if (copy_to_user(to->transp+tooff, from->transp+fromoff, size)) |
return -EFAULT; |
break; |
} |
return 0; |
} |
/** |
* fb_set_cmap - set the colormap |
* @cmap: frame buffer colormap structure |
* @kspc: boolean, 0 copy local, 1 get_user() function |
* @info: frame buffer info structure |
* |
* Sets the colormap @cmap for a screen of device @info. |
* |
* Returns negative errno on error, or zero on success. |
* |
*/ |
int fb_set_cmap(struct fb_cmap *cmap, int kspc, struct fb_info *info) |
{ |
int i, start; |
u16 *red, *green, *blue, *transp; |
u_int hred, hgreen, hblue, htransp; |
red = cmap->red; |
green = cmap->green; |
blue = cmap->blue; |
transp = cmap->transp; |
start = cmap->start; |
if (start < 0 || !info->fbops->fb_setcolreg) |
return -EINVAL; |
for (i = 0; i < cmap->len; i++) { |
if (kspc) { |
hred = *red; |
hgreen = *green; |
hblue = *blue; |
htransp = transp ? *transp : 0xffff; |
} else { |
hred = *red; |
hgreen = *green; |
hblue = *blue; |
htransp = transp ? *transp : 0xffff; |
//get_user(hred, red); |
//get_user(hgreen, green); |
//get_user(hblue, blue); |
//if (transp) |
//get_user(htransp, transp); |
//else |
//htransp = 0xffff; |
} |
red++; |
green++; |
blue++; |
if (transp) |
transp++; |
if (info->fbops->fb_setcolreg(start++, hred, hgreen, hblue, htransp, info)) |
return 0; |
} |
return 0; |
} |
/** |
* fb_default_cmap - get default colormap |
* @len: size of palette for a depth |
* |
* Gets the default colormap for a specific screen depth. @len |
* is the size of the palette for a particular screen depth. |
* |
* Returns pointer to a frame buffer colormap structure. |
* |
*/ |
struct fb_cmap *fb_default_cmap(int len) |
{ |
if (len <= 2) |
return &default_2_colors; |
if (len <= 4) |
return &default_4_colors; |
if (len <= 8) |
return &default_8_colors; |
return &default_16_colors; |
} |
/** |
* fb_invert_cmaps - invert all defaults colormaps |
* |
* Invert all default colormaps. |
* |
*/ |
void fb_invert_cmaps(void) |
{ |
u_int i; |
for (i = 0; i < 2; i++) { |
red2[i] = ~red2[i]; |
green2[i] = ~green2[i]; |
blue2[i] = ~blue2[i]; |
} |
for (i = 0; i < 4; i++) { |
red4[i] = ~red4[i]; |
green4[i] = ~green4[i]; |
blue4[i] = ~blue4[i]; |
} |
for (i = 0; i < 8; i++) { |
red8[i] = ~red8[i]; |
green8[i] = ~green8[i]; |
blue8[i] = ~blue8[i]; |
} |
for (i = 0; i < 16; i++) { |
red16[i] = ~red16[i]; |
green16[i] = ~green16[i]; |
blue16[i] = ~blue16[i]; |
} |
} |
/* |
* Visible symbols for modules |
*/ |
EXPORT_SYMBOL(fb_alloc_cmap); |
EXPORT_SYMBOL(fb_dealloc_cmap); |
EXPORT_SYMBOL(fb_copy_cmap); |
EXPORT_SYMBOL(fb_set_cmap); |
EXPORT_SYMBOL(fb_default_cmap); |
EXPORT_SYMBOL(fb_invert_cmaps); |
/shark/trunk/drivers/fb/softcursor.c |
---|
0,0 → 1,88 |
/* |
* linux/drivers/video/softcursor.c -- Generic software cursor for frame buffer devices |
* |
* Created 14 Nov 2002 by James Simmons |
* |
* 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 <linuxcomp.h> |
#include <linux/module.h> |
#include <linux/string.h> |
#include <linux/tty.h> |
#include <linux/fb.h> |
#include <linux/slab.h> |
#include <asm/uaccess.h> |
#include <asm/io.h> |
int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) |
{ |
unsigned int scan_align = info->pixmap.scan_align - 1; |
unsigned int buf_align = info->pixmap.buf_align - 1; |
unsigned int i, size, dsize, s_pitch, d_pitch; |
u8 *dst, src[64]; |
if (cursor->set & FB_CUR_SETSIZE) { |
info->cursor.image.height = cursor->image.height; |
info->cursor.image.width = cursor->image.width; |
} |
if (cursor->set & FB_CUR_SETPOS) { |
info->cursor.image.dx = cursor->image.dx; |
info->cursor.image.dy = cursor->image.dy; |
} |
if (cursor->set & FB_CUR_SETHOT) |
info->cursor.hot = cursor->hot; |
if (cursor->set & FB_CUR_SETCMAP) { |
if (cursor->image.depth == 1) { |
info->cursor.image.bg_color = cursor->image.bg_color; |
info->cursor.image.fg_color = cursor->image.fg_color; |
} else { |
if (cursor->image.cmap.len) |
fb_copy_cmap(&cursor->image.cmap, &info->cursor.image.cmap, 0); |
} |
info->cursor.image.depth = cursor->image.depth; |
} |
s_pitch = (info->cursor.image.width + 7) >> 3; |
dsize = s_pitch * info->cursor.image.height; |
d_pitch = (s_pitch + scan_align) & ~scan_align; |
size = d_pitch * info->cursor.image.height + buf_align; |
size &= ~buf_align; |
dst = info->pixmap.addr + fb_get_buffer_offset(info, size); |
if (info->cursor.enable) { |
switch (info->cursor.rop) { |
case ROP_XOR: |
for (i = 0; i < dsize; i++) |
src[i] = cursor->image.data[i] ^ info->cursor.mask[i]; |
break; |
case ROP_COPY: |
default: |
for (i = 0; i < dsize; i++) |
src[i] = cursor->image.data[i] & info->cursor.mask[i]; |
break; |
} |
} else |
memcpy(src, cursor->image.data, dsize); |
move_buf_aligned(info, dst, src, d_pitch, s_pitch, info->cursor.image.height); |
info->cursor.image.data = dst; |
info->fbops->fb_imageblit(info, &info->cursor.image); |
atomic_dec(&info->pixmap.count); |
smp_mb__after_atomic_dec(); |
return 0; |
} |
EXPORT_SYMBOL(soft_cursor); |
MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>"); |
MODULE_DESCRIPTION("Generic software cursor"); |
MODULE_LICENSE("GPL"); |
/shark/trunk/drivers/fb/cfbimgblt.c |
---|
0,0 → 1,340 |
/* |
* Generic BitBLT function for frame buffer with packed pixels of any depth. |
* |
* Copyright (C) June 1999 James Simmons |
* |
* 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. |
* |
* NOTES: |
* |
* This function copys a image from system memory to video memory. The |
* image can be a bitmap where each 0 represents the background color and |
* each 1 represents the foreground color. Great for font handling. It can |
* also be a color image. This is determined by image_depth. The color image |
* must be laid out exactly in the same format as the framebuffer. Yes I know |
* their are cards with hardware that coverts images of various depths to the |
* framebuffer depth. But not every card has this. All images must be rounded |
* up to the nearest byte. For example a bitmap 12 bits wide must be two |
* bytes width. |
* |
* Tony: |
* Incorporate mask tables similar to fbcon-cfb*.c in 2.4 API. This speeds |
* up the code significantly. |
* |
* Code for depths not multiples of BITS_PER_LONG is still kludgy, which is |
* still processed a bit at a time. |
* |
* Also need to add code to deal with cards endians that are different than |
* the native cpu endians. I also need to deal with MSB position in the word. |
*/ |
#include <linuxcomp.h> |
#include <linux/config.h> |
#include <linux/module.h> |
#include <linux/string.h> |
#include <linux/fb.h> |
#include <asm/types.h> |
#define DEBUG |
#ifdef DEBUG |
#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt,__FUNCTION__,## args) |
#else |
#define DPRINTK(fmt, args...) |
#endif |
static u32 cfb_tab8[] = { |
#if defined(__BIG_ENDIAN) |
0x00000000,0x000000ff,0x0000ff00,0x0000ffff, |
0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff, |
0xff000000,0xff0000ff,0xff00ff00,0xff00ffff, |
0xffff0000,0xffff00ff,0xffffff00,0xffffffff |
#elif defined(__LITTLE_ENDIAN) |
0x00000000,0xff000000,0x00ff0000,0xffff0000, |
0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00, |
0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff, |
0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff |
#else |
#error FIXME: No endianness?? |
#endif |
}; |
static u32 cfb_tab16[] = { |
#if defined(__BIG_ENDIAN) |
0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff |
#elif defined(__LITTLE_ENDIAN) |
0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff |
#else |
#error FIXME: No endianness?? |
#endif |
}; |
static u32 cfb_tab32[] = { |
0x00000000, 0xffffffff |
}; |
#define FB_WRITEL fb_writel |
#define FB_READL fb_readl |
#if defined (__BIG_ENDIAN) |
#define LEFT_POS(bpp) (32 - bpp) |
#define SHIFT_HIGH(val, bits) ((val) >> (bits)) |
#define SHIFT_LOW(val, bits) ((val) << (bits)) |
#else |
#define LEFT_POS(bpp) (0) |
#define SHIFT_HIGH(val, bits) ((val) << (bits)) |
#define SHIFT_LOW(val, bits) ((val) >> (bits)) |
#endif |
static inline void color_imageblit(const struct fb_image *image, |
struct fb_info *p, u8 *dst1, |
u32 start_index, |
u32 pitch_index) |
{ |
/* Draw the penguin */ |
u32 *dst, *dst2, color = 0, val, shift; |
int i, n, bpp = p->var.bits_per_pixel; |
u32 null_bits = 32 - bpp; |
u32 *palette = (u32 *) p->pseudo_palette; |
const u8 *src = image->data; |
dst2 = (u32 *) dst1; |
for (i = image->height; i--; ) { |
n = image->width; |
dst = (u32 *) dst1; |
shift = 0; |
val = 0; |
if (start_index) { |
u32 start_mask = ~(SHIFT_HIGH(~(u32)0, start_index)); |
val = FB_READL(dst) & start_mask; |
shift = start_index; |
} |
while (n--) { |
if (p->fix.visual == FB_VISUAL_TRUECOLOR || |
p->fix.visual == FB_VISUAL_DIRECTCOLOR ) |
color = palette[*src]; |
else |
color = *src; |
color <<= LEFT_POS(bpp); |
val |= SHIFT_HIGH(color, shift); |
if (shift >= null_bits) { |
FB_WRITEL(val, dst++); |
val = (shift == null_bits) ? 0 : |
SHIFT_LOW(color, 32 - shift); |
} |
shift += bpp; |
shift &= (32 - 1); |
src++; |
} |
if (shift) { |
u32 end_mask = SHIFT_HIGH(~(u32)0, shift); |
FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); |
} |
dst1 += p->fix.line_length; |
if (pitch_index) { |
dst2 += p->fix.line_length; |
dst1 = (char *) dst2; |
(unsigned long) dst1 &= ~(sizeof(u32) - 1); |
start_index += pitch_index; |
start_index &= 32 - 1; |
} |
} |
} |
static inline void slow_imageblit(const struct fb_image *image, struct fb_info *p, |
u8 *dst1, u32 fgcolor, |
u32 bgcolor, |
u32 start_index, |
u32 pitch_index) |
{ |
u32 shift, color = 0, bpp = p->var.bits_per_pixel; |
u32 *dst, *dst2, val, pitch = p->fix.line_length; |
u32 null_bits = 32 - bpp; |
u32 spitch = (image->width+7)/8; |
const u8 *src = image->data, *s; |
u32 i, j, l; |
dst2 = (u32 *) dst1; |
for (i = image->height; i--; ) { |
shift = val = 0; |
l = 8; |
j = image->width; |
dst = (u32 *) dst1; |
s = src; |
/* write leading bits */ |
if (start_index) { |
u32 start_mask = ~(SHIFT_HIGH(~(u32)0, start_index)); |
val = FB_READL(dst) & start_mask; |
shift = start_index; |
} |
while (j--) { |
l--; |
color = (*s & (1 << l)) ? fgcolor : bgcolor; |
color <<= LEFT_POS(bpp); |
val |= SHIFT_HIGH(color, shift); |
/* Did the bitshift spill bits to the next long? */ |
if (shift >= null_bits) { |
FB_WRITEL(val, dst++); |
val = (shift == null_bits) ? 0 : |
SHIFT_LOW(color,32 - shift); |
} |
shift += bpp; |
shift &= (32 - 1); |
if (!l) { l = 8; s++; }; |
} |
/* write trailing bits */ |
if (shift) { |
u32 end_mask = SHIFT_HIGH(~(u32)0, shift); |
FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); |
} |
dst1 += pitch; |
src += spitch; |
if (pitch_index) { |
dst2 += pitch; |
dst1 = (char *) dst2; |
(unsigned long) dst1 &= ~(sizeof(u32) - 1); |
start_index += pitch_index; |
start_index &= 32 - 1; |
} |
} |
} |
/* |
* fast_imageblit - optimized monochrome color expansion |
* |
* Only if: bits_per_pixel == 8, 16, or 32 |
* image->width is divisible by pixel/dword (ppw); |
* fix->line_legth is divisible by 4; |
* beginning and end of a scanline is dword aligned |
*/ |
static inline void fast_imageblit(const struct fb_image *image, struct fb_info *p, |
u8 *dst1, u32 fgcolor, |
u32 bgcolor) |
{ |
u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel; |
u32 ppw = 32/bpp, spitch = (image->width + 7)/8; |
u32 bit_mask, end_mask, eorx, shift; |
const char *s = image->data, *src; |
u32 *dst; |
u32 *tab = NULL; |
int i, j, k; |
switch (bpp) { |
case 8: |
tab = cfb_tab8; |
break; |
case 16: |
tab = cfb_tab16; |
break; |
case 32: |
tab = cfb_tab32; |
break; |
} |
for (i = ppw-1; i--; ) { |
fgx <<= bpp; |
bgx <<= bpp; |
fgx |= fgcolor; |
bgx |= bgcolor; |
} |
bit_mask = (1 << ppw) - 1; |
eorx = fgx ^ bgx; |
k = image->width/ppw; |
for (i = image->height; i--; ) { |
dst = (u32 *) dst1, shift = 8; src = s; |
for (j = k; j--; ) { |
shift -= ppw; |
end_mask = tab[(*src >> shift) & bit_mask]; |
FB_WRITEL((end_mask & eorx)^bgx, dst++); |
if (!shift) { shift = 8; src++; } |
} |
dst1 += p->fix.line_length; |
s += spitch; |
} |
} |
void cfb_imageblit(struct fb_info *p, const struct fb_image *image) |
{ |
u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0; |
u32 bpl = sizeof(u32), bpp = p->var.bits_per_pixel; |
u32 width = image->width, height = image->height; |
u32 dx = image->dx, dy = image->dy; |
int x2, y2, vxres, vyres; |
u8 *dst1; |
vxres = p->var.xres_virtual; |
vyres = p->var.yres_virtual; |
/* |
* We could use hardware clipping but on many cards you get around |
* hardware clipping by writing to framebuffer directly like we are |
* doing here. |
*/ |
if (image->dx > vxres || image->dy > vyres) |
return; |
x2 = image->dx + image->width; |
y2 = image->dy + image->height; |
dx = image->dx > 0 ? image->dx : 0; |
dy = image->dy > 0 ? image->dy : 0; |
x2 = x2 < vxres ? x2 : vxres; |
y2 = y2 < vyres ? y2 : vyres; |
width = x2 - dx; |
height = y2 - dy; |
bitstart = (dy * p->fix.line_length * 8) + (dx * bpp); |
start_index = bitstart & (32 - 1); |
pitch_index = (p->fix.line_length & (bpl - 1)) * 8; |
bitstart /= 8; |
bitstart &= ~(bpl - 1); |
dst1 = p->screen_base + bitstart; |
if (p->fbops->fb_sync) |
p->fbops->fb_sync(p); |
if (image->depth == 1) { |
if (p->fix.visual == FB_VISUAL_TRUECOLOR || |
p->fix.visual == FB_VISUAL_DIRECTCOLOR) { |
fgcolor = ((u32*)(p->pseudo_palette))[image->fg_color]; |
bgcolor = ((u32*)(p->pseudo_palette))[image->bg_color]; |
} else { |
fgcolor = image->fg_color; |
bgcolor = image->bg_color; |
} |
if (32 % bpp == 0 && !start_index && !pitch_index && |
((width & (32/bpp-1)) == 0) && |
bpp >= 8 && bpp <= 32) |
fast_imageblit(image, p, dst1, fgcolor, bgcolor); |
else |
slow_imageblit(image, p, dst1, fgcolor, bgcolor, |
start_index, pitch_index); |
} else if (image->depth <= bpp) |
color_imageblit(image, p, dst1, start_index, pitch_index); |
} |
EXPORT_SYMBOL(cfb_imageblit); |
MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>"); |
MODULE_DESCRIPTION("Generic software accelerated imaging drawing"); |
MODULE_LICENSE("GPL"); |
/shark/trunk/drivers/fb/makefile |
---|
10,11 → 10,12 |
OBJS_PATH = $(BASE)/drivers/fb |
OBJS = fbmem.o vesafb.o |
OBJS = fbmem.o fbcmap.o cfbfillrect.o softcursor.o cfbcopyarea.o cfbimgblt.o\ |
vga16fb.o vgastate.o vesafb.o |
OTHERINCL += -I$(BASE)/drivers/linuxc26/include |
C_OPT += -D__KERNEL__ -D__i386__ |
C_OPT += -D__KERNEL__ -D__i386__ -DCONFIG_FB_VGA16 |
include $(BASE)/config/lib.mk |
/shark/trunk/drivers/fb/vga16fb.c |
---|
0,0 → 1,1415 |
/* |
* linux/drivers/video/vga16.c -- VGA 16-color framebuffer driver |
* |
* Copyright 1999 Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz> |
* Based on VGA info at http://www.goodnet.com/~tinara/FreeVGA/home.htm |
* Based on VESA framebuffer (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de> |
* |
* 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 <linuxcomp.h> |
#include <linux/module.h> |
#include <linux/kernel.h> |
#include <linux/errno.h> |
#include <linux/string.h> |
#include <linux/mm.h> |
#include <linux/tty.h> |
#include <linux/slab.h> |
#include <linux/delay.h> |
#include <linux/fb.h> |
#include <linux/ioport.h> |
#include <linux/init.h> |
#include <asm/io.h> |
#include <video/vga.h> |
#define GRAPHICS_ADDR_REG VGA_GFX_I /* Graphics address register. */ |
#define GRAPHICS_DATA_REG VGA_GFX_D /* Graphics data register. */ |
#define SET_RESET_INDEX VGA_GFX_SR_VALUE /* Set/Reset Register index. */ |
#define ENABLE_SET_RESET_INDEX VGA_GFX_SR_ENABLE /* Enable Set/Reset Register index. */ |
#define DATA_ROTATE_INDEX VGA_GFX_DATA_ROTATE /* Data Rotate Register index. */ |
#define GRAPHICS_MODE_INDEX VGA_GFX_MODE /* Graphics Mode Register index. */ |
#define BIT_MASK_INDEX VGA_GFX_BIT_MASK /* Bit Mask Register index. */ |
#define dac_reg (VGA_PEL_IW) |
#define dac_val (VGA_PEL_D) |
#define VGA_FB_PHYS 0xA0000 |
#define VGA_FB_PHYS_LEN 65536 |
#define MODE_SKIP4 1 |
#define MODE_8BPP 2 |
#define MODE_CFB 4 |
#define MODE_TEXT 8 |
/* --------------------------------------------------------------------- */ |
/* |
* card parameters |
*/ |
static struct fb_info vga16fb; |
static struct vga16fb_par { |
/* structure holding original VGA register settings when the |
screen is blanked */ |
struct { |
unsigned char SeqCtrlIndex; /* Sequencer Index reg. */ |
unsigned char CrtCtrlIndex; /* CRT-Contr. Index reg. */ |
unsigned char CrtMiscIO; /* Miscellaneous register */ |
unsigned char HorizontalTotal; /* CRT-Controller:00h */ |
unsigned char HorizDisplayEnd; /* CRT-Controller:01h */ |
unsigned char StartHorizRetrace; /* CRT-Controller:04h */ |
unsigned char EndHorizRetrace; /* CRT-Controller:05h */ |
unsigned char Overflow; /* CRT-Controller:07h */ |
unsigned char StartVertRetrace; /* CRT-Controller:10h */ |
unsigned char EndVertRetrace; /* CRT-Controller:11h */ |
unsigned char ModeControl; /* CRT-Controller:17h */ |
unsigned char ClockingMode; /* Seq-Controller:01h */ |
} vga_state; |
struct vgastate state; |
atomic_t ref_count; |
int palette_blanked, vesa_blanked, mode, isVGA; |
u8 misc, pel_msk, vss, clkdiv; |
u8 crtc[VGA_CRT_C]; |
} vga16_par; |
/* --------------------------------------------------------------------- */ |
static struct fb_var_screeninfo vga16fb_defined = { |
.xres = 640, |
.yres = 480, |
.xres_virtual = 640, |
.yres_virtual = 480, |
.bits_per_pixel = 4, |
.activate = FB_ACTIVATE_TEST, |
.height = -1, |
.width = -1, |
.pixclock = 39721, |
.left_margin = 48, |
.right_margin = 16, |
.upper_margin = 39, |
.lower_margin = 8, |
.hsync_len = 96, |
.vsync_len = 2, |
.vmode = FB_VMODE_NONINTERLACED, |
}; |
/* name should not depend on EGA/VGA */ |
static struct fb_fix_screeninfo vga16fb_fix __initdata = { |
.id = "VGA16 VGA", |
.smem_start = VGA_FB_PHYS, |
.smem_len = VGA_FB_PHYS_LEN, |
.type = FB_TYPE_VGA_PLANES, |
.type_aux = FB_AUX_VGA_PLANES_VGA4, |
.visual = FB_VISUAL_PSEUDOCOLOR, |
.xpanstep = 8, |
.ypanstep = 1, |
.line_length = 640/8, |
.accel = FB_ACCEL_NONE |
}; |
/* The VGA's weird architecture often requires that we read a byte and |
write a byte to the same location. It doesn't matter *what* byte |
we write, however. This is because all the action goes on behind |
the scenes in the VGA's 32-bit latch register, and reading and writing |
video memory just invokes latch behavior. |
To avoid race conditions (is this necessary?), reading and writing |
the memory byte should be done with a single instruction. One |
suitable instruction is the x86 bitwise OR. The following |
read-modify-write routine should optimize to one such bitwise |
OR. */ |
static inline void rmw(volatile char *p) |
{ |
readb(p); |
writeb(1, p); |
} |
/* Set the Graphics Mode Register, and return its previous value. |
Bits 0-1 are write mode, bit 3 is read mode. */ |
static inline int setmode(int mode) |
{ |
int oldmode; |
vga_io_w(GRAPHICS_ADDR_REG, GRAPHICS_MODE_INDEX); |
oldmode = vga_io_r(GRAPHICS_DATA_REG); |
vga_io_w(GRAPHICS_DATA_REG, mode); |
return oldmode; |
} |
/* Select the Bit Mask Register and return its value. */ |
static inline int selectmask(void) |
{ |
return vga_io_rgfx(BIT_MASK_INDEX); |
} |
/* Set the value of the Bit Mask Register. It must already have been |
selected with selectmask(). */ |
static inline void setmask(int mask) |
{ |
vga_io_w(GRAPHICS_DATA_REG, mask); |
} |
/* Set the Data Rotate Register and return its old value. |
Bits 0-2 are rotate count, bits 3-4 are logical operation |
(0=NOP, 1=AND, 2=OR, 3=XOR). */ |
static inline int setop(int op) |
{ |
int oldop; |
vga_io_w(GRAPHICS_ADDR_REG, DATA_ROTATE_INDEX); |
oldop = vga_io_r(GRAPHICS_DATA_REG); |
vga_io_w(GRAPHICS_DATA_REG, op); |
return oldop; |
} |
/* Set the Enable Set/Reset Register and return its old value. |
The code here always uses value 0xf for thsi register. */ |
static inline int setsr(int sr) |
{ |
int oldsr; |
vga_io_w(GRAPHICS_ADDR_REG, ENABLE_SET_RESET_INDEX); |
oldsr = vga_io_r(GRAPHICS_DATA_REG); |
vga_io_w(GRAPHICS_DATA_REG, sr); |
return oldsr; |
} |
/* Set the Set/Reset Register and return its old value. */ |
static inline int setcolor(int color) |
{ |
int oldcolor; |
vga_io_w(GRAPHICS_ADDR_REG, SET_RESET_INDEX); |
oldcolor = vga_io_r(GRAPHICS_DATA_REG); |
vga_io_w(GRAPHICS_DATA_REG, color); |
return oldcolor; |
} |
/* Return the value in the Graphics Address Register. */ |
static inline int getindex(void) |
{ |
return vga_io_r(GRAPHICS_ADDR_REG); |
} |
/* Set the value in the Graphics Address Register. */ |
static inline void setindex(int index) |
{ |
vga_io_w(GRAPHICS_ADDR_REG, index); |
} |
static void vga16fb_pan_var(struct fb_info *info, |
struct fb_var_screeninfo *var) |
{ |
struct vga16fb_par *par = (struct vga16fb_par *) info->par; |
u32 xoffset, pos; |
xoffset = var->xoffset; |
if (info->var.bits_per_pixel == 8) { |
pos = (info->var.xres_virtual * var->yoffset + xoffset) >> 2; |
} else if (par->mode & MODE_TEXT) { |
int fh = 16; // FIXME !!! font height. Fugde for now. |
pos = (info->var.xres_virtual * (var->yoffset / fh) + xoffset) >> 3; |
} else { |
if (info->var.nonstd) |
xoffset--; |
pos = (info->var.xres_virtual * var->yoffset + xoffset) >> 3; |
} |
vga_io_wcrt(VGA_CRTC_START_HI, pos >> 8); |
vga_io_wcrt(VGA_CRTC_START_LO, pos & 0xFF); |
/* if we support CFB4, then we must! support xoffset with pixel |
* granularity if someone supports xoffset in bit resolution */ |
vga_io_r(VGA_IS1_RC); /* reset flip-flop */ |
vga_io_w(VGA_ATT_IW, VGA_ATC_PEL); |
if (var->bits_per_pixel == 8) |
vga_io_w(VGA_ATT_IW, (xoffset & 3) << 1); |
else |
vga_io_w(VGA_ATT_IW, xoffset & 7); |
vga_io_r(VGA_IS1_RC); |
vga_io_w(VGA_ATT_IW, 0x20); |
} |
static void vga16fb_update_fix(struct fb_info *info) |
{ |
if (info->var.bits_per_pixel == 4) { |
if (info->var.nonstd) { |
info->fix.type = FB_TYPE_PACKED_PIXELS; |
info->fix.line_length = info->var.xres_virtual / 2; |
} else { |
info->fix.type = FB_TYPE_VGA_PLANES; |
info->fix.type_aux = FB_AUX_VGA_PLANES_VGA4; |
info->fix.line_length = info->var.xres_virtual / 8; |
} |
} else if (info->var.bits_per_pixel == 0) { |
info->fix.type = FB_TYPE_TEXT; |
info->fix.type_aux = FB_AUX_TEXT_CGA; |
info->fix.line_length = info->var.xres_virtual / 4; |
} else { /* 8bpp */ |
if (info->var.nonstd) { |
info->fix.type = FB_TYPE_VGA_PLANES; |
info->fix.type_aux = FB_AUX_VGA_PLANES_CFB8; |
info->fix.line_length = info->var.xres_virtual / 4; |
} else { |
info->fix.type = FB_TYPE_PACKED_PIXELS; |
info->fix.line_length = info->var.xres_virtual; |
} |
} |
} |
static void vga16fb_clock_chip(struct vga16fb_par *par, |
unsigned int pixclock, |
const struct fb_info *info, |
int mul, int div) |
{ |
static struct { |
u32 pixclock; |
u8 misc; |
u8 seq_clock_mode; |
} *ptr, *best, vgaclocks[] = { |
{ 79442 /* 12.587 */, 0x00, 0x08}, |
{ 70616 /* 14.161 */, 0x04, 0x08}, |
{ 39721 /* 25.175 */, 0x00, 0x00}, |
{ 35308 /* 28.322 */, 0x04, 0x00}, |
{ 0 /* bad */, 0x00, 0x00}}; |
int err; |
pixclock = (pixclock * mul) / div; |
best = vgaclocks; |
err = pixclock - best->pixclock; |
if (err < 0) err = -err; |
for (ptr = vgaclocks + 1; ptr->pixclock; ptr++) { |
int tmp; |
tmp = pixclock - ptr->pixclock; |
if (tmp < 0) tmp = -tmp; |
if (tmp < err) { |
err = tmp; |
best = ptr; |
} |
} |
par->misc |= best->misc; |
par->clkdiv = best->seq_clock_mode; |
pixclock = (best->pixclock * div) / mul; |
} |
#define FAIL(X) return -EINVAL |
static int vga16fb_open(struct fb_info *info, int user) |
{ |
struct vga16fb_par *par = (struct vga16fb_par *) info->par; |
int cnt = atomic_read(&par->ref_count); |
if (!cnt) { |
memset(&par->state, 0, sizeof(struct vgastate)); |
par->state.flags = VGA_SAVE_FONTS | VGA_SAVE_MODE | |
VGA_SAVE_CMAP; |
save_vga(&par->state); |
} |
atomic_inc(&par->ref_count); |
return 0; |
} |
static int vga16fb_release(struct fb_info *info, int user) |
{ |
struct vga16fb_par *par = (struct vga16fb_par *) info->par; |
int cnt = atomic_read(&par->ref_count); |
if (!cnt) |
return -EINVAL; |
if (cnt == 1) |
restore_vga(&par->state); |
atomic_dec(&par->ref_count); |
return 0; |
} |
static int vga16fb_check_var(struct fb_var_screeninfo *var, |
struct fb_info *info) |
{ |
struct vga16fb_par *par = (struct vga16fb_par *) info->par; |
u32 xres, right, hslen, left, xtotal; |
u32 yres, lower, vslen, upper, ytotal; |
u32 vxres, xoffset, vyres, yoffset; |
u32 pos; |
u8 r7, rMode; |
int shift; |
int mode; |
u32 maxmem; |
par->pel_msk = 0xFF; |
if (var->bits_per_pixel == 4) { |
if (var->nonstd) { |
if (!par->isVGA) |
return -EINVAL; |
shift = 3; |
mode = MODE_SKIP4 | MODE_CFB; |
maxmem = 16384; |
par->pel_msk = 0x0F; |
} else { |
shift = 3; |
mode = 0; |
maxmem = 65536; |
} |
} else if (var->bits_per_pixel == 8) { |
if (!par->isVGA) |
return -EINVAL; /* no support on EGA */ |
shift = 2; |
if (var->nonstd) { |
mode = MODE_8BPP | MODE_CFB; |
maxmem = 65536; |
} else { |
mode = MODE_SKIP4 | MODE_8BPP | MODE_CFB; |
maxmem = 16384; |
} |
} else |
return -EINVAL; |
xres = (var->xres + 7) & ~7; |
vxres = (var->xres_virtual + 0xF) & ~0xF; |
xoffset = (var->xoffset + 7) & ~7; |
left = (var->left_margin + 7) & ~7; |
right = (var->right_margin + 7) & ~7; |
hslen = (var->hsync_len + 7) & ~7; |
if (vxres < xres) |
vxres = xres; |
if (xres + xoffset > vxres) |
xoffset = vxres - xres; |
var->xres = xres; |
var->right_margin = right; |
var->hsync_len = hslen; |
var->left_margin = left; |
var->xres_virtual = vxres; |
var->xoffset = xoffset; |
xres >>= shift; |
right >>= shift; |
hslen >>= shift; |
left >>= shift; |
vxres >>= shift; |
xtotal = xres + right + hslen + left; |
if (xtotal >= 256) |
FAIL("xtotal too big"); |
if (hslen > 32) |
FAIL("hslen too big"); |
if (right + hslen + left > 64) |
FAIL("hblank too big"); |
par->crtc[VGA_CRTC_H_TOTAL] = xtotal - 5; |
par->crtc[VGA_CRTC_H_BLANK_START] = xres - 1; |
par->crtc[VGA_CRTC_H_DISP] = xres - 1; |
pos = xres + right; |
par->crtc[VGA_CRTC_H_SYNC_START] = pos; |
pos += hslen; |
par->crtc[VGA_CRTC_H_SYNC_END] = pos & 0x1F; |
pos += left - 2; /* blank_end + 2 <= total + 5 */ |
par->crtc[VGA_CRTC_H_BLANK_END] = (pos & 0x1F) | 0x80; |
if (pos & 0x20) |
par->crtc[VGA_CRTC_H_SYNC_END] |= 0x80; |
yres = var->yres; |
lower = var->lower_margin; |
vslen = var->vsync_len; |
upper = var->upper_margin; |
vyres = var->yres_virtual; |
yoffset = var->yoffset; |
if (yres > vyres) |
vyres = yres; |
if (vxres * vyres > maxmem) { |
vyres = maxmem / vxres; |
if (vyres < yres) |
return -ENOMEM; |
} |
if (yoffset + yres > vyres) |
yoffset = vyres - yres; |
var->yres = yres; |
var->lower_margin = lower; |
var->vsync_len = vslen; |
var->upper_margin = upper; |
var->yres_virtual = vyres; |
var->yoffset = yoffset; |
if (var->vmode & FB_VMODE_DOUBLE) { |
yres <<= 1; |
lower <<= 1; |
vslen <<= 1; |
upper <<= 1; |
} |
ytotal = yres + lower + vslen + upper; |
if (ytotal > 1024) { |
ytotal >>= 1; |
yres >>= 1; |
lower >>= 1; |
vslen >>= 1; |
upper >>= 1; |
rMode = 0x04; |
} else |
rMode = 0x00; |
if (ytotal > 1024) |
FAIL("ytotal too big"); |
if (vslen > 16) |
FAIL("vslen too big"); |
par->crtc[VGA_CRTC_V_TOTAL] = ytotal - 2; |
r7 = 0x10; /* disable linecompare */ |
if (ytotal & 0x100) r7 |= 0x01; |
if (ytotal & 0x200) r7 |= 0x20; |
par->crtc[VGA_CRTC_PRESET_ROW] = 0; |
par->crtc[VGA_CRTC_MAX_SCAN] = 0x40; /* 1 scanline, no linecmp */ |
if (var->vmode & FB_VMODE_DOUBLE) |
par->crtc[VGA_CRTC_MAX_SCAN] |= 0x80; |
par->crtc[VGA_CRTC_CURSOR_START] = 0x20; |
par->crtc[VGA_CRTC_CURSOR_END] = 0x00; |
if ((mode & (MODE_CFB | MODE_8BPP)) == MODE_CFB) |
xoffset--; |
pos = yoffset * vxres + (xoffset >> shift); |
par->crtc[VGA_CRTC_START_HI] = pos >> 8; |
par->crtc[VGA_CRTC_START_LO] = pos & 0xFF; |
par->crtc[VGA_CRTC_CURSOR_HI] = 0x00; |
par->crtc[VGA_CRTC_CURSOR_LO] = 0x00; |
pos = yres - 1; |
par->crtc[VGA_CRTC_V_DISP_END] = pos & 0xFF; |
par->crtc[VGA_CRTC_V_BLANK_START] = pos & 0xFF; |
if (pos & 0x100) |
r7 |= 0x0A; /* 0x02 -> DISP_END, 0x08 -> BLANK_START */ |
if (pos & 0x200) { |
r7 |= 0x40; /* 0x40 -> DISP_END */ |
par->crtc[VGA_CRTC_MAX_SCAN] |= 0x20; /* BLANK_START */ |
} |
pos += lower; |
par->crtc[VGA_CRTC_V_SYNC_START] = pos & 0xFF; |
if (pos & 0x100) |
r7 |= 0x04; |
if (pos & 0x200) |
r7 |= 0x80; |
pos += vslen; |
par->crtc[VGA_CRTC_V_SYNC_END] = (pos & 0x0F) & ~0x10; /* disabled IRQ */ |
pos += upper - 1; /* blank_end + 1 <= ytotal + 2 */ |
par->crtc[VGA_CRTC_V_BLANK_END] = pos & 0xFF; /* 0x7F for original VGA, |
but some SVGA chips requires all 8 bits to set */ |
if (vxres >= 512) |
FAIL("vxres too long"); |
par->crtc[VGA_CRTC_OFFSET] = vxres >> 1; |
if (mode & MODE_SKIP4) |
par->crtc[VGA_CRTC_UNDERLINE] = 0x5F; /* 256, cfb8 */ |
else |
par->crtc[VGA_CRTC_UNDERLINE] = 0x1F; /* 16, vgap */ |
par->crtc[VGA_CRTC_MODE] = rMode | ((mode & MODE_TEXT) ? 0xA3 : 0xE3); |
par->crtc[VGA_CRTC_LINE_COMPARE] = 0xFF; |
par->crtc[VGA_CRTC_OVERFLOW] = r7; |
par->vss = 0x00; /* 3DA */ |
par->misc = 0xE3; /* enable CPU, ports 0x3Dx, positive sync */ |
if (var->sync & FB_SYNC_HOR_HIGH_ACT) |
par->misc &= ~0x40; |
if (var->sync & FB_SYNC_VERT_HIGH_ACT) |
par->misc &= ~0x80; |
par->mode = mode; |
if (mode & MODE_8BPP) |
/* pixel clock == vga clock / 2 */ |
vga16fb_clock_chip(par, var->pixclock, info, 1, 2); |
else |
/* pixel clock == vga clock */ |
vga16fb_clock_chip(par, var->pixclock, info, 1, 1); |
var->red.offset = var->green.offset = var->blue.offset = |
var->transp.offset = 0; |
var->red.length = var->green.length = var->blue.length = |
(par->isVGA) ? 6 : 2; |
var->transp.length = 0; |
var->activate = FB_ACTIVATE_NOW; |
var->height = -1; |
var->width = -1; |
var->accel_flags = 0; |
return 0; |
} |
#undef FAIL |
static int vga16fb_set_par(struct fb_info *info) |
{ |
struct vga16fb_par *par = (struct vga16fb_par *) info->par; |
u8 gdc[VGA_GFX_C]; |
u8 seq[VGA_SEQ_C]; |
u8 atc[VGA_ATT_C]; |
int fh, i; |
seq[VGA_SEQ_CLOCK_MODE] = 0x01 | par->clkdiv; |
if (par->mode & MODE_TEXT) |
seq[VGA_SEQ_PLANE_WRITE] = 0x03; |
else |
seq[VGA_SEQ_PLANE_WRITE] = 0x0F; |
seq[VGA_SEQ_CHARACTER_MAP] = 0x00; |
if (par->mode & MODE_TEXT) |
seq[VGA_SEQ_MEMORY_MODE] = 0x03; |
else if (par->mode & MODE_SKIP4) |
seq[VGA_SEQ_MEMORY_MODE] = 0x0E; |
else |
seq[VGA_SEQ_MEMORY_MODE] = 0x06; |
gdc[VGA_GFX_SR_VALUE] = 0x00; |
gdc[VGA_GFX_SR_ENABLE] = 0x00; |
gdc[VGA_GFX_COMPARE_VALUE] = 0x00; |
gdc[VGA_GFX_DATA_ROTATE] = 0x00; |
gdc[VGA_GFX_PLANE_READ] = 0; |
if (par->mode & MODE_TEXT) { |
gdc[VGA_GFX_MODE] = 0x10; |
gdc[VGA_GFX_MISC] = 0x06; |
} else { |
if (par->mode & MODE_CFB) |
gdc[VGA_GFX_MODE] = 0x40; |
else |
gdc[VGA_GFX_MODE] = 0x00; |
gdc[VGA_GFX_MISC] = 0x05; |
} |
gdc[VGA_GFX_COMPARE_MASK] = 0x0F; |
gdc[VGA_GFX_BIT_MASK] = 0xFF; |
for (i = 0x00; i < 0x10; i++) |
atc[i] = i; |
if (par->mode & MODE_TEXT) |
atc[VGA_ATC_MODE] = 0x04; |
else if (par->mode & MODE_8BPP) |
atc[VGA_ATC_MODE] = 0x41; |
else |
atc[VGA_ATC_MODE] = 0x81; |
atc[VGA_ATC_OVERSCAN] = 0x00; /* 0 for EGA, 0xFF for VGA */ |
atc[VGA_ATC_PLANE_ENABLE] = 0x0F; |
if (par->mode & MODE_8BPP) |
atc[VGA_ATC_PEL] = (info->var.xoffset & 3) << 1; |
else |
atc[VGA_ATC_PEL] = info->var.xoffset & 7; |
atc[VGA_ATC_COLOR_PAGE] = 0x00; |
if (par->mode & MODE_TEXT) { |
fh = 16; // FIXME !!! Fudge font height. |
par->crtc[VGA_CRTC_MAX_SCAN] = (par->crtc[VGA_CRTC_MAX_SCAN] |
& ~0x1F) | (fh - 1); |
} |
vga_io_w(VGA_MIS_W, vga_io_r(VGA_MIS_R) | 0x01); |
/* Enable graphics register modification */ |
if (!par->isVGA) { |
vga_io_w(EGA_GFX_E0, 0x00); |
vga_io_w(EGA_GFX_E1, 0x01); |
} |
/* update misc output register */ |
vga_io_w(VGA_MIS_W, par->misc); |
/* synchronous reset on */ |
vga_io_wseq(0x00, 0x01); |
if (par->isVGA) |
vga_io_w(VGA_PEL_MSK, par->pel_msk); |
/* write sequencer registers */ |
vga_io_wseq(VGA_SEQ_CLOCK_MODE, seq[VGA_SEQ_CLOCK_MODE] | 0x20); |
for (i = 2; i < VGA_SEQ_C; i++) { |
vga_io_wseq(i, seq[i]); |
} |
/* synchronous reset off */ |
vga_io_wseq(0x00, 0x03); |
/* deprotect CRT registers 0-7 */ |
vga_io_wcrt(VGA_CRTC_V_SYNC_END, par->crtc[VGA_CRTC_V_SYNC_END]); |
/* write CRT registers */ |
for (i = 0; i < VGA_CRTC_REGS; i++) { |
vga_io_wcrt(i, par->crtc[i]); |
} |
/* write graphics controller registers */ |
for (i = 0; i < VGA_GFX_C; i++) { |
vga_io_wgfx(i, gdc[i]); |
} |
/* write attribute controller registers */ |
for (i = 0; i < VGA_ATT_C; i++) { |
vga_io_r(VGA_IS1_RC); /* reset flip-flop */ |
vga_io_wattr(i, atc[i]); |
} |
/* Wait for screen to stabilize. */ |
mdelay(50); |
vga_io_wseq(VGA_SEQ_CLOCK_MODE, seq[VGA_SEQ_CLOCK_MODE]); |
vga_io_r(VGA_IS1_RC); |
vga_io_w(VGA_ATT_IW, 0x20); |
vga16fb_update_fix(info); |
return 0; |
} |
static void ega16_setpalette(int regno, unsigned red, unsigned green, unsigned blue) |
{ |
static unsigned char map[] = { 000, 001, 010, 011 }; |
int val; |
if (regno >= 16) |
return; |
val = map[red>>14] | ((map[green>>14]) << 1) | ((map[blue>>14]) << 2); |
vga_io_r(VGA_IS1_RC); /* ! 0x3BA */ |
vga_io_wattr(regno, val); |
vga_io_r(VGA_IS1_RC); /* some clones need it */ |
vga_io_w(VGA_ATT_IW, 0x20); /* unblank screen */ |
} |
static void vga16_setpalette(int regno, unsigned red, unsigned green, unsigned blue) |
{ |
outb(regno, dac_reg); |
outb(red >> 10, dac_val); |
outb(green >> 10, dac_val); |
outb(blue >> 10, dac_val); |
} |
static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green, |
unsigned blue, unsigned transp, |
struct fb_info *info) |
{ |
struct vga16fb_par *par = (struct vga16fb_par *) info->par; |
int gray; |
/* |
* Set a single color register. The values supplied are |
* already rounded down to the hardware's capabilities |
* (according to the entries in the `var' structure). Return |
* != 0 for invalid regno. |
*/ |
if (regno >= 256) |
return 1; |
gray = info->var.grayscale; |
if (gray) { |
/* gray = 0.30*R + 0.59*G + 0.11*B */ |
red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; |
} |
if (par->isVGA) |
vga16_setpalette(regno,red,green,blue); |
else |
ega16_setpalette(regno,red,green,blue); |
return 0; |
} |
static int vga16fb_pan_display(struct fb_var_screeninfo *var, |
struct fb_info *info) |
{ |
if (var->xoffset + info->var.xres > info->var.xres_virtual || |
var->yoffset + info->var.yres > info->var.yres_virtual) |
return -EINVAL; |
vga16fb_pan_var(info, var); |
info->var.xoffset = var->xoffset; |
info->var.yoffset = var->yoffset; |
info->var.vmode &= ~FB_VMODE_YWRAP; |
return 0; |
} |
/* The following VESA blanking code is taken from vgacon.c. The VGA |
blanking code was originally by Huang shi chao, and modified by |
Christoph Rimek (chrimek@toppoint.de) and todd j. derr |
(tjd@barefoot.org) for Linux. */ |
#define attrib_port VGA_ATC_IW |
#define seq_port_reg VGA_SEQ_I |
#define seq_port_val VGA_SEQ_D |
#define gr_port_reg VGA_GFX_I |
#define gr_port_val VGA_GFX_D |
#define video_misc_rd VGA_MIS_R |
#define video_misc_wr VGA_MIS_W |
#define vga_video_port_reg VGA_CRT_IC |
#define vga_video_port_val VGA_CRT_DC |
static void vga_vesa_blank(struct vga16fb_par *par, int mode) |
{ |
unsigned char SeqCtrlIndex; |
unsigned char CrtCtrlIndex; |
//cli(); |
SeqCtrlIndex = vga_io_r(seq_port_reg); |
CrtCtrlIndex = vga_io_r(vga_video_port_reg); |
/* save original values of VGA controller registers */ |
if(!par->vesa_blanked) { |
par->vga_state.CrtMiscIO = vga_io_r(video_misc_rd); |
//sti(); |
par->vga_state.HorizontalTotal = vga_io_rcrt(0x00); /* HorizontalTotal */ |
par->vga_state.HorizDisplayEnd = vga_io_rcrt(0x01); /* HorizDisplayEnd */ |
par->vga_state.StartHorizRetrace = vga_io_rcrt(0x04); /* StartHorizRetrace */ |
par->vga_state.EndHorizRetrace = vga_io_rcrt(0x05); /* EndHorizRetrace */ |
par->vga_state.Overflow = vga_io_rcrt(0x07); /* Overflow */ |
par->vga_state.StartVertRetrace = vga_io_rcrt(0x10); /* StartVertRetrace */ |
par->vga_state.EndVertRetrace = vga_io_rcrt(0x11); /* EndVertRetrace */ |
par->vga_state.ModeControl = vga_io_rcrt(0x17); /* ModeControl */ |
par->vga_state.ClockingMode = vga_io_rseq(0x01); /* ClockingMode */ |
} |
/* assure that video is enabled */ |
/* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */ |
//cli(); |
vga_io_wseq(0x01, par->vga_state.ClockingMode | 0x20); |
/* test for vertical retrace in process.... */ |
if ((par->vga_state.CrtMiscIO & 0x80) == 0x80) |
vga_io_w(video_misc_wr, par->vga_state.CrtMiscIO & 0xef); |
/* |
* Set <End of vertical retrace> to minimum (0) and |
* <Start of vertical Retrace> to maximum (incl. overflow) |
* Result: turn off vertical sync (VSync) pulse. |
*/ |
if (mode & VESA_VSYNC_SUSPEND) { |
outb_p(0x10,vga_video_port_reg); /* StartVertRetrace */ |
outb_p(0xff,vga_video_port_val); /* maximum value */ |
outb_p(0x11,vga_video_port_reg); /* EndVertRetrace */ |
outb_p(0x40,vga_video_port_val); /* minimum (bits 0..3) */ |
outb_p(0x07,vga_video_port_reg); /* Overflow */ |
outb_p(par->vga_state.Overflow | 0x84,vga_video_port_val); /* bits 9,10 of vert. retrace */ |
} |
if (mode & VESA_HSYNC_SUSPEND) { |
/* |
* Set <End of horizontal retrace> to minimum (0) and |
* <Start of horizontal Retrace> to maximum |
* Result: turn off horizontal sync (HSync) pulse. |
*/ |
outb_p(0x04,vga_video_port_reg); /* StartHorizRetrace */ |
outb_p(0xff,vga_video_port_val); /* maximum */ |
outb_p(0x05,vga_video_port_reg); /* EndHorizRetrace */ |
outb_p(0x00,vga_video_port_val); /* minimum (0) */ |
} |
/* restore both index registers */ |
outb_p(SeqCtrlIndex,seq_port_reg); |
outb_p(CrtCtrlIndex,vga_video_port_reg); |
//sti(); |
} |
static void vga_vesa_unblank(struct vga16fb_par *par) |
{ |
unsigned char SeqCtrlIndex; |
unsigned char CrtCtrlIndex; |
//cli(); |
SeqCtrlIndex = vga_io_r(seq_port_reg); |
CrtCtrlIndex = vga_io_r(vga_video_port_reg); |
/* restore original values of VGA controller registers */ |
vga_io_w(video_misc_wr, par->vga_state.CrtMiscIO); |
/* HorizontalTotal */ |
vga_io_wcrt(0x00, par->vga_state.HorizontalTotal); |
/* HorizDisplayEnd */ |
vga_io_wcrt(0x01, par->vga_state.HorizDisplayEnd); |
/* StartHorizRetrace */ |
vga_io_wcrt(0x04, par->vga_state.StartHorizRetrace); |
/* EndHorizRetrace */ |
vga_io_wcrt(0x05, par->vga_state.EndHorizRetrace); |
/* Overflow */ |
vga_io_wcrt(0x07, par->vga_state.Overflow); |
/* StartVertRetrace */ |
vga_io_wcrt(0x10, par->vga_state.StartVertRetrace); |
/* EndVertRetrace */ |
vga_io_wcrt(0x11, par->vga_state.EndVertRetrace); |
/* ModeControl */ |
vga_io_wcrt(0x17, par->vga_state.ModeControl); |
/* ClockingMode */ |
vga_io_wseq(0x01, par->vga_state.ClockingMode); |
/* restore index/control registers */ |
vga_io_w(seq_port_reg, SeqCtrlIndex); |
vga_io_w(vga_video_port_reg, CrtCtrlIndex); |
//sti(); |
} |
static void vga_pal_blank(void) |
{ |
int i; |
for (i=0; i<16; i++) { |
outb_p (i, dac_reg) ; |
outb_p (0, dac_val) ; |
outb_p (0, dac_val) ; |
outb_p (0, dac_val) ; |
} |
} |
/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */ |
static int vga16fb_blank(int blank, struct fb_info *info) |
{ |
struct vga16fb_par *par = (struct vga16fb_par *) info->par; |
switch (blank) { |
case 0: /* Unblank */ |
if (par->vesa_blanked) { |
vga_vesa_unblank(par); |
par->vesa_blanked = 0; |
} |
if (par->palette_blanked) { |
//do_install_cmap(info->currcon, info); |
par->palette_blanked = 0; |
} |
break; |
case 1: /* blank */ |
vga_pal_blank(); |
par->palette_blanked = 1; |
break; |
default: /* VESA blanking */ |
vga_vesa_blank(par, blank-1); |
par->vesa_blanked = 1; |
break; |
} |
return 0; |
} |
void vga_8planes_fillrect(struct fb_info *info, const struct fb_fillrect *rect) |
{ |
u32 dx = rect->dx, width = rect->width; |
char oldindex = getindex(); |
char oldmode = setmode(0x40); |
char oldmask = selectmask(); |
int line_ofs, height; |
char oldop, oldsr; |
char *where; |
dx /= 4; |
where = info->screen_base + dx + rect->dy * info->fix.line_length; |
if (rect->rop == ROP_COPY) { |
oldop = setop(0); |
oldsr = setsr(0); |
width /= 4; |
line_ofs = info->fix.line_length - width; |
setmask(0xff); |
height = rect->height; |
while (height--) { |
int x; |
/* we can do memset... */ |
for (x = width; x > 0; --x) { |
writeb(rect->color, where); |
where++; |
} |
where += line_ofs; |
} |
} else { |
char oldcolor = setcolor(0xf); |
int y; |
oldop = setop(0x18); |
oldsr = setsr(0xf); |
setmask(0x0F); |
for (y = 0; y < rect->height; y++) { |
rmw(where); |
rmw(where+1); |
where += info->fix.line_length; |
} |
setcolor(oldcolor); |
} |
setmask(oldmask); |
setsr(oldsr); |
setop(oldop); |
setmode(oldmode); |
setindex(oldindex); |
} |
void vga16fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) |
{ |
int x, x2, y2, vxres, vyres, width, height, line_ofs; |
char *dst; |
vxres = info->var.xres_virtual; |
vyres = info->var.yres_virtual; |
if (!rect->width || !rect->height || rect->dx > vxres || rect->dy > vyres) |
return; |
/* We could use hardware clipping but on many cards you get around |
* hardware clipping by writing to framebuffer directly. */ |
x2 = rect->dx + rect->width; |
y2 = rect->dy + rect->height; |
x2 = x2 < vxres ? x2 : vxres; |
y2 = y2 < vyres ? y2 : vyres; |
width = x2 - rect->dx; |
switch (info->fix.type) { |
case FB_TYPE_VGA_PLANES: |
if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) { |
height = y2 - rect->dy; |
width = rect->width/8; |
line_ofs = info->fix.line_length - width; |
dst = info->screen_base + (rect->dx/8) + rect->dy * info->fix.line_length; |
switch (rect->rop) { |
case ROP_COPY: |
setmode(0); |
setop(0); |
setsr(0xf); |
setcolor(rect->color); |
selectmask(); |
setmask(0xff); |
while (height--) { |
for (x = 0; x < width; x++) { |
writeb(0, dst); |
dst++; |
} |
dst += line_ofs; |
} |
break; |
case ROP_XOR: |
setmode(0); |
setop(0x18); |
setsr(0xf); |
setcolor(0xf); |
selectmask(); |
setmask(0xff); |
while (height--) { |
for (x = 0; x < width; x++) { |
rmw(dst); |
dst++; |
} |
dst += line_ofs; |
} |
break; |
} |
} else |
vga_8planes_fillrect(info, rect); |
break; |
case FB_TYPE_PACKED_PIXELS: |
default: |
cfb_fillrect(info, rect); |
break; |
} |
} |
void vga_8planes_copyarea(struct fb_info *info, const struct fb_copyarea *area) |
{ |
char oldindex = getindex(); |
char oldmode = setmode(0x41); |
char oldop = setop(0); |
char oldsr = setsr(0xf); |
int height, line_ofs, x; |
u32 sx, dx, width; |
char *dest, *src; |
height = area->height; |
sx = area->sx / 4; |
dx = area->dx / 4; |
width = area->width / 4; |
if (area->dy < area->sy || (area->dy == area->sy && dx < sx)) { |
line_ofs = info->fix.line_length - width; |
dest = info->screen_base + dx + area->dy * info->fix.line_length; |
src = info->screen_base + sx + area->sy * info->fix.line_length; |
while (height--) { |
for (x = 0; x < width; x++) { |
readb(src); |
writeb(0, dest); |
src++; |
dest++; |
} |
src += line_ofs; |
dest += line_ofs; |
} |
} else { |
line_ofs = info->fix.line_length - width; |
dest = info->screen_base + dx + width + |
(area->dy + height - 1) * info->fix.line_length; |
src = info->screen_base + sx + width + |
(area->sy + height - 1) * info->fix.line_length; |
while (height--) { |
for (x = 0; x < width; x++) { |
--src; |
--dest; |
readb(src); |
writeb(0, dest); |
} |
src -= line_ofs; |
dest -= line_ofs; |
} |
} |
setsr(oldsr); |
setop(oldop); |
setmode(oldmode); |
setindex(oldindex); |
} |
void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *area) |
{ |
u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy; |
int x, x2, y2, old_dx, old_dy, vxres, vyres; |
int height, width, line_ofs; |
char *dst = NULL, *src = NULL; |
vxres = info->var.xres_virtual; |
vyres = info->var.yres_virtual; |
if (area->dx > vxres || area->sx > vxres || area->dy > vyres || |
area->sy > vyres) |
return; |
/* clip the destination */ |
old_dx = area->dx; |
old_dy = area->dy; |
/* |
* We could use hardware clipping but on many cards you get around |
* hardware clipping by writing to framebuffer directly. |
*/ |
x2 = area->dx + area->width; |
y2 = area->dy + area->height; |
dx = area->dx > 0 ? area->dx : 0; |
dy = area->dy > 0 ? area->dy : 0; |
x2 = x2 < vxres ? x2 : vxres; |
y2 = y2 < vyres ? y2 : vyres; |
width = x2 - dx; |
height = y2 - dy; |
/* update sx1,sy1 */ |
sx += (dx - old_dx); |
sy += (dy - old_dy); |
/* the source must be completely inside the virtual screen */ |
if (sx < 0 || sy < 0 || (sx + width) > vxres || (sy + height) > vyres) |
return; |
switch (info->fix.type) { |
case FB_TYPE_VGA_PLANES: |
if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) { |
width = width/8; |
height = height; |
line_ofs = info->fix.line_length - width; |
setmode(1); |
setop(0); |
setsr(0xf); |
if (dy < sy || (dy == sy && dx < sx)) { |
dst = info->screen_base + (dx/8) + dy * info->fix.line_length; |
src = info->screen_base + (sx/8) + sy * info->fix.line_length; |
while (height--) { |
for (x = 0; x < width; x++) { |
readb(src); |
writeb(0, dst); |
dst++; |
src++; |
} |
src += line_ofs; |
dst += line_ofs; |
} |
} else { |
dst = info->screen_base + (dx/8) + width + |
(dy + height - 1) * info->fix.line_length; |
src = info->screen_base + (sx/8) + width + |
(sy + height - 1) * info->fix.line_length; |
while (height--) { |
for (x = 0; x < width; x++) { |
dst--; |
src--; |
readb(src); |
writeb(0, dst); |
} |
src -= line_ofs; |
dst -= line_ofs; |
} |
} |
} else |
vga_8planes_copyarea(info, area); |
break; |
case FB_TYPE_PACKED_PIXELS: |
default: |
cfb_copyarea(info, area); |
break; |
} |
} |
#ifdef __LITTLE_ENDIAN |
static unsigned int transl_l[] = |
{0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF}; |
static unsigned int transl_h[] = |
{0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00, |
0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00}; |
#else |
#ifdef __BIG_ENDIAN |
static unsigned int transl_h[] = |
{0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF}; |
static unsigned int transl_l[] = |
{0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00, |
0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00}; |
#else |
#error "Only __BIG_ENDIAN and __LITTLE_ENDIAN are supported in vga-planes" |
#endif |
#endif |
void vga_8planes_imageblit(struct fb_info *info, const struct fb_image *image) |
{ |
char oldindex = getindex(); |
char oldmode = setmode(0x40); |
char oldop = setop(0); |
char oldsr = setsr(0); |
char oldmask = selectmask(); |
const char *cdat = image->data; |
u32 dx = image->dx; |
char *where; |
int y; |
dx /= 4; |
where = info->screen_base + dx + image->dy * info->fix.line_length; |
setmask(0xff); |
writeb(image->bg_color, where); |
readb(where); |
selectmask(); |
setmask(image->fg_color ^ image->bg_color); |
setmode(0x42); |
setop(0x18); |
for (y = 0; y < image->height; y++, where += info->fix.line_length) |
writew(transl_h[cdat[y]&0xF] | transl_l[cdat[y] >> 4], where); |
setmask(oldmask); |
setsr(oldsr); |
setop(oldop); |
setmode(oldmode); |
setindex(oldindex); |
} |
void vga_imageblit_expand(struct fb_info *info, const struct fb_image *image) |
{ |
char *where = info->screen_base + (image->dx/8) + |
image->dy * info->fix.line_length; |
struct vga16fb_par *par = (struct vga16fb_par *) info->par; |
char *cdat = (char *) image->data, *dst; |
int x, y; |
switch (info->fix.type) { |
case FB_TYPE_VGA_PLANES: |
if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) { |
if (par->isVGA) { |
setmode(2); |
setop(0); |
setsr(0xf); |
setcolor(image->fg_color); |
selectmask(); |
setmask(0xff); |
writeb(image->bg_color, where); |
rmb(); |
readb(where); /* fill latches */ |
setmode(3); |
wmb(); |
for (y = 0; y < image->height; y++) { |
dst = where; |
for (x = image->width/8; x--;) |
writeb(*cdat++, dst++); |
where += info->fix.line_length; |
} |
wmb(); |
} else { |
setmode(0); |
setop(0); |
setsr(0xf); |
setcolor(image->bg_color); |
selectmask(); |
setmask(0xff); |
for (y = 0; y < image->height; y++) { |
dst = where; |
for (x=image->width/8; x--;){ |
rmw(dst); |
setcolor(image->fg_color); |
selectmask(); |
if (*cdat) { |
setmask(*cdat++); |
rmw(dst++); |
} |
} |
where += info->fix.line_length; |
} |
} |
} else |
vga_8planes_imageblit(info, image); |
break; |
case FB_TYPE_PACKED_PIXELS: |
default: |
cfb_imageblit(info, image); |
break; |
} |
} |
void vga_imageblit_color(struct fb_info *info, const struct fb_image *image) |
{ |
/* |
* Draw logo |
*/ |
struct vga16fb_par *par = (struct vga16fb_par *) info->par; |
char *where = info->screen_base + image->dy * info->fix.line_length + |
image->dx/8; |
const char *cdat = image->data, *dst; |
int x, y; |
switch (info->fix.type) { |
case FB_TYPE_VGA_PLANES: |
if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4 && |
par->isVGA) { |
setsr(0xf); |
setop(0); |
setmode(0); |
for (y = 0; y < image->height; y++) { |
for (x = 0; x < image->width; x++) { |
dst = where + x/8; |
setcolor(*cdat); |
selectmask(); |
setmask(1 << (7 - (x % 8))); |
fb_readb(dst); |
fb_writeb(0, dst); |
cdat++; |
} |
where += info->fix.line_length; |
} |
} |
break; |
case FB_TYPE_PACKED_PIXELS: |
cfb_imageblit(info, image); |
break; |
default: |
break; |
} |
} |
void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image) |
{ |
if (image->depth == 1) |
vga_imageblit_expand(info, image); |
else if (image->depth <= info->var.bits_per_pixel) |
vga_imageblit_color(info, image); |
} |
static struct fb_ops vga16fb_ops = { |
.owner = THIS_MODULE, |
.fb_open = vga16fb_open, |
.fb_release = vga16fb_release, |
.fb_check_var = vga16fb_check_var, |
.fb_set_par = vga16fb_set_par, |
.fb_setcolreg = vga16fb_setcolreg, |
.fb_pan_display = vga16fb_pan_display, |
.fb_blank = vga16fb_blank, |
.fb_fillrect = vga16fb_fillrect, |
.fb_copyarea = vga16fb_copyarea, |
.fb_imageblit = vga16fb_imageblit, |
.fb_cursor = soft_cursor, |
}; |
int vga16fb_setup(char *options) |
{ |
char *this_opt; |
if (!options || !*options) |
return 0; |
while ((this_opt = strsep(&options, ",")) != NULL) { |
if (!*this_opt) continue; |
} |
return 0; |
} |
int __init vga16fb_init(void) |
{ |
int i; |
printk(KERN_DEBUG "vga16fb: initializing\n"); |
/* XXX share VGA_FB_PHYS and I/O region with vgacon and others */ |
vga16fb.screen_base = ioremap(VGA_FB_PHYS, VGA_FB_PHYS_LEN); |
if (!vga16fb.screen_base) { |
printk(KERN_ERR "vga16fb: unable to map device\n"); |
return -ENOMEM; |
} |
printk(KERN_INFO "vga16fb: mapped to 0x%p\n", vga16fb.screen_base); |
vga16_par.isVGA = ORIG_VIDEO_ISVGA; |
vga16_par.palette_blanked = 0; |
vga16_par.vesa_blanked = 0; |
i = vga16_par.isVGA? 6 : 2; |
vga16fb_defined.red.length = i; |
vga16fb_defined.green.length = i; |
vga16fb_defined.blue.length = i; |
/* name should not depend on EGA/VGA */ |
vga16fb.fbops = &vga16fb_ops; |
vga16fb.var = vga16fb_defined; |
vga16fb.fix = vga16fb_fix; |
vga16fb.par = &vga16_par; |
vga16fb.flags = FBINFO_FLAG_DEFAULT; |
i = (vga16fb_defined.bits_per_pixel == 8) ? 256 : 16; |
fb_alloc_cmap(&vga16fb.cmap, i, 0); |
if (vga16fb_check_var(&vga16fb.var, &vga16fb)) |
return -EINVAL; |
vga16fb_update_fix(&vga16fb); |
if (register_framebuffer(&vga16fb) < 0) { |
iounmap(vga16fb.screen_base); |
return -EINVAL; |
} |
printk(KERN_INFO "fb%d: %s frame buffer device\n", |
vga16fb.node, vga16fb.fix.id); |
return 0; |
} |
static void __exit vga16fb_exit(void) |
{ |
unregister_framebuffer(&vga16fb); |
iounmap(vga16fb.screen_base); |
/* XXX unshare VGA regions */ |
} |
#ifdef MODULE |
MODULE_LICENSE("GPL"); |
module_init(vga16fb_init); |
#endif |
module_exit(vga16fb_exit); |
/* |
* Overrides for Emacs so that we follow Linus's tabbing style. |
* --------------------------------------------------------------------------- |
* Local variables: |
* c-basic-offset: 8 |
* End: |
*/ |
/shark/trunk/drivers/linuxc26/linuxcomp.c |
---|
12,6 → 12,8 |
#include <linux/ctype.h> |
#include <linux/device.h> |
#include <linux/completion.h> |
#include <linux/tty.h> |
#include <asm/setup.h> |
unsigned char _ctype[] = { |
_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ |
366,3 → 368,40 |
int unregister_chrdev(unsigned int a, const char *b) { |
return 0; |
} |
void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags) { |
return (void *)offset; |
} |
void iounmap(void *addr) { |
} |
void *vmalloc(unsigned long size) { |
return malloc(size); |
} |
void vfree(void *addr) { |
return free(addr); |
} |
/* TODO */ |
char * strsep(char **a,const char *b) { |
return NULL; |
} |
struct screen_info screen_info; |
int linuxcomp_init(void) { |
return 0; |
} |
/shark/trunk/drivers/linuxc26/shark_linuxc26.c |
---|
23,6 → 23,7 |
extern int devices_init(void); |
extern int buses_init(void); |
extern int classes_init(void); |
extern int linuxcomp_init(void); |
unsigned long read_time(void) { |
41,6 → 42,7 |
printk("LINUXC26_register_module\n"); |
linuxcomp_init(); |
devices_init(); |
buses_init(); |
classes_init(); |