Annotation of prex-old/dev/i386/pc/console.c, Revision 1.1.1.1
1.1 nbrk 1: /*-
2: * Copyright (c) 2005-2007, Kohsuke Ohtani
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. Neither the name of the author nor the names of any co-contributors
14: * may be used to endorse or promote products derived from this software
15: * without specific prior written permission.
16: *
17: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27: * SUCH DAMAGE.
28: */
29:
30: /*
31: * console.c - pc console driver
32: */
33:
34: #include <driver.h>
35: #include <cpu.h>
36: #include <sys/tty.h>
37:
38: #define CRTC_INDEX 0x3d4
39: #define CRTC_DATA 0x3d5
40: #define GRAC_INDEX 0x3ce
41: #define GRAC_DATA 0x3cf
42:
43: #define VID_RAM 0xB8000
44:
45: static int console_init(void);
46: static int console_read(device_t, char *, size_t *, int);
47: static int console_write(device_t, char *, size_t *, int);
48: static int console_ioctl(device_t, int, u_long);
49:
50: /*
51: * Driver structure
52: */
53: struct driver console_drv = {
54: /* name */ "Console",
55: /* order */ 4,
56: /* init */ console_init,
57: };
58:
59: static struct devio console_io = {
60: /* open */ NULL,
61: /* close */ NULL,
62: /* read */ console_read,
63: /* write */ console_write,
64: /* ioctl */ console_ioctl,
65: /* event */ NULL,
66: };
67:
68: static device_t console_dev;
69: static struct tty console_tty;
70:
71: static short *vram;
72: static int pos_x;
73: static int pos_y;
74: static int cols;
75: static int rows;
76: static u_short attrib;
77:
78: static int esc_index;
79: static int esc_arg1;
80: static int esc_arg2;
81: static int esc_argc;
82: static int esc_saved_x;
83: static int esc_saved_y;
84:
85: static u_short ansi_colors[] = {0, 4, 2, 6, 1, 5, 3, 7};
86:
87: static void
88: scroll_up(void)
89: {
90: int i;
91:
92: memcpy(vram, vram + cols, cols * (rows - 1) * 2);
93: for (i = 0; i < cols; i++)
94: vram[cols * (rows - 1) + i] = ' ' | (attrib << 8);
95: }
96:
97: static void
98: move_cursor(void)
99: {
100: int pos = pos_y * cols + pos_x;
101:
102: irq_lock();
103: outb(0x0e, CRTC_INDEX);
104: outb((u_char)((pos >> 8) & 0xff), CRTC_DATA);
105: outb(0x0f, CRTC_INDEX);
106: outb((u_char)(pos & 0xff), CRTC_DATA);
107: irq_unlock();
108: }
109:
110: static void
111: reset_cursor(void)
112: {
113: int offset;
114:
115: irq_lock();
116: outb(0x0e, CRTC_INDEX);
117: offset = inb(CRTC_DATA);
118: offset <<= 8;
119: outb(0x0f, CRTC_INDEX);
120: offset += inb(CRTC_DATA);
121: pos_x = offset % cols;
122: pos_y = offset / cols;
123: irq_unlock();
124: }
125:
126: static void
127: new_line(void)
128: {
129:
130: pos_x = 0;
131: pos_y++;
132: if (pos_y >= rows) {
133: pos_y = rows - 1;
134: scroll_up();
135: }
136: }
137:
138: static void
139: clear_screen(void)
140: {
141: int i;
142:
143: for (i = 0; i < cols * rows; i++)
144: vram[i] = ' ' | (attrib << 8);
145: pos_x = 0;
146: pos_y = 0;
147: move_cursor();
148: }
149:
150: /*
151: * Check for escape code sequence.
152: * Rreturn true if escape
153: *
154: * <Support list>
155: * ESC[#;#H or : moves cursor to line #, column #
156: * ESC[#;#f
157: * ESC[#A : moves cursor up # lines
158: * ESC[#B : moves cursor down # lines
159: * ESC[#C : moves cursor right # spaces
160: * ESC[#D : moves cursor left # spaces
161: * ESC[#;#R : reports current cursor line & column
162: * ESC[s : save cursor position for recall later
163: * ESC[u : return to saved cursor position
164: * ESC[2J : clear screen and home cursor
165: * ESC[K : clear to end of line
166: * ESC[#m : attribute (0=attribure off, 4=underline, 5=blink)
167: */
168: static int
169: check_escape(char c)
170: {
171: int move = 0;
172: int val;
173: u_short color;
174:
175: if (c == 033) {
176: esc_index = 1;
177: esc_argc = 0;
178: return 1;
179: }
180: if (esc_index == 0)
181: return 0;
182:
183: if (c >= '0' && c <= '9') {
184: val = c - '0';
185: switch (esc_argc) {
186: case 0:
187: esc_arg1 = val;
188: esc_index++;
189: break;
190: case 1:
191: esc_arg1 = esc_arg1 * 10 + val;
192: break;
193: case 2:
194: esc_arg2 = val;
195: esc_index++;
196: break;
197: case 3:
198: esc_arg2 = esc_arg2 * 10 + val;
199: break;
200: default:
201: goto reset;
202: }
203: esc_argc++;
204: return 1;
205: }
206:
207: esc_index++;
208:
209: switch (esc_index) {
210: case 2:
211: if (c != '[')
212: goto reset;
213: return 1;
214: case 3:
215: switch (c) {
216: case 's': /* Save cursor position */
217: esc_saved_x = pos_x;
218: esc_saved_y = pos_y;
219: break;
220: case 'u': /* Return to saved cursor position */
221: pos_x = esc_saved_x;
222: pos_y = esc_saved_y;
223: move_cursor();
224: break;
225: case 'K': /* Clear to end of line */
226: break;
227: }
228: goto reset;
229: case 4:
230: switch (c) {
231: case 'A': /* Move cursor up # lines */
232: pos_y -= esc_arg1;
233: if (pos_y < 0)
234: pos_y = 0;
235: move = 1;
236: break;
237: case 'B': /* Move cursor down # lines */
238: pos_y += esc_arg1;
239: if (pos_y >= rows)
240: pos_y = rows - 1;
241: move = 1;
242: break;
243: case 'C': /* Move cursor forward # spaces */
244: pos_x += esc_arg1;
245: if (pos_x >= cols)
246: pos_x = cols - 1;
247: move = 1;
248: break;
249: case 'D': /* Move cursor back # spaces */
250: pos_x -= esc_arg1;
251: if (pos_x < 0)
252: pos_x = 0;
253: move = 1;
254: break;
255: case ';':
256: if (esc_argc == 1)
257: esc_argc = 2;
258: return 1;
259: case 'J':
260: if (esc_arg1 == 2) /* Clear screen */
261: clear_screen();
262: break;
263: case 'm': /* Change attribute */
264: switch (esc_arg1) {
265: case 0: /* reset */
266: attrib = 0x0F;
267: break;
268: case 1: /* bold */
269: attrib = 0x0F;
270: break;
271: case 4: /* under line */
272: break;
273: case 5: /* blink */
274: attrib |= 0x80;
275: break;
276: case 30: case 31: case 32: case 33:
277: case 34: case 35: case 36: case 37:
278: color = ansi_colors[esc_arg1 - 30];
279: attrib = (attrib & 0xf0) | color;
280: break;
281: case 40: case 41: case 42: case 43:
282: case 44: case 45: case 46: case 47:
283: color = ansi_colors[esc_arg1 - 40];
284: attrib = (attrib & 0x0f) | (color << 4);
285: break;
286: }
287: break;
288:
289: }
290: if (move)
291: move_cursor();
292: goto reset;
293: case 6:
294: switch (c) {
295: case 'H':
296: case 'f':
297: pos_y = esc_arg1;
298: pos_x = esc_arg2;
299: if (pos_y >= rows)
300: pos_y = rows - 1;
301: if (pos_x >= cols)
302: pos_x = cols - 1;
303: move_cursor();
304: break;
305: case 'R':
306: /* XXX */
307: break;
308: }
309: goto reset;
310: default:
311: goto reset;
312: }
313: return 1;
314: reset:
315: esc_index = 0;
316: esc_argc = 0;
317: return 1;
318: }
319:
320: static void
321: put_char(char c)
322: {
323:
324: if (check_escape(c))
325: return;
326:
327: switch (c) {
328: case '\n':
329: new_line();
330: return;
331: case '\r':
332: pos_x = 0;
333: return;
334: case '\b':
335: if (pos_x == 0)
336: return;
337: pos_x--;
338: return;
339: }
340:
341: vram[pos_y * cols + pos_x] = c | (attrib << 8);
342: pos_x++;
343: if (pos_x >= cols) {
344: pos_x = 0;
345: pos_y++;
346: if (pos_y >= rows) {
347: pos_y = rows - 1;
348: scroll_up();
349: }
350: }
351: }
352:
353: static void
354: console_output(struct tty *tp)
355: {
356: int c;
357:
358: sched_lock();
359: while ((c = ttyq_getc(&tp->t_outq)) >= 0)
360: put_char(c);
361: move_cursor();
362: esc_index = 0;
363: sched_unlock();
364: }
365:
366: /*
367: * Read
368: */
369: static int
370: console_read(device_t dev, char *buf, size_t *nbyte, int blkno)
371: {
372:
373: return tty_read(&console_tty, buf, nbyte);
374: }
375:
376: /*
377: * Write
378: */
379: static int
380: console_write(device_t dev, char *buf, size_t *nbyte, int blkno)
381: {
382:
383: return tty_write(&console_tty, buf, nbyte);
384: }
385:
386: /*
387: * I/O control
388: */
389: static int
390: console_ioctl(device_t dev, int cmd, u_long arg)
391: {
392:
393: return tty_ioctl(&console_tty, cmd, (void *)arg);
394: }
395:
396: /*
397: * Attach input device.
398: */
399: void
400: console_attach(struct tty **tpp)
401: {
402:
403: *tpp = &console_tty;
404: }
405:
406: #if defined(DEBUG) && defined(CONFIG_DIAG_SCREEN)
407: /*
408: * Diag print handler
409: */
410: static void
411: diag_print(char *str)
412: {
413: size_t count;
414: char c;
415:
416: sched_lock();
417: for (count = 0; count < 128; count++) {
418: c = *str;
419: if (c == '\0')
420: break;
421: put_char(c);
422:
423: #if defined(CONFIG_DIAG_BOCHS)
424: if (inb(0xe9) == 0xe9) {
425: if (c == '\n')
426: outb((int)'\r', 0xe9);
427: outb(c, 0xe9);
428: }
429: #endif
430: str++;
431: }
432: move_cursor();
433: esc_index = 0;
434: sched_unlock();
435: }
436: #endif
437:
438: /*
439: * Init
440: */
441: static int
442: console_init(void)
443: {
444: struct boot_info *boot_info;
445:
446: machine_bootinfo(&boot_info);
447: cols = boot_info->video.text_x;
448: rows = boot_info->video.text_y;
449:
450: esc_index = 0;
451: attrib = 0x0F;
452:
453: vram = phys_to_virt((void *)VID_RAM);
454: console_dev = device_create(&console_io, "console", DF_CHR);
455: reset_cursor();
456: #if defined(DEBUG) && defined(CONFIG_DIAG_SCREEN)
457: debug_attach(diag_print);
458: #endif
459: tty_register(&console_io, &console_tty, console_output);
460: console_tty.t_winsize.ws_row = rows;
461: console_tty.t_winsize.ws_col = cols;
462: return 0;
463: }
CVSweb