command help was optimized for all possible screen resolutions; command fdisk support...
[ZeXOS.git] / kernel / drivers / char / video / video.c
blobd3a21aafa5de4fea5901318ebd8c510e3da9be11
1 /*
2 * ZeX/OS
3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
4 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
5 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
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;
30 #ifdef ARCH_i386
32 /* These define our textpointer, our background and foreground
33 * colors (attributes), and x and y cursor coordinates */
34 unsigned short *textmemptr;
35 int attrib = 0x0F;
36 int csr_x = 0, csr_y = 0;
38 const int MiscOutputReg = 0x3c2;
39 const int DataReg = 0x3c0;
40 const int AddressReg = 0x3c0;
42 const char mode03[][32] = {
43 { 0x03, 0x00, 0x03, 0x00, 0x02 },
44 { 0x5F, 0x4F, 0x50, 0x82, 0x55, 0x81, 0xBF, 0x1F,
45 0x00, 0x4F, 0x0D, 0x0E, 0x00, 0x00, 0x00, 0x50,
46 0x9C, 0x0E, 0x8F, 0x28, 0x1F, 0x96, 0xB9, 0xA3,
47 0xFF },
48 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x00,
49 0xFF },
50 { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
51 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
52 0x0C, 0x00, 0x0F, 0x08, 0x00 }
55 const char mode13[][32] = {
56 { 0x03, 0x01, 0x0f, 0x00, 0x0e }, /* 0x3c4, index 0-4*/
57 { 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f,
58 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59 0x9c, 0x0e, 0x8f, 0x28, 0x40, 0x96, 0xb9, 0xa3,
60 0xff }, /* 0x3d4, index 0-0x18*/
61 { 0, 0, 0, 0, 0, 0x40, 0x05, 0x0f, 0xff }, /* 0x3ce, index 0-8*/
62 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
63 0x41, 0, 0x0f, 0, 0 } /* 0x3c0, index 0-0x14*/
66 /*const char mode18[][32] = {
68 { 0x03, 0x01, 0x08, 0x00, 0x06 },
69 { 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E,
70 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71 0xEA, 0x0C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xE3,
72 0xFF },
73 { 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x05, 0x0F,
74 0xFF },
75 { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
76 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
77 0x01, 0x00, 0x0F, 0x00, 0x00 }
78 };*/
80 /* Scrolls the screen */
81 void scroll (void)
83 unsigned blank, temp;
85 /* A blank is defined as a space... we need to give it
86 * backcolor too */
87 blank = 0x20 | (attrib << 8);
89 /* Row 25 is the end, this means we need to scroll up */
90 if (csr_y >= 25) {
91 /* Move the current text chunk that makes up the screen
92 * back in the buffer by a line */
93 temp = csr_y - 25 + 1;
94 memcpy (textmemptr, textmemptr + temp * 80, (25 - temp) * 80 * 2);
96 /* Finally, we set the chunk of memory that occupies
97 * the last line of text to our 'blank' character */
98 memsetw (textmemptr + (25 - temp) * 80, blank, 80);
99 csr_y = 25 - 1;
103 /* Updates the hardware cursor: the little blinking line
104 * on the screen under the last character pressed! */
105 void move_csr (void)
107 unsigned temp;
109 /* The equation for finding the index in a linear
110 * chunk of memory can be represented by:
111 * Index = [(y * width) + x] */
112 temp = csr_y * 80 + csr_x;
114 /* This sends a command to indicies 14 and 15 in the
115 * CRT Control Register of the VGA controller. These
116 * are the high and low bytes of the index that show
117 * where the hardware cursor is to be 'blinking'. */
118 outb (0x3D4, 14);
119 outb (0x3D5, temp >> 8);
120 outb (0x3D4, 15);
121 outb (0x3D5, temp);
124 /* Clears the screen */
125 void cls ()
127 unsigned blank;
128 int i;
130 /* Again, we need the 'short' that will be used to
131 * represent a space with color */
132 blank = 0x20 | (attrib << 8);
134 /* Sets the entire screen to spaces in our current
135 * color */
136 for (i = 0; i < 25; i ++)
137 memsetw (textmemptr + i * 80, blank, 80);
139 /* Update out virtual cursor, and then move the
140 * hardware cursor */
141 csr_x = 0;
142 csr_y = 0;
144 move_csr();
147 /* Puts a single character on the screen */
148 void putch (unsigned char c)
150 #ifndef CONFIG_UI_CONSOLESERIAL
151 unsigned short *where;
152 unsigned att = attrib << 8;
154 /* Handle a backspace, by moving the cursor back one space */
155 if (c == 0x08) {
156 if (csr_x != 0)
157 csr_x --;
159 /* delete last character */
160 where = textmemptr + (csr_y * 80 + csr_x);
161 *where = ' ' | att; /* Character AND attributes: color */
164 /* Handles a tab by incrementing the cursor's x, but only
165 * to a point that will make it divisible by 8 */
166 else if (c == 0x09)
167 csr_x = (csr_x + 8) & ~(8 - 1);
169 /* Handles a 'Carriage Return', which simply brings the
170 * cursor back to the margin */
171 else if (c == '\r')
172 csr_x = 0;
174 /* We handle our newlines the way DOS and the BIOS do: we
175 * treat it as if a 'CR' was also there, so we bring the
176 * cursor to the margin and we increment the 'y' value */
177 else if (c == '\n') {
178 csr_x = 0;
179 csr_y ++;
181 /* Any character greater than and including a space, is a
182 * printable character. The equation for finding the index
183 * in a linear chunk of memory can be represented by:
184 * Index = [(y * width) + x] */
185 else if (c >= ' ') {
186 where = textmemptr + (csr_y * 80 + csr_x);
187 *where = c | att; /* Character AND attributes: color */
188 csr_x ++;
191 /* If the cursor has reached the edge of the screen's width, we
192 * insert a new line in there */
193 if (csr_x >= 80) {
194 csr_x = 0;
195 csr_y ++;
198 /* Scroll the screen if needed, and finally move the cursor */
199 scroll ();
200 move_csr ();
201 #else
202 #ifdef CONFIG_DRV_RS232
203 /* Serial console output */
204 rs232_write ((char) c);
205 #endif
206 #endif
209 /* Sets the forecolor and backcolor that we will use */
210 void settextcolor (unsigned char forecolor, unsigned char backcolor)
212 /* Top 4 bytes are the background, bottom 4 bytes
213 * are the foreground color */
214 attrib = (backcolor << 4) | (forecolor & 0x0F);
217 /* Set the cursor to selected position */
218 void gotoxy (unsigned x, unsigned y)
220 csr_x = x;
221 csr_y = y;
223 scroll ();
224 move_csr ();
227 /* video card mono/colour detection by Dark Fiber
228 * returns 0=mono, 1=colour
230 int video_type (void)
232 char c = (*(unsigned short*) 0x410&0x30);
234 /* C can be 0x00 or 0x20 for colour, 0x30 for mono */
235 if(c == 0x30)
236 return 0; // mono
237 else
238 return 1; // colour
241 /* Sets our text-mode VGA pointer, then clears the screen for us */
242 unsigned int init_video (void)
244 if (video_type ()) // check type of video card - color/mono
245 textmemptr = (unsigned short *) 0xB8000;
246 else
247 textmemptr = (unsigned short *) 0xA0000;
249 vgagui = 0;
251 cls ();
253 if (init_video_vesa ())
254 init_vgafb ();
256 return 1;
260 Graphics mode
263 extern unsigned short *vesafb;
264 char *vgafb; /* frame buffer */
265 char *vgadb; /* double buffer */
267 unsigned vgafb_res_x, vgafb_res_y;
269 char *init_vgafb ()
271 vgadb = (char *) 0;
272 vgafb = (char *) 0;
274 #ifdef CONFIG_DRV_VGA
275 int i;
277 /* VGA mode */
278 if (!vgagui) {
279 outb_p (0x63, MiscOutputReg);
280 outb_p (0x00, 0x3da);
282 for (i = 0; i < 5; i ++) {
283 outb_p (i, 0x3c4);
284 outb_p (mode13[0][i], 0x3c4+1);
287 outw_p (0x0e11, 0x3d4);
289 for (i = 0; i < 0x19; i ++) {
290 outb_p (i, 0x3d4);
291 outb_p (mode13[1][i], (0x3d4 + 1));
294 for (i = 0; i < 0x9; i ++) {
295 outb_p (i, 0x3ce);
296 outb_p (mode13[2][i], (0x3ce + 1));
299 inb_p (0x3da);
301 for (i = 0; i < 0x15; i ++) {
302 inw (DataReg);
303 outb_p (i, AddressReg);
304 outb_p (mode13[3][i], DataReg);
307 outb_p (0x20, 0x3c0);
309 vgagui = 1;
311 vgafb_res_x = 320;
312 vgafb_res_y = 200;
314 vgafb = (char *) 0xA0000;
315 vgadb = 0;//(char *) kmalloc (sizeof (char) * vgafb_res_x * vgafb_res_y);
318 #endif
319 #ifdef CONFIG_DRV_VESA
320 /* VESA mode */
321 if (vgagui == 2) {
322 vgafb_res_x = 800;
323 vgafb_res_y = 600;
325 vgafb = (char *) vesafb;
326 vgadb = (char *) PAGE_MEM_LOW+0x100000;//kmalloc (sizeof (short) * vgafb_res_x * vgafb_res_y);
327 //vgatb = (char *) PAGE_MEM_LOW+0x200000;//kmalloc (sizeof (char) * vgafb_res_x * vgafb_res_y);
330 if (!vgadb)
331 vgadb = vgafb;
332 #endif
334 return vgadb;
337 void gexit ()
339 if (vgagui != 1) {
340 /* for VESA mode */
341 if (vgagui == 2)
342 gcls (0);
344 return;
347 int i;
349 outb_p (0x67, MiscOutputReg);
350 outb_p (0x00, 0x3da);
352 for (i = 0; i < 5; i ++) {
353 outb_p (i, 0x3c4);
354 outb_p (mode03[0][i], 0x3c4+1);
357 outw_p (0x0e11, 0x3d4);
359 for (i = 0; i < 0x19; i ++) {
360 outb_p (i, 0x3d4);
361 outb_p (mode03[1][i], (0x3d4 + 1));
364 for (i = 0; i < 0x9; i ++) {
365 outb_p (i, 0x3ce);
366 outb_p (mode03[2][i], (0x3ce + 1));
369 inb_p (0x3da);
371 for (i = 0; i < 0x15; i ++) {
372 inw (DataReg);
373 outb_p (i, AddressReg);
374 outb_p (mode03[3][i], DataReg);
377 outb_p (0x20, 0x3c0);
379 vgagui = 0;
381 vgafb_res_x = 0;
382 vgafb_res_y = 0;
384 if (vgadb != vgafb)
385 kfree (vgadb);
388 /* Draw pixel (dot) on the screen with specified color */
389 void gpixel (unsigned x, unsigned y, unsigned color)
391 if (x >= vgafb_res_x || y >= vgafb_res_y)
392 return;
394 unsigned i = y * vgafb_res_x + x;
396 if (vgagui == 2) {
397 unsigned short *db = (unsigned short *) vgadb;
399 db[i] = color;
401 return;
404 if (vgagui == 1) {
405 vgadb[i] = color;
407 return;
411 /* Swap double-buffered screen */
412 void gfbswap ()
414 paging_disable ();
416 #ifdef CONFIG_DRV_GMM
417 unsigned l = (vgafb_res_x * vgafb_res_y) / 2;
418 unsigned i = 0;
419 unsigned *fb = (unsigned *) vgafb;
420 unsigned *db = (unsigned *) vgadb;
422 for (; i < l; i ++) {
423 fb[i] = db[i];
424 db[i] = 0;
426 #else
427 if (vgadb != vgafb) {
428 unsigned l = vgafb_res_x * vgafb_res_y * vgagui;
429 unsigned i = 0;
430 for (i = 0; i < l; i ++) {
431 vgafb[i] = vgadb[i];
432 vgadb[i] = 0;
435 #endif
437 paging_enable ();
440 /* Clear screen with specified color*/
441 void gcls (unsigned color)
443 unsigned short *db = (unsigned short *) vgadb;
445 unsigned x;
446 unsigned l = vgafb_res_x * vgafb_res_y;
448 for (x = 0; x < l; x ++)
449 db[x] = color;
452 #endif
454 /** ARM architecture **/
455 #ifdef ARCH_arm
456 void putch (unsigned char c)
458 /* uart output for embedded devices */
459 rs232_write ((char) c);
462 /* Sets the forecolor and backcolor that we will use */
463 void settextcolor (unsigned char forecolor, unsigned char backcolor)
468 void cls ()
473 /* Set the cursor to selected position */
474 void gotoxy (unsigned x, unsigned y)
479 unsigned int init_video (void)
482 return 0;
484 #endif
486 /* Device handler */
487 bool video_acthandler (unsigned act, char *block, char *more, int block_len)
489 switch (act) {
490 case DEV_ACT_INIT:
493 return 1;
495 break;
498 return 0;