Cleanup in elf.c with .bss section clean; adm command mounts cdrom instead of floppy...
[ZeXOS.git] / kernel / drivers / char / video / video.c
blob1b76b66d4bde230e67fb417f1ebc62fe6dc16299
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 unsigned char vgagui = 0; /* 0 - textual; 1 - 8bpp graphics; 2 - 16bpp graphics mode*/
29 char *vgafb; /* frame buffer */
30 char *vgadb; /* double buffer */
32 unsigned vgafb_res_x, vgafb_res_y; /* screen resolution */
33 int attrib = 0x0F;
34 int csr_x = 0, csr_y = 0;
36 extern unsigned short *vesafb;
38 #ifdef ARCH_i386
40 /* These define our textpointer, our background and foreground
41 * colors (attributes), and x and y cursor coordinates */
42 unsigned short *textmemptr;
44 const int MiscOutputReg = 0x3c2;
45 const int DataReg = 0x3c0;
46 const int AddressReg = 0x3c0;
48 const char mode03[][32] = {
49 { 0x03, 0x00, 0x03, 0x00, 0x02 },
50 { 0x5F, 0x4F, 0x50, 0x82, 0x55, 0x81, 0xBF, 0x1F,
51 0x00, 0x4F, 0x0D, 0x0E, 0x00, 0x00, 0x00, 0x50,
52 0x9C, 0x0E, 0x8F, 0x28, 0x1F, 0x96, 0xB9, 0xA3,
53 0xFF },
54 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x00,
55 0xFF },
56 { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
57 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
58 0x0C, 0x00, 0x0F, 0x08, 0x00 }
61 const char mode13[][32] = {
62 { 0x03, 0x01, 0x0f, 0x00, 0x0e }, /* 0x3c4, index 0-4*/
63 { 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f,
64 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65 0x9c, 0x0e, 0x8f, 0x28, 0x40, 0x96, 0xb9, 0xa3,
66 0xff }, /* 0x3d4, index 0-0x18*/
67 { 0, 0, 0, 0, 0, 0x40, 0x05, 0x0f, 0xff }, /* 0x3ce, index 0-8*/
68 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
69 0x41, 0, 0x0f, 0, 0 } /* 0x3c0, index 0-0x14*/
72 /*const char mode18[][32] = {
74 { 0x03, 0x01, 0x08, 0x00, 0x06 },
75 { 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E,
76 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77 0xEA, 0x0C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xE3,
78 0xFF },
79 { 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x05, 0x0F,
80 0xFF },
81 { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
82 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
83 0x01, 0x00, 0x0F, 0x00, 0x00 }
84 };*/
86 /* Scrolls the screen */
87 void video_scroll (void)
89 unsigned blank, temp;
91 /* A blank is defined as a space... we need to give it
92 * backcolor too */
93 blank = 0x20 | (attrib << 8);
95 /* Row 25 is the end, this means we need to scroll up */
96 if (csr_y >= 25) {
97 /* Move the current text chunk that makes up the screen
98 * back in the buffer by a line */
99 temp = csr_y - 25 + 1;
100 memcpy (textmemptr, textmemptr + temp * 80, (25 - temp) * 80 * 2);
102 /* Finally, we set the chunk of memory that occupies
103 * the last line of text to our 'blank' character */
104 memsetw (textmemptr + (25 - temp) * 80, blank, 80);
105 csr_y = 25 - 1;
109 /* Updates the hardware cursor: the little blinking line
110 * on the screen under the last character pressed! */
111 void video_move_csr (void)
113 unsigned temp;
115 /* The equation for finding the index in a linear
116 * chunk of memory can be represented by:
117 * Index = [(y * width) + x] */
118 temp = csr_y * 80 + csr_x;
120 /* This sends a command to indicies 14 and 15 in the
121 * CRT Control Register of the VGA controller. These
122 * are the high and low bytes of the index that show
123 * where the hardware cursor is to be 'blinking'. */
124 outb (0x3D4, 14);
125 outb (0x3D5, temp >> 8);
126 outb (0x3D4, 15);
127 outb (0x3D5, temp);
130 /* Clears the screen */
131 void video_cls ()
133 unsigned blank;
134 int i;
136 /* Again, we need the 'short' that will be used to
137 * represent a space with color */
138 blank = 0x20 | (attrib << 8);
140 /* Sets the entire screen to spaces in our current
141 * color */
142 for (i = 0; i < 25; i ++)
143 memsetw (textmemptr + i * 80, blank, 80);
145 /* Update out virtual cursor, and then move the
146 * hardware cursor */
147 csr_x = 0;
148 csr_y = 0;
150 video_move_csr();
153 /* Puts a single character on the screen */
154 void video_putch (unsigned char c)
156 #ifndef CONFIG_UI_CONSOLESERIAL
157 unsigned short *where;
158 unsigned att = attrib << 8;
160 /* Handle a backspace, by moving the cursor back one space */
161 if (c == 0x08) {
162 if (csr_x != 0)
163 csr_x --;
165 /* delete last character */
166 where = textmemptr + (csr_y * 80 + csr_x);
167 *where = ' ' | att; /* Character AND attributes: color */
170 /* Handles a tab by incrementing the cursor's x, but only
171 * to a point that will make it divisible by 8 */
172 else if (c == 0x09)
173 csr_x = (csr_x + 8) & ~(8 - 1);
175 /* Handles a 'Carriage Return', which simply brings the
176 * cursor back to the margin */
177 else if (c == '\r')
178 csr_x = 0;
180 /* We handle our newlines the way DOS and the BIOS do: we
181 * treat it as if a 'CR' was also there, so we bring the
182 * cursor to the margin and we increment the 'y' value */
183 else if (c == '\n') {
184 csr_x = 0;
185 csr_y ++;
187 /* Any character greater than and including a space, is a
188 * printable character. The equation for finding the index
189 * in a linear chunk of memory can be represented by:
190 * Index = [(y * width) + x] */
191 else if (c >= ' ') {
192 where = textmemptr + (csr_y * 80 + csr_x);
193 *where = c | att; /* Character AND attributes: color */
194 csr_x ++;
197 /* If the cursor has reached the edge of the screen's width, we
198 * insert a new line in there */
199 if (csr_x >= 80) {
200 csr_x = 0;
201 csr_y ++;
204 /* Scroll the screen if needed, and finally move the cursor */
205 video_scroll ();
206 video_move_csr ();
207 #else
208 #ifdef CONFIG_DRV_RS232
209 /* Serial console output */
210 rs232_write ((char) c);
211 #endif
212 #endif
215 void video_setattrib (int attr)
217 attrib = attr;
220 int video_getattrib ()
222 return attrib;
225 /* Sets the forecolor and backcolor that we will use */
226 void video_color (unsigned char forecolor, unsigned char backcolor)
228 /* Top 4 bytes are the background, bottom 4 bytes
229 * are the foreground color */
230 attrib = (backcolor << 4) | (forecolor & 0x0F);
233 /* Set the cursor to selected position */
234 void video_gotoxy (unsigned x, unsigned y)
236 csr_x = x;
237 csr_y = y;
239 video_scroll ();
240 video_move_csr ();
243 /* video card mono/colour detection by Dark Fiber
244 * returns 0=mono, 1=colour
246 int video_type (void)
248 char c = (*(unsigned short*) 0x410&0x30);
250 /* C can be 0x00 or 0x20 for colour, 0x30 for mono */
251 if(c == 0x30)
252 return 0; // mono
253 else
254 return 1; // colour
257 /* Sets our text-mode VGA pointer, then clears the screen for us */
258 unsigned int init_video (void)
260 if (video_type ()) // check type of video card - color/mono
261 textmemptr = (unsigned short *) 0xB8000;
262 else
263 textmemptr = (unsigned short *) 0xA0000;
265 vgagui = 0;
267 video_cls ();
269 if (init_video_vesa ())
270 init_vgafb ();
272 return 1;
276 Graphics mode
279 char *init_vgafb ()
281 vgadb = (char *) 0;
282 vgafb = (char *) 0;
284 #ifdef CONFIG_DRV_VGA
285 int i;
287 /* VGA mode */
288 if (!vgagui) {
289 outb_p (0x63, MiscOutputReg);
290 outb_p (0x00, 0x3da);
292 for (i = 0; i < 5; i ++) {
293 outb_p (i, 0x3c4);
294 outb_p (mode13[0][i], 0x3c4+1);
297 outw_p (0x0e11, 0x3d4);
299 for (i = 0; i < 0x19; i ++) {
300 outb_p (i, 0x3d4);
301 outb_p (mode13[1][i], (0x3d4 + 1));
304 for (i = 0; i < 0x9; i ++) {
305 outb_p (i, 0x3ce);
306 outb_p (mode13[2][i], (0x3ce + 1));
309 inb_p (0x3da);
311 for (i = 0; i < 0x15; i ++) {
312 inw (DataReg);
313 outb_p (i, AddressReg);
314 outb_p (mode13[3][i], DataReg);
317 outb_p (0x20, 0x3c0);
319 vgagui = 1;
321 vgafb_res_x = 320;
322 vgafb_res_y = 200;
324 vgafb = (char *) 0xA0000;
325 vgadb = 0;//(char *) kmalloc (sizeof (char) * vgafb_res_x * vgafb_res_y);
328 #endif
329 #ifdef CONFIG_DRV_VESA
330 /* VESA mode */
331 if (vgagui == 2) {
332 vgafb_res_x = 800;
333 vgafb_res_y = 600;
335 vgafb = (char *) vesafb;
336 vgadb = (char *) 0x400000;//kmalloc (sizeof (short) * vgafb_res_x * vgafb_res_y);
337 //vgatb = (char *) PAGE_MEM_LOW+0x200000;//kmalloc (sizeof (char) * vgafb_res_x * vgafb_res_y);
340 if (!vgadb)
341 vgadb = vgafb;
342 #endif
344 return vgadb;
347 void video_gfx_exit ()
349 if (vgagui != 1) {
350 /* for VESA mode */
351 if (vgagui == 2)
352 video_gfx_cls (0);
354 return;
357 int i;
359 outb_p (0x67, MiscOutputReg);
360 outb_p (0x00, 0x3da);
362 for (i = 0; i < 5; i ++) {
363 outb_p (i, 0x3c4);
364 outb_p (mode03[0][i], 0x3c4+1);
367 outw_p (0x0e11, 0x3d4);
369 for (i = 0; i < 0x19; i ++) {
370 outb_p (i, 0x3d4);
371 outb_p (mode03[1][i], (0x3d4 + 1));
374 for (i = 0; i < 0x9; i ++) {
375 outb_p (i, 0x3ce);
376 outb_p (mode03[2][i], (0x3ce + 1));
379 inb_p (0x3da);
381 for (i = 0; i < 0x15; i ++) {
382 inw (DataReg);
383 outb_p (i, AddressReg);
384 outb_p (mode03[3][i], DataReg);
387 outb_p (0x20, 0x3c0);
389 vgagui = 0;
391 vgafb_res_x = 0;
392 vgafb_res_y = 0;
394 if (vgadb != vgafb)
395 kfree (vgadb);
398 /* Draw pixel (dot) on the screen with specified color */
399 void video_gfx_pixel (unsigned x, unsigned y, unsigned color)
401 if (x >= vgafb_res_x || y >= vgafb_res_y)
402 return;
404 unsigned i = y * vgafb_res_x + x;
406 if (vgagui == 2) {
407 unsigned short *db = (unsigned short *) vgadb;
409 db[i] = color;
411 return;
414 if (vgagui == 1) {
415 vgadb[i] = color;
417 return;
421 /* Swap double-buffered screen */
422 void video_gfx_fbswap ()
424 paging_disable ();
426 #ifdef CONFIG_DRV_GMM
427 unsigned l = (vgafb_res_x * vgafb_res_y) / 2;
428 unsigned i = 0;
429 unsigned *fb = (unsigned *) vgafb;
430 unsigned *db = (unsigned *) vgadb;
432 for (; i < l; i ++) {
433 fb[i] = db[i];
434 db[i] = 0;
436 #else
437 if (vgadb != vgafb) {
438 unsigned l = vgafb_res_x * vgafb_res_y * vgagui;
439 unsigned i = 0;
440 for (i = 0; i < l; i ++) {
441 vgafb[i] = vgadb[i];
442 vgadb[i] = 0;
445 #endif
447 paging_enable ();
450 /* Clear screen with specified color*/
451 void video_gfx_cls (unsigned color)
453 unsigned short *db = (unsigned short *) vgadb;
455 unsigned x;
456 unsigned l = vgafb_res_x * vgafb_res_y;
458 for (x = 0; x < l; x ++)
459 db[x] = color;
462 #endif
464 /** ARM architecture **/
465 #ifdef ARCH_arm
466 /* Draw pixel (dot) on the screen with specified color */
467 void video_gfx_pixel (unsigned x, unsigned y, unsigned color)
469 unsigned i = y * 640 + x;
470 unsigned short *db = (unsigned short *) 0x500000;
472 db[i] = color;
475 /* Clear screen with specified color*/
476 void video_gfx_cls (unsigned color)
478 unsigned short *db = (unsigned short *) vgadb;
480 unsigned x;
481 unsigned l = vgafb_res_x * vgafb_res_y;
483 for (x = 0; x < l; x ++)
484 db[x] = color;
487 /* Swap double-buffered screen */
488 void video_gfx_fbswap ()
490 /*#ifdef CONFIG_DRV_GMM
491 unsigned l = (vgafb_res_x * vgafb_res_y) / 2;
492 unsigned i = 0;
493 unsigned *fb = (unsigned *) vgafb;
494 unsigned *db = (unsigned *) vgadb;
496 for (; i < l; i ++) {
497 fb[i] = db[i];
498 db[i] = 0;
500 #else
501 if (vgadb != vgafb) {
502 unsigned l = vgafb_res_x * vgafb_res_y * vgagui;
503 unsigned i = 0;
504 for (i = 0; i < l; i ++) {
505 vgafb[i] = vgadb[i];
506 vgadb[i] = 0;
509 #endif*/
512 void video_putch (unsigned char c)
514 /* uart output for embedded devices */
515 rs232_write ((char) c);
518 /* Sets the forecolor and backcolor that we will use */
519 void video_color (unsigned char forecolor, unsigned char backcolor)
521 /* Top 4 bytes are the background, bottom 4 bytes
522 * are the foreground color */
523 attrib = (backcolor << 4) | (forecolor & 0x0F);
526 void video_cls ()
531 /* Set the cursor to selected position */
532 void video_gotoxy (unsigned x, unsigned y)
537 unsigned int init_video (void)
539 return 0;
541 #endif
543 /* Device handler */
544 bool video_acthandler (unsigned act, char *block, char *more, int block_len)
546 switch (act) {
547 case DEV_ACT_INIT:
550 return 1;
552 break;
555 return 0;