jinix內(nèi)核虛擬控制臺(tái)實(shí)現(xiàn)(原創(chuàng))
Posted on 2007-07-10 20:15 天衣有縫 閱讀(2046) 評(píng)論(2) 編輯 收藏 引用 所屬分類: os stuffjinix是小弟正在實(shí)現(xiàn)的一個(gè)c++
kernel,因?yàn)檎{(diào)試緣故,所以早早的把控制臺(tái)部分調(diào)出來了,以便于后來的調(diào)試。代碼使用c++寫的,如果使用c寫內(nèi)核也很容易移植過去。轉(zhuǎn)載請(qǐng)保留原 創(chuàng):http://m.shnenglu.com/jinglexy,mail & msn: jinglexy at yahoo dot com dot cn。這部分代碼是在內(nèi)存管理之前實(shí)現(xiàn)的,所以沒有做到任意個(gè)數(shù)虛擬控制臺(tái)(內(nèi)核在編譯時(shí)候確定個(gè)數(shù)),并且每個(gè)控制臺(tái)顯存地址固定起來了。如果要實(shí)現(xiàn)也 比較簡單:啟動(dòng)時(shí)候初始化一個(gè)控制臺(tái),在MM初始化完后初始化其他控制臺(tái),每個(gè)控制臺(tái)包含自己的顯存緩沖區(qū),切換控制臺(tái)的時(shí)候?qū)⒃摼彌_區(qū)拷貝到顯存中即 可。
文件:textio.h, textio.cpp, ostream.h, ostream.cpp
textio.h源文件如下:
1: #ifndef __JINIX_TEXTIO_H
2: #define __JINIX_TEXTIO_H
3: #include <jinix/types.h>
4:
5: /* 在字符模式下,適配器使用0xB8000-0xBF000作為視頻內(nèi)存。
6: * 通常我們處于80x25大小屏幕,有16種顏色。
7: * 由于一個(gè)屏幕只需要80x25x2個(gè)字節(jié),即4k,所以該視頻內(nèi)存可以分為多個(gè)頁。
8: * 我們使用所有的頁,但是當(dāng)前只能有一個(gè)頁面可見。
9: * 為了顯示一個(gè)字符,將用到2個(gè)字節(jié),一個(gè)字節(jié)是字符值(地址為N),
10: * 另一個(gè)字節(jié)是字符屬性(即顏色,地址為N + 1)。屬性字節(jié)定義如下:
11: *
12: * Bit 7 閃爍
13: * Bits 6-4 背景色
14: * Bit 3 明亮模式(0為暗,1為亮)
15: * Bit3 2-0 前景色:分別是黑,蘭,綠,青,洋紅,深粉,深黃,灰色
16: *
17: * 操作端口基址:0x3d4h, 0x3d5h
18: * 參考資料:osd文檔中的osd/cons/index.htm
19: * CGA顯示模式,顯存從0xB8000開始一共32kb字節(jié),在jinix中每個(gè)虛擬控制臺(tái)只使用4k字節(jié)(80x25x2),
20: * 且不考慮滾屏操作(為了簡單處理),所以最多可以有8個(gè)控制臺(tái)
21: */
22: typedef enum {
23: BLACK, BLUE, GREEN, CYAN,
24: RED, MAGENTA, BROWN, GRAY,
25: DARKGRAY, LIGHTBLUE, LIGHTGREEN, LIGHTCYAN,
26: LIGHTRED, LIGHTMAGENTA, YELLOW, WHITE
27: } TextColor;
28:
29: const int CGA_VIDEO_PTR = 0xB8000;
30: const int CGA_CONSOLE_SIZE = 4000;
31: const char BLANK_CHAR = ' ';
32:
33: class TextIO
34: {
35: public:
36: TextIO() ;
37: ~TextIO() ;
38: void init_page(int page); /* must call first!!! */
39: void move_cursor(void);
40: void move_page(void);
41: void setxy(int newx, int newy);
42:
43: int getx() { return x; }
44: int gety() { return y; }
45:
46: void scrollup();
47: void clear();
48:
49: void set_fg(TextColor fg);
50: void set_bg(TextColor bg);
51:
52: void putstr(char *s);
53: /* inline */void putchar(char c);
54:
55: private:
56: int x, y;
57: char colors;
58: char *pvideo_start; /* 虛擬控制臺(tái)顯存首地址 */
59: /* struct termios termios; posix compatible later... */
60: };
61:
62: #endif
63:
64:
這個(gè)文件完成顯存的一些字符操作,及顯存頁面切換,滾屏也很簡單。沒有加入posix兼容的一些特性,
還沒有想好是否加在這里。rs232也會(huì)使用終端特性,所以考慮后期將字符設(shè)備驅(qū)動(dòng)抽象成一個(gè)基類,
作為textio類的父類。有什么好的想法可以和我討論:http://m.shnenglu.com/jinglexy
ostream.h源文件:
1: #ifndef __JINIX_OSTREAM_H
2: #define __JINIX_OSTREAM_H
3: #include <jinix/textio.h>
4:
5: /* format flags */
6: #define boolalpha 0x0001 /* 未實(shí)現(xiàn) */
7: #define showbase 0x0002
8: #define showpoint 0x0004 /* 未實(shí)現(xiàn) */
9: #define showpos 0x0008 /* 未實(shí)現(xiàn) */
10: #define skipws 0x0010 /* 未實(shí)現(xiàn) */
11: #define unitbuf 0x0020 /* 未實(shí)現(xiàn) */
12: #define uppercase 0x0040 /* 未實(shí)現(xiàn) */
13: #define dec 0x0080
14: #define hex 0x0100
15: #define oct 0x0200
16: #define bin 0x0400
17: #define internal 0x0800 /* 未實(shí)現(xiàn) */
18: #define left 0x1000 /* 未實(shí)現(xiàn) */
19: #define right 0x2000 /* 未實(shí)現(xiàn) */
20:
21: class OStream : public TextIO
22: {
23: public:
24: OStream();
25: OStream& operator <<(char *str);
26: OStream& operator <<(char c);
27: OStream& operator <<(unsigned char *str);
28: OStream& operator <<(unsigned char c);
29: OStream& operator <<(int i);
30: OStream& operator <<(unsigned int i);
31: OStream& operator <<(long i);
32: OStream& operator <<(unsigned long i);
33: OStream& operator <<(long long i);
34: OStream& operator <<(unsigned long long i);
35: void flags(int f);
36:
37: private:
38: int current_flags; /* 顯示模式: 進(jìn)制數(shù), 對(duì)齊形式等 */
39: };
40:
41: #define cout __vconsole[__cur_console]
42: void switch_console(int console);
43:
44: /* 單元測(cè)試 */
45: void ostream_dotest(void);
46:
47: /* 不要使用下面兩個(gè)全局變量 */
48: extern class OStream __vconsole[];
49: extern int __cur_console;
50: #endif
51:
52:
不熟悉設(shè)計(jì)模式,所以結(jié)構(gòu)比較混亂,好的模式應(yīng)該可以規(guī)避這些不雅的代碼吧,呵呵
textio.cpp源文件:
1: #include <asm/portio.h>
2: #include <asm/system.h>
3: #include <jinix/tty.h>
4: #include <jinix/textio.h>
5:
6: TextIO::TextIO()
7: {
8: x = 0;
9: y = 0;
10: colors = TTY_CHAR_ATTRIBUTE;
11: pvideo_start = (char*)NULL;
12: }
13:
14: TextIO::~TextIO()
15: {
16: }
17:
18: void TextIO::init_page(int page)
19: {
20: if (page < 0 || page > VIRTUAL_CONSOLE_COUNT - 1)
21: return;
22:
23: /* after init, console[0].pvideo_start is 0xb8000;
24: * console[1].pvideo_start is 0xb8fa0
25: * console[2].pvideo_start is 0xb9f40
26: * console[3].pvideo_start is 0xbaee0
27: */
28: pvideo_start = (char*)CGA_VIDEO_PTR + page * CGA_CONSOLE_SIZE;
29: /* debug(if not, gdb fly out): */ page++;
30: }
31:
32: void TextIO::move_cursor(void)
33: {
34: int temp;
35: temp = y * TTY_COLUMNS_NR + x;
36:
37: /* disable interrupt */
38: __cli();
39: PortIO::outportb(0x3D4, 14);
40: PortIO::outportb(0x3D5, temp >> 8);
41: PortIO::outportb(0x3D4, 15);
42: PortIO::outportb(0x3D5, temp);
43: /* enable interrupt */
44: __sti();
45: }
46:
47: void TextIO::move_page(void)
48: {
49: int temp;
50: temp = (int)(pvideo_start - CGA_VIDEO_PTR) / 2;
51:
52: /* disable interrupt */
53: __cli();
54: PortIO::outportb(0x3D4, 12);
55: PortIO::outportb(0x3D5, temp >> 8);
56: PortIO::outportb(0x3D4, 13);
57: PortIO::outportb(0x3D5, temp);
58: /* enable interrupt */
59: __sti();
60: }
61:
62: void TextIO::setxy(int newx, int newy)
63: {
64: if (newx >= 0 && newx < TTY_COLUMNS_NR)
65: x = newx;
66:
67: if (newy >= 0 && newy < TTY_LINES_NR)
68: y = newy;
69: }
70:
71: /* it will scroll only one line */
72: void TextIO::scrollup()
73: {
74: char *src, *dst;
75: int i, j;
76:
77: dst = pvideo_start;
78: src = pvideo_start + TTY_COLUMNS_NR * 2;
79:
80: for (i = 0; i < TTY_LINES_NR - 1; i++)
81: for (j = 0; j < TTY_COLUMNS_NR * 2; j++) /* every char 2 bytes */
82: *dst++ = *src++;
83:
84: /* new line */
85: for (i = 0; i < TTY_COLUMNS_NR; i++) {
86: *dst++ = BLANK_CHAR;
87: *dst++ = colors;
88: }
89: }
90:
91: void TextIO::clear(void)
92: {
93: int i;
94: char *src;
95:
96: src = pvideo_start;
97: for (i = 0; i < TTY_COLUMNS_NR * TTY_LINES_NR; i++) {
98: *src++ = BLANK_CHAR;
99: *src++ = colors;
100: }
101:
102: setxy(0, 0);
103: move_cursor();
104: }
105:
106: void TextIO::set_fg(TextColor fg)
107: {
108: colors = (colors & 0xf0) | (fg & 0x0f);
109: }
110:
111: void TextIO::set_bg(TextColor bg)
112: {
113: colors = (colors & 0x0f) | ((bg << 4) & 0xf0);
114: }
115:
116: void TextIO::putstr(char *s)
117: {
118: while (*s)
119: putchar(*s++);
120: }
121:
122: /* extern inline */void TextIO::putchar(char c)
123: {
124: int t;
125:
126: switch(c) {
127: case '\r':
128: {
129: int i;
130: x = 0;
131:
132: /* 清除一行 */
133: t = ((x + y * TTY_COLUMNS_NR) << 1);
134: for(i = 0 ; i < TTY_COLUMNS_NR; i++) {
135: *(pvideo_start + t + (i << 1)) = BLANK_CHAR;
136: *(pvideo_start + t + (i << 1) + 1) = colors;
137: }
138: break;
139: }
140:
141: case '\n':
142: {
143: x = 0;
144: y++;
145: break;
146: }
147:
148: case '\t':
149: {
150: if (x + TTY_TABWIDTH >= TTY_COLUMNS_NR) {
151: x = (x + TTY_TABWIDTH - TTY_COLUMNS_NR);
152: y++;
153: } else {
154: x += TTY_TABWIDTH;
155: }
156:
157: break;
158: }
159:
160: case '\b':
161: {
162: t = x + y * TTY_COLUMNS_NR;
163:
164: if (t <= 0)
165: break;
166: t--;
167:
168: if (x > 0) {
169: x--;
170: } else {
171: y--;
172: x = TTY_COLUMNS_NR - 1;
173: }
174:
175: *(pvideo_start + (t << 1)) = BLANK_CHAR;
176: *(pvideo_start + (t << 1) + 1) = colors;
177: break;
178: }
179:
180: default:
181: {
182: if(c < ' ') break; /* only print visible char */
183: t = x + y * TTY_COLUMNS_NR;
184:
185: *(pvideo_start + (t << 1)) = c;
186: *(pvideo_start + (t << 1) + 1) = colors;
187: x++;
188:
189: if(x == 80) {
190: x = 0;
191: y++;
192: }
193: break;
194: }
195: }
196:
197: if (TTY_LINES_NR == y) {
198: scrollup();
199: y--;
200: }
201: move_cursor();
202: }
203:
204:
需要注意的是多個(gè)端口同時(shí)操作需要關(guān)閉中斷,否則一旦在多任務(wù)中被調(diào)度出去,后果很嚴(yán)重,呵呵
1: #include <jinix/tty.h>
2: #include <jinix/ostream.h>
3: #include <asm/string.h>
4:
5: class OStream __vconsole[VIRTUAL_CONSOLE_COUNT];
6: int __cur_console; /* 當(dāng)前控制臺(tái) */
7:
8: OStream::OStream()
9: {
10: current_flags = dec;
11: }
12:
13: OStream& OStream::operator <<(char *str)
14: {
15: putstr(str);
16: return *this;
17: }
18:
19: OStream& OStream::operator <<(char c)
20: {
21: putchar(c);
22: return *this;
23: }
24:
25: OStream& OStream::operator <<(unsigned char *str)
26: {
27: putstr((char *)str);
28: return *this;
29: }
30:
31: OStream& OStream::operator <<(unsigned char c)
32: {
33: putchar((char)c);
34: return *this;
35: }
36:
37: OStream& OStream::operator <<(int i)
38: {
39: char buf[33]; /* 2進(jìn)制支持 */
40:
41: if (current_flags & dec)
42: itoa(buf, 10, i);
43: else if (current_flags & hex)
44: itoa(buf, 16, i);
45: else if (current_flags & oct)
46: itoa(buf, 8, i);
47: else if (current_flags & bin)
48: itoa(buf, 2, i);
49:
50: if (current_flags & hex && current_flags & showbase)
51: putstr("0x");
52:
53: putstr(buf);
54: return *this;
55: }
56:
57: OStream& OStream::operator <<(unsigned int i)
58: {
59: *this << (int)i;
60: return *this;
61: }
62:
63: OStream& OStream::operator <<(long i)
64: {
65: *this << (int)i;
66: return *this;
67: }
68:
69: OStream& OStream::operator <<(unsigned long i)
70: {
71: *this << (int)i;
72: return *this;
73: }
74:
75: OStream& OStream::operator <<(long long i)
76: {
77: char buf[65]; /* 2進(jìn)制支持 */
78:
79: if (current_flags & dec)
80: itoa(buf, 10, i);
81: else if (current_flags & hex)
82: itoa(buf, 16, i);
83: else if (current_flags & oct)
84: itoa(buf, 8, i);
85: else if (current_flags & bin)
86: itoa(buf, 2, i);
87:
88: if (current_flags & hex && current_flags & showbase)
89: putstr("0x");
90:
91: putstr(buf);
92: return *this;
93: }
94:
95: OStream& OStream::operator <<(unsigned long long i)
96: {
97: *this << (long long)i;
98: return *this;
99: }
100:
101: void OStream::flags(int f)
102: {
103: current_flags = f;
104: }
105:
106: void switch_console(int console)
107: {
108: if (console < 0 || console > VIRTUAL_CONSOLE_COUNT - 1)
109: return;
110:
111: /* set current console */
112: __cur_console = console;
113:
114: /* move page */
115: cout.move_page();
116:
117: /* move cursor */
118: cout.move_cursor();
119: }
120:
121: /* only call when init */
122: void __kernel_init_switch_console(int console)
123: {
124: if (console < 0 || console > VIRTUAL_CONSOLE_COUNT - 1)
125: return;
126:
127: /* set current console */
128: __cur_console = console;
129: }
130:
131: void ostream_dotest(void)
132: {
133: int i;
134:
135: i = 0;
136: {
137: /* 虛擬控制臺(tái)切換測(cè)試 */
138: for(i = 0; i < VIRTUAL_CONSOLE_COUNT; i++) {
139: switch_console(i);
140: cout.putstr("0123456789abcdefghijklmnoprfdsafdieqxzcvaeax");
141: }
142:
143: for(i = 0; i < VIRTUAL_CONSOLE_COUNT; i++) {
144: switch_console(i);
145: cout.putstr("0123456789abcdefghijklmnoprfdsafdieqxzcvaeax");
146: }
147:
148: switch_console(0);
149: cout.putstr("00000000000000000000000");
150: switch_console(1);
151: cout.putstr("11111111111111111111111");
152: switch_console(2);
153: cout.putstr("22222222222222222222222");
154: switch_console(3);
155: cout.putstr("33333333333333333333333");
156: }
157:
158: {
159: /* 復(fù)雜字符串輸出測(cè)試 */
160: switch_console(0);
161: for(i = 0; i < 20; i++) {
162: cout.putstr("++++++++++++++++++++");
163: cout.putstr("++++++++++++++++++++");
164: cout.putstr("++++++++++++++++++++");
165: cout.putstr("++++++++++++++++++++");
166: }
167:
168: cout.putstr("\r");
169: cout.putstr("00000000000000000000000\n");
170: cout.putstr("0\t0\t0\t0\t0\t0\t0\t0\t0\t0\ta\n");
171: cout.putstr("+_+_+_+_+_+_+_+_+_+_+_");
172: cout.putstr("\b\b\b\b\b*&*&*&*&*&*&*&*&");
173: i++;
174: }
175:
176: {
177: /* 清屏,滾屏,及滾屏對(duì)切換虛擬控制臺(tái)的影響測(cè)試 */
178: cout.clear();
179: for(i = 0; i < 24; i++) {
180: cout.putstr("++++++++++++++++++++");
181: cout.putstr("++++++++++++++++++++");
182: cout.putstr("++++++++++++++++++++");
183: cout.putstr("++++++++++++++++++++");
184: }
185: cout.putstr("_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+");
186: switch_console(1);
187: cout.putstr("in console 1 now\n");
188: switch_console(0);
189: cout.putstr("aaa");
190: i++;
191: }
192:
193: {
194: /* 顏色測(cè)試 */
195: /*
196: BLACK, BLUE, GREEN, CYAN,
197: RED, MAGENTA, BROWN, GRAY,
198: DARKGRAY, LIGHTBLUE, LIGHTGREEN, LIGHTCYAN,
199: LIGHTRED, LIGHTMAGENTA, YELLOW, WHITE
200: */
201: switch_console(0);
202: cout.set_fg(GREEN);
203: /* cout.set_fg(LIGHTBLUE); */
204: /* cout.set_bg(GREEN); */
205: cout.putstr("bad boy, y you goto here?\n");
206: cout.putstr("sorry, sir, never again\n");
207: i++;
208: }
209:
210: {
211: /* ostream類測(cè)試 */
212: switch_console(0);
213: cout << "hi, " << "Welcome use cout object.\n";
214: extern unsigned int multiboot_magic;
215: cout.flags(hex | showbase);
216: multiboot_magic = 0x1BADB002;
217: cout << "after boot, the magic is " << multiboot_magic << "\n";
218: cout << "are you satisfaction with cout?\n";
219: i++;
220: }
221: }
222:
223:
上面代碼包含了測(cè)試用例,現(xiàn)在我們的c++ 內(nèi)核也可以用cout 對(duì)象了,是不是很有成就感?