ZDE improvements - global zbitmap_t structure added, added native support for buttons...
[ZeXOS.git] / kernel / drivers / char / video / video.c
blob5a4e231fdfd3baa6780c2e97f37553251ddf4c1c
1 /*
2 * ZeX/OS
3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
4 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
5 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include <build.h>
23 #include <system.h>
24 #include <arch/io.h>
25 #include <string.h>
26 #include <config.h>
28 static unsigned char vgaused = 0; /* some program using graphics mode ? */
29 unsigned char vgagui = 0; /* 0 - textual; 1 - 8bpp graphics; 2 - 16bpp graphics mode*/
30 char *vgafb; /* frame buffer */
31 char *vgadb; /* double buffer */
33 unsigned vgafb_res_x, vgafb_res_y; /* screen resolution */
34 int attrib = 0x0F;
35 int csr_x = 0, csr_y = 0;
37 extern unsigned short *vesafb;
39 #ifdef ARCH_i386
41 /* These define our textpointer, our background and foreground
42 * colors (attributes), and x and y cursor coordinates */
43 unsigned short *textmemptr;
45 const int MiscOutputReg = 0x3c2;
46 const int DataReg = 0x3c0;
47 const int AddressReg = 0x3c0;
49 const char mode03[][32] = {
50 { 0x03, 0x00, 0x03, 0x00, 0x02 },
51 { 0x5F, 0x4F, 0x50, 0x82, 0x55, 0x81, 0xBF, 0x1F,
52 0x00, 0x4F, 0x0D, 0x0E, 0x00, 0x00, 0x00, 0x50,
53 0x9C, 0x0E, 0x8F, 0x28, 0x1F, 0x96, 0xB9, 0xA3,
54 0xFF },
55 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x00,
56 0xFF },
57 { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
58 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
59 0x0C, 0x00, 0x0F, 0x08, 0x00 }
62 const char mode13[][32] = {
63 { 0x03, 0x01, 0x0f, 0x00, 0x0e }, /* 0x3c4, index 0-4*/
64 { 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f,
65 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66 0x9c, 0x0e, 0x8f, 0x28, 0x40, 0x96, 0xb9, 0xa3,
67 0xff }, /* 0x3d4, index 0-0x18*/
68 { 0, 0, 0, 0, 0, 0x40, 0x05, 0x0f, 0xff }, /* 0x3ce, index 0-8*/
69 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
70 0x41, 0, 0x0f, 0, 0 } /* 0x3c0, index 0-0x14*/
73 /*const char mode18[][32] = {
75 { 0x03, 0x01, 0x08, 0x00, 0x06 },
76 { 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E,
77 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
78 0xEA, 0x0C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xE3,
79 0xFF },
80 { 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x05, 0x0F,
81 0xFF },
82 { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
83 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
84 0x01, 0x00, 0x0F, 0x00, 0x00 }
85 };*/
87 /* Scrolls the screen */
88 void video_scroll (void)
90 unsigned blank, temp;
92 /* A blank is defined as a space... we need to give it
93 * backcolor too */
94 blank = 0x20 | (attrib << 8);
96 /* Row 25 is the end, this means we need to scroll up */
97 if (csr_y >= 25) {
98 /* Move the current text chunk that makes up the screen
99 * back in the buffer by a line */
100 temp = csr_y - 25 + 1;
101 memcpy (textmemptr, textmemptr + temp * 80, (25 - temp) * 80 * 2);
103 /* Finally, we set the chunk of memory that occupies
104 * the last line of text to our 'blank' character */
105 memsetw (textmemptr + (25 - temp) * 80, blank, 80);
106 csr_y = 25 - 1;
110 /* Updates the hardware cursor: the little blinking line
111 * on the screen under the last character pressed! */
112 void video_move_csr (void)
114 unsigned temp;
116 /* The equation for finding the index in a linear
117 * chunk of memory can be represented by:
118 * Index = [(y * width) + x] */
119 temp = csr_y * 80 + csr_x;
121 /* This sends a command to indicies 14 and 15 in the
122 * CRT Control Register of the VGA controller. These
123 * are the high and low bytes of the index that show
124 * where the hardware cursor is to be 'blinking'. */
125 outb (0x3D4, 14);
126 outb (0x3D5, temp >> 8);
127 outb (0x3D4, 15);
128 outb (0x3D5, temp);
131 /* Clears the screen */
132 void video_cls ()
134 unsigned blank;
135 int i;
137 /* Again, we need the 'short' that will be used to
138 * represent a space with color */
139 blank = 0x20 | (attrib << 8);
141 /* Sets the entire screen to spaces in our current
142 * color */
143 for (i = 0; i < 25; i ++)
144 memsetw (textmemptr + i * 80, blank, 80);
146 /* Update out virtual cursor, and then move the
147 * hardware cursor */
148 csr_x = 0;
149 csr_y = 0;
151 video_move_csr();
154 /* Puts a single character on the screen */
155 void video_putch (unsigned char c)
157 #ifndef CONFIG_UI_CONSOLESERIAL
158 unsigned short *where;
159 unsigned att = attrib << 8;
161 /* Handle a backspace, by moving the cursor back one space */
162 if (c == 0x08) {
163 if (csr_x != 0)
164 csr_x --;
166 /* delete last character */
167 where = textmemptr + (csr_y * 80 + csr_x);
168 *where = ' ' | att; /* Character AND attributes: color */
171 /* Handles a tab by incrementing the cursor's x, but only
172 * to a point that will make it divisible by 8 */
173 else if (c == 0x09)
174 csr_x = (csr_x + 8) & ~(8 - 1);
176 /* Handles a 'Carriage Return', which simply brings the
177 * cursor back to the margin */
178 else if (c == '\r')
179 csr_x = 0;
181 /* We handle our newlines the way DOS and the BIOS do: we
182 * treat it as if a 'CR' was also there, so we bring the
183 * cursor to the margin and we increment the 'y' value */
184 else if (c == '\n') {
185 csr_x = 0;
186 csr_y ++;
188 /* Any character greater than and including a space, is a
189 * printable character. The equation for finding the index
190 * in a linear chunk of memory can be represented by:
191 * Index = [(y * width) + x] */
192 else if (c >= ' ') {
193 where = textmemptr + (csr_y * 80 + csr_x);
194 *where = c | att; /* Character AND attributes: color */
195 csr_x ++;
198 /* If the cursor has reached the edge of the screen's width, we
199 * insert a new line in there */
200 if (csr_x >= 80) {
201 csr_x = 0;
202 csr_y ++;
205 /* Scroll the screen if needed, and finally move the cursor */
206 video_scroll ();
207 video_move_csr ();
208 #else
209 #ifdef CONFIG_DRV_RS232
210 /* Serial console output */
211 rs232_write ((char) c);
212 #endif
213 #endif
216 void video_setattrib (int attr)
218 attrib = attr;
221 int video_getattrib ()
223 return attrib;
226 /* Sets the forecolor and backcolor that we will use */
227 void video_color (unsigned char forecolor, unsigned char backcolor)
229 /* Top 4 bytes are the background, bottom 4 bytes
230 * are the foreground color */
231 attrib = (backcolor << 4) | (forecolor & 0x0F);
234 /* Set the cursor to selected position */
235 void video_gotoxy (unsigned x, unsigned y)
237 csr_x = x;
238 csr_y = y;
240 video_scroll ();
241 video_move_csr ();
244 /* video card mono/colour detection by Dark Fiber
245 * returns 0=mono, 1=colour
247 int video_type (void)
249 char c = (*(unsigned short*) 0x410&0x30);
251 /* C can be 0x00 or 0x20 for colour, 0x30 for mono */
252 if(c == 0x30)
253 return 0; // mono
254 else
255 return 1; // colour
258 /* Sets our text-mode VGA pointer, then clears the screen for us */
259 unsigned int init_video (void)
261 if (video_type ()) // check type of video card - color/mono
262 textmemptr = (unsigned short *) 0xB8000;
263 else
264 textmemptr = (unsigned short *) 0xA0000;
266 vgagui = 0;
267 vgaused = 0;
269 video_cls ();
271 if (init_video_vesa ())
272 init_vgafb ();
274 return 1;
278 Graphics mode
281 char *init_vgafb ()
283 //if (vgaused)
284 // return (char *) ~0;
286 vgaused ++;
288 vgadb = (char *) 0;
289 vgafb = (char *) 0;
291 #ifdef CONFIG_DRV_VGA
292 int i;
294 /* VGA mode */
295 if (!vgagui) {
296 outb_p (0x63, MiscOutputReg);
297 outb_p (0x00, 0x3da);
299 for (i = 0; i < 5; i ++) {
300 outb_p (i, 0x3c4);
301 outb_p (mode13[0][i], 0x3c4+1);
304 outw_p (0x0e11, 0x3d4);
306 for (i = 0; i < 0x19; i ++) {
307 outb_p (i, 0x3d4);
308 outb_p (mode13[1][i], (0x3d4 + 1));
311 for (i = 0; i < 0x9; i ++) {
312 outb_p (i, 0x3ce);
313 outb_p (mode13[2][i], (0x3ce + 1));
316 inb_p (0x3da);
318 for (i = 0; i < 0x15; i ++) {
319 inw (DataReg);
320 outb_p (i, AddressReg);
321 outb_p (mode13[3][i], DataReg);
324 outb_p (0x20, 0x3c0);
326 vgagui = 1;
328 vgafb_res_x = 320;
329 vgafb_res_y = 200;
331 vgafb = (char *) 0xA0000;
332 vgadb = 0;//(char *) kmalloc (sizeof (char) * vgafb_res_x * vgafb_res_y);
335 #endif
336 #ifdef CONFIG_DRV_VESA
337 /* VESA mode */
338 if (vgagui == 2) {
339 vgafb_res_x = 800;
340 vgafb_res_y = 600;
342 vgafb = (char *) vesafb;
343 vgadb = (char *) 0x400000;//kmalloc (sizeof (short) * vgafb_res_x * vgafb_res_y);
344 //vgatb = (char *) PAGE_MEM_LOW+0x200000;//kmalloc (sizeof (char) * vgafb_res_x * vgafb_res_y);
347 if (!vgadb)
348 vgadb = vgafb;
349 #endif
351 return vgadb;
354 void video_gfx_exit ()
356 /* we dont use VGA anymore */
357 if (vgaused)
358 vgaused = 0;
360 if (vgagui != 1) {
361 /* for VESA mode */
362 if (vgagui == 2)
363 video_gfx_cls (0);
365 return;
368 int i;
370 outb_p (0x67, MiscOutputReg);
371 outb_p (0x00, 0x3da);
373 for (i = 0; i < 5; i ++) {
374 outb_p (i, 0x3c4);
375 outb_p (mode03[0][i], 0x3c4+1);
378 outw_p (0x0e11, 0x3d4);
380 for (i = 0; i < 0x19; i ++) {
381 outb_p (i, 0x3d4);
382 outb_p (mode03[1][i], (0x3d4 + 1));
385 for (i = 0; i < 0x9; i ++) {
386 outb_p (i, 0x3ce);
387 outb_p (mode03[2][i], (0x3ce + 1));
390 inb_p (0x3da);
392 for (i = 0; i < 0x15; i ++) {
393 inw (DataReg);
394 outb_p (i, AddressReg);
395 outb_p (mode03[3][i], DataReg);
398 outb_p (0x20, 0x3c0);
400 vgagui = 0;
402 vgafb_res_x = 0;
403 vgafb_res_y = 0;
405 if (vgadb != vgafb)
406 kfree (vgadb);
409 /* Draw pixel (dot) on the screen with specified color */
410 void video_gfx_pixel (unsigned x, unsigned y, unsigned color)
412 if (x >= vgafb_res_x || y >= vgafb_res_y)
413 return;
415 unsigned i = y * vgafb_res_x + x;
417 if (vgagui == 2) {
418 unsigned short *db = (unsigned short *) vgadb;
420 db[i] = color;
422 return;
425 if (vgagui == 1) {
426 vgadb[i] = color;
428 return;
432 /* Swap double-buffered screen */
433 void video_gfx_fbswap ()
435 paging_disable ();
437 #ifdef CONFIG_DRV_GMM
438 unsigned l = (vgafb_res_x * vgafb_res_y) / 2;
439 unsigned i = 0;
440 unsigned *fb = (unsigned *) vgafb;
441 unsigned *db = (unsigned *) vgadb;
443 for (; i < l; i ++) {
444 fb[i] = db[i];
445 db[i] = 0;
447 #else
448 if (vgadb != vgafb) {
449 unsigned l = vgafb_res_x * vgafb_res_y * vgagui;
450 unsigned i = 0;
451 for (i = 0; i < l; i ++) {
452 vgafb[i] = vgadb[i];
453 vgadb[i] = 0;
456 #endif
458 paging_enable ();
461 /* Clear screen with specified color*/
462 void video_gfx_cls (unsigned color)
464 unsigned short *db = (unsigned short *) vgadb;
466 unsigned x;
467 unsigned l = vgafb_res_x * vgafb_res_y;
469 for (x = 0; x < l; x ++)
470 db[x] = color;
473 #endif
475 /** ARM architecture **/
476 #ifdef ARCH_arm
477 /* Draw pixel (dot) on the screen with specified color */
478 void video_gfx_pixel (unsigned x, unsigned y, unsigned color)
480 unsigned i = y * 640 + x;
481 unsigned short *db = (unsigned short *) 0x500000;
483 db[i] = color;
486 /* Clear screen with specified color*/
487 void video_gfx_cls (unsigned color)
489 unsigned short *db = (unsigned short *) vgadb;
491 unsigned x;
492 unsigned l = vgafb_res_x * vgafb_res_y;
494 for (x = 0; x < l; x ++)
495 db[x] = color;
498 /* Swap double-buffered screen */
499 void video_gfx_fbswap ()
501 /*#ifdef CONFIG_DRV_GMM
502 unsigned l = (vgafb_res_x * vgafb_res_y) / 2;
503 unsigned i = 0;
504 unsigned *fb = (unsigned *) vgafb;
505 unsigned *db = (unsigned *) vgadb;
507 for (; i < l; i ++) {
508 fb[i] = db[i];
509 db[i] = 0;
511 #else
512 if (vgadb != vgafb) {
513 unsigned l = vgafb_res_x * vgafb_res_y * vgagui;
514 unsigned i = 0;
515 for (i = 0; i < l; i ++) {
516 vgafb[i] = vgadb[i];
517 vgadb[i] = 0;
520 #endif*/
523 void video_putch (unsigned char c)
525 /* uart output for embedded devices */
526 rs232_write ((char) c);
529 /* Sets the forecolor and backcolor that we will use */
530 void video_color (unsigned char forecolor, unsigned char backcolor)
532 /* Top 4 bytes are the background, bottom 4 bytes
533 * are the foreground color */
534 attrib = (backcolor << 4) | (forecolor & 0x0F);
537 void video_cls ()
542 /* Set the cursor to selected position */
543 void video_gotoxy (unsigned x, unsigned y)
548 unsigned int init_video (void)
550 return 0;
552 #endif
554 /* Device handler */
555 bool video_acthandler (unsigned act, char *block, char *more, int block_len)
557 switch (act) {
558 case DEV_ACT_INIT:
560 vgaused = 0;
561 return 1;
563 break;
566 return 0;