cga.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "../port/error.h"
  7. enum {
  8. Black,
  9. Blue,
  10. Green,
  11. Cyan,
  12. Red,
  13. Magenta,
  14. Brown,
  15. Grey,
  16. Bright = 0x08,
  17. Blinking = 0x80,
  18. Yellow = Bright|Brown,
  19. White = Bright|Grey,
  20. };
  21. enum {
  22. Width = 80*2,
  23. Height = 25,
  24. Attr = (Black<<4)|Grey, /* high nibble background
  25. * low foreground
  26. */
  27. Poststrlen = 0,
  28. Postcodelen = 2,
  29. Postlen = Poststrlen+Postcodelen,
  30. };
  31. #define CGASCREENBASE ((uchar*)KADDR(0xB8000))
  32. #define CGA CGASCREENBASE
  33. static int cgapos;
  34. static Lock cgascreenlock;
  35. static uchar
  36. cgaregr(int index)
  37. {
  38. outb(0x3D4, index);
  39. return inb(0x3D4+1) & 0xFF;
  40. }
  41. static void
  42. cgaregw(int index, int data)
  43. {
  44. outb(0x3D4, index);
  45. outb(0x3D4+1, data);
  46. }
  47. static void
  48. movecursor(void)
  49. {
  50. cgaregw(0x0E, (cgapos/2>>8) & 0xFF);
  51. cgaregw(0x0F, cgapos/2 & 0xFF);
  52. CGASCREENBASE[cgapos+1] = Attr;
  53. }
  54. static void
  55. cgascreenputc(int c)
  56. {
  57. int i;
  58. uchar *p;
  59. if(c == '\n'){
  60. cgapos = cgapos/Width;
  61. cgapos = (cgapos+1)*Width;
  62. }
  63. else if(c == '\t'){
  64. i = 8 - ((cgapos/2)&7);
  65. while(i-->0)
  66. cgascreenputc(' ');
  67. }
  68. else if(c == '\b'){
  69. if(cgapos >= 2)
  70. cgapos -= 2;
  71. cgascreenputc(' ');
  72. cgapos -= 2;
  73. }
  74. else{
  75. CGASCREENBASE[cgapos++] = c;
  76. CGASCREENBASE[cgapos++] = Attr;
  77. }
  78. if(cgapos >= Width*Height){
  79. memmove(CGASCREENBASE, &CGASCREENBASE[Width], Width*(Height-1));
  80. p = &CGASCREENBASE[Width*(Height-1)];
  81. for(i=0; i<Width/2; i++){
  82. *p++ = ' ';
  83. *p++ = Attr;
  84. }
  85. cgapos = Width*(Height-1);
  86. }
  87. movecursor();
  88. }
  89. static void
  90. cgascreenputs(char* s, int n)
  91. {
  92. if(!islo()){
  93. /*
  94. * Don't deadlock trying to
  95. * print in an interrupt.
  96. */
  97. if(!canlock(&cgascreenlock))
  98. return;
  99. }
  100. else
  101. lock(&cgascreenlock);
  102. while(n-- > 0)
  103. cgascreenputc(*s++);
  104. unlock(&cgascreenlock);
  105. }
  106. char hex[] = "0123456789ABCDEF";
  107. void
  108. cgapost(int code)
  109. {
  110. uchar *cga;
  111. cga = CGA;
  112. cga[Width*Height-Postcodelen*2] = hex[(code>>4) & 0x0F];
  113. cga[Width*Height-Postcodelen*2+1] = Attr;
  114. cga[Width*Height-Postcodelen*2+2] = hex[code & 0x0F];
  115. cga[Width*Height-Postcodelen*2+3] = Attr;
  116. }
  117. void
  118. screeninit(void)
  119. {
  120. cgapos = cgaregr(0x0E)<<8;
  121. cgapos |= cgaregr(0x0F);
  122. cgapos *= 2;
  123. screenputs = cgascreenputs;
  124. }