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