|
|
1.1 ! root 1: /* ! 2: * console.c ! 3: * ! 4: * This module implements the console io functions ! 5: * 'void con_init(void)' ! 6: * 'void con_write(struct tty_queue * queue)' ! 7: * Hopefully this will be a rather complete VT102 implementation. ! 8: * ! 9: */ ! 10: ! 11: /* ! 12: * NOTE!!! We sometimes disable and enable interrupts for a short while ! 13: * (to put a word in video IO), but this will work even for keyboard ! 14: * interrupts. We know interrupts aren't enabled when getting a keyboard ! 15: * interrupt, as we use trap-gates. Hopefully all is well. ! 16: */ ! 17: ! 18: #include <linux/sched.h> ! 19: #include <linux/tty.h> ! 20: #include <asm/io.h> ! 21: #include <asm/system.h> ! 22: ! 23: #define SCREEN_START 0xb8000 ! 24: #define SCREEN_END 0xc0000 ! 25: #define LINES 25 ! 26: #define COLUMNS 80 ! 27: #define NPAR 16 ! 28: ! 29: extern void keyboard_interrupt(void); ! 30: ! 31: static unsigned long origin=SCREEN_START; ! 32: static unsigned long scr_end=SCREEN_START+LINES*COLUMNS*2; ! 33: static unsigned long pos; ! 34: static unsigned long x,y; ! 35: static unsigned long top=0,bottom=LINES; ! 36: static unsigned long lines=LINES,columns=COLUMNS; ! 37: static unsigned long state=0; ! 38: static unsigned long npar,par[NPAR]; ! 39: static unsigned long ques=0; ! 40: static unsigned char attr=0x07; ! 41: ! 42: /* ! 43: * this is what the terminal answers to a ESC-Z or csi0c ! 44: * query (= vt100 response). ! 45: */ ! 46: #define RESPONSE "\033[?1;2c" ! 47: ! 48: static inline void gotoxy(unsigned int new_x,unsigned int new_y) ! 49: { ! 50: if (new_x>=columns || new_y>=lines) ! 51: return; ! 52: x=new_x; ! 53: y=new_y; ! 54: pos=origin+((y*columns+x)<<1); ! 55: } ! 56: ! 57: static inline void set_origin(void) ! 58: { ! 59: cli(); ! 60: outb_p(12,0x3d4); ! 61: outb_p(0xff&((origin-SCREEN_START)>>9),0x3d5); ! 62: outb_p(13,0x3d4); ! 63: outb_p(0xff&((origin-SCREEN_START)>>1),0x3d5); ! 64: sti(); ! 65: } ! 66: ! 67: static void scrup(void) ! 68: { ! 69: if (!top && bottom==lines) { ! 70: origin += columns<<1; ! 71: pos += columns<<1; ! 72: scr_end += columns<<1; ! 73: if (scr_end>SCREEN_END) { ! 74: __asm__("cld\n\t" ! 75: "rep\n\t" ! 76: "movsl\n\t" ! 77: "movl _columns,%1\n\t" ! 78: "rep\n\t" ! 79: "stosw" ! 80: ::"a" (0x0720), ! 81: "c" ((lines-1)*columns>>1), ! 82: "D" (SCREEN_START), ! 83: "S" (origin) ! 84: :"cx","di","si"); ! 85: scr_end -= origin-SCREEN_START; ! 86: pos -= origin-SCREEN_START; ! 87: origin = SCREEN_START; ! 88: } else { ! 89: __asm__("cld\n\t" ! 90: "rep\n\t" ! 91: "stosl" ! 92: ::"a" (0x07200720), ! 93: "c" (columns>>1), ! 94: "D" (scr_end-(columns<<1)) ! 95: :"cx","di"); ! 96: } ! 97: set_origin(); ! 98: } else { ! 99: __asm__("cld\n\t" ! 100: "rep\n\t" ! 101: "movsl\n\t" ! 102: "movl _columns,%%ecx\n\t" ! 103: "rep\n\t" ! 104: "stosw" ! 105: ::"a" (0x0720), ! 106: "c" ((bottom-top-1)*columns>>1), ! 107: "D" (origin+(columns<<1)*top), ! 108: "S" (origin+(columns<<1)*(top+1)) ! 109: :"cx","di","si"); ! 110: } ! 111: } ! 112: ! 113: static void scrdown(void) ! 114: { ! 115: __asm__("std\n\t" ! 116: "rep\n\t" ! 117: "movsl\n\t" ! 118: "addl $2,%%edi\n\t" /* %edi has been decremented by 4 */ ! 119: "movl _columns,%%ecx\n\t" ! 120: "rep\n\t" ! 121: "stosw" ! 122: ::"a" (0x0720), ! 123: "c" ((bottom-top-1)*columns>>1), ! 124: "D" (origin+(columns<<1)*bottom-4), ! 125: "S" (origin+(columns<<1)*(bottom-1)-4) ! 126: :"ax","cx","di","si"); ! 127: } ! 128: ! 129: static void lf(void) ! 130: { ! 131: if (y+1<bottom) { ! 132: y++; ! 133: pos += columns<<1; ! 134: return; ! 135: } ! 136: scrup(); ! 137: } ! 138: ! 139: static void ri(void) ! 140: { ! 141: if (y>top) { ! 142: y--; ! 143: pos -= columns<<1; ! 144: return; ! 145: } ! 146: scrdown(); ! 147: } ! 148: ! 149: static void cr(void) ! 150: { ! 151: pos -= x<<1; ! 152: x=0; ! 153: } ! 154: ! 155: static void del(void) ! 156: { ! 157: if (x) { ! 158: pos -= 2; ! 159: x--; ! 160: *(unsigned short *)pos = 0x0720; ! 161: } ! 162: } ! 163: ! 164: static void csi_J(int par) ! 165: { ! 166: long count __asm__("cx"); ! 167: long start __asm__("di"); ! 168: ! 169: switch (par) { ! 170: case 0: /* erase from cursor to end of display */ ! 171: count = (scr_end-pos)>>1; ! 172: start = pos; ! 173: break; ! 174: case 1: /* erase from start to cursor */ ! 175: count = (pos-origin)>>1; ! 176: start = origin; ! 177: break; ! 178: case 2: /* erase whole display */ ! 179: count = columns*lines; ! 180: start = origin; ! 181: break; ! 182: default: ! 183: return; ! 184: } ! 185: __asm__("cld\n\t" ! 186: "rep\n\t" ! 187: "stosw\n\t" ! 188: ::"c" (count), ! 189: "D" (start),"a" (0x0720) ! 190: :"cx","di"); ! 191: } ! 192: ! 193: static void csi_K(int par) ! 194: { ! 195: long count __asm__("cx"); ! 196: long start __asm__("di"); ! 197: ! 198: switch (par) { ! 199: case 0: /* erase from cursor to end of line */ ! 200: if (x>=columns) ! 201: return; ! 202: count = columns-x; ! 203: start = pos; ! 204: break; ! 205: case 1: /* erase from start of line to cursor */ ! 206: start = pos - (x<<1); ! 207: count = (x<columns)?x:columns; ! 208: break; ! 209: case 2: /* erase whole line */ ! 210: start = pos - (x<<1); ! 211: count = columns; ! 212: break; ! 213: default: ! 214: return; ! 215: } ! 216: __asm__("cld\n\t" ! 217: "rep\n\t" ! 218: "stosw\n\t" ! 219: ::"c" (count), ! 220: "D" (start),"a" (0x0720) ! 221: :"cx","di"); ! 222: } ! 223: ! 224: void csi_m(void) ! 225: { ! 226: int i; ! 227: ! 228: for (i=0;i<=npar;i++) ! 229: switch (par[i]) { ! 230: case 0:attr=0x07;break; ! 231: case 1:attr=0x0f;break; ! 232: case 4:attr=0x0f;break; ! 233: case 7:attr=0x70;break; ! 234: case 27:attr=0x07;break; ! 235: } ! 236: } ! 237: ! 238: static inline void set_cursor(void) ! 239: { ! 240: cli(); ! 241: outb_p(14,0x3d4); ! 242: outb_p(0xff&((pos-SCREEN_START)>>9),0x3d5); ! 243: outb_p(15,0x3d4); ! 244: outb_p(0xff&((pos-SCREEN_START)>>1),0x3d5); ! 245: sti(); ! 246: } ! 247: ! 248: static void respond(struct tty_struct * tty) ! 249: { ! 250: char * p = RESPONSE; ! 251: ! 252: cli(); ! 253: while (*p) { ! 254: PUTCH(*p,tty->read_q); ! 255: p++; ! 256: } ! 257: sti(); ! 258: copy_to_cooked(tty); ! 259: } ! 260: ! 261: static void insert_char(void) ! 262: { ! 263: int i=x; ! 264: unsigned short tmp,old=0x0720; ! 265: unsigned short * p = (unsigned short *) pos; ! 266: ! 267: while (i++<columns) { ! 268: tmp=*p; ! 269: *p=old; ! 270: old=tmp; ! 271: p++; ! 272: } ! 273: } ! 274: ! 275: static void insert_line(void) ! 276: { ! 277: int oldtop,oldbottom; ! 278: ! 279: oldtop=top; ! 280: oldbottom=bottom; ! 281: top=y; ! 282: bottom=lines; ! 283: scrdown(); ! 284: top=oldtop; ! 285: bottom=oldbottom; ! 286: } ! 287: ! 288: static void delete_char(void) ! 289: { ! 290: int i; ! 291: unsigned short * p = (unsigned short *) pos; ! 292: ! 293: if (x>=columns) ! 294: return; ! 295: i = x; ! 296: while (++i < columns) { ! 297: *p = *(p+1); ! 298: p++; ! 299: } ! 300: *p=0x0720; ! 301: } ! 302: ! 303: static void delete_line(void) ! 304: { ! 305: int oldtop,oldbottom; ! 306: ! 307: oldtop=top; ! 308: oldbottom=bottom; ! 309: top=y; ! 310: bottom=lines; ! 311: scrup(); ! 312: top=oldtop; ! 313: bottom=oldbottom; ! 314: } ! 315: ! 316: static void csi_at(int nr) ! 317: { ! 318: if (nr>columns) ! 319: nr=columns; ! 320: else if (!nr) ! 321: nr=1; ! 322: while (nr--) ! 323: insert_char(); ! 324: } ! 325: ! 326: static void csi_L(int nr) ! 327: { ! 328: if (nr>lines) ! 329: nr=lines; ! 330: else if (!nr) ! 331: nr=1; ! 332: while (nr--) ! 333: insert_line(); ! 334: } ! 335: ! 336: static void csi_P(int nr) ! 337: { ! 338: if (nr>columns) ! 339: nr=columns; ! 340: else if (!nr) ! 341: nr=1; ! 342: while (nr--) ! 343: delete_char(); ! 344: } ! 345: ! 346: static void csi_M(int nr) ! 347: { ! 348: if (nr>lines) ! 349: nr=lines; ! 350: else if (!nr) ! 351: nr=1; ! 352: while (nr--) ! 353: delete_line(); ! 354: } ! 355: ! 356: static int saved_x=0; ! 357: static int saved_y=0; ! 358: ! 359: static void save_cur(void) ! 360: { ! 361: saved_x=x; ! 362: saved_y=y; ! 363: } ! 364: ! 365: static void restore_cur(void) ! 366: { ! 367: x=saved_x; ! 368: y=saved_y; ! 369: pos=origin+((y*columns+x)<<1); ! 370: } ! 371: ! 372: void con_write(struct tty_struct * tty) ! 373: { ! 374: int nr; ! 375: char c; ! 376: ! 377: nr = CHARS(tty->write_q); ! 378: while (nr--) { ! 379: GETCH(tty->write_q,c); ! 380: switch(state) { ! 381: case 0: ! 382: if (c>31 && c<127) { ! 383: if (x>=columns) { ! 384: x -= columns; ! 385: pos -= columns<<1; ! 386: lf(); ! 387: } ! 388: __asm__("movb _attr,%%ah\n\t" ! 389: "movw %%ax,%1\n\t" ! 390: ::"a" (c),"m" (*(short *)pos) ! 391: :"ax"); ! 392: pos += 2; ! 393: x++; ! 394: } else if (c==27) ! 395: state=1; ! 396: else if (c==10 || c==11 || c==12) ! 397: lf(); ! 398: else if (c==13) ! 399: cr(); ! 400: else if (c==ERASE_CHAR(tty)) ! 401: del(); ! 402: else if (c==8) { ! 403: if (x) { ! 404: x--; ! 405: pos -= 2; ! 406: } ! 407: } else if (c==9) { ! 408: c=8-(x&7); ! 409: x += c; ! 410: pos += c<<1; ! 411: if (x>columns) { ! 412: x -= columns; ! 413: pos -= columns<<1; ! 414: lf(); ! 415: } ! 416: c=9; ! 417: } ! 418: break; ! 419: case 1: ! 420: state=0; ! 421: if (c=='[') ! 422: state=2; ! 423: else if (c=='E') ! 424: gotoxy(0,y+1); ! 425: else if (c=='M') ! 426: ri(); ! 427: else if (c=='D') ! 428: lf(); ! 429: else if (c=='Z') ! 430: respond(tty); ! 431: else if (x=='7') ! 432: save_cur(); ! 433: else if (x=='8') ! 434: restore_cur(); ! 435: break; ! 436: case 2: ! 437: for(npar=0;npar<NPAR;npar++) ! 438: par[npar]=0; ! 439: npar=0; ! 440: state=3; ! 441: if (ques=(c=='?')) ! 442: break; ! 443: case 3: ! 444: if (c==';' && npar<NPAR-1) { ! 445: npar++; ! 446: break; ! 447: } else if (c>='0' && c<='9') { ! 448: par[npar]=10*par[npar]+c-'0'; ! 449: break; ! 450: } else state=4; ! 451: case 4: ! 452: state=0; ! 453: switch(c) { ! 454: case 'G': case '`': ! 455: if (par[0]) par[0]--; ! 456: gotoxy(par[0],y); ! 457: break; ! 458: case 'A': ! 459: if (!par[0]) par[0]++; ! 460: gotoxy(x,y-par[0]); ! 461: break; ! 462: case 'B': case 'e': ! 463: if (!par[0]) par[0]++; ! 464: gotoxy(x,y+par[0]); ! 465: break; ! 466: case 'C': case 'a': ! 467: if (!par[0]) par[0]++; ! 468: gotoxy(x+par[0],y); ! 469: break; ! 470: case 'D': ! 471: if (!par[0]) par[0]++; ! 472: gotoxy(x-par[0],y); ! 473: break; ! 474: case 'E': ! 475: if (!par[0]) par[0]++; ! 476: gotoxy(0,y+par[0]); ! 477: break; ! 478: case 'F': ! 479: if (!par[0]) par[0]++; ! 480: gotoxy(0,y-par[0]); ! 481: break; ! 482: case 'd': ! 483: if (par[0]) par[0]--; ! 484: gotoxy(x,par[0]); ! 485: break; ! 486: case 'H': case 'f': ! 487: if (par[0]) par[0]--; ! 488: if (par[1]) par[1]--; ! 489: gotoxy(par[1],par[0]); ! 490: break; ! 491: case 'J': ! 492: csi_J(par[0]); ! 493: break; ! 494: case 'K': ! 495: csi_K(par[0]); ! 496: break; ! 497: case 'L': ! 498: csi_L(par[0]); ! 499: break; ! 500: case 'M': ! 501: csi_M(par[0]); ! 502: break; ! 503: case 'P': ! 504: csi_P(par[0]); ! 505: break; ! 506: case '@': ! 507: csi_at(par[0]); ! 508: break; ! 509: case 'm': ! 510: csi_m(); ! 511: break; ! 512: case 'r': ! 513: if (par[0]) par[0]--; ! 514: if (!par[1]) par[1]=lines; ! 515: if (par[0] < par[1] && ! 516: par[1] <= lines) { ! 517: top=par[0]; ! 518: bottom=par[1]; ! 519: } ! 520: break; ! 521: case 's': ! 522: save_cur(); ! 523: break; ! 524: case 'u': ! 525: restore_cur(); ! 526: break; ! 527: } ! 528: } ! 529: } ! 530: set_cursor(); ! 531: } ! 532: ! 533: /* ! 534: * void con_init(void); ! 535: * ! 536: * This routine initalizes console interrupts, and does nothing ! 537: * else. If you want the screen to clear, call tty_write with ! 538: * the appropriate escape-sequece. ! 539: */ ! 540: void con_init(void) ! 541: { ! 542: register unsigned char a; ! 543: ! 544: gotoxy(*(unsigned char *)(0x90000+510),*(unsigned char *)(0x90000+511)); ! 545: set_trap_gate(0x21,&keyboard_interrupt); ! 546: outb_p(inb_p(0x21)&0xfd,0x21); ! 547: a=inb_p(0x61); ! 548: outb_p(a|0x80,0x61); ! 549: outb(a,0x61); ! 550: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.