cga.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "u.h"
  10. #include "../port/lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include "../port/error.h"
  15. enum {
  16. Black,
  17. Blue,
  18. Green,
  19. Cyan,
  20. Red,
  21. Magenta,
  22. Brown,
  23. Grey,
  24. Bright = 0x08,
  25. Blinking = 0x80,
  26. Yellow = Bright|Brown,
  27. White = Bright|Grey,
  28. };
  29. enum {
  30. Width = 80*2,
  31. Height = 25,
  32. Attr = (Black<<4)|Grey, /* high nibble background
  33. * low foreground
  34. */
  35. };
  36. #define CGASCREENBASE ((uchar*)KADDR(0xB8000))
  37. #define inb(x) 0 /* TODO */
  38. #define outb(x, y) /* TODO */
  39. static int cgapos;
  40. static Lock cgascreenlock;
  41. static uchar
  42. cgaregr(int index)
  43. {
  44. USED(index);
  45. outb(0x3D4, index);
  46. return inb(0x3D4+1) & 0xFF;
  47. }
  48. static void
  49. cgaregw(int index, int data)
  50. {
  51. USED(index, data);
  52. outb(0x3D4, index);
  53. outb(0x3D4+1, data);
  54. }
  55. static void
  56. movecursor(void)
  57. {
  58. cgaregw(0x0E, (cgapos/2>>8) & 0xFF);
  59. cgaregw(0x0F, cgapos/2 & 0xFF);
  60. CGASCREENBASE[cgapos+1] = Attr;
  61. }
  62. static void
  63. cgascreenputc(int c)
  64. {
  65. int i;
  66. uchar *p;
  67. if(c == '\n'){
  68. cgapos = cgapos/Width;
  69. cgapos = (cgapos+1)*Width;
  70. }
  71. else if(c == '\t'){
  72. i = 8 - ((cgapos/2)&7);
  73. while(i-->0)
  74. cgascreenputc(' ');
  75. }
  76. else if(c == '\b'){
  77. if(cgapos >= 2)
  78. cgapos -= 2;
  79. cgascreenputc(' ');
  80. cgapos -= 2;
  81. }
  82. else{
  83. CGASCREENBASE[cgapos++] = c;
  84. CGASCREENBASE[cgapos++] = Attr;
  85. }
  86. if(cgapos >= Width*Height){
  87. memmove(CGASCREENBASE, &CGASCREENBASE[Width], Width*(Height-1));
  88. p = &CGASCREENBASE[Width*(Height-1)];
  89. for(i=0; i<Width/2; i++){
  90. *p++ = ' ';
  91. *p++ = Attr;
  92. }
  93. cgapos = Width*(Height-1);
  94. }
  95. movecursor();
  96. }
  97. static void
  98. cgascreenputs(char* s, int n)
  99. {
  100. if(!islo()){
  101. /*
  102. * Don't deadlock trying to
  103. * print in an interrupt.
  104. */
  105. if(!canlock(&cgascreenlock))
  106. return;
  107. }
  108. else
  109. lock(&cgascreenlock);
  110. while(n-- > 0)
  111. cgascreenputc(*s++);
  112. unlock(&cgascreenlock);
  113. }
  114. void
  115. screeninit(void)
  116. {
  117. cgapos = cgaregr(0x0E)<<8;
  118. cgapos |= cgaregr(0x0F);
  119. cgapos *= 2;
  120. screenputs = cgascreenputs;
  121. }