1 /**
2  ** svgalib.c ---- Linux driver, i.e. an interface to SVGALIB
3  **
4  ** Copyright (c) 1995 Csaba Biegl, 820 Stirrup Dr, Nashville, TN 37221
5  ** [e-mail: csaba@vuse.vanderbilt.edu]
6  **
7  ** This file is part of the GRX graphics library.
8  **
9  ** The GRX graphics library is free software; you can redistribute it
10  ** and/or modify it under some conditions; see the "copying.grx" file
11  ** for details.
12  **
13  ** This library is distributed in the hope that it will be useful,
14  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  **
17  **/
18 
19 #include <string.h>
20 #include <vga.h>
21 
22 #include "libgrx.h"
23 #include "grdriver.h"
24 #include "arith.h"
25 #include "memcopy.h"
26 #include "memfill.h"
27 
28 #define  NUM_MODES    80                /* max # of supported modes */
29 #define  NUM_EXTS     15                /* max # of mode extensions */
30 
31 static int initted  = (-1);
32 static int initmode = 0;
33 static int isEGA;
34 
detect(void)35 static int detect(void)
36 {
37 	if(initted < 0) {
38 #if 0
39 	    /* make sure VGA will map to 64K boundary ... */
40 	    long endmem = (long)(sbrk(0));
41 	    if((endmem & 0xffffL) != 0) {
42 		brk((void *)((endmem + 0xffffL) & ~0xffffL));
43 	    }
44 #endif
45 	    if(vga_init() >= 0) {
46 		initted  = 1;
47 		isEGA    = (vga_getcurrentchipset() == EGA);
48 		initmode = vga_getcurrentmode();
49 	    }
50 	    else initted = 0;
51 	}
52 	return((initted > 0) ? TRUE : FALSE);
53 }
54 
reset(void)55 static void reset(void)
56 {
57 	if(initted > 0 && vga_getcurrentmode() != initmode)
58 	    vga_setmode(initmode);
59 }
60 
setrwbanks(int rb,int wb)61 static void setrwbanks(int rb,int wb)
62 {
63 	vga_setreadpage(rb);
64 	vga_setwritepage(wb);
65 }
66 
loadcolor(int c,int r,int g,int b)67 static void loadcolor(int c,int r,int g,int b)
68 {
69 	vga_setpalette(c,(r >> 2),(g >> 2),(b >> 2));
70 }
71 
setmode(GrVideoMode * mp,int noclear)72 static int setmode(GrVideoMode *mp,int noclear)
73 {
74 	vga_setmode(mp->mode);
75 	if (mp->extinfo->flags & GR_VMODEF_LINEAR) {
76 	  if (vga_setlinearaddressing() == -1)
77 	    return(FALSE);
78 	}
79 	mp->extinfo->frame = (char *)vga_getgraphmem();
80 	return(TRUE);
81 }
82 
settext(GrVideoMode * mp,int noclear)83 static int settext(GrVideoMode *mp,int noclear)
84 {
85 	vga_setmode(mp->mode);
86 	return(TRUE);
87 }
88 
89 GrVideoModeExt _GrViDrvEGAVGAtextModeExt = {
90     GR_frameText,                       /* frame driver */
91     NULL,                               /* frame driver override */
92     NULL,                               /* frame buffer address */
93     { 6, 6, 6 },                        /* color precisions */
94     { 0, 0, 0 },                        /* color component bit positions */
95     0,                                  /* mode flag bits */
96     settext,                            /* mode set */
97     NULL,                               /* virtual size set */
98     NULL,                               /* virtual scroll */
99     NULL,                               /* bank set function */
100     NULL,                               /* double bank set function */
101     NULL,                               /* color loader */
102 };
103 
104 static GrVideoModeExt exts[NUM_EXTS];
105 static GrVideoMode   modes[NUM_MODES] = {
106     /* pres.  bpp wdt   hgt   mode   scan  priv. &ext                             */
107     {  TRUE,  4,  80,   25,   TEXT,  160,  0,    &_GrViDrvEGAVGAtextModeExt },
108     {  0  }
109 };
110 
build_video_mode(vga_modeinfo * ip,GrVideoMode * mp,GrVideoModeExt * ep)111 static int build_video_mode(
112     vga_modeinfo   *ip,
113     GrVideoMode    *mp,
114     GrVideoModeExt *ep
115 ){
116 	mp->present    = TRUE;
117 	mp->width      = ip->width;
118 	mp->height     = ip->height;
119 	mp->lineoffset = ip->linewidth;
120 	mp->extinfo    = NULL;
121 	mp->privdata   = 0;
122 	ep->drv        = NULL;
123 	ep->frame      = NULL;          /* filled in after mode set */
124 	ep->flags      = 0;
125 	ep->setup      = setmode;
126 	ep->setvsize   = NULL;          /* tbd */
127 	ep->scroll     = NULL;          /* tbd */
128 	ep->setbank    = isEGA ? NULL : vga_setpage;
129 	ep->setrwbanks = (ip->flags & HAVE_RWPAGE) ? setrwbanks : NULL;
130 	ep->loadcolor  = NULL;
131 	switch(ip->colors) {
132 #ifdef INOUTP_FRAMEDRIVERS
133 	  case 2:
134 	    mp->bpp       = 1;
135 	    ep->mode      = GR_frameEGAVGA1;
136 	    ep->cprec[0]  =
137 	    ep->cprec[1]  =
138 	    ep->cprec[2]  = 1;
139 	    ep->cpos[0]   =
140 	    ep->cpos[1]   =
141 	    ep->cpos[2]   = 0;
142 	    break;
143 	  case 16:
144 	    mp->bpp       = 4;
145 	    ep->mode      = isEGA ? GR_frameEGA4 : GR_frameSVGA4;
146 	    ep->cprec[0]  =
147 	    ep->cprec[1]  =
148 	    ep->cprec[2]  = isEGA ? 2 : 6;
149 	    ep->cpos[0]   =
150 	    ep->cpos[1]   =
151 	    ep->cpos[2]   = 0;
152 	    ep->loadcolor = loadcolor;
153 	    break;
154 #endif
155 	  case 256:
156 	    mp->bpp       = 8;
157 	    if (ip->flags & IS_MODEX)
158 #ifdef INOUTP_FRAMEDRIVERS
159 		ep->mode = GR_frameVGA8X;
160 #else
161 		return(FALSE);
162 #endif
163 	    else
164 	    if (ip->flags & CAPABLE_LINEAR) {
165 		ep->mode  = GR_frameSVGA8_LFB;
166 		ep->flags|= GR_VMODEF_LINEAR;
167 	    } else
168 		ep->mode = GR_frameSVGA8;
169 	    ep->cprec[0]  =
170 	    ep->cprec[1]  =
171 	    ep->cprec[2]  = 6;
172 	    ep->cpos[0]   =
173 	    ep->cpos[1]   =
174 	    ep->cpos[2]   = 0;
175 	    ep->loadcolor = loadcolor;
176 	    break;
177 	  case 32*1024:
178 	    mp->bpp       = 15;
179 	    if (ip->flags & CAPABLE_LINEAR) {
180 		ep->mode  = GR_frameSVGA16_LFB;
181 		ep->flags|= GR_VMODEF_LINEAR;
182 	    } else
183 		ep->mode      = GR_frameSVGA16;
184 	    ep->cprec[0]  =
185 	    ep->cprec[1]  =
186 	    ep->cprec[2]  = 5;
187 	    ep->cpos[0]   = 10;
188 	    ep->cpos[1]   = 5;
189 	    ep->cpos[2]   = 0;
190 	    break;
191 	  case 64*1024:
192 	    mp->bpp       = 16;
193 	    if (ip->flags & CAPABLE_LINEAR) {
194 		ep->mode  = GR_frameSVGA16_LFB;
195 		ep->flags|= GR_VMODEF_LINEAR;
196 	    } else
197 		ep->mode      = GR_frameSVGA16;
198 	    ep->cprec[0]  = 5;
199 	    ep->cprec[1]  = 6;
200 	    ep->cprec[2]  = 5;
201 	    ep->cpos[0]   = 11;
202 	    ep->cpos[1]   = 5;
203 	    ep->cpos[2]   = 0;
204 	    break;
205 	  case 16*1024*1024:
206 	    mp->bpp       = 24;
207 	    if (ip->flags & CAPABLE_LINEAR) {
208 		ep->mode  = GR_frameSVGA24_LFB;
209 		ep->flags|= GR_VMODEF_LINEAR;
210 	    } else
211 		ep->mode  = GR_frameSVGA24;
212 	    ep->cprec[0]  =
213 	    ep->cprec[1]  =
214 	    ep->cprec[2]  = 8;
215 	    ep->cpos[0]   = 16;
216 	    ep->cpos[1]   = 8;
217 	    ep->cpos[2]   = 0;
218 	    if(ip->bytesperpixel == 3) break;
219 	    mp->bpp       = 32;
220 	    ep->mode      = (ip->flags & CAPABLE_LINEAR) ? GR_frameSVGA32L_LFB
221 							 : GR_frameSVGA32L;
222 	    if(!(ip->flags & RGB_MISORDERED)) break;
223 	    ep->cpos[0]   = 24;
224 	    ep->cpos[1]   = 16;
225 	    ep->cpos[2]   = 8;
226 	    ep->mode      = (ip->flags & CAPABLE_LINEAR) ? GR_frameSVGA32H_LFB
227 							 : GR_frameSVGA32H;
228 	    break;
229 	  default:
230 	    return(FALSE);
231 	}
232 	return(TRUE);
233 }
234 
add_video_mode(GrVideoMode * mp,GrVideoModeExt * ep,GrVideoMode ** mpp,GrVideoModeExt ** epp)235 static void add_video_mode(
236     GrVideoMode *mp,  GrVideoModeExt *ep,
237     GrVideoMode **mpp,GrVideoModeExt **epp
238 ){
239 	if(*mpp < &modes[NUM_MODES]) {
240 	    if(!mp->extinfo) {
241 		GrVideoModeExt *etp = &exts[0];
242 		while(etp < *epp) {
243 		    if(memcmp(etp,ep,sizeof(GrVideoModeExt)) == 0) {
244 			mp->extinfo = etp;
245 			break;
246 		    }
247 		    etp++;
248 		}
249 		if(!mp->extinfo) {
250 		    if(etp >= &exts[NUM_EXTS]) return;
251 		    sttcopy(etp,ep);
252 		    mp->extinfo = etp;
253 		    *epp = ++etp;
254 		}
255 	    }
256 	    sttcopy(*mpp,mp);
257 	    (*mpp)++;
258 	}
259 }
260 
init(char * options)261 static int init(char *options)
262 {
263 	if(detect()) {
264 	    vga_modeinfo  *mdinfo;
265 	    GrVideoMode    mode,*modep = &modes[1];
266 	    GrVideoModeExt ext, *extp  = &exts[0];
267 	    int            mindex;
268 	    memzero(modep,(sizeof(modes) - sizeof(modes[0])));
269 	    for(mindex = G320x200x16; mindex <= GLASTMODE; mindex++) {
270 		if(!(vga_hasmode(mindex)))                 continue;
271 		if(!(mdinfo = vga_getmodeinfo(mindex)))    continue;
272 		if(!(build_video_mode(mdinfo,&mode,&ext))) continue;
273 		mode.mode = mindex;
274 		add_video_mode(&mode,&ext,&modep,&extp);
275 	    }
276 	    _GrVideoDriverSVGALIB.adapter = isEGA ? GR_EGA : GR_VGA;
277 	    return(TRUE);
278 	}
279 	return(FALSE);
280 }
281 
282 GrVideoDriver _GrVideoDriverSVGALIB = {
283     "svgalib",                          /* name */
284     GR_VGA,                             /* adapter type */
285     NULL,                               /* inherit modes from this driver */
286     modes,                              /* mode table */
287     itemsof(modes),                     /* # of modes */
288     detect,                             /* detection routine */
289     init,                               /* initialization routine */
290     reset,                              /* reset routine */
291     _gr_selectmode,                     /* standard mode select routine */
292     0                                   /* no additional capabilities */
293 };
294 
295