Fixed inverted test that led to everything below the refresh box being
[AROS.git] / arch / all-native / hidd / vga.hidd / vgahw.c
blobd3da80104812304c459309ff3ea6092f0d975374
1 /*
2 Copyright © 1995-2012, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: VGA Inside...
6 Lang: English.
7 */
9 /*
10 NOTE: This file is mostly based on XFree86 vgaWH.c sources
13 /****************************************************************************************/
15 #include <proto/exec.h>
16 #include <oop/oop.h>
17 #include <string.h>
19 #include "vgahw.h"
20 #include "vgaclass.h"
21 #include "bitmap.h"
23 /****************************************************************************************/
25 #undef SysBase
26 #define SysBase (*(struct ExecBase **)4UL)
28 /****************************************************************************************/
30 #define min(a,b) ((a) < (b) ? (a) : (b))
31 #define max(a,b) ((a) > (b) ? (a) : (b))
33 /****************************************************************************************/
35 /* Default ANSI (PC's) palette */
37 unsigned char vgaANSIPalette[]=
39 0, 0, 0, 0, 0, 42, 0, 42, 0, 0, 42, 42,
40 42, 0, 0, 42, 0, 42, 42, 21, 0, 42, 42, 42,
41 21, 21, 21, 21, 21, 63, 21, 63, 21, 21, 63, 63,
42 63, 21, 21, 63, 21, 63, 63, 63, 21, 63, 63, 63,
43 0, 0, 0, 5, 5, 5, 8, 8, 8, 11, 11, 11,
44 14, 14, 14, 17, 17, 17, 20, 20, 20, 24, 24, 24,
45 28, 28, 28, 32, 32, 32, 36, 36, 36, 40, 40, 40,
46 45, 45, 45, 50, 50, 50, 56, 56, 56, 63, 63, 63,
47 0, 0, 63, 16, 0, 63, 31, 0, 63, 47, 0, 63,
48 63, 0, 63, 63, 0, 47, 63, 0, 31, 63, 0, 16,
49 63, 0, 0, 63, 16, 0, 63, 31, 0, 63, 47, 0,
50 63, 63, 0, 47, 63, 0, 31, 63, 0, 16, 63, 0,
51 0, 63, 0, 0, 63, 16, 0, 63, 31, 0, 63, 47,
52 0, 63, 63, 0, 47, 63, 0, 31, 63, 0, 16, 63,
53 31, 31, 63, 39, 31, 63, 47, 31, 63, 55, 31, 63,
54 63, 31, 63, 63, 31, 55, 63, 31, 47, 63, 31, 39,
55 63, 31, 31, 63, 39, 31, 63, 47, 31, 63, 55, 31,
56 63, 63, 31, 55, 63, 31, 47, 63, 31, 39, 63, 31,
57 31, 63, 31, 31, 63, 39, 31, 63, 47, 31, 63, 55,
58 31, 63, 63, 31, 55, 63, 31, 47, 63, 31, 39, 63,
59 45, 45, 63, 49, 45, 63, 54, 45, 63, 58, 45, 63,
60 63, 45, 63, 63, 45, 58, 63, 45, 54, 63, 45, 49,
61 63, 45, 45, 63, 49, 45, 63, 54, 45, 63, 58, 45,
62 63, 63, 45, 58, 63, 45, 54, 63, 45, 49, 63, 45,
63 45, 63, 45, 45, 63, 49, 45, 63, 54, 45, 63, 58,
64 45, 63, 63, 45, 58, 63, 45, 54, 63, 45, 49, 63,
65 0, 0, 28, 7, 0, 28, 14, 0, 28, 21, 0, 28,
66 28, 0, 28, 28, 0, 21, 28, 0, 14, 28, 0, 7,
67 28, 0, 0, 28, 7, 0, 28, 14, 0, 28, 21, 0,
68 28, 28, 0, 21, 28, 0, 14, 28, 0, 7, 28, 0,
69 0, 28, 0, 0, 28, 7, 0, 28, 14, 0, 28, 21,
70 0, 28, 28, 0, 21, 28, 0, 14, 28, 0, 7, 28,
71 14, 14, 28, 17, 14, 28, 21, 14, 28, 24, 14, 28,
72 28, 14, 28, 28, 14, 24, 28, 14, 21, 28, 14, 17,
73 28, 14, 14, 28, 17, 14, 28, 21, 14, 28, 24, 14,
74 28, 28, 14, 24, 28, 14, 21, 28, 14, 17, 28, 14,
75 14, 28, 14, 14, 28, 17, 14, 28, 21, 14, 28, 24,
76 14, 28, 28, 14, 24, 28, 14, 21, 28, 14, 17, 28,
77 20, 20, 28, 22, 20, 28, 24, 20, 28, 26, 20, 28,
78 28, 20, 28, 28, 20, 26, 28, 20, 24, 28, 20, 22,
79 28, 20, 20, 28, 22, 20, 28, 24, 20, 28, 26, 20,
80 28, 28, 20, 26, 28, 20, 24, 28, 20, 22, 28, 20,
81 20, 28, 20, 20, 28, 22, 20, 28, 24, 20, 28, 26,
82 20, 28, 28, 20, 26, 28, 20, 24, 28, 20, 22, 28,
83 0, 0, 16, 4, 0, 16, 8, 0, 16, 12, 0, 16,
84 16, 0, 16, 16, 0, 12, 16, 0, 8, 16, 0, 4,
85 16, 0, 0, 16, 4, 0, 16, 8, 0, 16, 12, 0,
86 16, 16, 0, 12, 16, 0, 8, 16, 0, 4, 16, 0,
87 0, 16, 0, 0, 16, 4, 0, 16, 8, 0, 16, 12,
88 0, 16, 16, 0, 12, 16, 0, 8, 16, 0, 4, 16,
89 8, 8, 16, 10, 8, 16, 12, 8, 16, 14, 8, 16,
90 16, 8, 16, 16, 8, 14, 16, 8, 12, 16, 8, 10,
91 16, 8, 8, 16, 10, 8, 16, 12, 8, 16, 14, 8,
92 16, 16, 8, 14, 16, 8, 12, 16, 8, 10, 16, 8,
93 8, 16, 8, 8, 16, 10, 8, 16, 12, 8, 16, 14,
94 8, 16, 16, 8, 14, 16, 8, 12, 16, 8, 10, 16,
95 11, 11, 16, 12, 11, 16, 13, 11, 16, 15, 11, 16,
96 16, 11, 16, 16, 11, 15, 16, 11, 13, 16, 11, 12,
97 16, 11, 11, 16, 12, 11, 16, 13, 11, 16, 15, 11,
98 16, 16, 11, 15, 16, 11, 13, 16, 11, 12, 16, 11,
99 11, 16, 11, 11, 16, 12, 11, 16, 13, 11, 16, 15,
100 11, 16, 16, 11, 15, 16, 11, 13, 16, 11, 12, 16,
101 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
102 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
105 /****************************************************************************************/
108 ** Load specified palette, if NULL load default
110 void vgaLoadPalette(struct vgaHWRec *regs, unsigned char *pal)
112 int i;
114 if (!pal)
115 pal = (unsigned char *)&vgaANSIPalette;
117 for (i=0; i<768; i++)
119 regs->DAC[i]=*(unsigned char*)pal++;
123 /****************************************************************************************/
125 #define SS_START 1
126 #define SS_FINISH 0
128 /****************************************************************************************/
131 ** vgaHWSaveScreen
132 ** perform a sequencer reset.
134 void vgaSaveScreen(int start)
136 if (start == SS_START)
138 outw(0x3C4, 0x0100); /* synchronous reset */
140 else
142 outw(0x3C4, 0x0300); /* end reset */
146 /****************************************************************************************/
149 ** Blank the screen.
151 int vgaBlankScreen(int on)
153 unsigned char scrn;
155 outb(0x3C4,1);
156 scrn = inb(0x3C5);
158 if(on)
160 scrn &= 0xDF; /* enable screen */
162 else
164 scrn |= 0x20; /* blank screen */
167 vgaSaveScreen(SS_START);
168 outw(0x3C4, (scrn << 8) | 0x01); /* change mode */
169 vgaSaveScreen(SS_FINISH);
171 return TRUE;
174 /****************************************************************************************/
176 #define vgaIOBase 0x3d0
178 /****************************************************************************************/
181 ** vgaDACLoad --
182 ** load the DAC
184 void vgaDACLoad(struct vgaHWRec *restore, unsigned char start, int num)
186 int i, n;
188 n = start * 3;
189 outb(0x3C8,start);
190 for (i=0; i<num*3; i++)
192 outb(0x3C9, restore->DAC[n++]);
193 /* DACDelay;
194 I beleive incrementing variables and checking cycle counter
195 provides enough delay. Uncomment this in case of problems */
200 ** vgaRestore --
201 ** restore a video mode
203 void vgaRestore(struct vgaHWRec *restore)
205 int i;
207 inb(vgaIOBase + 0x0A); /* Reset flip-flop */
208 outb(0x3C0, 0x00); /* Enables pallete access */
210 restore->MiscOutReg |= 0x01;
211 outb(0x3C2, restore->MiscOutReg);
213 for (i=1; i<5; i++) outw(0x3C4, (restore->Sequencer[i] << 8) | i);
215 /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 or CRTC[17] */
217 outw(vgaIOBase + 4, ((restore->CRTC[17] & 0x7F) << 8) | 17);
219 for (i=0; i<25; i++) outw(vgaIOBase + 4,(restore->CRTC[i] << 8) | i);
221 for (i=0; i<9; i++) outw(0x3CE, (restore->Graphics[i] << 8) | i);
223 for (i=0; i<21; i++) {
224 inb(vgaIOBase + 0x0A);
225 outb(0x3C0,i); outb(0x3C0, restore->Attribute[i]);
228 outb(0x3C6,0xFF);
230 vgaDACLoad(restore, 0, 256);
232 /* Turn on PAS bit */
233 inb(vgaIOBase + 0x0A);
234 outb(0x3C0, 0x20);
237 /****************************************************************************************/
240 ** Init VGA registers for given displaymode
242 int vgaInitMode(struct vgaModeDesc *mode, struct vgaHWRec *regs)
244 unsigned int i;
245 int hblankstart;
246 int hblankend;
247 int vblankstart;
248 int vblankend;
251 initialize default colormap for monochrome
253 for (i = 0; i < 3; i++) regs->DAC[i] = 0x00;
254 for (i = 3; i < 768; i++) regs->DAC[i] = 0x3F;
256 /* Initialise overscan register */
257 regs->Attribute[17] = 0xFF;
259 regs->NoClock = mode->clock;
262 compute correct Hsync & Vsync polarity
265 int VDisplay = mode->Height;
266 // if (mode->Flags & V_DBLSCAN)
267 // VDisplay *= 2;
268 if (VDisplay < 400)
269 regs->MiscOutReg = 0xA3; /* +hsync -vsync */
270 else if (VDisplay < 480)
271 regs->MiscOutReg = 0x63; /* -hsync +vsync */
272 else if (VDisplay < 768)
273 regs->MiscOutReg = 0xE3; /* -hsync -vsync 0xE3 */
274 else
275 regs->MiscOutReg = 0x23; /* +hsync +vsync */
278 regs->MiscOutReg |= (regs->NoClock & 0x03) << 2;
281 Time Sequencer
283 regs->Sequencer[0] = 0x02;
284 // if (mode->Flags & V_CLKDIV2) /* TODO */
285 // regs->Sequencer[1] = 0x09;
286 // else
287 regs->Sequencer[1] = 0x01;
289 regs->Sequencer[2] = 0x0F;
290 regs->Sequencer[3] = 0x00; /* Font select */
291 regs->Sequencer[4] = 0x06; /* Misc */
294 CRTC Controller
297 hblankstart = min(mode->HSyncStart, mode->HDisplay);
298 hblankend = max(mode->HSyncEnd, mode->HTotal);
299 if ((hblankend - hblankstart) >= 63 * 8)
301 hblankstart = hblankend - 63 * 8;
304 vblankstart = min(mode->VSyncStart, mode->VDisplay);
305 vblankend = max(mode->VSyncEnd, mode->VTotal);
306 if ((vblankend - vblankstart) >= 127)
308 vblankstart = vblankend - 127;
311 regs->CRTC[CRTC_H_TOTAL] = (mode->HTotal / 8) - 5;
312 regs->CRTC[CRTC_H_DISPLAY] = (mode->HDisplay / 8) - 1;
313 regs->CRTC[CRTC_H_BLANK_START] = (hblankstart / 8) -1;
314 regs->CRTC[CRTC_H_BLANK_END] = (((hblankend / 8) - 1) & 0x1F) | 0x80;
316 i = (((mode->HSkew << 2) + 0x10) & ~0x1F);
317 if (i < 0x80)
319 regs->CRTC[CRTC_H_BLANK_END] |= i;
322 regs->CRTC[CRTC_H_SYNC_START] = (mode->HSyncStart / 8);
323 regs->CRTC[CRTC_H_SYNC_END] = ((((hblankend / 8) - 1) & 0x20 ) << 2 ) |
324 (((mode->HSyncEnd / 8)) & 0x1F);
325 regs->CRTC[CRTC_V_TOTAL] = (mode->VTotal - 2) & 0xFF;
326 regs->CRTC[CRTC_OVERFLOW] = (((mode->VTotal -2) & 0x100) >> 8 ) |
327 (((mode->VDisplay -1) & 0x100) >> 7 ) |
328 ((mode->VSyncStart & 0x100) >> 6 ) |
329 (((vblankstart - 1) & 0x100) >> 5 ) |
330 0x10 |
331 (((mode->VTotal -2) & 0x200) >> 4 ) |
332 (((mode->VDisplay -1) & 0x200) >> 3 ) |
333 ((mode->VSyncStart & 0x200) >> 2 );
334 regs->CRTC[CRTC_PRESET_ROW] = 0x00;
335 regs->CRTC[CRTC_MAX_SCAN] = (((vblankstart - 1) & 0x200) >>4) | 0x40;
336 // if (mode->Flags & V_DBLSCAN)
337 // new->CRTC[9] |= 0x80;
338 regs->CRTC[CRTC_CURSOR_START] = 0x00;
339 regs->CRTC[CRTC_CURSOR_END] = 0x00;
340 regs->CRTC[CRTC_START_HI] = 0x00;
341 regs->CRTC[CRTC_START_LO] = 0x00;
342 regs->CRTC[CRTC_CURSOR_HI] = 0x00;
343 regs->CRTC[CRTC_CURSOR_LO] = 0x00;
344 regs->CRTC[CRTC_V_SYNC_START] = mode->VSyncStart & 0xFF;
345 regs->CRTC[CRTC_V_SYNC_END] = (mode->VSyncEnd & 0x0F) | 0x20;
346 regs->CRTC[CRTC_V_DISP_END] = (mode->VDisplay -1) & 0xFF;
347 regs->CRTC[CRTC_OFFSET] = mode->Width >> (8 - mode->Depth); /* just a guess */
348 regs->CRTC[CRTC_UNDERLINE] = 0x00;
349 regs->CRTC[CRTC_V_BLANK_START] = (vblankstart - 1) & 0xFF;
350 regs->CRTC[CRTC_V_BLANK_END] = (vblankend - 1) & 0xFF;
351 regs->CRTC[CRTC_MODE] = 0xE3;
352 regs->CRTC[CRTC_LINE_COMPARE] = 0xFF;
354 if ((hblankend / 8) == (mode->HTotal / 8))
356 i = (regs->CRTC[CRTC_H_BLANK_END] & 0x1f) | ((regs->CRTC[CRTC_H_SYNC_END] & 0x80) >> 2);
357 if ((i-- > (regs->CRTC[CRTC_H_BLANK_START] & 0x3F)) &&
358 (hblankend == mode->HTotal))
360 i = 0;
363 regs->CRTC[CRTC_H_BLANK_END] = (regs->CRTC[CRTC_H_BLANK_END] & ~0x1F) | (i & 0x1f);
364 regs->CRTC[CRTC_H_SYNC_END] = (regs->CRTC[CRTC_H_SYNC_END] & ~0x80) | ((i << 2) & 0x80);
367 if (vblankend == mode->VTotal)
369 i = regs->CRTC[CRTC_V_BLANK_END];
370 if ((i > regs->CRTC[CRTC_V_BLANK_START]) &&
371 ((i & 0x7F) > (regs->CRTC[CRTC_V_BLANK_START] & 0x7F)) &&
372 !(regs->CRTC[CRTC_MAX_SCAN] & 0x9f))
374 i = 0;
376 else
378 i = (UBYTE)(i - 1);
380 regs->CRTC[CRTC_V_BLANK_END] = i;
384 Graphics Display Controller
386 regs->Graphics[0] = 0x00;
387 regs->Graphics[1] = 0x00;
388 regs->Graphics[2] = 0x00;
389 regs->Graphics[3] = 0x00;
390 regs->Graphics[4] = 0x00;
391 regs->Graphics[5] = 0x00;
392 regs->Graphics[6] = 0x05; /* only map 64k VGA memory !!!! */
393 regs->Graphics[7] = 0x0F;
394 regs->Graphics[8] = 0xFF;
396 regs->Attribute[0] = 0x00; /* standard colormap translation */
397 regs->Attribute[1] = 0x01;
398 regs->Attribute[2] = 0x02;
399 regs->Attribute[3] = 0x03;
400 regs->Attribute[4] = 0x04;
401 regs->Attribute[5] = 0x05;
402 regs->Attribute[6] = 0x06;
403 regs->Attribute[7] = 0x07;
404 regs->Attribute[8] = 0x08;
405 regs->Attribute[9] = 0x09;
406 regs->Attribute[10] = 0x0A;
407 regs->Attribute[11] = 0x0B;
408 regs->Attribute[12] = 0x0C;
409 regs->Attribute[13] = 0x0D;
410 regs->Attribute[14] = 0x0E;
411 regs->Attribute[15] = 0x0F;
412 regs->Attribute[16] = 0x81; /* wrong for the ET4000 */
413 regs->Attribute[17] = 0x00; /* GJA -- overscan. */
415 Attribute[17] is the overscan, and is initialised above only at startup
416 time, and not when mode switching.
418 regs->Attribute[18] = 0x0F;
419 regs->Attribute[19] = 0x00;
420 regs->Attribute[20] = 0x00;
422 return TRUE;
425 /****************************************************************************************/
427 void vgaRefreshPixel(struct bitmap_data *data, unsigned int x, unsigned int y)
429 int pix;
430 char *ptr, *ptr2;
431 UWORD fg;
432 unsigned int srcx = x - data->xoffset;
433 unsigned int srcy = y - data->yoffset;
435 ptr = (char *)(data->VideoData + srcx + (srcy * data->bpr));
436 fg = *ptr;
437 ptr2 = (char *)(IPTR)(0xa0000 + (x + (y * data->disp_width)) / 8);
438 pix = 0x8000 >> (x % 8);
440 outw(0x3c4,0x0f02);
441 outw(0x3ce,pix | 8);
442 outw(0x3ce,0x0005);
443 outw(0x3ce,0x0003);
444 outw(0x3ce,(fg << 8));
445 outw(0x3ce,0x0f01);
447 *ptr2 |= 1; // This or'ed value isn't important
450 /****************************************************************************************/
452 void vgaRefreshArea(struct bitmap_data *bmap, struct Box *pbox)
454 int width, height, FBPitch, left, right, i, j, SRCPitch, phase;
455 register ULONG m;
456 unsigned char s1, s2, s3, s4;
457 ULONG *src, *srcPtr;
458 unsigned char *dst, *dstPtr;
459 unsigned int srcx, srcy;
461 /* In 640x480x16 mode VRAM data has planar layout. All 4 bitplanes share
462 the same addresses, we use sequencer register in order to select
463 which plane to write to.
464 is very weird: we have LONGs in which first bytes contain bits 0 of
465 eight pixels, second bytes contain bits 1, third - bits 2 and fourth
466 - bits 3. Despite being planar, this is totally different to Amiga
467 native planar format.
468 Our pixelbuffer always has a simple chunky format, so we perform a
469 4-step chunky to planar conversion. In order to select VRAM bitplanes
470 we use a sequencer's plane select register */
472 /* Start and end coordinates of our box have to be on byte border */
473 left = pbox->x1 & ~7; /* Round down left (start) coordinate */
474 right = (pbox->x2 & ~7) + 7; /* Round up right (end) coordinate */
476 /* Check if refresh region is completely beyond physical display limits.
477 If so, do nothing */
478 if ((left >= bmap->disp_width) || (pbox->y1 >= bmap->disp_height))
479 return;
480 /* Now adjust bottom-right corner */
481 if (right >= bmap->disp_width)
482 right = bmap->disp_width - 1;
483 if (pbox->y2 <= bmap->disp_height)
484 height = pbox->y2 - pbox->y1 + 1;
485 else
486 height = bmap->disp_height - pbox->y1;
488 /* We don't check top-left corner of the display.
489 We assume that refresh region will never have negative
490 coordinates. Also we assume that the entire screen is
491 covered with the bitmap (i.e. bitmap is not smaller than
492 physical display area and is not moved out of the view.
493 We could implement this, but we trade this off for speed */
495 FBPitch = bmap->disp_width >> 3; /* UBYTEs per line for VRAM */
496 SRCPitch = bmap->bpr >> 2; /* ULONGs per line for pixelbuffer */
498 /* Disable data preprocessing in graphics controller */
499 outw(0x3ce, 0x0005); /* MDR = 0 (direct write) */
500 outw(0x3ce, 0x0001); /* Disable Set/Reset operation */
501 outw(0x3ce, 0x0000); /* Set/Reset data = 0 */
502 outw(0x3ce, 0x0003); /* RFSR = 0 (no shift, no modify) */
503 outw(0x3ce, 0xff08); /* Bit mask = 0xFF (all bits from CPU) */
505 width = (right - left + 1) >> 3; /* Width of destination box in UBYTEs */
506 /* Calculate start addresses in the pixelbuffer and VRAM */
507 srcx = left - bmap->xoffset;
508 srcy = pbox->y1 - bmap->yoffset;
509 /* src is not ULONG-aligned here */
510 src = (ULONG *)(bmap->VideoData + srcx) + srcy * SRCPitch;
511 dst = (unsigned char*)0x000a0000 + (pbox->y1 * FBPitch) + (left >> 3);
513 /* In order to speedup we operate on LONGs. However since our start
514 coordinate may be not LONG-aligned, we probably have to copy
515 some BYTEs before we reach LONG border. phase is a number
516 of these bytes */
517 phase = (IPTR)dst & 3L;
518 if (phase) {
519 phase = 4 - phase;
520 if(phase > width) phase = width;
521 width -= phase;
524 while(height--) /* For each line */
526 outw(0x3c4, 0x0102); /* Enable write to plane 0 */
527 dstPtr = dst; /* Take start pointers */
528 srcPtr = src;
529 i = width;
530 j = phase;
532 while(j--)
534 /* Take bits 0 of the 8 pixels and combine them
535 (0B0B0B0B and 0A0A0A0A become BABABABA).
536 We take 8 pixels from source buffer because in one VRAM
537 plane one byte holds 8 bits for 8 different pixels.
538 After this we will get the following:
540 pixel 3 7 2 6 1 5 0 4
541 m 76543210 76543210 76543210 76543210
543 where bottom line is bitstring stored in m and top line
544 contains numbers of pixels these bits came from. Other
545 bits will be 0 (since we masked them out)
547 m = (srcPtr[1] & 0x01010101) | ((srcPtr[0] & 0x01010101) << 4);
548 /* And here we recombine the data into single byte and write
549 them into VRAM. Result of these shift-or operations is:
551 pixel 01234567
552 value 76543210
554 again, bottom line is bit number and top one is pixel number
556 *dstPtr++ = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3);
557 srcPtr += 2;
560 while(i >= 4) {
561 m = (srcPtr[1] & 0x01010101) | ((srcPtr[0] & 0x01010101) << 4);
562 s1 = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3);
563 m = (srcPtr[3] & 0x01010101) | ((srcPtr[2] & 0x01010101) << 4);
564 s2 = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3);
565 m = (srcPtr[5] & 0x01010101) | ((srcPtr[4] & 0x01010101) << 4);
566 s3 = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3);
567 m = (srcPtr[7] & 0x01010101) | ((srcPtr[6] & 0x01010101) << 4);
568 s4 = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3);
569 *((ULONG*)dstPtr) = s1 | (s2 << 8) | (s3 << 16) | (s4 << 24);
570 srcPtr += 8;
571 dstPtr += 4;
572 i -= 4;
575 while(i--) {
576 m = (srcPtr[1] & 0x01010101) | ((srcPtr[0] & 0x01010101) << 4);
577 *dstPtr++ = (m >> 24) | (m >> 15) | (m >> 6) | (m << 3);
578 srcPtr += 2;
581 outw(0x3c4, 0x0202); /* Enable write to plane 1 */
582 dstPtr = dst;
583 srcPtr = src;
584 i = width;
585 j = phase;
587 while(j--) {
588 m = (srcPtr[1] & 0x02020202) | ((srcPtr[0] & 0x02020202) << 4);
589 *dstPtr++ = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2);
590 srcPtr += 2;
593 while(i >= 4) {
594 m = (srcPtr[1] & 0x02020202) | ((srcPtr[0] & 0x02020202) << 4);
595 s1 = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2);
596 m = (srcPtr[3] & 0x02020202) | ((srcPtr[2] & 0x02020202) << 4);
597 s2 = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2);
598 m = (srcPtr[5] & 0x02020202) | ((srcPtr[4] & 0x02020202) << 4);
599 s3 = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2);
600 m = (srcPtr[7] & 0x02020202) | ((srcPtr[6] & 0x02020202) << 4);
601 s4 = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2);
602 *((ULONG*)dstPtr) = s1 | (s2 << 8) | (s3 << 16) | (s4 << 24);
603 srcPtr += 8;
604 dstPtr += 4;
605 i -= 4;
608 while(i--) {
609 m = (srcPtr[1] & 0x02020202) | ((srcPtr[0] & 0x02020202) << 4);
610 *dstPtr++ = (m >> 25) | (m >> 16) | (m >> 7) | (m << 2);
611 srcPtr += 2;
614 outw(0x3c4, 0x0402); /* Enable write to plane 2 */
615 dstPtr = dst;
616 srcPtr = src;
617 i = width;
618 j = phase;
620 while(j--) {
621 m = (srcPtr[1] & 0x04040404) | ((srcPtr[0] & 0x04040404) << 4);
622 *dstPtr++ = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1);
623 srcPtr += 2;
626 while(i >= 4) {
627 m = (srcPtr[1] & 0x04040404) | ((srcPtr[0] & 0x04040404) << 4);
628 s1 = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1);
629 m = (srcPtr[3] & 0x04040404) | ((srcPtr[2] & 0x04040404) << 4);
630 s2 = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1);
631 m = (srcPtr[5] & 0x04040404) | ((srcPtr[4] & 0x04040404) << 4);
632 s3 = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1);
633 m = (srcPtr[7] & 0x04040404) | ((srcPtr[6] & 0x04040404) << 4);
634 s4 = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1);
635 *((ULONG*)dstPtr) = s1 | (s2 << 8) | (s3 << 16) | (s4 << 24);
636 srcPtr += 8;
637 dstPtr += 4;
638 i -= 4;
641 while(i--) {
642 m = (srcPtr[1] & 0x04040404) | ((srcPtr[0] & 0x04040404) << 4);
643 *dstPtr++ = (m >> 26) | (m >> 17) | (m >> 8) | (m << 1);
644 srcPtr += 2;
647 outw(0x3c4, 0x0802); /* Enable write to plane 3 */
648 dstPtr = dst;
649 srcPtr = src;
650 i = width;
651 j = phase;
653 while(j--) {
654 m = (srcPtr[1] & 0x08080808) | ((srcPtr[0] & 0x08080808) << 4);
655 *dstPtr++ = (m >> 27) | (m >> 18) | (m >> 9) | m;
656 srcPtr += 2;
659 while(i >= 4) {
660 m = (srcPtr[1] & 0x08080808) | ((srcPtr[0] & 0x08080808) << 4);
661 s1 = (m >> 27) | (m >> 18) | (m >> 9) | m;
662 m = (srcPtr[3] & 0x08080808) | ((srcPtr[2] & 0x08080808) << 4);
663 s2 = (m >> 27) | (m >> 18) | (m >> 9) | m;
664 m = (srcPtr[5] & 0x08080808) | ((srcPtr[4] & 0x08080808) << 4);
665 s3 = (m >> 27) | (m >> 18) | (m >> 9) | m;
666 m = (srcPtr[7] & 0x08080808) | ((srcPtr[6] & 0x08080808) << 4);
667 s4 = (m >> 27) | (m >> 18) | (m >> 9) | m;
668 *((ULONG*)dstPtr) = s1 | (s2 << 8) | (s3 << 16) | (s4 << 24);
669 srcPtr += 8;
670 dstPtr += 4;
671 i -= 4;
674 while(i--) {
675 m = (srcPtr[1] & 0x08080808) | ((srcPtr[0] & 0x08080808) << 4);
676 *dstPtr++ = (m >> 27) | (m >> 18) | (m >> 9) | m;
677 srcPtr += 2;
680 dst += FBPitch;
681 src += SRCPitch;
683 } /* while(height--) */
686 /****************************************************************************************/
688 void vgaEraseArea(struct bitmap_data *bmap, struct Box *pbox)
690 int width, height, FBPitch, left, right;
691 unsigned char *dst;
693 FBPitch = bmap->disp_width >> 3; /* UBYTEs per line for VRAM */
695 /* Disable data preprocessing in graphics controller */
696 outw(0x3ce, 0x0005); /* MDR = 0 (direct write) */
697 outw(0x3ce, 0x0001); /* Disable Set/Reset operation */
698 outw(0x3ce, 0x0000); /* Set/Reset data = 0 */
699 outw(0x3ce, 0x0003); /* RFSR = 0 (no shift, no modify) */
700 outw(0x3ce, 0xff08); /* Bit mask = 0xFF (all bits from CPU) */
702 /* Start and end coordinates of our box have to be on byte border */
703 left = (pbox->x1 & ~7) + 7; /* Round up left (start) coordinate */
704 right = (pbox->x2 & ~7) + 7; /* Round up right (end) coordinate */
705 width = (right - left + 1) >> 3; /* Width of destination box in UBYTEs */
706 height = pbox->y2 - pbox->y1 + 1;
707 dst = (unsigned char*)0x000a0000 + (pbox->y1 * FBPitch) + (left >> 3);
709 outw(0x3c4, 0x0F02); /* Enable write to all planes */
711 while(height--) /* For each line */
713 memset(dst, 0, width);
714 dst += FBPitch;
715 } /* while(height--) */
718 /****************************************************************************************/