git.y1.nz

fbui

Framebuffer-based graphical environment
download: https://git.y1.nz/archives/fbui.tar.gz
README | Files | Log | Refs

drivers/video/vga16fb.c

      1 /*
      2  * linux/drivers/video/vga16.c -- VGA 16-color framebuffer driver
      3  * 
      4  * Copyright 1999 Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz>
      5  * Based on VGA info at http://www.goodnet.com/~tinara/FreeVGA/home.htm
      6  * Based on VESA framebuffer (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
      7  *
      8  * This file is subject to the terms and conditions of the GNU General
      9  * Public License.  See the file COPYING in the main directory of this
     10  * archive for more details.  
     11  */
     12 
     13 #include <linux/module.h>
     14 #include <linux/kernel.h>
     15 #include <linux/errno.h>
     16 #include <linux/string.h>
     17 #include <linux/mm.h>
     18 #include <linux/tty.h>
     19 #include <linux/slab.h>
     20 #include <linux/delay.h>
     21 #include <linux/fb.h>
     22 #include <linux/ioport.h>
     23 #include <linux/init.h>
     24 
     25 #include <asm/io.h>
     26 #include <video/vga.h>
     27 
     28 #define GRAPHICS_ADDR_REG VGA_GFX_I	/* Graphics address register. */
     29 #define GRAPHICS_DATA_REG VGA_GFX_D	/* Graphics data register. */
     30 
     31 #define SET_RESET_INDEX 	VGA_GFX_SR_VALUE	/* Set/Reset Register index. */
     32 #define ENABLE_SET_RESET_INDEX	VGA_GFX_SR_ENABLE	/* Enable Set/Reset Register index. */
     33 #define DATA_ROTATE_INDEX	VGA_GFX_DATA_ROTATE	/* Data Rotate Register index. */
     34 #define GRAPHICS_MODE_INDEX	VGA_GFX_MODE		/* Graphics Mode Register index. */
     35 #define BIT_MASK_INDEX		VGA_GFX_BIT_MASK	/* Bit Mask Register index. */
     36 
     37 #define dac_reg	(VGA_PEL_IW)
     38 #define dac_val	(VGA_PEL_D)
     39 
     40 #define VGA_FB_PHYS 0xA0000
     41 #define VGA_FB_PHYS_LEN 65536
     42 
     43 #define MODE_SKIP4	1
     44 #define MODE_8BPP	2
     45 #define MODE_CFB	4
     46 #define MODE_TEXT	8
     47 
     48 /* --------------------------------------------------------------------- */
     49 
     50 /*
     51  * card parameters
     52  */
     53 
     54 static struct fb_info vga16fb; 
     55 
     56 static struct vga16fb_par {
     57 	/* structure holding original VGA register settings when the
     58            screen is blanked */
     59 	struct {
     60 		unsigned char	SeqCtrlIndex;		/* Sequencer Index reg.   */
     61 		unsigned char	CrtCtrlIndex;		/* CRT-Contr. Index reg.  */
     62 		unsigned char	CrtMiscIO;		/* Miscellaneous register */
     63 		unsigned char	HorizontalTotal;	/* CRT-Controller:00h */
     64 		unsigned char	HorizDisplayEnd;	/* CRT-Controller:01h */
     65 		unsigned char	StartHorizRetrace;	/* CRT-Controller:04h */
     66 		unsigned char	EndHorizRetrace;	/* CRT-Controller:05h */
     67 		unsigned char	Overflow;		/* CRT-Controller:07h */
     68 		unsigned char	StartVertRetrace;	/* CRT-Controller:10h */
     69 		unsigned char	EndVertRetrace;		/* CRT-Controller:11h */
     70 		unsigned char	ModeControl;		/* CRT-Controller:17h */
     71 		unsigned char	ClockingMode;		/* Seq-Controller:01h */
     72 	} vga_state;
     73 	struct vgastate state;
     74 	atomic_t ref_count;
     75 	int palette_blanked, vesa_blanked, mode, isVGA;
     76 	u8 misc, pel_msk, vss, clkdiv;
     77 	u8 crtc[VGA_CRT_C];
     78 } vga16_par;
     79 
     80 /* --------------------------------------------------------------------- */
     81 
     82 static struct fb_var_screeninfo vga16fb_defined = {
     83 	.xres		= 640,
     84 	.yres		= 480,
     85 	.xres_virtual	= 640,
     86 	.yres_virtual	= 480,
     87 	.bits_per_pixel	= 4,	
     88 	.activate	= FB_ACTIVATE_TEST,
     89 	.height		= -1,
     90 	.width		= -1,
     91 	.pixclock	= 39721,
     92 	.left_margin	= 48,
     93 	.right_margin	= 16,
     94 	.upper_margin	= 39,
     95 	.lower_margin	= 8,
     96 	.hsync_len 	= 96,
     97 	.vsync_len	= 2,
     98 	.vmode		= FB_VMODE_NONINTERLACED,
     99 };
    100 
    101 /* name should not depend on EGA/VGA */
    102 static struct fb_fix_screeninfo vga16fb_fix __initdata = {
    103 	.id		= "VGA16 VGA",
    104 	.smem_start	= VGA_FB_PHYS,
    105 	.smem_len	= VGA_FB_PHYS_LEN,
    106 	.type		= FB_TYPE_VGA_PLANES,
    107 	.type_aux	= FB_AUX_VGA_PLANES_VGA4,
    108 	.visual		= FB_VISUAL_PSEUDOCOLOR,
    109 	.xpanstep	= 8,
    110 	.ypanstep	= 1,
    111 	.line_length	= 640/8,
    112 	.accel		= FB_ACCEL_NONE
    113 };
    114 
    115 /* The VGA's weird architecture often requires that we read a byte and
    116    write a byte to the same location.  It doesn't matter *what* byte
    117    we write, however.  This is because all the action goes on behind
    118    the scenes in the VGA's 32-bit latch register, and reading and writing
    119    video memory just invokes latch behavior.
    120 
    121    To avoid race conditions (is this necessary?), reading and writing
    122    the memory byte should be done with a single instruction.  One
    123    suitable instruction is the x86 bitwise OR.  The following
    124    read-modify-write routine should optimize to one such bitwise
    125    OR. */
    126 static inline void rmw(volatile char *p)
    127 {
    128 	readb(p);
    129 	writeb(1, p);
    130 }
    131 
    132 /* Set the Graphics Mode Register, and return its previous value.
    133    Bits 0-1 are write mode, bit 3 is read mode. */
    134 static inline int setmode(int mode)
    135 {
    136 	int oldmode;
    137 	
    138 	vga_io_w(GRAPHICS_ADDR_REG, GRAPHICS_MODE_INDEX);
    139 	oldmode = vga_io_r(GRAPHICS_DATA_REG);
    140 	vga_io_w(GRAPHICS_DATA_REG, mode);
    141 	return oldmode;
    142 }
    143 
    144 /* Select the Bit Mask Register and return its value. */
    145 static inline int selectmask(void)
    146 {
    147 	return vga_io_rgfx(BIT_MASK_INDEX);
    148 }
    149 
    150 /* Set the value of the Bit Mask Register.  It must already have been
    151    selected with selectmask(). */
    152 static inline void setmask(int mask)
    153 {
    154 	vga_io_w(GRAPHICS_DATA_REG, mask);
    155 }
    156 
    157 /* Set the Data Rotate Register and return its old value. 
    158    Bits 0-2 are rotate count, bits 3-4 are logical operation
    159    (0=NOP, 1=AND, 2=OR, 3=XOR). */
    160 static inline int setop(int op)
    161 {
    162 	int oldop;
    163 	
    164 	vga_io_w(GRAPHICS_ADDR_REG, DATA_ROTATE_INDEX);
    165 	oldop = vga_io_r(GRAPHICS_DATA_REG);
    166 	vga_io_w(GRAPHICS_DATA_REG, op);
    167 	return oldop;
    168 }
    169 
    170 /* Set the Enable Set/Reset Register and return its old value.  
    171    The code here always uses value 0xf for thsi register. */
    172 static inline int setsr(int sr)
    173 {
    174 	int oldsr;
    175 
    176 	vga_io_w(GRAPHICS_ADDR_REG, ENABLE_SET_RESET_INDEX);
    177 	oldsr = vga_io_r(GRAPHICS_DATA_REG);
    178 	vga_io_w(GRAPHICS_DATA_REG, sr);
    179 	return oldsr;
    180 }
    181 
    182 /* Set the Set/Reset Register and return its old value. */
    183 static inline int setcolor(int color)
    184 {
    185 	int oldcolor;
    186 
    187 	vga_io_w(GRAPHICS_ADDR_REG, SET_RESET_INDEX);
    188 	oldcolor = vga_io_r(GRAPHICS_DATA_REG);
    189 	vga_io_w(GRAPHICS_DATA_REG, color);
    190 	return oldcolor;
    191 }
    192 
    193 /* Return the value in the Graphics Address Register. */
    194 static inline int getindex(void)
    195 {
    196 	return vga_io_r(GRAPHICS_ADDR_REG);
    197 }
    198 
    199 /* Set the value in the Graphics Address Register. */
    200 static inline void setindex(int index)
    201 {
    202 	vga_io_w(GRAPHICS_ADDR_REG, index);
    203 }
    204 
    205 static void vga16fb_pan_var(struct fb_info *info, 
    206 			    struct fb_var_screeninfo *var)
    207 {
    208 	struct vga16fb_par *par = (struct vga16fb_par *) info->par;
    209 	u32 xoffset, pos;
    210 
    211 	xoffset = var->xoffset;
    212 	if (info->var.bits_per_pixel == 8) {
    213 		pos = (info->var.xres_virtual * var->yoffset + xoffset) >> 2;
    214 	} else if (par->mode & MODE_TEXT) {
    215 		int fh = 16; // FIXME !!! font height. Fugde for now.
    216 		pos = (info->var.xres_virtual * (var->yoffset / fh) + xoffset) >> 3;
    217 	} else {
    218 		if (info->var.nonstd)
    219 			xoffset--;
    220 		pos = (info->var.xres_virtual * var->yoffset + xoffset) >> 3;
    221 	}
    222 	vga_io_wcrt(VGA_CRTC_START_HI, pos >> 8);
    223 	vga_io_wcrt(VGA_CRTC_START_LO, pos & 0xFF);
    224 	/* if we support CFB4, then we must! support xoffset with pixel
    225 	 * granularity if someone supports xoffset in bit resolution */
    226 	vga_io_r(VGA_IS1_RC);		/* reset flip-flop */
    227 	vga_io_w(VGA_ATT_IW, VGA_ATC_PEL);
    228 	if (var->bits_per_pixel == 8)
    229 		vga_io_w(VGA_ATT_IW, (xoffset & 3) << 1);
    230 	else
    231 		vga_io_w(VGA_ATT_IW, xoffset & 7);
    232 	vga_io_r(VGA_IS1_RC);
    233 	vga_io_w(VGA_ATT_IW, 0x20);
    234 }
    235 
    236 static void vga16fb_update_fix(struct fb_info *info)
    237 {
    238 	if (info->var.bits_per_pixel == 4) {
    239 		if (info->var.nonstd) {
    240 			info->fix.type = FB_TYPE_PACKED_PIXELS;
    241 			info->fix.line_length = info->var.xres_virtual / 2;
    242 		} else {
    243 			info->fix.type = FB_TYPE_VGA_PLANES;
    244 			info->fix.type_aux = FB_AUX_VGA_PLANES_VGA4;
    245 			info->fix.line_length = info->var.xres_virtual / 8;
    246 		}
    247 	} else if (info->var.bits_per_pixel == 0) {
    248 		info->fix.type = FB_TYPE_TEXT;
    249 		info->fix.type_aux = FB_AUX_TEXT_CGA;
    250 		info->fix.line_length = info->var.xres_virtual / 4;
    251 	} else {	/* 8bpp */
    252 		if (info->var.nonstd) {
    253 			info->fix.type = FB_TYPE_VGA_PLANES;
    254 			info->fix.type_aux = FB_AUX_VGA_PLANES_CFB8;
    255 			info->fix.line_length = info->var.xres_virtual / 4;
    256 		} else {
    257 			info->fix.type = FB_TYPE_PACKED_PIXELS;
    258 			info->fix.line_length = info->var.xres_virtual;
    259 		}
    260 	}
    261 }
    262 
    263 static void vga16fb_clock_chip(struct vga16fb_par *par,
    264 			       unsigned int pixclock,
    265 			       const struct fb_info *info,
    266 			       int mul, int div)
    267 {
    268 	static struct {
    269 		u32 pixclock;
    270 		u8  misc;
    271 		u8  seq_clock_mode;
    272 	} *ptr, *best, vgaclocks[] = {
    273 		{ 79442 /* 12.587 */, 0x00, 0x08},
    274 		{ 70616 /* 14.161 */, 0x04, 0x08},
    275 		{ 39721 /* 25.175 */, 0x00, 0x00},
    276 		{ 35308 /* 28.322 */, 0x04, 0x00},
    277 		{     0 /* bad */,    0x00, 0x00}};
    278 	int err;
    279 
    280 	pixclock = (pixclock * mul) / div;
    281 	best = vgaclocks;
    282 	err = pixclock - best->pixclock;
    283 	if (err < 0) err = -err;
    284 	for (ptr = vgaclocks + 1; ptr->pixclock; ptr++) {
    285 		int tmp;
    286 
    287 		tmp = pixclock - ptr->pixclock;
    288 		if (tmp < 0) tmp = -tmp;
    289 		if (tmp < err) {
    290 			err = tmp;
    291 			best = ptr;
    292 		}
    293 	}
    294 	par->misc |= best->misc;
    295 	par->clkdiv = best->seq_clock_mode;
    296 	pixclock = (best->pixclock * div) / mul;		
    297 }
    298 			       
    299 #define FAIL(X) return -EINVAL
    300 
    301 static int vga16fb_open(struct fb_info *info, int user)
    302 {
    303 	struct vga16fb_par *par = (struct vga16fb_par *) info->par;
    304 	int cnt = atomic_read(&par->ref_count);
    305 
    306 	if (!cnt) {
    307 		memset(&par->state, 0, sizeof(struct vgastate));
    308 		par->state.flags = VGA_SAVE_FONTS | VGA_SAVE_MODE |
    309 			VGA_SAVE_CMAP;
    310 		save_vga(&par->state);
    311 	}
    312 	atomic_inc(&par->ref_count);
    313 	return 0;
    314 }
    315 
    316 static int vga16fb_release(struct fb_info *info, int user)
    317 {
    318 	struct vga16fb_par *par = (struct vga16fb_par *) info->par;
    319 	int cnt = atomic_read(&par->ref_count);
    320 
    321 	if (!cnt)
    322 		return -EINVAL;
    323 	if (cnt == 1)
    324 		restore_vga(&par->state);
    325 	atomic_dec(&par->ref_count);
    326 
    327 	return 0;
    328 }
    329 
    330 static int vga16fb_check_var(struct fb_var_screeninfo *var,
    331 			     struct fb_info *info)
    332 {
    333 	struct vga16fb_par *par = (struct vga16fb_par *) info->par;
    334 	u32 xres, right, hslen, left, xtotal;
    335 	u32 yres, lower, vslen, upper, ytotal;
    336 	u32 vxres, xoffset, vyres, yoffset;
    337 	u32 pos;
    338 	u8 r7, rMode;
    339 	int shift;
    340 	int mode;
    341 	u32 maxmem;
    342 
    343 	par->pel_msk = 0xFF;
    344 
    345 	if (var->bits_per_pixel == 4) {
    346 		if (var->nonstd) {
    347 			if (!par->isVGA)
    348 				return -EINVAL;
    349 			shift = 3;
    350 			mode = MODE_SKIP4 | MODE_CFB;
    351 			maxmem = 16384;
    352 			par->pel_msk = 0x0F;
    353 		} else {
    354 			shift = 3;
    355 			mode = 0;
    356 			maxmem = 65536;
    357 		}
    358 	} else if (var->bits_per_pixel == 8) {
    359 		if (!par->isVGA)
    360 			return -EINVAL;	/* no support on EGA */
    361 		shift = 2;
    362 		if (var->nonstd) {
    363 			mode = MODE_8BPP | MODE_CFB;
    364 			maxmem = 65536;
    365 		} else {
    366 			mode = MODE_SKIP4 | MODE_8BPP | MODE_CFB;
    367 			maxmem = 16384;
    368 		}
    369 	} else
    370 		return -EINVAL;
    371 
    372 	xres = (var->xres + 7) & ~7;
    373 	vxres = (var->xres_virtual + 0xF) & ~0xF;
    374 	xoffset = (var->xoffset + 7) & ~7;
    375 	left = (var->left_margin + 7) & ~7;
    376 	right = (var->right_margin + 7) & ~7;
    377 	hslen = (var->hsync_len + 7) & ~7;
    378 
    379 	if (vxres < xres)
    380 		vxres = xres;
    381 	if (xres + xoffset > vxres)
    382 		xoffset = vxres - xres;
    383 
    384 	var->xres = xres;
    385 	var->right_margin = right;
    386 	var->hsync_len = hslen;
    387 	var->left_margin = left;
    388 	var->xres_virtual = vxres;
    389 	var->xoffset = xoffset;
    390 
    391 	xres >>= shift;
    392 	right >>= shift;
    393 	hslen >>= shift;
    394 	left >>= shift;
    395 	vxres >>= shift;
    396 	xtotal = xres + right + hslen + left;
    397 	if (xtotal >= 256)
    398 		FAIL("xtotal too big");
    399 	if (hslen > 32)
    400 		FAIL("hslen too big");
    401 	if (right + hslen + left > 64)
    402 		FAIL("hblank too big");
    403 	par->crtc[VGA_CRTC_H_TOTAL] = xtotal - 5;
    404 	par->crtc[VGA_CRTC_H_BLANK_START] = xres - 1;
    405 	par->crtc[VGA_CRTC_H_DISP] = xres - 1;
    406 	pos = xres + right;
    407 	par->crtc[VGA_CRTC_H_SYNC_START] = pos;
    408 	pos += hslen;
    409 	par->crtc[VGA_CRTC_H_SYNC_END] = pos & 0x1F;
    410 	pos += left - 2; /* blank_end + 2 <= total + 5 */
    411 	par->crtc[VGA_CRTC_H_BLANK_END] = (pos & 0x1F) | 0x80;
    412 	if (pos & 0x20)
    413 		par->crtc[VGA_CRTC_H_SYNC_END] |= 0x80;
    414 
    415 	yres = var->yres;
    416 	lower = var->lower_margin;
    417 	vslen = var->vsync_len;
    418 	upper = var->upper_margin;
    419 	vyres = var->yres_virtual;
    420 	yoffset = var->yoffset;
    421 
    422 	if (yres > vyres)
    423 		vyres = yres;
    424 	if (vxres * vyres > maxmem) {
    425 		vyres = maxmem / vxres;
    426 		if (vyres < yres)
    427 			return -ENOMEM;
    428 	}
    429 	if (yoffset + yres > vyres)
    430 		yoffset = vyres - yres;
    431 	var->yres = yres;
    432 	var->lower_margin = lower;
    433 	var->vsync_len = vslen;
    434 	var->upper_margin = upper;
    435 	var->yres_virtual = vyres;
    436 	var->yoffset = yoffset;
    437 
    438 	if (var->vmode & FB_VMODE_DOUBLE) {
    439 		yres <<= 1;
    440 		lower <<= 1;
    441 		vslen <<= 1;
    442 		upper <<= 1;
    443 	}
    444 	ytotal = yres + lower + vslen + upper;
    445 	if (ytotal > 1024) {
    446 		ytotal >>= 1;
    447 		yres >>= 1;
    448 		lower >>= 1;
    449 		vslen >>= 1;
    450 		upper >>= 1;
    451 		rMode = 0x04;
    452 	} else
    453 		rMode = 0x00;
    454 	if (ytotal > 1024)
    455 		FAIL("ytotal too big");
    456 	if (vslen > 16)
    457 		FAIL("vslen too big");
    458 	par->crtc[VGA_CRTC_V_TOTAL] = ytotal - 2;
    459 	r7 = 0x10;	/* disable linecompare */
    460 	if (ytotal & 0x100) r7 |= 0x01;
    461 	if (ytotal & 0x200) r7 |= 0x20;
    462 	par->crtc[VGA_CRTC_PRESET_ROW] = 0;
    463 	par->crtc[VGA_CRTC_MAX_SCAN] = 0x40;	/* 1 scanline, no linecmp */
    464 	if (var->vmode & FB_VMODE_DOUBLE)
    465 		par->crtc[VGA_CRTC_MAX_SCAN] |= 0x80;
    466 	par->crtc[VGA_CRTC_CURSOR_START] = 0x20;
    467 	par->crtc[VGA_CRTC_CURSOR_END]   = 0x00;
    468 	if ((mode & (MODE_CFB | MODE_8BPP)) == MODE_CFB)
    469 		xoffset--;
    470 	pos = yoffset * vxres + (xoffset >> shift);
    471 	par->crtc[VGA_CRTC_START_HI]     = pos >> 8;
    472 	par->crtc[VGA_CRTC_START_LO]     = pos & 0xFF;
    473 	par->crtc[VGA_CRTC_CURSOR_HI]    = 0x00;
    474 	par->crtc[VGA_CRTC_CURSOR_LO]    = 0x00;
    475 	pos = yres - 1;
    476 	par->crtc[VGA_CRTC_V_DISP_END] = pos & 0xFF;
    477 	par->crtc[VGA_CRTC_V_BLANK_START] = pos & 0xFF;
    478 	if (pos & 0x100)
    479 		r7 |= 0x0A;	/* 0x02 -> DISP_END, 0x08 -> BLANK_START */
    480 	if (pos & 0x200) {
    481 		r7 |= 0x40;	/* 0x40 -> DISP_END */
    482 		par->crtc[VGA_CRTC_MAX_SCAN] |= 0x20; /* BLANK_START */
    483 	}
    484 	pos += lower;
    485 	par->crtc[VGA_CRTC_V_SYNC_START] = pos & 0xFF;
    486 	if (pos & 0x100)
    487 		r7 |= 0x04;
    488 	if (pos & 0x200)
    489 		r7 |= 0x80;
    490 	pos += vslen;
    491 	par->crtc[VGA_CRTC_V_SYNC_END] = (pos & 0x0F) & ~0x10; /* disabled IRQ */
    492 	pos += upper - 1; /* blank_end + 1 <= ytotal + 2 */
    493 	par->crtc[VGA_CRTC_V_BLANK_END] = pos & 0xFF; /* 0x7F for original VGA,
    494                      but some SVGA chips requires all 8 bits to set */
    495 	if (vxres >= 512)
    496 		FAIL("vxres too long");
    497 	par->crtc[VGA_CRTC_OFFSET] = vxres >> 1;
    498 	if (mode & MODE_SKIP4)
    499 		par->crtc[VGA_CRTC_UNDERLINE] = 0x5F;	/* 256, cfb8 */
    500 	else
    501 		par->crtc[VGA_CRTC_UNDERLINE] = 0x1F;	/* 16, vgap */
    502 	par->crtc[VGA_CRTC_MODE] = rMode | ((mode & MODE_TEXT) ? 0xA3 : 0xE3);
    503 	par->crtc[VGA_CRTC_LINE_COMPARE] = 0xFF;
    504 	par->crtc[VGA_CRTC_OVERFLOW] = r7;
    505 
    506 	par->vss = 0x00;	/* 3DA */
    507 
    508 	par->misc = 0xE3;	/* enable CPU, ports 0x3Dx, positive sync */
    509 	if (var->sync & FB_SYNC_HOR_HIGH_ACT)
    510 		par->misc &= ~0x40;
    511 	if (var->sync & FB_SYNC_VERT_HIGH_ACT)
    512 		par->misc &= ~0x80;
    513 	
    514 	par->mode = mode;
    515 
    516 	if (mode & MODE_8BPP)
    517 		/* pixel clock == vga clock / 2 */
    518 		vga16fb_clock_chip(par, var->pixclock, info, 1, 2);
    519 	else
    520 		/* pixel clock == vga clock */
    521 		vga16fb_clock_chip(par, var->pixclock, info, 1, 1);
    522 	
    523 	var->red.offset = var->green.offset = var->blue.offset = 
    524 	var->transp.offset = 0;
    525 	var->red.length = var->green.length = var->blue.length =
    526 		(par->isVGA) ? 6 : 2;
    527 	var->transp.length = 0;
    528 	var->activate = FB_ACTIVATE_NOW;
    529 	var->height = -1;
    530 	var->width = -1;
    531 	var->accel_flags = 0;
    532 	return 0;
    533 }
    534 #undef FAIL
    535 
    536 static int vga16fb_set_par(struct fb_info *info)
    537 {
    538 	struct vga16fb_par *par = (struct vga16fb_par *) info->par;
    539 	u8 gdc[VGA_GFX_C];
    540 	u8 seq[VGA_SEQ_C];
    541 	u8 atc[VGA_ATT_C];
    542 	int fh, i;
    543 
    544 	seq[VGA_SEQ_CLOCK_MODE] = 0x01 | par->clkdiv;
    545 	if (par->mode & MODE_TEXT)
    546 		seq[VGA_SEQ_PLANE_WRITE] = 0x03;
    547 	else
    548 		seq[VGA_SEQ_PLANE_WRITE] = 0x0F;
    549 	seq[VGA_SEQ_CHARACTER_MAP] = 0x00;
    550 	if (par->mode & MODE_TEXT)
    551 		seq[VGA_SEQ_MEMORY_MODE] = 0x03;
    552 	else if (par->mode & MODE_SKIP4)
    553 		seq[VGA_SEQ_MEMORY_MODE] = 0x0E;
    554 	else
    555 		seq[VGA_SEQ_MEMORY_MODE] = 0x06;
    556 
    557 	gdc[VGA_GFX_SR_VALUE] = 0x00;
    558 	gdc[VGA_GFX_SR_ENABLE] = 0x00;
    559 	gdc[VGA_GFX_COMPARE_VALUE] = 0x00;
    560 	gdc[VGA_GFX_DATA_ROTATE] = 0x00;
    561 	gdc[VGA_GFX_PLANE_READ] = 0;
    562 	if (par->mode & MODE_TEXT) {
    563 		gdc[VGA_GFX_MODE] = 0x10;
    564 		gdc[VGA_GFX_MISC] = 0x06;
    565 	} else {
    566 		if (par->mode & MODE_CFB)
    567 			gdc[VGA_GFX_MODE] = 0x40;
    568 		else
    569 			gdc[VGA_GFX_MODE] = 0x00;
    570 		gdc[VGA_GFX_MISC] = 0x05;
    571 	}
    572 	gdc[VGA_GFX_COMPARE_MASK] = 0x0F;
    573 	gdc[VGA_GFX_BIT_MASK] = 0xFF;
    574 
    575 	for (i = 0x00; i < 0x10; i++)
    576 		atc[i] = i;
    577 	if (par->mode & MODE_TEXT)
    578 		atc[VGA_ATC_MODE] = 0x04;
    579 	else if (par->mode & MODE_8BPP)
    580 		atc[VGA_ATC_MODE] = 0x41;
    581 	else
    582 		atc[VGA_ATC_MODE] = 0x81;
    583 	atc[VGA_ATC_OVERSCAN] = 0x00;	/* 0 for EGA, 0xFF for VGA */
    584 	atc[VGA_ATC_PLANE_ENABLE] = 0x0F;
    585 	if (par->mode & MODE_8BPP)
    586 		atc[VGA_ATC_PEL] = (info->var.xoffset & 3) << 1;
    587 	else
    588 		atc[VGA_ATC_PEL] = info->var.xoffset & 7;
    589 	atc[VGA_ATC_COLOR_PAGE] = 0x00;
    590 	
    591 	if (par->mode & MODE_TEXT) {
    592 		fh = 16; // FIXME !!! Fudge font height. 
    593 		par->crtc[VGA_CRTC_MAX_SCAN] = (par->crtc[VGA_CRTC_MAX_SCAN] 
    594 					       & ~0x1F) | (fh - 1);
    595 	}
    596 
    597 	vga_io_w(VGA_MIS_W, vga_io_r(VGA_MIS_R) | 0x01);
    598 
    599 	/* Enable graphics register modification */
    600 	if (!par->isVGA) {
    601 		vga_io_w(EGA_GFX_E0, 0x00);
    602 		vga_io_w(EGA_GFX_E1, 0x01);
    603 	}
    604 	
    605 	/* update misc output register */
    606 	vga_io_w(VGA_MIS_W, par->misc);
    607 	
    608 	/* synchronous reset on */
    609 	vga_io_wseq(0x00, 0x01);
    610 
    611 	if (par->isVGA)
    612 		vga_io_w(VGA_PEL_MSK, par->pel_msk);
    613 
    614 	/* write sequencer registers */
    615 	vga_io_wseq(VGA_SEQ_CLOCK_MODE, seq[VGA_SEQ_CLOCK_MODE] | 0x20);
    616 	for (i = 2; i < VGA_SEQ_C; i++) {
    617 		vga_io_wseq(i, seq[i]);
    618 	}
    619 	
    620 	/* synchronous reset off */
    621 	vga_io_wseq(0x00, 0x03);
    622 
    623 	/* deprotect CRT registers 0-7 */
    624 	vga_io_wcrt(VGA_CRTC_V_SYNC_END, par->crtc[VGA_CRTC_V_SYNC_END]);
    625 
    626 	/* write CRT registers */
    627 	for (i = 0; i < VGA_CRTC_REGS; i++) {
    628 		vga_io_wcrt(i, par->crtc[i]);
    629 	}
    630 	
    631 	/* write graphics controller registers */
    632 	for (i = 0; i < VGA_GFX_C; i++) {
    633 		vga_io_wgfx(i, gdc[i]);
    634 	}
    635 	
    636 	/* write attribute controller registers */
    637 	for (i = 0; i < VGA_ATT_C; i++) {
    638 		vga_io_r(VGA_IS1_RC);		/* reset flip-flop */
    639 		vga_io_wattr(i, atc[i]);
    640 	}
    641 
    642 	/* Wait for screen to stabilize. */
    643 	mdelay(50);
    644 
    645 	vga_io_wseq(VGA_SEQ_CLOCK_MODE, seq[VGA_SEQ_CLOCK_MODE]);
    646 
    647 	vga_io_r(VGA_IS1_RC);
    648 	vga_io_w(VGA_ATT_IW, 0x20);
    649 
    650 	vga16fb_update_fix(info);
    651 	return 0;
    652 }
    653 
    654 static void ega16_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
    655 {
    656 	static unsigned char map[] = { 000, 001, 010, 011 };
    657 	int val;
    658 	
    659 	if (regno >= 16)
    660 		return;
    661 	val = map[red>>14] | ((map[green>>14]) << 1) | ((map[blue>>14]) << 2);
    662 	vga_io_r(VGA_IS1_RC);   /* ! 0x3BA */
    663 	vga_io_wattr(regno, val);
    664 	vga_io_r(VGA_IS1_RC);   /* some clones need it */
    665 	vga_io_w(VGA_ATT_IW, 0x20); /* unblank screen */
    666 }
    667 
    668 static void vga16_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
    669 {
    670 	outb(regno,       dac_reg);
    671 	outb(red   >> 10, dac_val);
    672 	outb(green >> 10, dac_val);
    673 	outb(blue  >> 10, dac_val);
    674 }
    675 
    676 static int vga16fb_setcolreg(unsigned regno, unsigned red, unsigned green,
    677 			     unsigned blue, unsigned transp,
    678 			     struct fb_info *info)
    679 {
    680 	struct vga16fb_par *par = (struct vga16fb_par *) info->par;
    681 	int gray;
    682 
    683 	/*
    684 	 *  Set a single color register. The values supplied are
    685 	 *  already rounded down to the hardware's capabilities
    686 	 *  (according to the entries in the `var' structure). Return
    687 	 *  != 0 for invalid regno.
    688 	 */
    689 	
    690 	if (regno >= 256)
    691 		return 1;
    692 
    693 	gray = info->var.grayscale;
    694 	
    695 	if (gray) {
    696 		/* gray = 0.30*R + 0.59*G + 0.11*B */
    697 		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
    698 	}
    699 	if (par->isVGA) 
    700 		vga16_setpalette(regno,red,green,blue);
    701 	else
    702 		ega16_setpalette(regno,red,green,blue);
    703 	return 0;
    704 }
    705 
    706 static int vga16fb_pan_display(struct fb_var_screeninfo *var,
    707 			       struct fb_info *info) 
    708 {
    709 	if (var->xoffset + info->var.xres > info->var.xres_virtual ||
    710 	    var->yoffset + info->var.yres > info->var.yres_virtual)
    711 		return -EINVAL;
    712 
    713 	vga16fb_pan_var(info, var);
    714 
    715 	info->var.xoffset = var->xoffset;
    716 	info->var.yoffset = var->yoffset;
    717 	info->var.vmode &= ~FB_VMODE_YWRAP;
    718 	return 0;
    719 }
    720 
    721 /* The following VESA blanking code is taken from vgacon.c.  The VGA
    722    blanking code was originally by Huang shi chao, and modified by
    723    Christoph Rimek (chrimek@toppoint.de) and todd j. derr
    724    (tjd@barefoot.org) for Linux. */
    725 #define attrib_port		VGA_ATC_IW
    726 #define seq_port_reg		VGA_SEQ_I
    727 #define seq_port_val		VGA_SEQ_D
    728 #define gr_port_reg		VGA_GFX_I
    729 #define gr_port_val		VGA_GFX_D
    730 #define video_misc_rd		VGA_MIS_R
    731 #define video_misc_wr		VGA_MIS_W
    732 #define vga_video_port_reg	VGA_CRT_IC
    733 #define vga_video_port_val	VGA_CRT_DC
    734 
    735 static void vga_vesa_blank(struct vga16fb_par *par, int mode)
    736 {
    737 	unsigned char SeqCtrlIndex;
    738 	unsigned char CrtCtrlIndex;
    739 	
    740 	//cli();
    741 	SeqCtrlIndex = vga_io_r(seq_port_reg);
    742 	CrtCtrlIndex = vga_io_r(vga_video_port_reg);
    743 
    744 	/* save original values of VGA controller registers */
    745 	if(!par->vesa_blanked) {
    746 		par->vga_state.CrtMiscIO = vga_io_r(video_misc_rd);
    747 		//sti();
    748 
    749 		par->vga_state.HorizontalTotal = vga_io_rcrt(0x00);	/* HorizontalTotal */
    750 		par->vga_state.HorizDisplayEnd = vga_io_rcrt(0x01);	/* HorizDisplayEnd */
    751 		par->vga_state.StartHorizRetrace = vga_io_rcrt(0x04);	/* StartHorizRetrace */
    752 		par->vga_state.EndHorizRetrace = vga_io_rcrt(0x05);	/* EndHorizRetrace */
    753 		par->vga_state.Overflow = vga_io_rcrt(0x07);		/* Overflow */
    754 		par->vga_state.StartVertRetrace = vga_io_rcrt(0x10);	/* StartVertRetrace */
    755 		par->vga_state.EndVertRetrace = vga_io_rcrt(0x11);	/* EndVertRetrace */
    756 		par->vga_state.ModeControl = vga_io_rcrt(0x17);	/* ModeControl */
    757 		par->vga_state.ClockingMode = vga_io_rseq(0x01);	/* ClockingMode */
    758 	}
    759 
    760 	/* assure that video is enabled */
    761 	/* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
    762 	//cli();
    763 	vga_io_wseq(0x01, par->vga_state.ClockingMode | 0x20);
    764 
    765 	/* test for vertical retrace in process.... */
    766 	if ((par->vga_state.CrtMiscIO & 0x80) == 0x80)
    767 		vga_io_w(video_misc_wr, par->vga_state.CrtMiscIO & 0xef);
    768 
    769 	/*
    770 	 * Set <End of vertical retrace> to minimum (0) and
    771 	 * <Start of vertical Retrace> to maximum (incl. overflow)
    772 	 * Result: turn off vertical sync (VSync) pulse.
    773 	 */
    774 	if (mode & VESA_VSYNC_SUSPEND) {
    775 		outb_p(0x10,vga_video_port_reg);	/* StartVertRetrace */
    776 		outb_p(0xff,vga_video_port_val); 	/* maximum value */
    777 		outb_p(0x11,vga_video_port_reg);	/* EndVertRetrace */
    778 		outb_p(0x40,vga_video_port_val);	/* minimum (bits 0..3)  */
    779 		outb_p(0x07,vga_video_port_reg);	/* Overflow */
    780 		outb_p(par->vga_state.Overflow | 0x84,vga_video_port_val); /* bits 9,10 of vert. retrace */
    781 	}
    782 
    783 	if (mode & VESA_HSYNC_SUSPEND) {
    784 		/*
    785 		 * Set <End of horizontal retrace> to minimum (0) and
    786 		 *  <Start of horizontal Retrace> to maximum
    787 		 * Result: turn off horizontal sync (HSync) pulse.
    788 		 */
    789 		outb_p(0x04,vga_video_port_reg);	/* StartHorizRetrace */
    790 		outb_p(0xff,vga_video_port_val);	/* maximum */
    791 		outb_p(0x05,vga_video_port_reg);	/* EndHorizRetrace */
    792 		outb_p(0x00,vga_video_port_val);	/* minimum (0) */
    793 	}
    794 
    795 	/* restore both index registers */
    796 	outb_p(SeqCtrlIndex,seq_port_reg);
    797 	outb_p(CrtCtrlIndex,vga_video_port_reg);
    798 	//sti();
    799 }
    800 
    801 static void vga_vesa_unblank(struct vga16fb_par *par)
    802 {
    803 	unsigned char SeqCtrlIndex;
    804 	unsigned char CrtCtrlIndex;
    805 	
    806 	//cli();
    807 	SeqCtrlIndex = vga_io_r(seq_port_reg);
    808 	CrtCtrlIndex = vga_io_r(vga_video_port_reg);
    809 
    810 	/* restore original values of VGA controller registers */
    811 	vga_io_w(video_misc_wr, par->vga_state.CrtMiscIO);
    812 
    813 	/* HorizontalTotal */
    814 	vga_io_wcrt(0x00, par->vga_state.HorizontalTotal);
    815 	/* HorizDisplayEnd */
    816 	vga_io_wcrt(0x01, par->vga_state.HorizDisplayEnd);
    817 	/* StartHorizRetrace */
    818 	vga_io_wcrt(0x04, par->vga_state.StartHorizRetrace);
    819 	/* EndHorizRetrace */
    820 	vga_io_wcrt(0x05, par->vga_state.EndHorizRetrace);
    821 	/* Overflow */
    822 	vga_io_wcrt(0x07, par->vga_state.Overflow);
    823 	/* StartVertRetrace */
    824 	vga_io_wcrt(0x10, par->vga_state.StartVertRetrace);
    825 	/* EndVertRetrace */
    826 	vga_io_wcrt(0x11, par->vga_state.EndVertRetrace);
    827 	/* ModeControl */
    828 	vga_io_wcrt(0x17, par->vga_state.ModeControl);
    829 	/* ClockingMode */
    830 	vga_io_wseq(0x01, par->vga_state.ClockingMode);
    831 
    832 	/* restore index/control registers */
    833 	vga_io_w(seq_port_reg, SeqCtrlIndex);
    834 	vga_io_w(vga_video_port_reg, CrtCtrlIndex);
    835 	//sti();
    836 }
    837 
    838 static void vga_pal_blank(void)
    839 {
    840 	int i;
    841 
    842 	for (i=0; i<16; i++) {
    843 		outb_p (i, dac_reg) ;
    844 		outb_p (0, dac_val) ;
    845 		outb_p (0, dac_val) ;
    846 		outb_p (0, dac_val) ;
    847 	}
    848 }
    849 
    850 /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
    851 static int vga16fb_blank(int blank, struct fb_info *info)
    852 {
    853 	struct vga16fb_par *par = (struct vga16fb_par *) info->par;
    854 
    855 	switch (blank) {
    856 	case 0:				/* Unblank */
    857 		if (par->vesa_blanked) {
    858 			vga_vesa_unblank(par);
    859 			par->vesa_blanked = 0;
    860 		}
    861 		if (par->palette_blanked) {
    862 			//do_install_cmap(info->currcon, info);
    863 			par->palette_blanked = 0;
    864 		}
    865 		break;
    866 	case 1:				/* blank */
    867 		vga_pal_blank();
    868 		par->palette_blanked = 1;
    869 		break;
    870 	default:			/* VESA blanking */
    871 		vga_vesa_blank(par, blank-1);
    872 		par->vesa_blanked = 1;
    873 		break;
    874 	}
    875 	return 0;
    876 }
    877 
    878 void vga_8planes_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
    879 {
    880 	u32 dx = rect->dx, width = rect->width;
    881         char oldindex = getindex();
    882         char oldmode = setmode(0x40);
    883         char oldmask = selectmask();
    884         int line_ofs, height;
    885         char oldop, oldsr;
    886         char *where;
    887 
    888         dx /= 4;
    889         where = info->screen_base + dx + rect->dy * info->fix.line_length;
    890 
    891         if (rect->rop == ROP_COPY) {
    892                 oldop = setop(0);
    893                 oldsr = setsr(0);
    894 
    895                 width /= 4;
    896                 line_ofs = info->fix.line_length - width;
    897                 setmask(0xff);
    898 
    899                 height = rect->height;
    900 
    901                 while (height--) {
    902                         int x;
    903 
    904                         /* we can do memset... */
    905                         for (x = width; x > 0; --x) {
    906                                 writeb(rect->color, where);
    907                                 where++;
    908                         }
    909                         where += line_ofs;
    910                 }
    911         } else {
    912                 char oldcolor = setcolor(0xf);
    913                 int y;
    914 
    915                 oldop = setop(0x18);
    916                 oldsr = setsr(0xf);
    917                 setmask(0x0F);
    918                 for (y = 0; y < rect->height; y++) {
    919                         rmw(where);
    920                         rmw(where+1);
    921                         where += info->fix.line_length;
    922                 }
    923                 setcolor(oldcolor);
    924         }
    925         setmask(oldmask);
    926         setsr(oldsr);
    927         setop(oldop);
    928         setmode(oldmode);
    929         setindex(oldindex);
    930 }
    931 
    932 void vga16fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
    933 {
    934 	int x, x2, y2, vxres, vyres, width, height, line_ofs;
    935 	char *dst;
    936 
    937 	vxres = info->var.xres_virtual;
    938 	vyres = info->var.yres_virtual;
    939 
    940 	if (!rect->width || !rect->height || rect->dx > vxres || rect->dy > vyres)
    941 		return;
    942 
    943 	/* We could use hardware clipping but on many cards you get around
    944 	 * hardware clipping by writing to framebuffer directly. */
    945 
    946 	x2 = rect->dx + rect->width;
    947 	y2 = rect->dy + rect->height;
    948 	x2 = x2 < vxres ? x2 : vxres;
    949 	y2 = y2 < vyres ? y2 : vyres;
    950 	width = x2 - rect->dx;
    951 
    952 	switch (info->fix.type) {
    953 	case FB_TYPE_VGA_PLANES:
    954 		if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) {
    955 
    956 			height = y2 - rect->dy;
    957 			width = rect->width/8;
    958 
    959 			line_ofs = info->fix.line_length - width;
    960 			dst = info->screen_base + (rect->dx/8) + rect->dy * info->fix.line_length;
    961 
    962 			switch (rect->rop) {
    963 			case ROP_COPY:
    964 				setmode(0);
    965 				setop(0);
    966 				setsr(0xf);
    967 				setcolor(rect->color);
    968 				selectmask();
    969 
    970 				setmask(0xff);
    971 
    972 				while (height--) {
    973 					for (x = 0; x < width; x++) {
    974 						writeb(0, dst);
    975 						dst++;
    976 					}
    977 					dst += line_ofs;
    978 				}
    979 				break;
    980 			case ROP_XOR:
    981 				setmode(0);
    982 				setop(0x18);
    983 				setsr(0xf);
    984 				setcolor(0xf);
    985 				selectmask();
    986 
    987 				setmask(0xff);
    988 				while (height--) {
    989 					for (x = 0; x < width; x++) {
    990 						rmw(dst);
    991 						dst++;
    992 					}
    993 					dst += line_ofs;
    994 				}
    995 				break;
    996 			}
    997 		} else 
    998 			vga_8planes_fillrect(info, rect);
    999 		break;
   1000 	case FB_TYPE_PACKED_PIXELS:
   1001 	default:
   1002 		cfb_fillrect(info, rect);
   1003 		break;
   1004 	}
   1005 }
   1006 
   1007 void vga_8planes_copyarea(struct fb_info *info, const struct fb_copyarea *area)
   1008 {
   1009         char oldindex = getindex();
   1010         char oldmode = setmode(0x41);
   1011         char oldop = setop(0);
   1012         char oldsr = setsr(0xf);
   1013         int height, line_ofs, x;
   1014 	u32 sx, dx, width;
   1015 	char *dest, *src;
   1016 
   1017         height = area->height;
   1018 
   1019         sx = area->sx / 4;
   1020         dx = area->dx / 4;
   1021         width = area->width / 4;
   1022 
   1023         if (area->dy < area->sy || (area->dy == area->sy && dx < sx)) {
   1024                 line_ofs = info->fix.line_length - width;
   1025                 dest = info->screen_base + dx + area->dy * info->fix.line_length;
   1026                 src = info->screen_base + sx + area->sy * info->fix.line_length;
   1027                 while (height--) {
   1028                         for (x = 0; x < width; x++) {
   1029                                 readb(src);
   1030                                 writeb(0, dest);
   1031                                 src++;
   1032                                 dest++;
   1033                         }
   1034                         src += line_ofs;
   1035                         dest += line_ofs;
   1036                 }
   1037         } else {
   1038                 line_ofs = info->fix.line_length - width;
   1039                 dest = info->screen_base + dx + width +
   1040 			(area->dy + height - 1) * info->fix.line_length;
   1041                 src = info->screen_base + sx + width +
   1042 			(area->sy + height - 1) * info->fix.line_length;
   1043                 while (height--) {
   1044                         for (x = 0; x < width; x++) {
   1045                                 --src;
   1046                                 --dest;
   1047                                 readb(src);
   1048                                 writeb(0, dest);
   1049                         }
   1050                         src -= line_ofs;
   1051                         dest -= line_ofs;
   1052                 }
   1053         }
   1054 
   1055         setsr(oldsr);
   1056         setop(oldop);
   1057         setmode(oldmode);
   1058         setindex(oldindex);
   1059 }
   1060 
   1061 void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
   1062 {
   1063 	u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy; 
   1064 	int x, x2, y2, old_dx, old_dy, vxres, vyres;
   1065 	int height, width, line_ofs;
   1066 	char *dst = NULL, *src = NULL;
   1067 
   1068 	vxres = info->var.xres_virtual;
   1069 	vyres = info->var.yres_virtual;
   1070 
   1071 	if (area->dx > vxres || area->sx > vxres || area->dy > vyres ||
   1072 	    area->sy > vyres)
   1073 		return;
   1074 
   1075 	/* clip the destination */
   1076 	old_dx = area->dx;
   1077 	old_dy = area->dy;
   1078 
   1079 	/*
   1080 	 * We could use hardware clipping but on many cards you get around
   1081 	 * hardware clipping by writing to framebuffer directly.
   1082 	 */
   1083 	x2 = area->dx + area->width;
   1084 	y2 = area->dy + area->height;
   1085 	dx = area->dx > 0 ? area->dx : 0;
   1086 	dy = area->dy > 0 ? area->dy : 0;
   1087 	x2 = x2 < vxres ? x2 : vxres;
   1088 	y2 = y2 < vyres ? y2 : vyres;
   1089 	width = x2 - dx;
   1090 	height = y2 - dy;
   1091 
   1092 	/* update sx1,sy1 */
   1093 	sx += (dx - old_dx);
   1094 	sy += (dy - old_dy);
   1095 
   1096 	/* the source must be completely inside the virtual screen */
   1097 	if (sx < 0 || sy < 0 || (sx + width) > vxres || (sy + height) > vyres)
   1098 		return;
   1099 
   1100 	switch (info->fix.type) {
   1101 	case FB_TYPE_VGA_PLANES:
   1102 		if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) {
   1103 			width = width/8;
   1104 			height = height;
   1105 			line_ofs = info->fix.line_length - width;
   1106 
   1107 			setmode(1);
   1108 			setop(0);
   1109 			setsr(0xf);
   1110 
   1111 			if (dy < sy || (dy == sy && dx < sx)) {
   1112 				dst = info->screen_base + (dx/8) + dy * info->fix.line_length;
   1113 				src = info->screen_base + (sx/8) + sy * info->fix.line_length;
   1114 				while (height--) {
   1115 					for (x = 0; x < width; x++) {
   1116 						readb(src);
   1117 						writeb(0, dst);
   1118 						dst++;
   1119 						src++;
   1120 					}
   1121 					src += line_ofs;
   1122 					dst += line_ofs;
   1123 				}
   1124 			} else {
   1125 				dst = info->screen_base + (dx/8) + width + 
   1126 					(dy + height - 1) * info->fix.line_length;
   1127 				src = info->screen_base + (sx/8) + width + 
   1128 					(sy + height  - 1) * info->fix.line_length;
   1129 				while (height--) {
   1130 					for (x = 0; x < width; x++) {
   1131 						dst--;
   1132 						src--;
   1133 						readb(src);
   1134 						writeb(0, dst);
   1135 					}
   1136 					src -= line_ofs;
   1137 					dst -= line_ofs;
   1138 				}
   1139 			}
   1140 		} else 
   1141 			vga_8planes_copyarea(info, area);
   1142 		break;
   1143 	case FB_TYPE_PACKED_PIXELS:
   1144 	default:
   1145 		cfb_copyarea(info, area);
   1146 		break;
   1147 	}
   1148 }
   1149 
   1150 #ifdef __LITTLE_ENDIAN
   1151 static unsigned int transl_l[] =
   1152 {0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF};
   1153 static unsigned int transl_h[] =
   1154 {0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00,
   1155  0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00};
   1156 #else
   1157 #ifdef __BIG_ENDIAN
   1158 static unsigned int transl_h[] =
   1159 {0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF};
   1160 static unsigned int transl_l[] =
   1161 {0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00,
   1162  0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00};
   1163 #else
   1164 #error "Only __BIG_ENDIAN and __LITTLE_ENDIAN are supported in vga-planes"
   1165 #endif
   1166 #endif
   1167 
   1168 void vga_8planes_imageblit(struct fb_info *info, const struct fb_image *image)
   1169 {
   1170         char oldindex = getindex();
   1171         char oldmode = setmode(0x40);
   1172         char oldop = setop(0);
   1173         char oldsr = setsr(0);
   1174         char oldmask = selectmask();
   1175         const char *cdat = image->data;
   1176 	u32 dx = image->dx;
   1177         char *where;
   1178         int y;
   1179 
   1180         dx /= 4;
   1181         where = info->screen_base + dx + image->dy * info->fix.line_length;
   1182 
   1183         setmask(0xff);
   1184         writeb(image->bg_color, where);
   1185         readb(where);
   1186         selectmask();
   1187         setmask(image->fg_color ^ image->bg_color);
   1188         setmode(0x42);
   1189         setop(0x18);
   1190         for (y = 0; y < image->height; y++, where += info->fix.line_length)
   1191                 writew(transl_h[cdat[y]&0xF] | transl_l[cdat[y] >> 4], where);
   1192         setmask(oldmask);
   1193         setsr(oldsr);
   1194         setop(oldop);
   1195         setmode(oldmode);
   1196         setindex(oldindex);
   1197 }
   1198 
   1199 void vga_imageblit_expand(struct fb_info *info, const struct fb_image *image)
   1200 {
   1201 	char *where = info->screen_base + (image->dx/8) + 
   1202 		image->dy * info->fix.line_length;
   1203 	struct vga16fb_par *par = (struct vga16fb_par *) info->par;
   1204 	char *cdat = (char *) image->data, *dst;
   1205 	int x, y;
   1206 
   1207 	switch (info->fix.type) {
   1208 	case FB_TYPE_VGA_PLANES:
   1209 		if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) {
   1210 			if (par->isVGA) {
   1211 				setmode(2);
   1212 				setop(0);
   1213 				setsr(0xf);
   1214 				setcolor(image->fg_color);
   1215 				selectmask();
   1216 				
   1217 				setmask(0xff);
   1218 				writeb(image->bg_color, where);
   1219 				rmb();
   1220 				readb(where); /* fill latches */
   1221 				setmode(3);
   1222 				wmb();
   1223 				for (y = 0; y < image->height; y++) {
   1224 					dst = where;
   1225 					for (x = image->width/8; x--;) 
   1226 						writeb(*cdat++, dst++);
   1227 					where += info->fix.line_length;
   1228 				}
   1229 				wmb();
   1230 			} else {
   1231 				setmode(0);
   1232 				setop(0);
   1233 				setsr(0xf);
   1234 				setcolor(image->bg_color);
   1235 				selectmask();
   1236 				
   1237 				setmask(0xff);
   1238 				for (y = 0; y < image->height; y++) {
   1239 					dst = where;
   1240 					for (x=image->width/8; x--;){
   1241 						rmw(dst);
   1242 						setcolor(image->fg_color);
   1243 						selectmask();
   1244 						if (*cdat) {
   1245 							setmask(*cdat++);
   1246 							rmw(dst++);
   1247 						}
   1248 					}
   1249 					where += info->fix.line_length;
   1250 				}
   1251 			}
   1252 		} else 
   1253 			vga_8planes_imageblit(info, image);
   1254 		break;
   1255 	case FB_TYPE_PACKED_PIXELS:
   1256 	default:
   1257 		cfb_imageblit(info, image);
   1258 		break;
   1259 	}
   1260 }
   1261 
   1262 void vga_imageblit_color(struct fb_info *info, const struct fb_image *image) 
   1263 {
   1264 	/*
   1265 	 * Draw logo 
   1266 	 */
   1267 	struct vga16fb_par *par = (struct vga16fb_par *) info->par;
   1268 	char *where = info->screen_base + image->dy * info->fix.line_length + 
   1269 		image->dx/8;
   1270 	const char *cdat = image->data, *dst;
   1271 	int x, y;
   1272 
   1273 	switch (info->fix.type) {
   1274 	case FB_TYPE_VGA_PLANES:
   1275 		if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4 &&
   1276 		    par->isVGA) {
   1277 			setsr(0xf);
   1278 			setop(0);
   1279 			setmode(0);
   1280 			
   1281 			for (y = 0; y < image->height; y++) {
   1282 				for (x = 0; x < image->width; x++) {
   1283 					dst = where + x/8;
   1284 
   1285 					setcolor(*cdat);
   1286 					selectmask();
   1287 					setmask(1 << (7 - (x % 8)));
   1288 					fb_readb(dst);
   1289 					fb_writeb(0, dst);
   1290 
   1291 					cdat++;
   1292 				}
   1293 				where += info->fix.line_length;
   1294 			}
   1295 		}
   1296 		break;
   1297 	case FB_TYPE_PACKED_PIXELS:
   1298 		cfb_imageblit(info, image);
   1299 		break;
   1300 	default:
   1301 		break;
   1302 	}
   1303 }
   1304 				
   1305 void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image)
   1306 {
   1307 	if (image->depth == 1)
   1308 		vga_imageblit_expand(info, image);
   1309 	else if (image->depth <= info->var.bits_per_pixel)
   1310 		vga_imageblit_color(info, image);
   1311 }
   1312 
   1313 #ifdef CONFIG_FB_UI
   1314 static void vga16fb_point (struct fb_info *info, short x, short y, u32 rgb)
   1315 {
   1316 }
   1317 static void vga16fb_hline (struct fb_info *info, short x0, short x1, short y, u32 rgb)
   1318 {
   1319 }
   1320 static void vga16fb_vline (struct fb_info *info, short x, short y0, short y1, u32 rgb)
   1321 {
   1322 }
   1323 static u32 vga16fb_read_point (struct fb_info *info, short x, short y)
   1324 {
   1325 }
   1326 static u32 vga16fb_putpixels_native (struct fb_info *info, short x, short y,
   1327         short n, unsigned char *src, char in_kernel)
   1328 {
   1329 }
   1330 static u32 vga16fb_getpixels_rgb (struct fb_info *info, short x, short y,
   1331         short n, unsigned char *src, char in_kernel)
   1332 {
   1333 }
   1334 static u32 vga16fb_putpixels_rgb (struct fb_info *info, short x, short y,
   1335         short n, unsigned char *src, char in_kernel)
   1336 {
   1337 }
   1338 static u32 vga16fb_putpixels_rgb3 (struct fb_info *info, short x, short y,
   1339         short n, unsigned char *src, char in_kernel)
   1340 {
   1341 }
   1342 static u32 vga16fb_copyarea2 (struct fb_info *info, short xsrc, short ysrc,
   1343         short w, short h, short xdest, short ydest)
   1344 {
   1345 }
   1346 #endif
   1347 
   1348 static struct fb_ops vga16fb_ops = {
   1349 	.owner		= THIS_MODULE,
   1350 	.fb_open        = vga16fb_open,
   1351 	.fb_release     = vga16fb_release,
   1352 	.fb_check_var	= vga16fb_check_var,
   1353 	.fb_set_par	= vga16fb_set_par,
   1354 	.fb_setcolreg 	= vga16fb_setcolreg,
   1355 	.fb_pan_display = vga16fb_pan_display,
   1356 	.fb_blank 	= vga16fb_blank,
   1357 	.fb_fillrect	= vga16fb_fillrect,
   1358 	.fb_copyarea	= vga16fb_copyarea,
   1359 	.fb_imageblit	= vga16fb_imageblit,
   1360 	.fb_cursor      = soft_cursor,
   1361 
   1362 #ifdef CONFIG_FB_UI
   1363         .fb_point       = vga16fb_point,
   1364         .fb_hline       = vga16fb_hline,
   1365         .fb_vline       = vga16fb_vline,
   1366         .fb_clear         = vga16fb_clear,
   1367         .fb_hline         = vga16fb_hline,
   1368         .fb_read_point    = vga16fb_read_point,
   1369         .fb_putpixels_native    = vga16fb_putpixels_native,
   1370         .fb_putpixels_rgb       = vga16fb_putpixels_rgb,
   1371         .fb_getpixels_rgb       = vga16fb_getpixels_rgb,
   1372         .fb_putpixels_rgb3      = vga16fb_putpixels_rgb3,
   1373         .fb_copyarea2 = vga16fb_copyarea2,
   1374 #endif
   1375 };
   1376 
   1377 
   1378 int vga16fb_setup(char *options)
   1379 {
   1380 	char *this_opt;
   1381 	
   1382 	if (!options || !*options)
   1383 		return 0;
   1384 	
   1385 	while ((this_opt = strsep(&options, ",")) != NULL) {
   1386 		if (!*this_opt) continue;
   1387 	}
   1388 	return 0;
   1389 }
   1390 
   1391 int __init vga16fb_init(void)
   1392 {
   1393 	int i;
   1394 	int ret;
   1395 #ifndef MODULE
   1396 	char *option = NULL;
   1397 
   1398 	if (fb_get_options("vga16fb", &option))
   1399 		return -ENODEV;
   1400 
   1401 	vga16fb_setup(option);
   1402 #endif
   1403 	printk(KERN_DEBUG "vga16fb: initializing\n");
   1404 
   1405 	/* XXX share VGA_FB_PHYS and I/O region with vgacon and others */
   1406 
   1407 	vga16fb.screen_base = (void *)VGA_MAP_MEM(VGA_FB_PHYS);
   1408 	if (!vga16fb.screen_base) {
   1409 		printk(KERN_ERR "vga16fb: unable to map device\n");
   1410 		ret = -ENOMEM;
   1411 		goto err_ioremap;
   1412 	}
   1413 	printk(KERN_INFO "vga16fb: mapped to 0x%p\n", vga16fb.screen_base);
   1414 
   1415 	vga16_par.isVGA = ORIG_VIDEO_ISVGA;
   1416 	vga16_par.palette_blanked = 0;
   1417 	vga16_par.vesa_blanked = 0;
   1418 
   1419 	i = vga16_par.isVGA? 6 : 2;
   1420 	
   1421 	vga16fb_defined.red.length   = i;
   1422 	vga16fb_defined.green.length = i;
   1423 	vga16fb_defined.blue.length  = i;	
   1424 
   1425 	/* name should not depend on EGA/VGA */
   1426 	vga16fb.fbops = &vga16fb_ops;
   1427 	vga16fb.var = vga16fb_defined;
   1428 	vga16fb.fix = vga16fb_fix;
   1429 	vga16fb.par = &vga16_par;
   1430 	vga16fb.flags = FBINFO_FLAG_DEFAULT |
   1431 		FBINFO_HWACCEL_YPAN;
   1432 
   1433 	i = (vga16fb_defined.bits_per_pixel == 8) ? 256 : 16;
   1434 	ret = fb_alloc_cmap(&vga16fb.cmap, i, 0);
   1435 	if (ret) {
   1436 		printk(KERN_ERR "vga16fb: unable to allocate colormap\n");
   1437 		ret = -ENOMEM;
   1438 		goto err_alloc_cmap;
   1439 	}
   1440 
   1441 	if (vga16fb_check_var(&vga16fb.var, &vga16fb)) {
   1442 		printk(KERN_ERR "vga16fb: unable to validate variable\n");
   1443 		ret = -EINVAL;
   1444 		goto err_check_var;
   1445 	}
   1446 
   1447 	vga16fb_update_fix(&vga16fb);
   1448 
   1449 	if (register_framebuffer(&vga16fb) < 0) {
   1450 		printk(KERN_ERR "vga16fb: unable to register framebuffer\n");
   1451 		ret = -EINVAL;
   1452 		goto err_check_var;
   1453 	}
   1454 
   1455 	printk(KERN_INFO "fb%d: %s frame buffer device\n",
   1456 	       vga16fb.node, vga16fb.fix.id);
   1457 
   1458 	return 0;
   1459 
   1460  err_check_var:
   1461 	fb_dealloc_cmap(&vga16fb.cmap);
   1462  err_alloc_cmap:
   1463 	iounmap(vga16fb.screen_base);
   1464  err_ioremap:
   1465 	return ret;
   1466 }
   1467 
   1468 static void __exit vga16fb_exit(void)
   1469 {
   1470     unregister_framebuffer(&vga16fb);
   1471     iounmap(vga16fb.screen_base);
   1472     fb_dealloc_cmap(&vga16fb.cmap);
   1473     /* XXX unshare VGA regions */
   1474 }
   1475 
   1476 #ifdef MODULE
   1477 MODULE_LICENSE("GPL");
   1478 #endif
   1479 module_init(vga16fb_init);
   1480 module_exit(vga16fb_exit);
   1481 
   1482 
   1483 /*
   1484  * Overrides for Emacs so that we follow Linus's tabbing style.
   1485  * ---------------------------------------------------------------------------
   1486  * Local variables:
   1487  * c-basic-offset: 8
   1488  * End:
   1489  */
   1490 

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.