00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00025
00026
00027
00028 #include "src/common/shared.hpp"
00029 #include "src/common/error.hpp"
00030 #include "src/common/io.hpp"
00031 #include "src/memory/align.hpp"
00032 #include "src/memory/memset.hpp"
00033 #include "src/memory/alloc4k.hpp"
00034 #include "src/memory/pager.hpp"
00035 #include "src/memory/heap.hpp"
00036 #include "src/common/string.hpp"
00037 #include "src/thread/scheduler.hpp"
00038 #include "src/tty/teletype.hpp"
00039
00040 bool volatile TTYDisableLock=false;
00041
00042 teletype videoHW ((ChCol*) VIDEO_MEMORY + CONSOLE_XSIZE, CONSOLE_XSIZE, CONSOLE_YSIZE, CONSOLE_YSIZE, NULL, NULL, CONSOLE_COLOR);
00043 teletype *active_console = &tty1;
00044
00045 teletype tty_panel ((ChCol*) VIDEO_MEMORY, CONSOLE_XSIZE, 1, 1, NULL, NULL, TTY_PANEL_COLOR);
00046
00047 teletype tty1 (tty1_buf, CONSOLE_XSIZE, CONSOLE_YSIZE, VIRTCONS_LINES, &videoHW, &tui_kbd_handler, CONSOLE_COLOR);
00048 teletype tty2 (tty2_buf, CONSOLE_XSIZE, CONSOLE_YSIZE, VIRTCONS_LINES, &videoHW, &tui_kbd_handler, CONSOLE_COLOR);
00049 teletype tty3 (tty3_buf, CONSOLE_XSIZE, CONSOLE_YSIZE, VIRTCONS_LINES, &videoHW, &tui_kbd_handler, CONSOLE_COLOR);
00050 teletype tty4 (tty4_buf, CONSOLE_XSIZE, CONSOLE_YSIZE, VIRTCONS_LINES, &videoHW, &tui_kbd_handler, CONSOLE_COLOR);
00051 teletype tty5 (tty5_buf, CONSOLE_XSIZE, CONSOLE_YSIZE, VIRTCONS_LINES, &videoHW, &tui_kbd_handler, CONSOLE_COLOR);
00052 teletype tty6 (tty6_buf, CONSOLE_XSIZE, CONSOLE_YSIZE, VIRTCONS_LINES, &videoHW, &tui_kbd_handler, CONSOLE_COLOR);
00053 teletype tty7 (tty7_buf, CONSOLE_XSIZE, CONSOLE_YSIZE, VIRTCONS_LINES, &videoHW, &tui_kbd_handler, CONSOLE_COLOR);
00054 teletype tty8 (tty8_buf, CONSOLE_XSIZE, CONSOLE_YSIZE, VIRTCONS_LINES, &videoHW, &tui_kbd_handler, CONSOLE_COLOR);
00055 teletype tty9 (tty9_buf, CONSOLE_XSIZE, CONSOLE_YSIZE, VIRTCONS_LINES, &videoHW, &tui_kbd_handler, CONSOLE_COLOR);
00056 teletype tty0 (tty0_buf, CONSOLE_XSIZE, CONSOLE_YSIZE, VIRTCONS_LINES, &videoHW, &tui_kbd_handler, CONSOLE_COLOR);
00057
00058 ChCol tty1_buf [VIRTCONS_LINES * CONSOLE_XSIZE] __attribute__ ((section (".bss.dontcare")));
00059 ChCol tty2_buf [VIRTCONS_LINES * CONSOLE_XSIZE] __attribute__ ((section (".bss.dontcare")));
00060 ChCol tty3_buf [VIRTCONS_LINES * CONSOLE_XSIZE] __attribute__ ((section (".bss.dontcare")));
00061 ChCol tty4_buf [VIRTCONS_LINES * CONSOLE_XSIZE] __attribute__ ((section (".bss.dontcare")));
00062 ChCol tty5_buf [VIRTCONS_LINES * CONSOLE_XSIZE] __attribute__ ((section (".bss.dontcare")));
00063 ChCol tty6_buf [VIRTCONS_LINES * CONSOLE_XSIZE] __attribute__ ((section (".bss.dontcare")));
00064 ChCol tty7_buf [VIRTCONS_LINES * CONSOLE_XSIZE] __attribute__ ((section (".bss.dontcare")));
00065 ChCol tty8_buf [VIRTCONS_LINES * CONSOLE_XSIZE] __attribute__ ((section (".bss.dontcare")));
00066 ChCol tty9_buf [VIRTCONS_LINES * CONSOLE_XSIZE] __attribute__ ((section (".bss.dontcare")));
00067 ChCol tty0_buf [VIRTCONS_LINES * CONSOLE_XSIZE] __attribute__ ((section (".bss.dontcare")));
00068
00069
00070 namespace Teletype {
00071
00072 ChCol *vidmem;
00073
00074
00075 void init()
00076 {
00077
00078 uint32 **pgd, *pgt;
00079 vidmem= (ChCol*) Memory::Physical::ballocate(4096, PAGE_ALIGN);
00080
00081
00082 asm volatile("mov %%cr3, %%eax" : "=a" (pgd));
00083
00084 pgt= (uint32*)((uint32)pgd[(uint32)vidmem/PGT_WIDE]&0xfffff000);
00085 pgt[((uint32)vidmem&0x003fffff)/PAGE_SIZE]= video_memory|PTE_PRESENT|PTE_WRITEABLE;
00086
00087
00088
00089
00090 asm volatile("movl %cr3, %eax\nmovl %eax, %cr3");
00091
00092 videoHW.video=vidmem+CONSOLE_XSIZE;
00093 tty_panel.video=vidmem;
00094 }
00095
00096 };
00097
00098
00099 teletype::teletype(ChCol *buffer, int _xsize, int _ysize, int _lines, teletype *vHW, int (*kbd_h)(), uint8 col)
00100 {
00101
00102 sem_init(&sem_tty,1,"tty");
00103
00104 video=(ChCol*) buffer;
00105
00106 xsize=_xsize; ysize=_ysize; lines= _lines; yfocus=yoffset=0;
00107 color = col;
00108 start=0;lgth=0;
00109
00110 HW = vHW;
00111 kbd_handler=kbd_h;
00112
00113
00114 clrscr();
00115 }
00116
00117
00118 void teletype::clrscr()
00119 {
00120
00121 memset((void*) video, color * 0x01000100, sizeof (ChCol) * xsize * lines);
00122
00123 yfocus=yoffset = 0;
00124 start=0;lgth=0;
00125 x=y=0;
00126 gotoxy(0, 0);
00127
00128 if (HW)
00129 if (this == active_console)
00130 HW->clrscr();
00131 }
00132
00133
00134 int teletype::line (int n)
00135 {
00136 int val = n + start;
00137
00138 if (val < 0)
00139 return -1;
00140 if (n >= lines)
00141 return -1;
00142
00143 if (val >= lines)
00144 return val - lines;
00145
00146 return val;
00147 }
00148
00149
00150 ChCol *teletype::lineptr (int n)
00151 {
00152 int l = line(n);
00153 ChCol *r;
00154
00155 if (l == -1)
00156 r= NULL; else
00157
00158 r= video + l * xsize;
00159
00160 if ((uint32)r<0x1000)
00161 { asm volatile("cli"); TTYDisableLock=true; say(const_cast<char*>("%x"),r);asm volatile ("cli\nhlt");}
00162 return r;
00163 }
00164
00165
00166 void teletype::movecurs(int n)
00167 {
00168 int k;
00169 int nl;
00170 x+=n;
00171 if (x >= xsize)
00172 {
00173 k = x / xsize;
00174 x = x % xsize;
00175 y+=k;
00176
00177 nl=y+yfocus+k;
00178 if (nl > lgth)
00179 lgth=nl;
00180 }
00181 if (y >= ysize)
00182 {
00183 yfocus += ysize - y + 1;
00184 yoffset=yfocus;
00185 y= ysize-1;
00186
00187 if (lgth>lines)
00188 del_top(lgth-lines);
00189
00190 if (HW)
00191 if (this == active_console)
00192 HW->repaint(this);
00193 }
00194 }
00195
00196
00197
00198 void teletype::llock() {
00199 _PF;
00200 if (TTYDisableLock)
00201 Preturn();
00202
00203
00204 int cnt=0xffff;
00205 while (cnt--)
00206 if (sem_trywait(&sem_tty)==ESUCCESS)
00207 Preturn();
00208 Preturn();
00209 }
00210
00211
00212 void teletype::lulock() {
00213
00214 sem_post(&sem_tty);
00215 }
00216
00217
00218 void teletype::repaint(teletype *tty)
00219 { _Pf("tty'::repaint");
00220 int i;
00221
00222 videoHW_toggle_cursor(tty->yfocus == tty->yoffset);
00223
00224 for (i=0;i<ysize;i++)
00225 memmove (lineptr(yoffset + i),
00226 tty->lineptr(tty->yoffset+i),
00227 160);
00228
00229 preturn();
00230 }
00231
00232
00233 void teletype::del_top(int n)
00234 {
00235
00236 memset((void*) lineptr(0), color * 0x01000100, n * sizeof(ChCol) * xsize);
00237
00238 yoffset-=n; yfocus-=n;
00239 start+=n;if (start>=lines) start-=lines;
00240 lgth-=n;
00241 }
00242
00243
00244 void teletype::gotoxy(int px, int py)
00245 {
00246
00247
00248
00249 x=px; y=py;
00250 if (this == active_console)
00251 videoHW_gotoxy(y * xsize + x + GOTOXY_ADDEND);
00252 return;
00253
00254
00255 if (yoffset != yfocus) {
00256 yoffset=yfocus;
00257 if (HW)
00258 if (this == active_console) HW->repaint(this); }
00259
00260
00261 return ;
00262
00263 if ((px < 0) || (px >= xsize))
00264 return ;
00265 if (py + yfocus < 0)
00266 return ;
00267 if (py + yfocus > lines)
00268 sysfail("oy! teletype::gotoxy, error #1");
00269 }
00270
00271
00272 void teletype::showtop(int py)
00273 {
00274
00275 if (py < 0)
00276 py = 0;
00277 if (py + ysize > lines)
00278 py = lines - ysize;
00279
00280 yoffset = py;
00281 if (HW)
00282 if (this == active_console)
00283 HW->repaint(this);
00284 }
00285
00286
00287 void teletype::put(char ch)
00288 {
00289 put(ch,color);
00290 }
00291
00292
00293 void teletype::put(char ch, uint8 col)
00294 { _Pf("Tty'::put");
00295
00296
00297 if (yoffset != yfocus) {
00298 yoffset=yfocus;
00299 if (HW) if (this == active_console) HW->repaint(this); }
00300
00301 switch (ch)
00302 {
00303 case '\n':
00304 movecurs(xsize-x);
00305 break;
00306 case '\t':
00307 tab(8);
00308
00309
00310
00311
00312
00313
00314
00315 break;
00316 case 13:
00317 x=0;
00318 break;
00319 case '\a':
00320 break;
00321 case '\b':
00322 poke (' ', x-1,y, color);
00323 movecurs(-1);
00324 break;
00325 default:
00326 poke (ch, x,y, col);
00327 movecurs(1);
00328 break;
00329 }
00330
00331
00332 preturn();
00333 }
00334
00335
00336 void teletype::putch(char ch)
00337 {
00338 putch(ch,color);
00339 }
00340
00341
00342 void teletype::putch(char ch, uint8 col)
00343 {
00344 put(ch,col);
00345 gotoxy(x,y);
00346 }
00347
00348
00349 void teletype::poke_str(char *ch, int px, int py, uint8 col, uint32 limit)
00350 {
00351 uint32 oldx=x,oldy=y;
00352 uint32 cnt=0;
00353 gotoxy(px,py);
00354 while ( (*ch) && (cnt < limit) ) put(*(ch++),col);
00355 gotoxy(oldx,oldy);
00356 }
00357
00358
00359 void teletype::poke (char ch, int px, int py, uint8 col)
00360 {
00361 ChCol *l = lineptr(py + yfocus);
00362
00363 if (l == NULL)
00364 return ;
00365 if (px < 0)
00366 return ;
00367 if (px >= xsize)
00368 return ;
00369
00370
00371 l[px].ch=ch;
00372 l[px].col=col;
00373
00374 if (HW)
00375 if (this == active_console)
00376 HW->poke(ch,px,py,col);
00377 }
00378
00379 int teletype::getx() {
00380 return x;
00381 }
00382
00383 int teletype::gety() {
00384 return y;
00385 }
00386
00387 int teletype::getxsize() {
00388 return xsize;
00389 }
00390
00391 int teletype::getysize() {
00392 return ysize;
00393 }
00394
00395
00396 void teletype::setcol(uint8 col) {
00397 color = col;
00398 }
00399
00400
00401 void teletype::scroll(int i)
00402 {
00403
00404 int newyoffset = yoffset + i * ysize / 2;
00405
00406 if (newyoffset + ysize > lgth)
00407 newyoffset = lgth - ysize;
00408
00409 showtop(newyoffset);
00410 }
00411
00412
00413 void teletype::tab(int i)
00414 {
00415 int new_x= align_up(x+1, i);
00416 while (x < new_x)
00417 {
00418 poke(' ', x,y, color);
00419 x++;
00420 }
00421 }
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435 void coutnum(uint32 n, uint32 radix, uint32 n_pos, char first_letter)
00436 {
00437 coutnum(active_console,n,radix,n_pos,first_letter);
00438 }
00439
00440
00441 void coutnum(teletype *tty, uint32 n, uint32 radix, uint32 n_pos, char first_letter) {
00442 coutnum(tty,n,radix,n_pos,first_letter,'0');
00443 }
00444
00445
00446 void coutnum(teletype *tty, uint32 n, uint32 radix, uint32 n_pos, char first_letter, char EmptyLetter)
00447 {
00448 uint32 cipher;
00449 bool FirstCipherPut=false;
00450 tty->llock();
00451 while (n_pos)
00452 {
00453 cipher = n / n_pos;
00454 if (cipher <= 9) { if ((cipher==0)&&(n_pos/radix)&&(FirstCipherPut==false)) tty->put(EmptyLetter); else
00455 { tty->put(cipher + (char) '0'); FirstCipherPut=true; } }
00456 else tty->put(cipher + first_letter - 0xA);
00457
00458 n -= cipher * n_pos;
00459 n_pos = n_pos / radix;
00460 }
00461 tty->gotoxy(tty->getx(),tty->gety());
00462 tty->lulock();
00463 }
00464
00465
00466 void coutnum(teletype *tty, uint32 n, uint32 radix, uint32 n_pos, char first_letter, uint8 col)
00467 {
00468 tty->llock();
00469 uint32 cipher;
00470 while (n_pos)
00471 {
00472 cipher = n / n_pos;
00473 if (cipher <= 9) tty->put(cipher + (char) '0',col);
00474 else tty->put(cipher + first_letter - 0xA,col);
00475
00476 n -= cipher * n_pos;
00477 n_pos = n_pos / radix;
00478 }
00479 tty->gotoxy(tty->getx(),tty->gety());
00480 tty->lulock();
00481 }
00482
00483
00484 void coutDec(uint32 i) {
00485 if (i == 0) {
00486 putch('0');
00487 return ;
00488 }
00489 for (uint32 rank=1000000000; rank; rank /= 10) {
00490 if (rank > i)
00491 continue;
00492 putch( '0'+(i / rank)%10 );
00493 }
00494 }
00495
00496
00497 void cout (const char *ch)
00498 {
00499
00500
00501 cout(active_console,const_cast<char*>(ch));
00502 }
00503
00504
00505 void cout(teletype *tty, char *ch)
00506 {
00507 tty->llock();
00508 while ( (*ch) ) tty->put(*(ch++));
00509 tty->gotoxy(tty->getx(),tty->gety());
00510 tty->lulock();
00511 }
00512
00513
00514 void cout (char *ch, uint8 color)
00515 {
00516 active_console->llock();
00517 while ( (*ch) ) active_console->put(*(ch++),color);
00518 active_console->gotoxy(active_console->getx(),active_console->gety());
00519 active_console->lulock();
00520 }
00521
00522
00523 void cout (uint32 i)
00524 {
00525 coutnum(i, 16, 0x10000000, 'A');
00526 }
00527
00528
00529 void cout (uint32 i,uint8 col)
00530 {
00531 coutnum(active_console, i, 16, 0x10000000, 'A', col);
00532 }
00533
00534
00535 void cout (teletype *tty, uint32 i)
00536 {
00537 coutnum(tty,i,16,0x10000000,'A');
00538 }
00539
00540
00541 void coutb(uint8 ch)
00542 {
00543 coutnum(ch, 0x10, 0x10, 'A');
00544 }
00545
00546
00547 void putch(char ch)
00548 {
00549 active_console->llock();
00550 active_console->putch(ch);
00551 active_console->lulock();
00552 }
00553
00554
00555 void writehere(char *ch, uint8 color, uint32 limit)
00556 {
00557 active_console->llock();
00558 active_console->poke_str(ch,color,active_console->getx(), active_console->gety(), limit);
00559 active_console->lulock();
00560 }
00561
00562
00563 void poke_char(char ch, uint8 color, int x, int y)
00564 {
00565 active_console->llock();
00566 active_console->poke(ch, x,y, color);
00567 active_console->lulock();
00568 }
00569
00570
00571 void poke_str(char *ch, uint8 color, int x, int y, uint32 limit)
00572 {
00573 active_console->llock();
00574 active_console->poke_str(ch, color, x,y, limit);
00575 active_console->lulock();
00576 }
00577
00578
00579 void kprintf(const char *text, ...)
00580 {
00581
00582 string formatted_text;
00583
00584 formatted_text.inval();
00585 formatted_text.formatText(const_cast<char*>(text), (char*)((uint32)&text + 1));
00586
00587 cout(formatted_text.v());
00588
00589
00590 formatted_text.done();
00591 }
00592
00593
00594 void ksnprintf(char *str, size_t size, char *format, ...)
00595 {
00596 string foo;
00597 uint32 len;
00598 foo.inval(); foo.formatText(format, (char*)((uint32)&format + 1));
00599 len= foo.length();
00600 len= (len<size?len:size-1);
00601 memmove(str, foo.v( ), len );
00602 str[len]='\0';
00603 }
00604
00605
00606 void kprintf_alert(char *text, ...)
00607 {
00608
00609 string formatted_text;
00610
00611 formatted_text.inval();
00612 formatted_text.formatText(text, (char*)((uint32)&text + 1));
00613
00614 alert(formatted_text.v());
00615
00616
00617 formatted_text.done();
00618 }
00619
00620
00621 void kprintf(teletype *tty, char *text, ...)
00622 {
00623
00624 string formatted_text;
00625
00626 formatted_text.inval();
00627 formatted_text.formatText(text, (char*)((uint32)&text + 1));
00628
00629 cout(tty, formatted_text.v());
00630
00631
00632 formatted_text.done();
00633 }
00634
00635
00636
00637 void videoHW_gotoxy(int n)
00638 {
00639 union
00640 {
00641 uint32 u;
00642 uint8 c[2];
00643 } un;
00644 un.u = n;
00645
00646 uint32 fl;
00647 asm volatile("pushf\npopl %0\ncli":"=g"(fl));
00648 IOPorts::outb (0x3d4, 0xf);
00649 IOPorts::outb (0x3d5, un.c[0]);
00650 IOPorts::outb (0x3d4, 0xe);
00651 IOPorts::outb (0x3d5, un.c[1]);
00652 asm volatile("pushl %0\npopf"::"g"(fl));
00653 }
00654
00655
00656 void videoHW_toggle_cursor(bool on)
00657 {
00658 uint8 val;
00659 uint32 fl;
00660 asm volatile("pushf\npopl %0\ncli":"=g"(fl));
00661
00662 IOPorts::outb(0x3d4, 0xa);
00663 val = IOPorts::inb(0x3d5);
00664
00665 val &= 0xff - 0x20;
00666 val |= (!on) << 5;
00667
00668 IOPorts::outb (0x3d4, 0xa);
00669 IOPorts::outb (0x3d5, val);
00670 asm volatile("pushl %0\npopf"::"g"(fl));
00671 }
00672
00673
00674 int tui_kbd_handler()
00675 {
00676 return 1;
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715 }
00716
00717
00718 void tty_switch(teletype *tty, char *name)
00719 {
00720
00721 active_console = tty;
00722
00723 tty->HW->repaint(tty);
00724
00725 tty->gotoxy(tty->getx(), tty->gety());
00726
00727 tty_panel.poke_str(name, TTY_NO_X,0, TTY_PANEL_COLOR, 5);
00728 }
00729
00730
00731
00732
00733
00734
00735