2 * Copyright (c) 1999, 2000, 2002 Greg Haerr <greg@censoft.com>
4 * 16 color 4 planes EGA/VGA Planar Video Driver for Microwindows
7 * Based on BOGL - Ben's Own Graphics Library.
8 * Written by Ben Pfaff <pfaffben@debian.org>.
9 * BOGL is licensed under the terms of the GNU General Public License
11 * In this driver, psd->linelen is line byte length, not line pixel length
13 * This file is meant to compile under Linux, ELKS, and MSDOS
14 * without changes. Please try to keep it that way.
19 #include <ibm/portio.h>
26 #if MSDOS | ELKS | __rtems__ | __ECOS
27 /* assumptions for speed: NOTE: psd is ignored in these routines*/
28 #define SCREENBASE EGA_BASE
29 #define BYTESPERLINE 80
31 /* run on top of framebuffer*/
32 #define SCREENBASE ((char *)psd->addr)
33 #define BYTESPERLINE (psd->linelen)
36 /* Values for the data rotate register to implement drawing modes. */
37 static unsigned char mode_table[MWMODE_MAX + 1] = {
38 0x00, 0x18, 0x10, 0x08, /* COPY, XOR, AND, OR implemented*/
39 0x00, 0x00, 0x00, 0x00, /* no VGA HW for other modes*/
40 0x00, 0x00, 0x00, 0x00,
41 0x00, 0x00, 0x00, 0x00,
44 /* precalculated mask bits*/
45 static unsigned char mask[8] = {
46 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01
51 fbvga_setiopermissions(PSD psd)
53 /* allow direct access to vga controller space*/
54 return ioperm(0x3c0, 0x20, 1);
58 /* Init VGA controller, calc linelen and mmap size, return 0 on fail*/
63 if(fbvga_setiopermissions(psd) == -1) {
64 EPRINTF("Can't set i/o permissions: %m\n");
69 * Fill in entry point for applications to call to
70 * regain i/o permissions. This is required after
71 * calling pthreads_create because pthreads resets
72 * the i/o permissions after thread creation.
73 * Note that this requires that systems using pthreads
74 * and VGA16 framebuffer to run setuid root :-(
76 psd->SetIOPermissions = fbvga_setiopermissions;
79 #if MSDOS | ELKS | __rtems__ | __ECOS
80 /* fill in screendevice struct if not framebuffer driver*/
81 psd->addr = SCREENBASE; /* long ptr -> short on 16bit sys*/
82 psd->linelen = BYTESPERLINE;
85 psd->addr = 0; /* long ptr -> short on 16bit sys*/
88 /* framebuffer mmap size*/
90 /* Set up some default values for the VGA Graphics Registers. */
97 /* draw a pixel at x,y of color c*/
99 ega_drawpixel(PSD psd,unsigned int x, unsigned int y, MWPIXELVAL c)
101 assert (x >= 0 && x < psd->xres);
102 assert (y >= 0 && y < psd->yres);
103 assert (c < psd->ncolors);
106 set_op(mode_table[gr_mode]);
108 select_and_set_mask (mask[x&7]);
109 RMW_FP ((FARADDR)SCREENBASE + (x>>3) + y * BYTESPERLINE);
113 /* Return 4-bit pixel value at x,y*/
115 ega_readpixel(PSD psd,unsigned int x,unsigned int y)
121 assert (x >= 0 && x < psd->xres);
122 assert (y >= 0 && y < psd->yres);
126 src = (unsigned char *)(SCREENBASE + (x>>3) + y * BYTESPERLINE);
128 src = SCREENBASE + (x>>3) + y * BYTESPERLINE;
130 for(plane=0; plane<4; ++plane) {
131 set_read_plane(plane);
132 if(GETBYTE_FP(src) & mask[x&7])
139 /* Draw horizontal line from x1,y to x2,y including final point*/
141 ega_drawhorzline(PSD psd, unsigned int x1, unsigned int x2, unsigned int y,
146 assert (x1 >= 0 && x1 < psd->xres);
147 assert (x2 >= 0 && x2 < psd->xres);
149 assert (y >= 0 && y < psd->yres);
150 assert (c < psd->ncolors);
154 set_op(mode_table[gr_mode]);
156 * The following fast drawhline code is buggy for XOR drawing,
157 * for some reason. So, we use the equivalent slower drawpixel
158 * method when not drawing MWMODE_COPY.
160 if(gr_mode == MWMODE_COPY) {
162 dst = (unsigned char *)(SCREENBASE + (x1>>3) + y*BYTESPERLINE);
164 dst = SCREENBASE + (x1>>3) + y * BYTESPERLINE;
166 if ((x1>>3) == (x2>>3)) {
167 select_and_set_mask ((0xff >> (x1 & 7)) & (0xff << (7 - (x2 & 7))));
170 select_and_set_mask (0xff >> (x1 & 7));
175 last = (unsigned char *)(SCREENBASE + (x2>>3) + y * BYTESPERLINE);
177 last = SCREENBASE + (x2>>3) + y * BYTESPERLINE;
180 PUTBYTE_FP(dst++, 1);
182 set_mask (0xff << (7 - (x2 & 7)));
186 /* slower method, draw pixel by pixel*/
189 set_mask (mask[x1&7]);
190 RMW_FP ((FARADDR)SCREENBASE + (x1++>>3) + y * BYTESPERLINE);
196 /* Draw a vertical line from x,y1 to x,y2 including final point*/
198 ega_drawvertline(PSD psd,unsigned int x, unsigned int y1, unsigned int y2,
203 assert (x >= 0 && x < psd->xres);
204 assert (y1 >= 0 && y1 < psd->yres);
205 assert (y2 >= 0 && y2 < psd->yres);
207 assert (c < psd->ncolors);
210 set_op(mode_table[gr_mode]);
212 select_and_set_mask (mask[x&7]);
214 dst = (unsigned char *)(SCREENBASE + (x>>3) + y1 * BYTESPERLINE);
215 last = (unsigned char *)(SCREENBASE + (x>>3) + y2 * BYTESPERLINE);
217 dst = SCREENBASE + (x>>3) + y1 * BYTESPERLINE;
218 last = SCREENBASE + (x>>3) + y2 * BYTESPERLINE;
220 while (dst <= last) {
228 SUBDRIVER vgaplan4 = {
230 (void *)ega_drawpixel,
231 (void *)ega_readpixel,
232 (void *)ega_drawhorzline,
233 (void *)ega_drawvertline,
234 (void *)gen_fillrect,