]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/boot/pc98/libpc98/vidconsole.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / boot / pc98 / libpc98 / vidconsole.c
1 /*-
2  * Copyright (c) 1998 Michael Smith (msmith@freebsd.org)
3  * Copyright (c) 1997 Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  *      Id: probe_keyboard.c,v 1.13 1997/06/09 05:10:55 bde Exp
28  */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include <stand.h>
34 #include <bootstrap.h>
35 #include <btxv86.h>
36 #include <machine/psl.h>
37 #include <machine/cpufunc.h>
38 #include "libi386.h"
39
40 #if KEYBOARD_PROBE
41 #include <machine/cpufunc.h>
42
43 static int      probe_keyboard(void);
44 #endif
45 static void     vidc_probe(struct console *cp);
46 static int      vidc_init(int arg);
47 static void     vidc_putchar(int c);
48 static int      vidc_getchar(void);
49 static int      vidc_ischar(void);
50
51 static int      vidc_started;
52
53 #ifdef TERM_EMU
54 #define MAXARGS         8
55 #define DEFAULT_FGCOLOR 7
56 #define DEFAULT_BGCOLOR 0
57
58 void            end_term(void);
59 void            bail_out(int c);
60 void            vidc_term_emu(int c);
61 void            get_pos(void);
62 void            curs_move(int x, int y);
63 void            write_char(int c, int fg, int bg);
64 void            scroll_up(int rows, int fg, int bg);
65 void            CD(void);
66 void            CM(void);
67 void            HO(void);
68
69 static int      args[MAXARGS], argc;
70 static int      fg_c, bg_c, curx, cury;
71 static int      esc;
72 #endif
73
74 static unsigned short *crtat, *Crtat;
75 static int row = 25, col = 80;
76 #ifdef TERM_EMU
77 static u_int8_t ibmpc_to_pc98[256] = {
78         0x01, 0x21, 0x81, 0xa1, 0x41, 0x61, 0xc1, 0xe1,
79         0x09, 0x29, 0x89, 0xa9, 0x49, 0x69, 0xc9, 0xe9,
80         0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
81         0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
82         0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
83         0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
84         0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
85         0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
86         0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
87         0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
88         0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
89         0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
90         0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5,
91         0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5,
92         0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
93         0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
94
95         0x03, 0x23, 0x83, 0xa3, 0x43, 0x63, 0xc3, 0xe3,
96         0x0b, 0x2b, 0x8b, 0xab, 0x4b, 0x6b, 0xcb, 0xeb,
97         0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
98         0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
99         0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
100         0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
101         0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
102         0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
103         0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
104         0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
105         0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
106         0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
107         0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf,
108         0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf,
109         0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef,
110         0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 
111 };
112 #define at2pc98(fg_at, bg_at)   ibmpc_to_pc98[((bg_at) << 4) | (fg_at)]
113 #endif /* TERM_EMU */
114
115 struct console vidconsole = {
116     "vidconsole",
117     "internal video/keyboard",
118     0,
119     vidc_probe,
120     vidc_init,
121     vidc_putchar,
122     vidc_getchar,
123     vidc_ischar
124 };
125
126 static void
127 vidc_probe(struct console *cp)
128 {
129     
130     /* look for a keyboard */
131 #if KEYBOARD_PROBE
132     if (probe_keyboard())
133 #endif
134     {
135         
136         cp->c_flags |= C_PRESENTIN;
137     }
138
139     /* XXX for now, always assume we can do BIOS screen output */
140     cp->c_flags |= C_PRESENTOUT;
141 }
142
143 static int
144 vidc_init(int arg)
145 {
146     int         i, hw_cursor;
147
148     if (vidc_started && arg == 0)
149         return (0);
150     vidc_started = 1;
151     Crtat = (unsigned short *)PTOV(0xA0000);
152     while ((inb(0x60) & 0x04) == 0)
153         ;
154     outb(0x62, 0xe0);
155     while ((inb(0x60) & 0x01) == 0)
156         ;
157     hw_cursor = inb(0x62);
158     hw_cursor |= (inb(0x62) << 8);
159     inb(0x62);
160     inb(0x62);
161     inb(0x62);
162     crtat = Crtat + hw_cursor;
163 #ifdef TERM_EMU
164     /* Init terminal emulator */
165     end_term();
166     get_pos();
167     curs_move(curx, cury);
168     fg_c = DEFAULT_FGCOLOR;
169     bg_c = DEFAULT_BGCOLOR;
170 #endif
171     for (i = 0; i < 10 && vidc_ischar(); i++)
172         (void)vidc_getchar();
173     return (0); /* XXX reinit? */
174 }
175
176 static void
177 beep(void)
178 {
179
180         outb(0x37, 6);
181         delay(40000);
182         outb(0x37, 7);
183 }
184
185 #if 0
186 static void
187 vidc_biosputchar(int c)
188 {
189     unsigned short *cp;
190     int i, pos;
191
192 #ifdef TERM_EMU
193     *crtat = (c == 0x5c ? 0xfc : c);
194     *(crtat + 0x1000) = at2pc98(fg, bg);
195 #else
196     switch(c) {
197     case '\b':
198         crtat--;
199         break;
200     case '\r':
201         crtat -= (crtat - Crtat) % col;
202         break;
203     case '\n':
204         crtat += col;
205         break;
206     default:
207         *crtat = (c == 0x5c ? 0xfc : c);
208         *(crtat++ + 0x1000) = 0xe1;
209         break;
210     }
211
212     if (crtat >= Crtat + col * row) {
213         cp = Crtat;
214         for (i = 1; i < row; i++) {
215             bcopy((void *)(cp + col), (void *)cp, col * 2);
216             cp += col;
217         }
218         for (i = 0; i < col; i++) {
219             *cp++ = ' ';
220         }
221         crtat -= col;
222     }
223     pos = crtat - Crtat;
224     while ((inb(0x60) & 0x04) == 0) {}
225     outb(0x62, 0x49);
226     outb(0x60, pos & 0xff);
227     outb(0x60, pos >> 8);
228 #endif
229 }
230 #endif
231
232 static void
233 vidc_rawputchar(int c)
234 {
235     int         i;
236
237     if (c == '\t')
238         /* lame tab expansion */
239         for (i = 0; i < 8; i++)
240             vidc_rawputchar(' ');
241     else {
242         /* Emulate AH=0eh (teletype output) */
243         switch(c) {
244         case '\a':
245             beep();
246             return;
247         case '\r':
248             curx = 0;
249             curs_move(curx, cury);
250             return;
251         case '\n':
252             cury++;
253             if (cury > 24) {
254                 scroll_up(1, fg_c, bg_c);
255                 cury--;
256             } else {
257                 curs_move(curx, cury);
258             }
259             return;
260         case '\b':
261             if (curx > 0) {
262                 curx--;
263                 curs_move(curx, cury);
264                 /* write_char(' ', fg_c, bg_c); XXX destructive(!) */
265                 return;
266             }
267             return;
268         default:
269             write_char(c, fg_c, bg_c);
270             curx++;
271             if (curx > 79) {
272                 curx = 0;
273                 cury++;
274             }
275             if (cury > 24) {
276                 curx = 0;
277                 scroll_up(1, fg_c, bg_c);
278                 cury--;
279             }
280         }
281         curs_move(curx, cury);
282     }
283 }
284
285 #ifdef TERM_EMU
286
287 /* Get cursor position on the screen. Result is in edx. Sets
288  * curx and cury appropriately.
289  */
290 void
291 get_pos(void)
292 {
293     int pos = crtat - Crtat;
294
295     curx = pos % col;
296     cury = pos / col;
297 }
298
299 /* Move cursor to x rows and y cols (0-based). */
300 void
301 curs_move(int x, int y)
302 {
303     int pos;
304
305     pos = x + y * col;
306     crtat = Crtat + pos;
307     pos = crtat - Crtat;
308     while((inb(0x60) & 0x04) == 0) {}
309     outb(0x62, 0x49);
310     outb(0x60, pos & 0xff);
311     outb(0x60, pos >> 8);
312     curx = x;
313     cury = y;
314 #define isvisible(c)    (((c) >= 32) && ((c) < 255))
315     if (!isvisible(*crtat & 0x00ff)) {
316         write_char(' ', fg_c, bg_c);
317     }
318 }
319
320 /* Scroll up the whole window by a number of rows. If rows==0,
321  * clear the window. fg and bg are attributes for the new lines
322  * inserted in the window.
323  */
324 void
325 scroll_up(int rows, int fgcol, int bgcol)
326 {
327     unsigned short *cp;
328     int i;
329
330     if (rows == 0)
331         rows = 25;
332     cp = Crtat;
333     for (i = rows; i < row; i++) {
334         bcopy((void *)(cp + col), (void *)cp, col * 2);
335         cp += col;
336     }
337     for (i = 0; i < col; i++) {
338         *(cp + 0x1000) = at2pc98(fgcol, bgcol);
339         *cp++ = ' ';
340     }
341 }
342
343 /* Write character and attribute at cursor position. */
344 void
345 write_char(int c, int fgcol, int bgcol)
346 {
347
348     *crtat = (c == 0x5c ? 0xfc : (c & 0xff));
349     *(crtat + 0x1000) = at2pc98(fgcol, bgcol);
350 }
351
352 /**************************************************************/
353 /*
354  * Screen manipulation functions. They use accumulated data in
355  * args[] and argc variables.
356  *
357  */
358
359 /* Clear display from current position to end of screen */
360 void
361 CD(void)
362 {
363     int pos;
364
365     get_pos();
366     for (pos = 0; crtat + pos <= Crtat + col * row; pos++) {
367         *(crtat + pos) = ' ';
368         *(crtat + pos + 0x1000) = at2pc98(fg_c, bg_c);
369     }
370     end_term();
371 }
372
373 /* Absolute cursor move to args[0] rows and args[1] columns
374  * (the coordinates are 1-based).
375  */
376 void
377 CM(void)
378 {
379
380     if (args[0] > 0)
381         args[0]--;
382     if (args[1] > 0)
383         args[1]--;
384     curs_move(args[1], args[0]);
385     end_term();
386 }
387
388 /* Home cursor (left top corner) */
389 void
390 HO(void)
391 {
392
393     argc = 1;
394     args[0] = args[1] = 1;
395     CM();
396 }
397
398 /* Clear internal state of the terminal emulation code */
399 void
400 end_term(void)
401 {
402
403     esc = 0;
404     argc = -1;
405 }
406
407 /* Gracefully exit ESC-sequence processing in case of misunderstanding */
408 void
409 bail_out(int c)
410 {
411     char buf[16], *ch;
412     int i;
413
414     if (esc) {
415         vidc_rawputchar('\033');
416         if (esc != '\033')
417             vidc_rawputchar(esc);
418         for (i = 0; i <= argc; ++i) {
419             sprintf(buf, "%d", args[i]);
420             ch = buf;
421             while (*ch)
422                 vidc_rawputchar(*ch++);
423         }
424     }
425     vidc_rawputchar(c);
426     end_term();
427 }
428
429 static void
430 get_arg(int c)
431 {
432
433     if (argc < 0)
434         argc = 0;
435     args[argc] *= 10;
436     args[argc] += c - '0';
437 }
438
439 /* Emulate basic capabilities of cons25 terminal */
440 void
441 vidc_term_emu(int c)
442 {
443     static int ansi_col[] = {
444         0, 4, 2, 6, 1, 5, 3, 7,
445     };
446     int t;
447     int i;
448
449     switch (esc) {
450     case 0:
451         switch (c) {
452         case '\033':
453             esc = c;
454             break;
455         default:
456             vidc_rawputchar(c);
457             break;
458         }
459         break;
460
461     case '\033':
462         switch (c) {
463         case '[':
464             esc = c;
465             args[0] = 0;
466             argc = -1;
467             break;
468         default:
469             bail_out(c);
470             break;
471         }
472         break;
473
474     case '[':
475         switch (c) {
476         case ';':
477             if (argc < 0)       /* XXX */
478                 argc = 0;
479             else if (argc + 1 >= MAXARGS)
480                 bail_out(c);
481             else
482                 args[++argc] = 0;
483             break;
484         case 'H':
485             if (argc < 0)
486                 HO();
487             else if (argc == 1)
488                 CM();
489             else
490                 bail_out(c);
491             break;
492         case 'J':
493             if (argc < 0)
494                 CD();
495             else
496                 bail_out(c);
497             break;
498         case 'm':
499             if (argc < 0) {
500                 fg_c = DEFAULT_FGCOLOR;
501                 bg_c = DEFAULT_BGCOLOR;
502             }
503             for (i = 0; i <= argc; ++i) {
504                 switch (args[i]) {
505                 case 0:         /* back to normal */
506                     fg_c = DEFAULT_FGCOLOR;
507                     bg_c = DEFAULT_BGCOLOR;
508                     break;
509                 case 1:         /* bold */
510                     fg_c |= 0x8;
511                     break;
512                 case 4:         /* underline */
513                 case 5:         /* blink */
514                     bg_c |= 0x8;
515                     break;
516                 case 7:         /* reverse */
517                     t = fg_c;
518                     fg_c = bg_c;
519                     bg_c = t;
520                     break;
521                 case 30: case 31: case 32: case 33:
522                 case 34: case 35: case 36: case 37:
523                     fg_c = ansi_col[args[i] - 30];
524                     break;
525                 case 39:        /* normal */
526                     fg_c = DEFAULT_FGCOLOR;
527                     break;
528                 case 40: case 41: case 42: case 43:
529                 case 44: case 45: case 46: case 47:
530                     bg_c = ansi_col[args[i] - 40];
531                     break;
532                 case 49:        /* normal */
533                     bg_c = DEFAULT_BGCOLOR;
534                     break;
535                 }
536             }
537             end_term();
538             break;
539         default:
540             if (isdigit(c))
541                 get_arg(c);
542             else
543                 bail_out(c);
544             break;
545         }
546         break;
547
548     default:
549         bail_out(c);
550         break;
551     }
552 }
553 #endif
554
555 static void
556 vidc_putchar(int c)
557 {
558 #ifdef TERM_EMU
559     vidc_term_emu(c);
560 #else
561     vidc_rawputchar(c);
562 #endif
563 }
564
565 static int
566 vidc_getchar(void)
567 {
568
569     if (vidc_ischar()) {
570         v86.ctl = 0;
571         v86.addr = 0x18;
572         v86.eax = 0x0;
573         v86int();
574         return (v86.eax & 0xff);
575     } else {
576         return (-1);
577     }
578 }
579
580 static int
581 vidc_ischar(void)
582 {
583
584     v86.ctl = 0;
585     v86.addr = 0x18;
586     v86.eax = 0x100;
587     v86int();
588     return ((v86.ebx >> 8) & 0x1);
589 }
590
591 #if KEYBOARD_PROBE
592 static int
593 probe_keyboard(void)
594 {
595     return (*(u_char *)PTOV(0xA1481) & 0x48);
596 }
597 #endif /* KEYBOARD_PROBE */