1 /* OpenCP Module Player
2 * copyright (c) '94-'10 Niklas Beisert <nbeisert@physik.tu-muenchen.de>
3 *
4 * Curses console driver
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * revision history: (please note changes here)
21 * -ss040615 Stian Skjelstad <stian@nixia.no>
22 * -first release
23 * -doj040914 Dirk Jagdmann <doj@cubic.org>
24 * -trust the framebuffers smem_len
25 * -ss040918 Stian Skjelstad <stian@nixia.no>
26 * -devfs/kernel 2.6 framebuffer names
27 */
28
29 #define _CONSOLE_DRIVER
30
31 #include "config.h"
32 #include <fcntl.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <sys/ioctl.h>
38 #include <sys/mman.h>
39 #include <sys/stat.h>
40 #include <sys/types.h>
41 #include <linux/fb.h>
42 #include <linux/version.h>
43 #include "types.h"
44
45 #include "poutput-fb.h"
46 #include "boot/console.h"
47 #include "poutput.h"
48
49 static struct fb_fix_screeninfo fix;
50 static struct fb_var_screeninfo orgmode;
51 static struct fb_var_screeninfo lowres;
52 static struct fb_var_screeninfo highres;
53 static struct fb_cmap colormap;
54 static uint16_t red[256]= {0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa, 0x5555, 0x5555, 0x5555, 0x5555, 0xffff, 0xffff, 0xffff, 0xffff};
55 static uint16_t green[256]={0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0x5555, 0xaaaa, 0x5555, 0x5555, 0xffff, 0xffff, 0x5555, 0x5555, 0xffff, 0xffff};
56 static uint16_t blue[256]= {0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff};
57
58 static int fd;
59 static uint8_t *fbmem;
60
get_static_info(void)61 static int get_static_info(void)
62 {
63 if (ioctl(fd, FBIOGET_FSCREENINFO, &fix))
64 {
65 perror("fb: ioctl(1, FBIOGET_FSCREENINFO, &fix)");
66 return -1;
67 }
68 return 0;
69 }
70
show_cursor(void)71 static void show_cursor(void)
72 {
73 #ifdef FBIOGET_CURSORSTATE
74 struct fb_cursorstate cur;
75 if (ioctl(fd, FBIOGET_CURSORSTATE, &cur, sizeof(cur)))
76 {
77 perror("fb: ioctl(1, FBIOGET_CURSORSTATE, &cursor)");
78 return;
79 }
80 cur.mode=FB_CURSOR_FLASH;
81 if (ioctl(fd, FBIOPUT_CURSORSTATE, &cur, sizeof(cur)))
82 {
83 perror("fb: ioctl(1, FBIOPUT_CURSORSTATE, &cursor)");
84 return;
85 }
86 #endif
87 }
88
hide_cursor(void)89 static void hide_cursor(void)
90 {
91 #ifdef FBIOGET_CURSORSTATE
92 struct fb_cursorstate cur;
93 if (ioctl(fd, FBIOGET_CURSORSTATE, &cur))
94 {
95 perror("fb: ioctl(1, FBIOGET_CURSORSTATE, &cursor)");
96 return;
97 }
98 cur.mode=FB_CURSOR_OFF;
99 if (ioctl(fd, FBIOPUT_CURSORSTATE, &cur))
100 {
101 perror("fb: ioctl(1, FBIOGET_CURSORSTATE, &cursor)");
102 return;
103 }
104 #endif
105 }
106
test_mode(struct fb_var_screeninfo * info)107 static int test_mode(struct fb_var_screeninfo *info)
108 {
109 int old;
110 old=info->activate;
111 info->activate=FB_ACTIVATE_TEST;
112 if (ioctl(fd, FBIOPUT_VSCREENINFO, info))
113 {
114 perror("fb: ioctl(1, FBIOPUT_VSCREENINFO, info)");
115 info->activate=old;
116 return -1;
117 }
118 info->activate=old;
119 return 0;
120 }
121
__gupdatepal(unsigned char color,unsigned char _red,unsigned char _green,unsigned char _blue)122 static void __gupdatepal(unsigned char color, unsigned char _red, unsigned char _green, unsigned char _blue)
123 {
124 red[color]=_red<<10;
125 green[color]=_green<<10;
126 blue[color]=_blue<<10;
127 }
128
__gflushpal(void)129 static void __gflushpal(void)
130 {
131 if (ioctl(fd, FBIOPUTCMAP, &colormap))
132 perror("fb: ioctl(fb, FBIOGETCMAP, &colormap)");
133 }
134
__plSetGraphMode(int high)135 static int __plSetGraphMode(int high)
136 {
137 /*
138 struct fb_fix_screeninfo fix2;
139 */
140
141 #ifdef DEBUG_FRAMEBUFFER
142 if (high==-1)
143 fprintf(stderr, "fb: set normale mode\n");
144 else if (high)
145 fprintf(stderr, "fb: set 1024x768\n");
146 else
147 fprintf(stderr, "fb: set 640x480\n");
148 #endif
149 if (high==-1)
150 {
151 plVidMem = 0;
152 ioctl(fd, FBIOPUT_VSCREENINFO, &orgmode);
153 return 0;
154 }
155
156 if (high)
157 {
158 if (!highres.xres)
159 return -1;
160 plScrMode=101;
161 plScrWidth=128;
162 plScrHeight=60;
163 ioctl(fd, FBIOPUT_VSCREENINFO, &highres);
164 plScrLineBytes=1024; /* not good, but my framebuffer bugs to much */
165 } else {
166 if (!lowres.xres)
167 return -1;
168 plScrMode=100;
169 plScrWidth=80;
170 plScrHeight=60;
171 ioctl(fd, FBIOPUT_VSCREENINFO, &lowres);
172 plScrLineBytes=640; /* not good, but my framebuffer bugs to much */
173 }
174
175 plVidMem = fbmem;
176 memset(fbmem, 0, fix.smem_len);
177
178 colormap.start=0;
179 colormap.len=256;
180 colormap.red=red;
181 colormap.green=green;
182 colormap.blue=blue;
183 /* Since some framebuffer-drivers fails give out the current palette with the bits scaled correct, we can't really
184 * use the FBIOGETCMAP. That sucks!
185
186 if (ioctl(fd, FBIOGETCMAP, &colormap))
187 perror("fb: ioctl(fb, FBIOGETCMAP, &colormap)");
188
189 * And tridentfb atleast is broken when reporting fix.line_length... hehe.. FUCK that driver!!!!
190
191 if (ioctl(fd, FBIOGET_FSCREENINFO, &fix2))
192 perror("fb: ioctl(1, FBIOGET_FSCREENINFO, &fix)");
193 fix2.line_length=fix.line_length;
194 fprintf(stderr, "DEBUG LINES: current %d, org %d, new %d\n", plScrLineBytes, fix.line_length, fix2.line_length);
195 plScrLineBytes=fix2.line_length;
196 */
197 return 0;
198 }
199
fb_init(int minor)200 int fb_init(int minor)
201 {
202 struct fb_var_screeninfo var2;
203 char *temp;
204
205 memset(&lowres, 0, sizeof(lowres));
206 memset(&lowres, 0, sizeof(highres));
207
208 if ((temp=getenv("FRAMEBUFFER")))
209 {
210 if ((fd=open(temp, O_RDWR))<0)
211 {
212 perror("fb: open($FRAMEBUFFER)");
213 return -1;
214 }
215 } else {
216 if ((fd=open("/dev/fb", O_RDWR))<0)
217 {
218 perror("fb: open(/dev/fb)");
219 if ((fd=open("/dev/fb/0", O_RDWR))<0)
220 {
221 perror("fb: open(/dev/fb/0)");
222 return -1;
223 }
224 }
225 }
226 if (get_static_info())
227 {
228 close(fd);
229 fd=-1;
230 return -1;
231 }
232 plScrLineBytes=fix.line_length;
233 #ifdef VERBOSE_FRAMEBUFFER
234 fprintf(stderr, "fb: FIX SCREEN INFO\n");
235 fprintf(stderr, "fb: id=%s\n", fix.id);
236 fprintf(stderr, "fb: smem_start=0x%08lx\n", fix.smem_start);
237 fprintf(stderr, "fb: smem_len=0x%08x\n", fix.smem_len);
238 fprintf(stderr, "fb: stype=");
239 switch (fix.type)
240 {
241 case FB_TYPE_PACKED_PIXELS:
242 fprintf(stderr, "Packed Pixels\n");
243 break;
244 case FB_TYPE_PLANES:
245 fprintf(stderr, "Non interleaved planes\n");
246 break;
247 case FB_TYPE_INTERLEAVED_PLANES:
248 fprintf(stderr, "Interleaved planes\n");
249 break;
250 case FB_TYPE_TEXT:
251 fprintf(stderr, "Text/attributes\nfb: type_aux=");
252 switch (fix.type_aux)
253 {
254 case FB_AUX_TEXT_MDA:
255 fprintf(stderr, "Monochrome text\n");
256 break;
257 case FB_AUX_TEXT_CGA:
258 fprintf(stderr, "CGA/EGA/VGA Color text\n");
259 break;
260 case FB_AUX_TEXT_S3_MMIO:
261 fprintf(stderr, "S3 MMIO fasttext\n");
262 break;
263 case FB_AUX_TEXT_MGA_STEP16:
264 fprintf(stderr, "MGA Millenium I: text, attr, 14 reserved bytes\n");
265 break;
266 case FB_AUX_TEXT_MGA_STEP8:
267 fprintf(stderr, "other MGAs: text, attr, 6 reserved bytes\n");
268 break;
269 default:
270 fprintf(stderr, "Unknown\n");
271 }
272 break;
273 case FB_TYPE_VGA_PLANES:
274 fprintf(stderr, "EGA/VGA planes\nfb: type_aux=");
275 switch (fix.type_aux)
276 {
277 case FB_AUX_VGA_PLANES_VGA4:
278 fprintf(stderr, "16 color planes (EGA/VGA)\n");
279 break;
280 case FB_AUX_VGA_PLANES_CFB4:
281 fprintf(stderr, "CFB4 in planes (VGA)\n");
282 break;
283 case FB_AUX_VGA_PLANES_CFB8:
284 fprintf(stderr, "CFB8 in planes (VGA)\n");
285 break;
286 default:
287 fprintf(stderr, "Unknown\n");
288 }
289 break;
290 default:
291 fprintf(stderr, "Unknown\n");
292 break;
293 }
294 fprintf(stderr, "fb: visual=");
295 switch (fix.visual)
296 {
297 case FB_VISUAL_MONO01:
298 fprintf(stderr, "Monochr. 1=Black 0=White\n");
299 break;
300 case FB_VISUAL_MONO10:
301 fprintf(stderr, "Monochr. 1=White 0=Black\n");
302 break;
303 case FB_VISUAL_TRUECOLOR:
304 fprintf(stderr, "True color\n");
305 break;
306 case FB_VISUAL_PSEUDOCOLOR:
307 fprintf(stderr, "Pseudo color (like atari)\n");
308 break;
309 case FB_VISUAL_DIRECTCOLOR:
310 fprintf(stderr, "Direct color\n");
311 break;
312 case FB_VISUAL_STATIC_PSEUDOCOLOR:
313 fprintf(stderr, "Pseudo color readonly\n");
314 break;
315 default:
316 fprintf(stderr, "Unknown\n");
317 }
318 fprintf(stderr, "fb: xpanstep=");
319 if (fix.xpanstep)
320 fprintf(stderr, "%d\n", fix.xpanstep);
321 else
322 fprintf(stderr, "Not supported\n");
323 fprintf(stderr, "fb: ypanstep=");
324 if (fix.ypanstep)
325 fprintf(stderr, "%d\n", fix.ypanstep);
326 else
327 fprintf(stderr, "Not supported\n");
328 fprintf(stderr, "fb: ywrapstep=");
329 if (fix.ywrapstep)
330 fprintf(stderr, "%d\n", fix.ywrapstep);
331 else
332 fprintf(stderr, "Not supported\n");
333 fprintf(stderr, "fb: line_length=%d\n", fix.line_length);
334 fprintf(stderr, "fb: mmio_start=0x%08lx\n", fix.mmio_start);
335 fprintf(stderr, "fb: mmio_len=0x%08x\n", fix.mmio_len);
336 fprintf(stderr, "fb: accel=%d\n", fix.accel);
337 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)
338 fprintf(stderr, "fb: capabilities=0x%04x\n", fix.capabilities);
339 fprintf(stderr, "fb: reserved0=0x%04x reserved1=0x%04x\n", fix.reserved[0], fix.reserved[1]);
340 #else
341 fprintf(stderr, "fb: reserved0=0x%04x reserved1=0x%04x reserved2=0x%04x\n", fix.reserved[0], fix.reserved[1], fix.reserved[2]);
342 #endif
343 #endif
344 if (ioctl(fd, FBIOGET_VSCREENINFO, &orgmode))
345 {
346 perror("fb: ioctl(1, FBIOGET_VSCREENINFO, &orgmode)");
347 close(fd);
348 fd=-1;
349 return -1;
350 }
351 orgmode.activate=FB_ACTIVATE_NOW;
352 #if VERBOSE_FRAMEBUFFER
353 fprintf(stderr, "VAR SCREEN INFO\n");
354 fprintf(stderr, "xres=%d\n", orgmode.xres);
355 fprintf(stderr, "yres=%d\n", orgmode.yres);
356 fprintf(stderr, "xres_virtual=%d\n", orgmode.xres_virtual);
357 fprintf(stderr, "yres_virtual=%d\n", orgmode.yres_virtual);
358 fprintf(stderr, "xoffset=%d\n", orgmode.xoffset);
359 fprintf(stderr, "yoffsett=%d\n", orgmode.yoffset);
360 fprintf(stderr, "bits_per_pixel=%d\n", orgmode.bits_per_pixel);
361 fprintf(stderr, "grayscale=%d\n", orgmode.grayscale);
362 /* R, G, B, Alpha goes here */
363 fprintf(stderr, "nonstd=%d\n", orgmode.nonstd);
364 fprintf(stderr, "(activate=%d)\n", orgmode.activate);
365 /* height / width goes here */
366 /* accel flags goes here */
367 #endif
368 var2.xres=var2.xres_virtual=640;
369 var2.yres=var2.yres_virtual=480;
370 var2.xoffset=var2.yoffset=0;
371 var2.bits_per_pixel=8;
372 var2.grayscale=0;
373 var2.nonstd=0;
374 var2.height=orgmode.height;
375 var2.width=orgmode.width;
376 var2.accel_flags=0;
377 var2.pixclock=32052;
378 var2.left_margin=128;
379 var2.right_margin=24;
380 var2.upper_margin=28;
381 var2.lower_margin=9;
382 var2.hsync_len=40;
383 var2.vsync_len=3;
384 var2.sync=orgmode.sync;
385 var2.vmode=0;
386 if (test_mode(&var2))
387 {
388 memcpy(&var2, &orgmode, sizeof(orgmode));
389 var2.activate=FB_ACTIVATE_TEST;
390 } else {
391 var2.activate=FB_ACTIVATE_NOW;
392 }
393 if ((var2.xres==640)&&(var2.yres==480))
394 {
395 fprintf(stderr, "fb: 640x480 is available\n");
396 memcpy(&lowres, &var2, sizeof(var2));
397 } else
398 fprintf(stderr, "fb: 640x480 is not available\n");
399
400 var2.xres=var2.xres_virtual=1024;
401 var2.yres=var2.yres_virtual=768;
402 var2.xoffset=var2.yoffset=0;
403 var2.bits_per_pixel=8;
404 var2.grayscale=0;
405 var2.nonstd=0;
406 var2.height=orgmode.height;
407 var2.width=orgmode.width;
408 var2.accel_flags=0;
409 var2.pixclock=15385;
410 var2.left_margin=160;
411 var2.right_margin=24;
412 var2.upper_margin=29;
413 var2.lower_margin=3;
414 var2.hsync_len=136;
415 var2.vsync_len=6;
416 var2.sync=orgmode.sync;
417 var2.vmode=0;
418 if (test_mode(&var2))
419 {
420 memcpy(&var2, &orgmode, sizeof(orgmode));
421 var2.activate=FB_ACTIVATE_TEST;
422 } else {
423 var2.activate=FB_ACTIVATE_NOW;
424 }
425 if ((var2.xres==1024)&&(var2.yres==768))
426 {
427 fprintf(stderr, "fb: 1024x768 is available\n");
428 memcpy(&highres, &var2, sizeof(var2));
429 } else
430 fprintf(stderr, "fb: 1024x768 is not available\n");
431 if ((!highres.xres)&&(!lowres.xres))
432 {
433 close(fd);
434 fd=-1;
435 return -1;
436 }
437
438 if ((fbmem=mmap(0, fix.smem_len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0))==MAP_FAILED)
439 {
440 perror("fb: mmap()");
441 close(fd);
442 fd=-1;
443 return -1;
444 }
445
446 _plSetGraphMode=__plSetGraphMode;
447 _gdrawstr=generic_gdrawstr;
448 _gdrawchar8=generic_gdrawchar8;
449 _gdrawchar8p=generic_gdrawchar8p;
450 _gdrawchar8t=generic_gdrawchar8t;
451 _gdrawcharp=generic_gdrawcharp;
452 _gdrawchar=generic_gdrawchar;
453 _gupdatestr=generic_gupdatestr;
454 _gupdatepal=__gupdatepal;
455 _gflushpal=__gflushpal;
456 hide_cursor();
457 plVidType=vidVESA;
458
459 return 0;
460 }
461
fb_done(void)462 void fb_done(void)
463 {
464 show_cursor();
465 munmap(fbmem, fix.smem_len);
466 if (fd<0)
467 return;
468 ioctl(fd, FBIOPUT_VSCREENINFO, &orgmode);
469 close(fd);
470 fd=-1;
471 }
472