]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/services/gfx/mw/v2_0/src/drivers/vgaplan4.c
Initial revision
[karo-tx-redboot.git] / packages / services / gfx / mw / v2_0 / src / drivers / vgaplan4.c
1 /*
2  * Copyright (c) 1999, 2000, 2002 Greg Haerr <greg@censoft.com>
3  *
4  * 16 color 4 planes EGA/VGA Planar Video Driver for Microwindows
5  * Portable C version
6  *
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
10  *
11  * In this driver, psd->linelen is line byte length, not line pixel length
12  *
13  * This file is meant to compile under Linux, ELKS, and MSDOS
14  * without changes.  Please try to keep it that way.
15  * 
16  */
17 /*#define NDEBUG*/
18 #if _MINIX
19 #include <ibm/portio.h>
20 #endif
21 #include <assert.h>
22 #include "device.h"
23 #include "vgaplan4.h"
24 #include "fb.h"
25
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
30 #else
31 /* run on top of framebuffer*/
32 #define SCREENBASE              ((char *)psd->addr)
33 #define BYTESPERLINE            (psd->linelen)
34 #endif
35
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,
42 };
43
44 /* precalculated mask bits*/
45 static unsigned char mask[8] = {
46         0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01
47 };
48
49 #if HAVEIOPERM
50 static int
51 fbvga_setiopermissions(PSD psd)
52 {
53         /* allow direct access to vga controller space*/
54         return ioperm(0x3c0, 0x20, 1);
55 }
56 #endif
57
58 /* Init VGA controller, calc linelen and mmap size, return 0 on fail*/
59 int
60 ega_init(PSD psd)
61 {
62 #if HAVEIOPERM
63         if(fbvga_setiopermissions(psd) == -1) {
64                 EPRINTF("Can't set i/o permissions: %m\n");
65                 return 0;
66         }
67
68         /* 
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 :-(
75          */
76         psd->SetIOPermissions = fbvga_setiopermissions;
77 #endif
78
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;
83 #endif
84 #if _MINIX
85         psd->addr = 0;                  /* long ptr -> short on 16bit sys*/
86         psd->linelen = 80;
87 #endif
88         /* framebuffer mmap size*/
89         psd->size = 0x10000;
90         /* Set up some default values for the VGA Graphics Registers. */
91         set_enable_sr (0x0f);
92         set_op (0);
93         set_mode (0);
94         return 1;
95 }
96
97 /* draw a pixel at x,y of color c*/
98 void
99 ega_drawpixel(PSD psd,unsigned int x, unsigned int y, MWPIXELVAL c)
100 {
101         assert (x >= 0 && x < psd->xres);
102         assert (y >= 0 && y < psd->yres);
103         assert (c < psd->ncolors);
104   
105         DRAWON;
106         set_op(mode_table[gr_mode]);
107         set_color (c);
108         select_and_set_mask (mask[x&7]);
109         RMW_FP ((FARADDR)SCREENBASE + (x>>3) + y * BYTESPERLINE);
110         DRAWOFF;
111 }
112
113 /* Return 4-bit pixel value at x,y*/
114 MWPIXELVAL
115 ega_readpixel(PSD psd,unsigned int x,unsigned int y)
116 {
117         FARADDR         src;
118         int             plane;
119         MWPIXELVAL      c = 0;
120         
121         assert (x >= 0 && x < psd->xres);
122         assert (y >= 0 && y < psd->yres);
123   
124         DRAWON;
125 #if _MINIX
126         src = (unsigned char *)(SCREENBASE + (x>>3) + y * BYTESPERLINE);
127 #else
128         src = SCREENBASE + (x>>3) + y * BYTESPERLINE;
129 #endif
130         for(plane=0; plane<4; ++plane) {
131                 set_read_plane(plane);
132                 if(GETBYTE_FP(src) & mask[x&7])
133                         c |= 1 << plane;
134         }
135         DRAWOFF;
136         return c;
137 }
138
139 /* Draw horizontal line from x1,y to x2,y including final point*/
140 void
141 ega_drawhorzline(PSD psd, unsigned int x1, unsigned int x2, unsigned int y,
142         MWPIXELVAL c)
143 {
144         FARADDR dst, last;
145
146         assert (x1 >= 0 && x1 < psd->xres);
147         assert (x2 >= 0 && x2 < psd->xres);
148         assert (x2 >= x1);
149         assert (y >= 0 && y < psd->yres);
150         assert (c < psd->ncolors);
151
152         DRAWON;
153         set_color (c);
154         set_op(mode_table[gr_mode]);
155         /*
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.
159         */
160         if(gr_mode == MWMODE_COPY) {
161 #if _MINIX
162                 dst = (unsigned char *)(SCREENBASE + (x1>>3) + y*BYTESPERLINE);
163 #else
164                 dst = SCREENBASE + (x1>>3) + y * BYTESPERLINE;
165 #endif
166                 if ((x1>>3) == (x2>>3)) {
167                         select_and_set_mask ((0xff >> (x1 & 7)) & (0xff << (7 - (x2 & 7))));
168                         RMW_FP (dst);
169                 } else {
170                         select_and_set_mask (0xff >> (x1 & 7));
171                         RMW_FP (dst++);
172
173                         set_mask (0xff);
174 #if _MINIX
175                         last = (unsigned char *)(SCREENBASE + (x2>>3) + y * BYTESPERLINE);
176 #else
177                         last = SCREENBASE + (x2>>3) + y * BYTESPERLINE;
178 #endif
179                         while (dst < last)
180                                 PUTBYTE_FP(dst++, 1);
181
182                         set_mask (0xff << (7 - (x2 & 7)));
183                         RMW_FP (dst);
184                 }
185         } else {
186                 /* slower method, draw pixel by pixel*/
187                 select_mask ();
188                 while(x1 <= x2) {
189                         set_mask (mask[x1&7]);
190                         RMW_FP ((FARADDR)SCREENBASE + (x1++>>3) + y * BYTESPERLINE);
191                 }
192         }
193         DRAWOFF;
194 }
195
196 /* Draw a vertical line from x,y1 to x,y2 including final point*/
197 void
198 ega_drawvertline(PSD psd,unsigned int x, unsigned int y1, unsigned int y2,
199         MWPIXELVAL c)
200 {
201         FARADDR dst, last;
202
203         assert (x >= 0 && x < psd->xres);
204         assert (y1 >= 0 && y1 < psd->yres);
205         assert (y2 >= 0 && y2 < psd->yres);
206         assert (y2 >= y1);
207         assert (c < psd->ncolors);
208
209         DRAWON;
210         set_op(mode_table[gr_mode]);
211         set_color (c);
212         select_and_set_mask (mask[x&7]);
213 #if _MINIX
214         dst = (unsigned char *)(SCREENBASE + (x>>3) + y1 * BYTESPERLINE);
215         last = (unsigned char *)(SCREENBASE + (x>>3) + y2 * BYTESPERLINE);
216 #else
217         dst = SCREENBASE + (x>>3) + y1 * BYTESPERLINE;
218         last = SCREENBASE + (x>>3) + y2 * BYTESPERLINE;
219 #endif
220         while (dst <= last) {
221                 RMW_FP (dst);
222                 dst += BYTESPERLINE;
223         }
224         DRAWOFF;
225 }
226
227 #if FBVGA
228 SUBDRIVER vgaplan4 = {
229         (void *)ega_init,
230         (void *)ega_drawpixel,
231         (void *)ega_readpixel,
232         (void *)ega_drawhorzline,
233         (void *)ega_drawvertline,
234         (void *)gen_fillrect,
235         (void *)ega_blit
236 };
237 #endif /* FBVGA*/