cga.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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. };
  28. #define CGASCREENBASE ((uchar*)KADDR(0xB8000))
  29. #define inb(x) 0 /* TODO */
  30. #define outb(x, y) /* TODO */
  31. static int cgapos;
  32. static Lock cgascreenlock;
  33. static uchar
  34. cgaregr(int index)
  35. {
  36. USED(index);
  37. outb(0x3D4, index);
  38. return inb(0x3D4+1) & 0xFF;
  39. }
  40. static void
  41. cgaregw(int index, int data)
  42. {
  43. USED(index, data);
  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. void
  107. screeninit(void)
  108. {
  109. cgapos = cgaregr(0x0E)<<8;
  110. cgapos |= cgaregr(0x0F);
  111. cgapos *= 2;
  112. screenputs = cgascreenputs;
  113. }