cga.c 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  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. static int cgapos;
  30. static Lock cgascreenlock;
  31. static uchar
  32. cgaregr(int index)
  33. {
  34. outb(0x3D4, index);
  35. return inb(0x3D4+1) & 0xFF;
  36. }
  37. static void
  38. cgaregw(int index, int data)
  39. {
  40. outb(0x3D4, index);
  41. outb(0x3D4+1, data);
  42. }
  43. static void
  44. movecursor(void)
  45. {
  46. cgaregw(0x0E, (cgapos/2>>8) & 0xFF);
  47. cgaregw(0x0F, cgapos/2 & 0xFF);
  48. CGASCREENBASE[cgapos+1] = Attr;
  49. }
  50. static void
  51. cgascreenputc(int c)
  52. {
  53. int i;
  54. uchar *p;
  55. if(c == '\n'){
  56. cgapos = cgapos/Width;
  57. cgapos = (cgapos+1)*Width;
  58. }
  59. else if(c == '\t'){
  60. i = 8 - ((cgapos/2)&7);
  61. while(i-->0)
  62. cgascreenputc(' ');
  63. }
  64. else if(c == '\b'){
  65. if(cgapos >= 2)
  66. cgapos -= 2;
  67. cgascreenputc(' ');
  68. cgapos -= 2;
  69. }
  70. else{
  71. CGASCREENBASE[cgapos++] = c;
  72. CGASCREENBASE[cgapos++] = Attr;
  73. }
  74. if(cgapos >= Width*Height){
  75. memmove(CGASCREENBASE, &CGASCREENBASE[Width], Width*(Height-1));
  76. p = &CGASCREENBASE[Width*(Height-1)];
  77. for(i=0; i<Width/2; i++){
  78. *p++ = ' ';
  79. *p++ = Attr;
  80. }
  81. cgapos = Width*(Height-1);
  82. }
  83. movecursor();
  84. }
  85. static void
  86. cgascreenputs(char* s, int n)
  87. {
  88. if(!islo()){
  89. /*
  90. * Don't deadlock trying to
  91. * print in an interrupt.
  92. */
  93. if(!canlock(&cgascreenlock))
  94. return;
  95. }
  96. else
  97. lock(&cgascreenlock);
  98. while(n-- > 0)
  99. cgascreenputc(*s++);
  100. unlock(&cgascreenlock);
  101. }
  102. void
  103. screeninit(void)
  104. {
  105. cgapos = cgaregr(0x0E)<<8;
  106. cgapos |= cgaregr(0x0F);
  107. cgapos *= 2;
  108. screenputs = cgascreenputs;
  109. }