This source file includes following definitions.
- gotoxy
- set_origin
- scrup
- scrdown
- lf
- ri
- cr
- del
- csi_J
- csi_K
- csi_m
- set_cursor
- respond
- insert_char
- insert_line
- delete_char
- delete_line
- csi_at
- csi_L
- csi_P
- csi_M
- save_cur
- restore_cur
- con_write
- con_init
- sysbeepstop
- sysbeep
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 #include <linux/sched.h>
31 #include <linux/tty.h>
32 #include <asm/io.h>
33 #include <asm/system.h>
34
35
36
37
38
39 #define ORIG_X (*(unsigned char *)0x90000)
40 #define ORIG_Y (*(unsigned char *)0x90001)
41 #define ORIG_VIDEO_PAGE (*(unsigned short *)0x90004)
42 #define ORIG_VIDEO_MODE ((*(unsigned short *)0x90006) & 0xff)
43 #define ORIG_VIDEO_COLS (((*(unsigned short *)0x90006) & 0xff00) >> 8)
44 #define ORIG_VIDEO_LINES (25)
45 #define ORIG_VIDEO_EGA_AX (*(unsigned short *)0x90008)
46 #define ORIG_VIDEO_EGA_BX (*(unsigned short *)0x9000a)
47 #define ORIG_VIDEO_EGA_CX (*(unsigned short *)0x9000c)
48
49 #define VIDEO_TYPE_MDA 0x10
50 #define VIDEO_TYPE_CGA 0x11
51 #define VIDEO_TYPE_EGAM 0x20
52 #define VIDEO_TYPE_EGAC 0x21
53
54 #define NPAR 16
55
56 extern void keyboard_interrupt(void);
57
58 static unsigned char video_type;
59 static unsigned long video_num_columns;
60 static unsigned long video_size_row;
61 static unsigned long video_num_lines;
62 static unsigned char video_page;
63 static unsigned long video_mem_start;
64 static unsigned long video_mem_end;
65 static unsigned short video_port_reg;
66 static unsigned short video_port_val;
67 static unsigned short video_erase_char;
68
69 static unsigned long origin;
70 static unsigned long scr_end;
71 static unsigned long pos;
72 static unsigned long x,y;
73 static unsigned long top,bottom;
74 static unsigned long state=0;
75 static unsigned long npar,par[NPAR];
76 static unsigned long ques=0;
77 static unsigned char attr=0x07;
78
79 static void sysbeep(void);
80
81
82
83
84
85 #define RESPONSE "\033[?1;2c"
86
87
88 static inline void gotoxy(unsigned int new_x,unsigned int new_y)
89 {
90 if (new_x > video_num_columns || new_y >= video_num_lines)
91 return;
92 x=new_x;
93 y=new_y;
94 pos=origin + y*video_size_row + (x<<1);
95 }
96
97 static inline void set_origin(void)
98 {
99 cli();
100 outb_p(12, video_port_reg);
101 outb_p(0xff&((origin-video_mem_start)>>9), video_port_val);
102 outb_p(13, video_port_reg);
103 outb_p(0xff&((origin-video_mem_start)>>1), video_port_val);
104 sti();
105 }
106
107 static void scrup(void)
108 {
109 if (video_type == VIDEO_TYPE_EGAC || video_type == VIDEO_TYPE_EGAM)
110 {
111 if (!top && bottom == video_num_lines) {
112 origin += video_size_row;
113 pos += video_size_row;
114 scr_end += video_size_row;
115 if (scr_end > video_mem_end) {
116 __asm__("cld\n\t"
117 "rep\n\t"
118 "movsl\n\t"
119 "movl _video_num_columns,%1\n\t"
120 "rep\n\t"
121 "stosw"
122 ::"a" (video_erase_char),
123 "c" ((video_num_lines-1)*video_num_columns>>1),
124 "D" (video_mem_start),
125 "S" (origin)
126 :"cx","di","si");
127 scr_end -= origin-video_mem_start;
128 pos -= origin-video_mem_start;
129 origin = video_mem_start;
130 } else {
131 __asm__("cld\n\t"
132 "rep\n\t"
133 "stosw"
134 ::"a" (video_erase_char),
135 "c" (video_num_columns),
136 "D" (scr_end-video_size_row)
137 :"cx","di");
138 }
139 set_origin();
140 } else {
141 __asm__("cld\n\t"
142 "rep\n\t"
143 "movsl\n\t"
144 "movl _video_num_columns,%%ecx\n\t"
145 "rep\n\t"
146 "stosw"
147 ::"a" (video_erase_char),
148 "c" ((bottom-top-1)*video_num_columns>>1),
149 "D" (origin+video_size_row*top),
150 "S" (origin+video_size_row*(top+1))
151 :"cx","di","si");
152 }
153 }
154 else
155 {
156 __asm__("cld\n\t"
157 "rep\n\t"
158 "movsl\n\t"
159 "movl _video_num_columns,%%ecx\n\t"
160 "rep\n\t"
161 "stosw"
162 ::"a" (video_erase_char),
163 "c" ((bottom-top-1)*video_num_columns>>1),
164 "D" (origin+video_size_row*top),
165 "S" (origin+video_size_row*(top+1))
166 :"cx","di","si");
167 }
168 }
169
170 static void scrdown(void)
171 {
172 if (video_type == VIDEO_TYPE_EGAC || video_type == VIDEO_TYPE_EGAM)
173 {
174 __asm__("std\n\t"
175 "rep\n\t"
176 "movsl\n\t"
177 "addl $2,%%edi\n\t"
178 "movl _video_num_columns,%%ecx\n\t"
179 "rep\n\t"
180 "stosw"
181 ::"a" (video_erase_char),
182 "c" ((bottom-top-1)*video_num_columns>>1),
183 "D" (origin+video_size_row*bottom-4),
184 "S" (origin+video_size_row*(bottom-1)-4)
185 :"ax","cx","di","si");
186 }
187 else
188 {
189 __asm__("std\n\t"
190 "rep\n\t"
191 "movsl\n\t"
192 "addl $2,%%edi\n\t"
193 "movl _video_num_columns,%%ecx\n\t"
194 "rep\n\t"
195 "stosw"
196 ::"a" (video_erase_char),
197 "c" ((bottom-top-1)*video_num_columns>>1),
198 "D" (origin+video_size_row*bottom-4),
199 "S" (origin+video_size_row*(bottom-1)-4)
200 :"ax","cx","di","si");
201 }
202 }
203
204 static void lf(void)
205 {
206 if (y+1<bottom) {
207 y++;
208 pos += video_size_row;
209 return;
210 }
211 scrup();
212 }
213
214 static void ri(void)
215 {
216 if (y>top) {
217 y--;
218 pos -= video_size_row;
219 return;
220 }
221 scrdown();
222 }
223
224 static void cr(void)
225 {
226 pos -= x<<1;
227 x=0;
228 }
229
230 static void del(void)
231 {
232 if (x) {
233 pos -= 2;
234 x--;
235 *(unsigned short *)pos = video_erase_char;
236 }
237 }
238
239 static void csi_J(int par)
240 {
241 long count __asm__("cx");
242 long start __asm__("di");
243
244 switch (par) {
245 case 0:
246 count = (scr_end-pos)>>1;
247 start = pos;
248 break;
249 case 1:
250 count = (pos-origin)>>1;
251 start = origin;
252 break;
253 case 2:
254 count = video_num_columns * video_num_lines;
255 start = origin;
256 break;
257 default:
258 return;
259 }
260 __asm__("cld\n\t"
261 "rep\n\t"
262 "stosw\n\t"
263 ::"c" (count),
264 "D" (start),"a" (video_erase_char)
265 :"cx","di");
266 }
267
268 static void csi_K(int par)
269 {
270 long count __asm__("cx");
271 long start __asm__("di");
272
273 switch (par) {
274 case 0:
275 if (x>=video_num_columns)
276 return;
277 count = video_num_columns-x;
278 start = pos;
279 break;
280 case 1:
281 start = pos - (x<<1);
282 count = (x<video_num_columns)?x:video_num_columns;
283 break;
284 case 2:
285 start = pos - (x<<1);
286 count = video_num_columns;
287 break;
288 default:
289 return;
290 }
291 __asm__("cld\n\t"
292 "rep\n\t"
293 "stosw\n\t"
294 ::"c" (count),
295 "D" (start),"a" (video_erase_char)
296 :"cx","di");
297 }
298
299 void csi_m(void)
300 {
301 int i;
302
303 for (i=0;i<=npar;i++)
304 switch (par[i]) {
305 case 0:attr=0x07;break;
306 case 1:attr=0x0f;break;
307 case 4:attr=0x0f;break;
308 case 7:attr=0x70;break;
309 case 27:attr=0x07;break;
310 }
311 }
312
313 static inline void set_cursor(void)
314 {
315 cli();
316 outb_p(14, video_port_reg);
317 outb_p(0xff&((pos-video_mem_start)>>9), video_port_val);
318 outb_p(15, video_port_reg);
319 outb_p(0xff&((pos-video_mem_start)>>1), video_port_val);
320 sti();
321 }
322
323 static void respond(struct tty_struct * tty)
324 {
325 char * p = RESPONSE;
326
327 cli();
328 while (*p) {
329 PUTCH(*p,tty->read_q);
330 p++;
331 }
332 sti();
333 copy_to_cooked(tty);
334 }
335
336 static void insert_char(void)
337 {
338 int i=x;
339 unsigned short tmp, old = video_erase_char;
340 unsigned short * p = (unsigned short *) pos;
341
342 while (i++<video_num_columns) {
343 tmp=*p;
344 *p=old;
345 old=tmp;
346 p++;
347 }
348 }
349
350 static void insert_line(void)
351 {
352 int oldtop,oldbottom;
353
354 oldtop=top;
355 oldbottom=bottom;
356 top=y;
357 bottom = video_num_lines;
358 scrdown();
359 top=oldtop;
360 bottom=oldbottom;
361 }
362
363 static void delete_char(void)
364 {
365 int i;
366 unsigned short * p = (unsigned short *) pos;
367
368 if (x>=video_num_columns)
369 return;
370 i = x;
371 while (++i < video_num_columns) {
372 *p = *(p+1);
373 p++;
374 }
375 *p = video_erase_char;
376 }
377
378 static void delete_line(void)
379 {
380 int oldtop,oldbottom;
381
382 oldtop=top;
383 oldbottom=bottom;
384 top=y;
385 bottom = video_num_lines;
386 scrup();
387 top=oldtop;
388 bottom=oldbottom;
389 }
390
391 static void csi_at(unsigned int nr)
392 {
393 if (nr > video_num_columns)
394 nr = video_num_columns;
395 else if (!nr)
396 nr = 1;
397 while (nr--)
398 insert_char();
399 }
400
401 static void csi_L(unsigned int nr)
402 {
403 if (nr > video_num_lines)
404 nr = video_num_lines;
405 else if (!nr)
406 nr = 1;
407 while (nr--)
408 insert_line();
409 }
410
411 static void csi_P(unsigned int nr)
412 {
413 if (nr > video_num_columns)
414 nr = video_num_columns;
415 else if (!nr)
416 nr = 1;
417 while (nr--)
418 delete_char();
419 }
420
421 static void csi_M(unsigned int nr)
422 {
423 if (nr > video_num_lines)
424 nr = video_num_lines;
425 else if (!nr)
426 nr=1;
427 while (nr--)
428 delete_line();
429 }
430
431 static int saved_x=0;
432 static int saved_y=0;
433
434 static void save_cur(void)
435 {
436 saved_x=x;
437 saved_y=y;
438 }
439
440 static void restore_cur(void)
441 {
442 gotoxy(saved_x, saved_y);
443 }
444
445 void con_write(struct tty_struct * tty)
446 {
447 int nr;
448 char c;
449
450 nr = CHARS(tty->write_q);
451 while (nr--) {
452 GETCH(tty->write_q,c);
453 switch(state) {
454 case 0:
455 if (c>31 && c<127) {
456 if (x>=video_num_columns) {
457 x -= video_num_columns;
458 pos -= video_size_row;
459 lf();
460 }
461 __asm__("movb _attr,%%ah\n\t"
462 "movw %%ax,%1\n\t"
463 ::"a" (c),"m" (*(short *)pos)
464 :"ax");
465 pos += 2;
466 x++;
467 } else if (c==27)
468 state=1;
469 else if (c==10 || c==11 || c==12)
470 lf();
471 else if (c==13)
472 cr();
473 else if (c==ERASE_CHAR(tty))
474 del();
475 else if (c==8) {
476 if (x) {
477 x--;
478 pos -= 2;
479 }
480 } else if (c==9) {
481 c=8-(x&7);
482 x += c;
483 pos += c<<1;
484 if (x>video_num_columns) {
485 x -= video_num_columns;
486 pos -= video_size_row;
487 lf();
488 }
489 c=9;
490 } else if (c==7)
491 sysbeep();
492 break;
493 case 1:
494 state=0;
495 if (c=='[')
496 state=2;
497 else if (c=='E')
498 gotoxy(0,y+1);
499 else if (c=='M')
500 ri();
501 else if (c=='D')
502 lf();
503 else if (c=='Z')
504 respond(tty);
505 else if (x=='7')
506 save_cur();
507 else if (x=='8')
508 restore_cur();
509 break;
510 case 2:
511 for(npar=0;npar<NPAR;npar++)
512 par[npar]=0;
513 npar=0;
514 state=3;
515 if (ques=(c=='?'))
516 break;
517 case 3:
518 if (c==';' && npar<NPAR-1) {
519 npar++;
520 break;
521 } else if (c>='0' && c<='9') {
522 par[npar]=10*par[npar]+c-'0';
523 break;
524 } else state=4;
525 case 4:
526 state=0;
527 switch(c) {
528 case 'G': case '`':
529 if (par[0]) par[0]--;
530 gotoxy(par[0],y);
531 break;
532 case 'A':
533 if (!par[0]) par[0]++;
534 gotoxy(x,y-par[0]);
535 break;
536 case 'B': case 'e':
537 if (!par[0]) par[0]++;
538 gotoxy(x,y+par[0]);
539 break;
540 case 'C': case 'a':
541 if (!par[0]) par[0]++;
542 gotoxy(x+par[0],y);
543 break;
544 case 'D':
545 if (!par[0]) par[0]++;
546 gotoxy(x-par[0],y);
547 break;
548 case 'E':
549 if (!par[0]) par[0]++;
550 gotoxy(0,y+par[0]);
551 break;
552 case 'F':
553 if (!par[0]) par[0]++;
554 gotoxy(0,y-par[0]);
555 break;
556 case 'd':
557 if (par[0]) par[0]--;
558 gotoxy(x,par[0]);
559 break;
560 case 'H': case 'f':
561 if (par[0]) par[0]--;
562 if (par[1]) par[1]--;
563 gotoxy(par[1],par[0]);
564 break;
565 case 'J':
566 csi_J(par[0]);
567 break;
568 case 'K':
569 csi_K(par[0]);
570 break;
571 case 'L':
572 csi_L(par[0]);
573 break;
574 case 'M':
575 csi_M(par[0]);
576 break;
577 case 'P':
578 csi_P(par[0]);
579 break;
580 case '@':
581 csi_at(par[0]);
582 break;
583 case 'm':
584 csi_m();
585 break;
586 case 'r':
587 if (par[0]) par[0]--;
588 if (!par[1]) par[1] = video_num_lines;
589 if (par[0] < par[1] &&
590 par[1] <= video_num_lines) {
591 top=par[0];
592 bottom=par[1];
593 }
594 break;
595 case 's':
596 save_cur();
597 break;
598 case 'u':
599 restore_cur();
600 break;
601 }
602 }
603 }
604 set_cursor();
605 }
606
607
608
609
610
611
612
613
614
615
616
617 void con_init(void)
618 {
619 register unsigned char a;
620 char *display_desc = "????";
621 char *display_ptr;
622
623 video_num_columns = ORIG_VIDEO_COLS;
624 video_size_row = video_num_columns * 2;
625 video_num_lines = ORIG_VIDEO_LINES;
626 video_page = ORIG_VIDEO_PAGE;
627 video_erase_char = 0x0720;
628
629 if (ORIG_VIDEO_MODE == 7)
630 {
631 video_mem_start = 0xb0000;
632 video_port_reg = 0x3b4;
633 video_port_val = 0x3b5;
634 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
635 {
636 video_type = VIDEO_TYPE_EGAM;
637 video_mem_end = 0xb8000;
638 display_desc = "EGAm";
639 }
640 else
641 {
642 video_type = VIDEO_TYPE_MDA;
643 video_mem_end = 0xb2000;
644 display_desc = "*MDA";
645 }
646 }
647 else
648 {
649 video_mem_start = 0xb8000;
650 video_port_reg = 0x3d4;
651 video_port_val = 0x3d5;
652 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
653 {
654 video_type = VIDEO_TYPE_EGAC;
655 video_mem_end = 0xbc000;
656 display_desc = "EGAc";
657 }
658 else
659 {
660 video_type = VIDEO_TYPE_CGA;
661 video_mem_end = 0xba000;
662 display_desc = "*CGA";
663 }
664 }
665
666
667
668 display_ptr = ((char *)video_mem_start) + video_size_row - 8;
669 while (*display_desc)
670 {
671 *display_ptr++ = *display_desc++;
672 display_ptr++;
673 }
674
675
676
677 origin = video_mem_start;
678 scr_end = video_mem_start + video_num_lines * video_size_row;
679 top = 0;
680 bottom = video_num_lines;
681
682 gotoxy(ORIG_X,ORIG_Y);
683 set_trap_gate(0x21,&keyboard_interrupt);
684 outb_p(inb_p(0x21)&0xfd,0x21);
685 a=inb_p(0x61);
686 outb_p(a|0x80,0x61);
687 outb(a,0x61);
688 }
689
690
691 void sysbeepstop(void)
692 {
693
694 outb(inb_p(0x61)&0xFC, 0x61);
695 }
696
697 int beepcount = 0;
698
699 static void sysbeep(void)
700 {
701
702 outb_p(inb_p(0x61)|3, 0x61);
703
704 outb_p(0xB6, 0x43);
705
706 outb_p(0x37, 0x42);
707 outb(0x06, 0x42);
708
709 beepcount = HZ/8;
710 }