00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "../drivers.h"
00020 #include <termios.h>
00021 #include <sys/ioctl.h>
00022 #include <sys/vm.h>
00023 #include <minix/callnr.h>
00024 #include <minix/com.h>
00025 #include "tty.h"
00026
00027 #include "../../kernel/const.h"
00028 #include "../../kernel/config.h"
00029 #include "../../kernel/type.h"
00030
00031
00032 #define MONO_BASE 0xB0000L
00033 #define COLOR_BASE 0xB8000L
00034 #define MONO_SIZE 0x1000
00035 #define COLOR_SIZE 0x4000
00036 #define EGA_SIZE 0x8000
00037 #define BLANK_COLOR 0x0700
00038 #define SCROLL_UP 0
00039 #define SCROLL_DOWN 1
00040 #define BLANK_MEM ((u16_t *) 0)
00041 #define CONS_RAM_WORDS 80
00042 #define MAX_ESC_PARMS 4
00043
00044
00045 #define M_6845 0x3B4
00046 #define C_6845 0x3D4
00047 #define INDEX 0
00048 #define DATA 1
00049 #define STATUS 6
00050 #define VID_ORG 12
00051 #define CURSOR 14
00052
00053
00054 #define TIMER_FREQ 1193182L
00055
00056
00057 #define BEEP_FREQ 0x0533
00058 #define B_TIME 3
00059
00060
00061 #define GA_SEQUENCER_INDEX 0x3C4
00062 #define GA_SEQUENCER_DATA 0x3C5
00063 #define GA_GRAPHICS_INDEX 0x3CE
00064 #define GA_GRAPHICS_DATA 0x3CF
00065 #define GA_VIDEO_ADDRESS 0xA0000L
00066 #define GA_FONT_SIZE 8192
00067
00068
00069 PUBLIC int vid_index;
00070 PUBLIC u16_t vid_seg;
00071 PUBLIC vir_bytes vid_off;
00072 PUBLIC unsigned vid_size;
00073 PUBLIC unsigned vid_mask;
00074 PUBLIC unsigned blank_color = BLANK_COLOR;
00075
00076
00077 PRIVATE int vid_port;
00078 PRIVATE int wrap;
00079 PRIVATE int softscroll;
00080 PRIVATE int beeping;
00081 PRIVATE unsigned font_lines;
00082 PRIVATE unsigned scr_width;
00083 PRIVATE unsigned scr_lines;
00084 PRIVATE unsigned scr_size;
00085
00086
00087 typedef struct console {
00088 tty_t *c_tty;
00089 int c_column;
00090 int c_row;
00091 int c_rwords;
00092 unsigned c_start;
00093 unsigned c_limit;
00094 unsigned c_org;
00095 unsigned c_cur;
00096 unsigned c_attr;
00097 unsigned c_blank;
00098 char c_reverse;
00099 char c_esc_state;
00100 char c_esc_intro;
00101 int *c_esc_parmp;
00102 int c_esc_parmv[MAX_ESC_PARMS];
00103 u16_t c_ramqueue[CONS_RAM_WORDS];
00104 } console_t;
00105
00106 PRIVATE int nr_cons= 1;
00107 PRIVATE console_t cons_table[NR_CONS];
00108 PRIVATE console_t *curcons;
00109
00110
00111 #define color (vid_port == C_6845)
00112
00113
00114 PRIVATE int ansi_colors[8] = {0, 4, 2, 6, 1, 5, 3, 7};
00115
00116
00117 struct sequence {
00118 unsigned short index;
00119 unsigned char port;
00120 unsigned char value;
00121 };
00122
00123 FORWARD _PROTOTYPE( int cons_write, (struct tty *tp, int try) );
00124 FORWARD _PROTOTYPE( void cons_echo, (tty_t *tp, int c) );
00125 FORWARD _PROTOTYPE( void out_char, (console_t *cons, int c) );
00126 FORWARD _PROTOTYPE( void cons_putk, (int c) );
00127 FORWARD _PROTOTYPE( void beep, (void) );
00128 FORWARD _PROTOTYPE( void do_escape, (console_t *cons, int c) );
00129 FORWARD _PROTOTYPE( void flush, (console_t *cons) );
00130 FORWARD _PROTOTYPE( void parse_escape, (console_t *cons, int c) );
00131 FORWARD _PROTOTYPE( void scroll_screen, (console_t *cons, int dir) );
00132 FORWARD _PROTOTYPE( void set_6845, (int reg, unsigned val) );
00133 FORWARD _PROTOTYPE( void get_6845, (int reg, unsigned *val) );
00134 FORWARD _PROTOTYPE( void stop_beep, (timer_t *tmrp) );
00135 FORWARD _PROTOTYPE( void cons_org0, (void) );
00136 FORWARD _PROTOTYPE( int ga_program, (struct sequence *seq) );
00137 FORWARD _PROTOTYPE( int cons_ioctl, (tty_t *tp, int) );
00138 PRIVATE _PROTOTYPE( void ser_putc, (char c) );
00139
00140
00141
00142
00143 PRIVATE int cons_write(tp, try)
00144 register struct tty *tp;
00145 int try;
00146 {
00147
00148
00149
00150
00151
00152 int count;
00153 int result;
00154 register char *tbuf;
00155 char buf[64];
00156 console_t *cons = tp->tty_priv;
00157
00158 if (try) return 1;
00159
00160
00161
00162
00163 if ((count = tp->tty_outleft) == 0 || tp->tty_inhibited) return;
00164
00165
00166
00167
00168 do {
00169 if (count > sizeof(buf)) count = sizeof(buf);
00170 if ((result = sys_vircopy(tp->tty_outproc, D, tp->tty_out_vir,
00171 SELF, D, (vir_bytes) buf, (vir_bytes) count)) != OK)
00172 break;
00173 tbuf = buf;
00174
00175
00176 tp->tty_out_vir += count;
00177 tp->tty_outcum += count;
00178 tp->tty_outleft -= count;
00179
00180
00181
00182
00183
00184 do {
00185 if ((unsigned) *tbuf < ' ' || cons->c_esc_state > 0
00186 || cons->c_column >= scr_width
00187 || cons->c_rwords >= buflen(cons->c_ramqueue))
00188 {
00189 out_char(cons, *tbuf++);
00190 } else {
00191 cons->c_ramqueue[cons->c_rwords++] =
00192 cons->c_attr | (*tbuf++ & BYTE);
00193 cons->c_column++;
00194 }
00195 } while (--count != 0);
00196 } while ((count = tp->tty_outleft) != 0 && !tp->tty_inhibited);
00197
00198 flush(cons);
00199
00200
00201 if (tp->tty_outleft == 0 || result != OK) {
00202
00203 tty_reply(tp->tty_outrepcode, tp->tty_outcaller, tp->tty_outproc,
00204 tp->tty_outcum);
00205 tp->tty_outcum = 0;
00206 }
00207 }
00208
00209
00210
00211
00212 PRIVATE void cons_echo(tp, c)
00213 register tty_t *tp;
00214 int c;
00215 {
00216
00217 console_t *cons = tp->tty_priv;
00218
00219 out_char(cons, c);
00220 flush(cons);
00221 }
00222
00223
00224
00225
00226 PRIVATE void out_char(cons, c)
00227 register console_t *cons;
00228 int c;
00229 {
00230
00231 if (cons->c_esc_state > 0) {
00232 parse_escape(cons, c);
00233 return;
00234 }
00235
00236 switch(c) {
00237 case 000:
00238 return;
00239
00240 case 007:
00241 flush(cons);
00242 beep();
00243 return;
00244
00245 case '\b':
00246 if (--cons->c_column < 0) {
00247 if (--cons->c_row >= 0) cons->c_column += scr_width;
00248 }
00249 flush(cons);
00250 return;
00251
00252 case '\n':
00253 if ((cons->c_tty->tty_termios.c_oflag & (OPOST|ONLCR))
00254 == (OPOST|ONLCR)) {
00255 cons->c_column = 0;
00256 }
00257
00258 case 013:
00259 case 014:
00260 if (cons->c_row == scr_lines-1) {
00261 scroll_screen(cons, SCROLL_UP);
00262 } else {
00263 cons->c_row++;
00264 }
00265 flush(cons);
00266 return;
00267
00268 case '\r':
00269 cons->c_column = 0;
00270 flush(cons);
00271 return;
00272
00273 case '\t':
00274 cons->c_column = (cons->c_column + TAB_SIZE) & ~TAB_MASK;
00275 if (cons->c_column > scr_width) {
00276 cons->c_column -= scr_width;
00277 if (cons->c_row == scr_lines-1) {
00278 scroll_screen(cons, SCROLL_UP);
00279 } else {
00280 cons->c_row++;
00281 }
00282 }
00283 flush(cons);
00284 return;
00285
00286 case 033:
00287 flush(cons);
00288 cons->c_esc_state = 1;
00289 return;
00290
00291 default:
00292 if (cons->c_column >= scr_width) {
00293 if (!LINEWRAP) return;
00294 if (cons->c_row == scr_lines-1) {
00295 scroll_screen(cons, SCROLL_UP);
00296 } else {
00297 cons->c_row++;
00298 }
00299 cons->c_column = 0;
00300 flush(cons);
00301 }
00302 if (cons->c_rwords == buflen(cons->c_ramqueue)) flush(cons);
00303 cons->c_ramqueue[cons->c_rwords++] = cons->c_attr | (c & BYTE);
00304 cons->c_column++;
00305 return;
00306 }
00307 }
00308
00309
00310
00311
00312 PRIVATE void scroll_screen(cons, dir)
00313 register console_t *cons;
00314 int dir;
00315 {
00316 unsigned new_line, new_org, chars;
00317
00318 flush(cons);
00319 chars = scr_size - scr_width;
00320
00321
00322
00323
00324
00325
00326
00327
00328 if (dir == SCROLL_UP) {
00329
00330 if (softscroll) {
00331 vid_vid_copy(cons->c_start + scr_width, cons->c_start, chars);
00332 } else
00333 if (!wrap && cons->c_org + scr_size + scr_width >= cons->c_limit) {
00334 vid_vid_copy(cons->c_org + scr_width, cons->c_start, chars);
00335 cons->c_org = cons->c_start;
00336 } else {
00337 cons->c_org = (cons->c_org + scr_width) & vid_mask;
00338 }
00339 new_line = (cons->c_org + chars) & vid_mask;
00340 } else {
00341
00342 if (softscroll) {
00343 vid_vid_copy(cons->c_start, cons->c_start + scr_width, chars);
00344 } else
00345 if (!wrap && cons->c_org < cons->c_start + scr_width) {
00346 new_org = cons->c_limit - scr_size;
00347 vid_vid_copy(cons->c_org, new_org + scr_width, chars);
00348 cons->c_org = new_org;
00349 } else {
00350 cons->c_org = (cons->c_org - scr_width) & vid_mask;
00351 }
00352 new_line = cons->c_org;
00353 }
00354
00355 blank_color = cons->c_blank;
00356 mem_vid_copy(BLANK_MEM, new_line, scr_width);
00357
00358
00359 if (cons == curcons) set_6845(VID_ORG, cons->c_org);
00360 flush(cons);
00361 }
00362
00363
00364
00365
00366 PRIVATE void flush(cons)
00367 register console_t *cons;
00368 {
00369
00370
00371
00372 unsigned cur;
00373 tty_t *tp = cons->c_tty;
00374
00375
00376 if (cons->c_rwords > 0) {
00377 mem_vid_copy(cons->c_ramqueue, cons->c_cur, cons->c_rwords);
00378 cons->c_rwords = 0;
00379
00380
00381 tp->tty_position = cons->c_column;
00382 tp->tty_reprint = TRUE;
00383 }
00384
00385
00386 if (cons->c_column < 0) cons->c_column = 0;
00387 if (cons->c_column > scr_width) cons->c_column = scr_width;
00388 if (cons->c_row < 0) cons->c_row = 0;
00389 if (cons->c_row >= scr_lines) cons->c_row = scr_lines - 1;
00390 cur = cons->c_org + cons->c_row * scr_width + cons->c_column;
00391 if (cur != cons->c_cur) {
00392 if (cons == curcons) set_6845(CURSOR, cur);
00393 cons->c_cur = cur;
00394 }
00395 }
00396
00397
00398
00399
00400 PRIVATE void parse_escape(cons, c)
00401 register console_t *cons;
00402 char c;
00403 {
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421 switch (cons->c_esc_state) {
00422 case 1:
00423 cons->c_esc_intro = '\0';
00424 cons->c_esc_parmp = bufend(cons->c_esc_parmv);
00425 do {
00426 *--cons->c_esc_parmp = 0;
00427 } while (cons->c_esc_parmp > cons->c_esc_parmv);
00428 switch (c) {
00429 case '[':
00430 cons->c_esc_intro = c;
00431 cons->c_esc_state = 2;
00432 break;
00433 case 'M':
00434 do_escape(cons, c);
00435 break;
00436 default:
00437 cons->c_esc_state = 0;
00438 }
00439 break;
00440
00441 case 2:
00442 if (c >= '0' && c <= '9') {
00443 if (cons->c_esc_parmp < bufend(cons->c_esc_parmv))
00444 *cons->c_esc_parmp = *cons->c_esc_parmp * 10 + (c-'0');
00445 } else
00446 if (c == ';') {
00447 if (cons->c_esc_parmp < bufend(cons->c_esc_parmv))
00448 cons->c_esc_parmp++;
00449 } else {
00450 do_escape(cons, c);
00451 }
00452 break;
00453 }
00454 }
00455
00456
00457
00458
00459 PRIVATE void do_escape(cons, c)
00460 register console_t *cons;
00461 char c;
00462 {
00463 int value, n;
00464 unsigned src, dst, count;
00465 int *parmp;
00466
00467
00468 flush(cons);
00469
00470 if (cons->c_esc_intro == '\0') {
00471
00472 switch (c) {
00473 case 'M':
00474 if (cons->c_row == 0) {
00475 scroll_screen(cons, SCROLL_DOWN);
00476 } else {
00477 cons->c_row--;
00478 }
00479 flush(cons);
00480 break;
00481
00482 default: break;
00483 }
00484 } else
00485 if (cons->c_esc_intro == '[') {
00486
00487 value = cons->c_esc_parmv[0];
00488 switch (c) {
00489 case 'A':
00490 n = (value == 0 ? 1 : value);
00491 cons->c_row -= n;
00492 flush(cons);
00493 break;
00494
00495 case 'B':
00496 n = (value == 0 ? 1 : value);
00497 cons->c_row += n;
00498 flush(cons);
00499 break;
00500
00501 case 'C':
00502 n = (value == 0 ? 1 : value);
00503 cons->c_column += n;
00504 flush(cons);
00505 break;
00506
00507 case 'D':
00508 n = (value == 0 ? 1 : value);
00509 cons->c_column -= n;
00510 flush(cons);
00511 break;
00512
00513 case 'H':
00514 cons->c_row = cons->c_esc_parmv[0] - 1;
00515 cons->c_column = cons->c_esc_parmv[1] - 1;
00516 flush(cons);
00517 break;
00518
00519 case 'J':
00520 switch (value) {
00521 case 0:
00522 count = scr_size - (cons->c_cur - cons->c_org);
00523 dst = cons->c_cur;
00524 break;
00525 case 1:
00526 count = cons->c_cur - cons->c_org;
00527 dst = cons->c_org;
00528 break;
00529 case 2:
00530 count = scr_size;
00531 dst = cons->c_org;
00532 break;
00533 default:
00534 count = 0;
00535 dst = cons->c_org;
00536 }
00537 blank_color = cons->c_blank;
00538 mem_vid_copy(BLANK_MEM, dst, count);
00539 break;
00540
00541 case 'K':
00542 switch (value) {
00543 case 0:
00544 count = scr_width - cons->c_column;
00545 dst = cons->c_cur;
00546 break;
00547 case 1:
00548 count = cons->c_column;
00549 dst = cons->c_cur - cons->c_column;
00550 break;
00551 case 2:
00552 count = scr_width;
00553 dst = cons->c_cur - cons->c_column;
00554 break;
00555 default:
00556 count = 0;
00557 dst = cons->c_cur;
00558 }
00559 blank_color = cons->c_blank;
00560 mem_vid_copy(BLANK_MEM, dst, count);
00561 break;
00562
00563 case 'L':
00564 n = value;
00565 if (n < 1) n = 1;
00566 if (n > (scr_lines - cons->c_row))
00567 n = scr_lines - cons->c_row;
00568
00569 src = cons->c_org + cons->c_row * scr_width;
00570 dst = src + n * scr_width;
00571 count = (scr_lines - cons->c_row - n) * scr_width;
00572 vid_vid_copy(src, dst, count);
00573 blank_color = cons->c_blank;
00574 mem_vid_copy(BLANK_MEM, src, n * scr_width);
00575 break;
00576
00577 case 'M':
00578 n = value;
00579 if (n < 1) n = 1;
00580 if (n > (scr_lines - cons->c_row))
00581 n = scr_lines - cons->c_row;
00582
00583 dst = cons->c_org + cons->c_row * scr_width;
00584 src = dst + n * scr_width;
00585 count = (scr_lines - cons->c_row - n) * scr_width;
00586 vid_vid_copy(src, dst, count);
00587 blank_color = cons->c_blank;
00588 mem_vid_copy(BLANK_MEM, dst + count, n * scr_width);
00589 break;
00590
00591 case '@':
00592 n = value;
00593 if (n < 1) n = 1;
00594 if (n > (scr_width - cons->c_column))
00595 n = scr_width - cons->c_column;
00596
00597 src = cons->c_cur;
00598 dst = src + n;
00599 count = scr_width - cons->c_column - n;
00600 vid_vid_copy(src, dst, count);
00601 blank_color = cons->c_blank;
00602 mem_vid_copy(BLANK_MEM, src, n);
00603 break;
00604
00605 case 'P':
00606 n = value;
00607 if (n < 1) n = 1;
00608 if (n > (scr_width - cons->c_column))
00609 n = scr_width - cons->c_column;
00610
00611 dst = cons->c_cur;
00612 src = dst + n;
00613 count = scr_width - cons->c_column - n;
00614 vid_vid_copy(src, dst, count);
00615 blank_color = cons->c_blank;
00616 mem_vid_copy(BLANK_MEM, dst + count, n);
00617 break;
00618
00619 case 'm':
00620 for (parmp = cons->c_esc_parmv; parmp <= cons->c_esc_parmp
00621 && parmp < bufend(cons->c_esc_parmv); parmp++) {
00622 if (cons->c_reverse) {
00623
00624 cons->c_attr = ((cons->c_attr & 0x7000) >> 4) |
00625 ((cons->c_attr & 0x0700) << 4) |
00626 ((cons->c_attr & 0x8800));
00627 }
00628 switch (n = *parmp) {
00629 case 0:
00630 cons->c_attr = cons->c_blank = BLANK_COLOR;
00631 cons->c_reverse = FALSE;
00632 break;
00633
00634 case 1:
00635
00636 cons->c_attr |= 0x0800;
00637 break;
00638
00639 case 4:
00640 if (color) {
00641
00642
00643 cons->c_attr = (cons->c_attr & 0xBBFF);
00644 } else {
00645
00646 cons->c_attr = (cons->c_attr & 0x99FF);
00647 }
00648 break;
00649
00650 case 5:
00651
00652 cons->c_attr |= 0x8000;
00653 break;
00654
00655 case 7:
00656 cons->c_reverse = TRUE;
00657 break;
00658
00659 default:
00660 if (n == 39) n = 37;
00661 if (n == 49) n = 40;
00662
00663 if (!color) {
00664
00665 } else
00666 if (30 <= n && n <= 37) {
00667
00668 cons->c_attr =
00669 (cons->c_attr & 0xF8FF) |
00670 (ansi_colors[(n - 30)] << 8);
00671 cons->c_blank =
00672 (cons->c_blank & 0xF8FF) |
00673 (ansi_colors[(n - 30)] << 8);
00674 } else
00675 if (40 <= n && n <= 47) {
00676
00677 cons->c_attr =
00678 (cons->c_attr & 0x8FFF) |
00679 (ansi_colors[(n - 40)] << 12);
00680 cons->c_blank =
00681 (cons->c_blank & 0x8FFF) |
00682 (ansi_colors[(n - 40)] << 12);
00683 }
00684 }
00685 if (cons->c_reverse) {
00686
00687 cons->c_attr = ((cons->c_attr & 0x7000) >> 4) |
00688 ((cons->c_attr & 0x0700) << 4) |
00689 ((cons->c_attr & 0x8800));
00690 }
00691 }
00692 break;
00693 }
00694 }
00695 cons->c_esc_state = 0;
00696 }
00697
00698
00699
00700
00701 PRIVATE void set_6845(reg, val)
00702 int reg;
00703 unsigned val;
00704 {
00705
00706
00707
00708
00709 pvb_pair_t char_out[4];
00710 pv_set(char_out[0], vid_port + INDEX, reg);
00711 pv_set(char_out[1], vid_port + DATA, (val>>8) & BYTE);
00712 pv_set(char_out[2], vid_port + INDEX, reg + 1);
00713 pv_set(char_out[3], vid_port + DATA, val&BYTE);
00714 sys_voutb(char_out, 4);
00715 }
00716
00717
00718
00719
00720 PRIVATE void get_6845(reg, val)
00721 int reg;
00722 unsigned *val;
00723 {
00724 char v1, v2;
00725 unsigned long v;
00726
00727 sys_outb(vid_port + INDEX, reg);
00728 sys_inb(vid_port + DATA, &v);
00729 v1 = v;
00730 sys_outb(vid_port + INDEX, reg+1);
00731 sys_inb(vid_port + DATA, &v);
00732 v2 = v;
00733 *val = (v1 << 8) | v2;
00734 }
00735
00736
00737
00738
00739 PRIVATE void beep()
00740 {
00741
00742
00743
00744
00745 static timer_t tmr_stop_beep;
00746 pvb_pair_t char_out[3];
00747 clock_t now;
00748 unsigned long port_b_val;
00749 int s;
00750
00751
00752 if ((s=getuptime(&now)) != OK)
00753 panic("TTY","Console couldn't get clock's uptime.", s);
00754 if (!beeping) {
00755
00756 pv_set(char_out[0], TIMER_MODE, 0xB6);
00757 pv_set(char_out[1], TIMER2, (BEEP_FREQ >> 0) & BYTE);
00758 pv_set(char_out[2], TIMER2, (BEEP_FREQ >> 8) & BYTE);
00759 if (sys_voutb(char_out, 3)==OK) {
00760 if (sys_inb(PORT_B, &port_b_val)==OK &&
00761 sys_outb(PORT_B, (port_b_val|3))==OK)
00762 beeping = TRUE;
00763 }
00764 }
00765
00766 tmrs_settimer(&tty_timers, &tmr_stop_beep, now+B_TIME, stop_beep, NULL);
00767 if (tty_timers->tmr_exp_time != tty_next_timeout) {
00768 tty_next_timeout = tty_timers->tmr_exp_time;
00769 if ((s=sys_setalarm(tty_next_timeout, 1)) != OK)
00770 panic("TTY","Console couldn't set alarm.", s);
00771 }
00772 }
00773
00774
00775
00776
00777
00778 PUBLIC void do_video(message *m)
00779 {
00780 int i, n, r, ops, watch;
00781 unsigned char c;
00782
00783
00784 r= EINVAL;
00785 switch (m->m_type) {
00786 case DEV_OPEN:
00787
00788 r= OK;
00789 break;
00790 case DEV_CLOSE:
00791 r= OK;
00792 break;
00793 case DEV_IOCTL:
00794 if (m->TTY_REQUEST == MIOCMAP || m->TTY_REQUEST == MIOCUNMAP)
00795 {
00796 int r, do_map;
00797 struct mapreq mapreq;
00798
00799 do_map= (m->REQUEST == MIOCMAP);
00800
00801
00802 r= sys_vircopy(m->IO_ENDPT, D,
00803 (vir_bytes)m->ADDRESS,
00804 SELF, D, (vir_bytes)&mapreq, sizeof(mapreq));
00805 if (r != OK)
00806 {
00807 tty_reply(TASK_REPLY, m->m_source, m->IO_ENDPT,
00808 r);
00809 return;
00810 }
00811 r= sys_vm_map(m->IO_ENDPT, do_map,
00812 (phys_bytes)mapreq.base, mapreq.size,
00813 mapreq.offset);
00814 tty_reply(TASK_REPLY, m->m_source, m->IO_ENDPT, r);
00815 return;
00816 }
00817 r= ENOTTY;
00818 break;
00819
00820 default:
00821 printf(
00822 "Warning, TTY(video) got unexpected request %d from %d\n",
00823 m->m_type, m->m_source);
00824 r= EINVAL;
00825 }
00826 tty_reply(TASK_REPLY, m->m_source, m->IO_ENDPT, r);
00827 }
00828
00829
00830
00831
00832
00833 PUBLIC void beep_x(freq, dur)
00834 unsigned freq;
00835 clock_t dur;
00836 {
00837
00838
00839
00840
00841 static timer_t tmr_stop_beep;
00842 pvb_pair_t char_out[3];
00843 clock_t now;
00844 unsigned long port_b_val;
00845 int s;
00846
00847 unsigned long ival= TIMER_FREQ / freq;
00848 if (ival == 0 || ival > 0xffff)
00849 return;
00850
00851
00852 if ((s=getuptime(&now)) != OK)
00853 panic("TTY","Console couldn't get clock's uptime.", s);
00854 if (!beeping) {
00855
00856 pv_set(char_out[0], TIMER_MODE, 0xB6);
00857 pv_set(char_out[1], TIMER2, (ival >> 0) & BYTE);
00858 pv_set(char_out[2], TIMER2, (ival >> 8) & BYTE);
00859 if (sys_voutb(char_out, 3)==OK) {
00860 if (sys_inb(PORT_B, &port_b_val)==OK &&
00861 sys_outb(PORT_B, (port_b_val|3))==OK)
00862 beeping = TRUE;
00863 }
00864 }
00865
00866 tmrs_settimer(&tty_timers, &tmr_stop_beep, now+dur, stop_beep, NULL);
00867 if (tty_timers->tmr_exp_time != tty_next_timeout) {
00868 tty_next_timeout = tty_timers->tmr_exp_time;
00869 if ((s=sys_setalarm(tty_next_timeout, 1)) != OK)
00870 panic("TTY","Console couldn't set alarm.", s);
00871 }
00872 }
00873
00874
00875
00876
00877 PRIVATE void stop_beep(tmrp)
00878 timer_t *tmrp;
00879 {
00880
00881 unsigned long port_b_val;
00882 if (sys_inb(PORT_B, &port_b_val)==OK &&
00883 sys_outb(PORT_B, (port_b_val & ~3))==OK)
00884 beeping = FALSE;
00885 }
00886
00887
00888
00889
00890 PUBLIC void scr_init(tp)
00891 tty_t *tp;
00892 {
00893
00894 console_t *cons;
00895 phys_bytes vid_base;
00896 u16_t bios_columns, bios_crtbase, bios_fontlines;
00897 u8_t bios_rows;
00898 int line;
00899 int s;
00900 static int vdu_initialized = 0;
00901 unsigned page_size;
00902
00903
00904 line = tp - &tty_table[0];
00905 if (line >= nr_cons) return;
00906 cons = &cons_table[line];
00907 cons->c_tty = tp;
00908 tp->tty_priv = cons;
00909
00910
00911 tp->tty_devwrite = cons_write;
00912 tp->tty_echo = cons_echo;
00913 tp->tty_ioctl = cons_ioctl;
00914
00915
00916 if (! vdu_initialized++) {
00917
00918
00919 s=sys_vircopy(SELF, BIOS_SEG, (vir_bytes) VDU_SCREEN_COLS_ADDR,
00920 SELF, D, (vir_bytes) &bios_columns, VDU_SCREEN_COLS_SIZE);
00921 s=sys_vircopy(SELF, BIOS_SEG, (vir_bytes) VDU_CRT_BASE_ADDR,
00922 SELF, D, (vir_bytes) &bios_crtbase, VDU_CRT_BASE_SIZE);
00923 s=sys_vircopy(SELF, BIOS_SEG, (vir_bytes) VDU_SCREEN_ROWS_ADDR,
00924 SELF, D, (vir_bytes) &bios_rows, VDU_SCREEN_ROWS_SIZE);
00925 s=sys_vircopy(SELF, BIOS_SEG, (vir_bytes) VDU_FONTLINES_ADDR,
00926 SELF, D, (vir_bytes) &bios_fontlines, VDU_FONTLINES_SIZE);
00927
00928 vid_port = bios_crtbase;
00929 scr_width = bios_columns;
00930 font_lines = bios_fontlines;
00931 scr_lines = machine.vdu_ega ? bios_rows+1 : 25;
00932
00933 if (color) {
00934 vid_base = COLOR_BASE;
00935 vid_size = COLOR_SIZE;
00936 } else {
00937 vid_base = MONO_BASE;
00938 vid_size = MONO_SIZE;
00939 }
00940 if (machine.vdu_ega) vid_size = EGA_SIZE;
00941 wrap = ! machine.vdu_ega;
00942
00943 s = sys_segctl(&vid_index, &vid_seg, &vid_off, vid_base, vid_size);
00944
00945 vid_size >>= 1;
00946 vid_mask = vid_size - 1;
00947
00948
00949 scr_size = scr_lines * scr_width;
00950
00951
00952 nr_cons = vid_size / scr_size;
00953 if (nr_cons > NR_CONS) nr_cons = NR_CONS;
00954 if (nr_cons > 1) wrap = 0;
00955 page_size = vid_size / nr_cons;
00956 }
00957
00958 cons->c_start = line * page_size;
00959 cons->c_limit = cons->c_start + page_size;
00960 cons->c_cur = cons->c_org = cons->c_start;
00961 cons->c_attr = cons->c_blank = BLANK_COLOR;
00962
00963 if (line != 0) {
00964
00965 blank_color = BLANK_COLOR;
00966 mem_vid_copy(BLANK_MEM, cons->c_start, scr_size);
00967 } else {
00968 int i, n;
00969
00970
00971
00972 scroll_screen(cons, SCROLL_UP);
00973 cons->c_row = scr_lines - 1;
00974 cons->c_column = 0;
00975 }
00976 select_console(0);
00977 cons_ioctl(tp, 0);
00978 }
00979
00980
00981
00982
00983 PUBLIC void kputc(c)
00984 int c;
00985 {
00986
00987
00988
00989 #if 0
00990 ser_putc(c);
00991 return;
00992 #endif
00993
00994 if (panicing)
00995 cons_putk(c);
00996 if (c != 0) {
00997 kmess.km_buf[kmess.km_next] = c;
00998 if (kmess.km_size < KMESS_BUF_SIZE)
00999 kmess.km_size += 1;
01000 kmess.km_next = (kmess.km_next + 1) % KMESS_BUF_SIZE;
01001 } else {
01002 notify(LOG_PROC_NR);
01003 }
01004 }
01005
01006
01007
01008
01009 PUBLIC void do_new_kmess(m)
01010 message *m;
01011 {
01012
01013 struct kmessages kmess;
01014 static int prev_next = 0;
01015 int size, next;
01016 int bytes;
01017 int r;
01018
01019
01020 #if DEAD_CODE
01021
01022
01023
01024
01025 if ((r=sys_getkmessages(&kmess)) != OK) {
01026 printf("TTY: couldn't get copy of kmessages: %d, 0x%x\n", r,r);
01027 return;
01028 }
01029 #endif
01030 sys_getkmessages(&kmess);
01031
01032
01033
01034
01035
01036
01037
01038 if (kmess.km_size > 0) {
01039 bytes = ((kmess.km_next + KMESS_BUF_SIZE) - prev_next) % KMESS_BUF_SIZE;
01040 r=prev_next;
01041 while (bytes > 0) {
01042 cons_putk( kmess.km_buf[(r%KMESS_BUF_SIZE)] );
01043 bytes --;
01044 r ++;
01045 }
01046 cons_putk(0);
01047 }
01048
01049
01050
01051
01052 prev_next = kmess.km_next;
01053 }
01054
01055
01056
01057
01058 PUBLIC void do_diagnostics(m_ptr)
01059 message *m_ptr;
01060 {
01061
01062 char c;
01063 vir_bytes src;
01064 int count;
01065 int result = OK;
01066 int proc_nr = m_ptr->DIAG_ENDPT;
01067 if (proc_nr == SELF) proc_nr = m_ptr->m_source;
01068
01069 src = (vir_bytes) m_ptr->DIAG_PRINT_BUF;
01070 for (count = m_ptr->DIAG_BUF_COUNT; count > 0; count--) {
01071 if (sys_vircopy(proc_nr, D, src++, SELF, D, (vir_bytes) &c, 1) != OK) {
01072 result = EFAULT;
01073 break;
01074 }
01075 cons_putk(c);
01076 }
01077 cons_putk(0);
01078 m_ptr->m_type = result;
01079 send(m_ptr->m_source, m_ptr);
01080 }
01081
01082
01083
01084
01085 PUBLIC void do_get_kmess(m_ptr)
01086 message *m_ptr;
01087 {
01088
01089 vir_bytes dst;
01090 int r;
01091
01092 dst = (vir_bytes) m_ptr->GETKM_PTR;
01093 r= OK;
01094 if (sys_vircopy(SELF, D, (vir_bytes)&kmess, m_ptr->m_source, D,
01095 dst, sizeof(kmess)) != OK) {
01096 r = EFAULT;
01097 }
01098 m_ptr->m_type = r;
01099 send(m_ptr->m_source, m_ptr);
01100 }
01101
01102
01103
01104
01105 PRIVATE void cons_putk(c)
01106 int c;
01107 {
01108
01109
01110 if (c != 0) {
01111 if (c == '\n') cons_putk('\r');
01112 out_char(&cons_table[0], (int) c);
01113 } else {
01114 flush(&cons_table[0]);
01115 }
01116 }
01117
01118
01119
01120
01121 PUBLIC void toggle_scroll()
01122 {
01123
01124
01125 cons_org0();
01126 softscroll = !softscroll;
01127 printf("%sware scrolling enabled.\n", softscroll ? "Soft" : "Hard");
01128 }
01129
01130
01131
01132
01133 PUBLIC void cons_stop()
01134 {
01135
01136 cons_org0();
01137 softscroll = 1;
01138 select_console(0);
01139 cons_table[0].c_attr = cons_table[0].c_blank = BLANK_COLOR;
01140 }
01141
01142
01143
01144
01145 PRIVATE void cons_org0()
01146 {
01147
01148 int cons_line;
01149 console_t *cons;
01150 unsigned n;
01151
01152 for (cons_line = 0; cons_line < nr_cons; cons_line++) {
01153 cons = &cons_table[cons_line];
01154 while (cons->c_org > cons->c_start) {
01155 n = vid_size - scr_size;
01156 if (n > cons->c_org - cons->c_start)
01157 n = cons->c_org - cons->c_start;
01158 vid_vid_copy(cons->c_org, cons->c_org - n, scr_size);
01159 cons->c_org -= n;
01160 }
01161 flush(cons);
01162 }
01163 select_console(ccurrent);
01164 }
01165
01166
01167
01168
01169 PUBLIC void select_console(int cons_line)
01170 {
01171
01172
01173 if (cons_line < 0 || cons_line >= nr_cons) return;
01174 ccurrent = cons_line;
01175 curcons = &cons_table[cons_line];
01176 set_6845(VID_ORG, curcons->c_org);
01177 set_6845(CURSOR, curcons->c_cur);
01178 }
01179
01180
01181
01182
01183 PUBLIC int con_loadfont(m)
01184 message *m;
01185 {
01186
01187 int result;
01188 static struct sequence seq1[7] = {
01189 { GA_SEQUENCER_INDEX, 0x00, 0x01 },
01190 { GA_SEQUENCER_INDEX, 0x02, 0x04 },
01191 { GA_SEQUENCER_INDEX, 0x04, 0x07 },
01192 { GA_SEQUENCER_INDEX, 0x00, 0x03 },
01193 { GA_GRAPHICS_INDEX, 0x04, 0x02 },
01194 { GA_GRAPHICS_INDEX, 0x05, 0x00 },
01195 { GA_GRAPHICS_INDEX, 0x06, 0x00 },
01196 };
01197 static struct sequence seq2[7] = {
01198 { GA_SEQUENCER_INDEX, 0x00, 0x01 },
01199 { GA_SEQUENCER_INDEX, 0x02, 0x03 },
01200 { GA_SEQUENCER_INDEX, 0x04, 0x03 },
01201 { GA_SEQUENCER_INDEX, 0x00, 0x03 },
01202 { GA_GRAPHICS_INDEX, 0x04, 0x00 },
01203 { GA_GRAPHICS_INDEX, 0x05, 0x10 },
01204 { GA_GRAPHICS_INDEX, 0x06, 0 },
01205 };
01206
01207 seq2[6].value= color ? 0x0E : 0x0A;
01208
01209 if (!machine.vdu_ega) return(ENOTTY);
01210 result = ga_program(seq1);
01211
01212 result = sys_physcopy(m->IO_ENDPT, D, (vir_bytes) m->ADDRESS,
01213 NONE, PHYS_SEG, (phys_bytes) GA_VIDEO_ADDRESS, (phys_bytes)GA_FONT_SIZE);
01214
01215 result = ga_program(seq2);
01216
01217 return(result);
01218 }
01219
01220
01221
01222
01223 PRIVATE int ga_program(seq)
01224 struct sequence *seq;
01225 {
01226 pvb_pair_t char_out[14];
01227 int i;
01228 for (i=0; i<7; i++) {
01229 pv_set(char_out[2*i], seq->index, seq->port);
01230 pv_set(char_out[2*i+1], seq->index+1, seq->value);
01231 seq++;
01232 }
01233 return sys_voutb(char_out, 14);
01234 }
01235
01236
01237
01238
01239 PRIVATE int cons_ioctl(tp, try)
01240 tty_t *tp;
01241 int try;
01242 {
01243
01244
01245 tp->tty_winsize.ws_row= scr_lines;
01246 tp->tty_winsize.ws_col= scr_width;
01247 tp->tty_winsize.ws_xpixel= scr_width * 8;
01248 tp->tty_winsize.ws_ypixel= scr_lines * font_lines;
01249 }
01250
01251 #define COM1_BASE 0x3F8
01252 #define COM1_THR (COM1_BASE + 0)
01253 #define LSR_THRE 0x20
01254 #define COM1_LSR (COM1_BASE + 5)
01255
01256 PRIVATE void ser_putc(char c)
01257 {
01258 unsigned long b;
01259 int i;
01260 int lsr, thr;
01261
01262 lsr= COM1_LSR;
01263 thr= COM1_THR;
01264 for (i= 0; i<100; i++)
01265 {
01266 sys_inb(lsr, &b);
01267 if (b & LSR_THRE)
01268 break;
01269 }
01270 sys_outb(thr, c);
01271 }