vgavesa.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "io.h"
  7. #include "../port/error.h"
  8. #include "ureg.h"
  9. #define Image IMAGE
  10. #include <draw.h>
  11. #include <memdraw.h>
  12. #include <cursor.h>
  13. #include "screen.h"
  14. #define WORD(p) ((p)[0] | ((p)[1]<<8))
  15. #define LONG(p) ((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24))
  16. #define PWORD(p, v) (p)[0] = (v); (p)[1] = (v)>>8
  17. #define PLONG(p, v) (p)[0] = (v); (p)[1] = (v)>>8; (p)[2] = (v)>>16; (p)[3] = (v)>>24
  18. extern void realmode(Ureg*);
  19. static uchar*
  20. vbesetup(Ureg *u, int ax)
  21. {
  22. ulong pa;
  23. pa = PADDR(RMBUF);
  24. memset(u, 0, sizeof *u);
  25. u->ax = ax;
  26. u->es = (pa>>4)&0xF000;
  27. u->di = pa&0xFFFF;
  28. return (void*)RMBUF;
  29. }
  30. static void
  31. vbecall(Ureg *u)
  32. {
  33. u->trap = 0x10;
  34. realmode(u);
  35. if((u->ax&0xFFFF) != 0x004F)
  36. error("vesa bios error");
  37. }
  38. static void
  39. vbecheck(void)
  40. {
  41. Ureg u;
  42. uchar *p;
  43. p = vbesetup(&u, 0x4F00);
  44. strcpy((char*)p, "VBE2");
  45. vbecall(&u);
  46. if(memcmp((char*)p, "VESA", 4) != 0)
  47. error("bad vesa signature");
  48. if(p[5] < 2)
  49. error("bad vesa version");
  50. }
  51. static int
  52. vbegetmode(void)
  53. {
  54. Ureg u;
  55. vbesetup(&u, 0x4F03);
  56. vbecall(&u);
  57. return u.bx;
  58. }
  59. static uchar*
  60. vbemodeinfo(int mode)
  61. {
  62. uchar *p;
  63. Ureg u;
  64. p = vbesetup(&u, 0x4F01);
  65. u.cx = mode;
  66. vbecall(&u);
  67. return p;
  68. }
  69. static void
  70. vesalinear(VGAscr* scr, int, int)
  71. {
  72. int i, mode, size;
  73. uchar *p;
  74. ulong paddr;
  75. Pcidev *pci;
  76. vbecheck();
  77. mode = vbegetmode();
  78. /* bochs loses the top bits - cannot use this
  79. if((mode&(1<<14)) == 0)
  80. error("not in linear graphics mode");
  81. */
  82. mode &= 0x3FFF;
  83. p = vbemodeinfo(mode);
  84. if(!(WORD(p+0) & (1<<4)))
  85. error("not in VESA graphics mode");
  86. if(!(WORD(p+0) & (1<<7)))
  87. error("not in linear graphics mode");
  88. paddr = LONG(p+40);
  89. size = WORD(p+20)*WORD(p+16);
  90. size = PGROUND(size);
  91. /*
  92. * figure out max size of memory so that we have
  93. * enough if the screen is resized.
  94. */
  95. pci = nil;
  96. while((pci = pcimatch(pci, 0, 0)) != nil){
  97. if(pci->ccrb != 3)
  98. continue;
  99. for(i=0; i<nelem(pci->mem); i++)
  100. if(paddr == (pci->mem[i].bar&~0x0F)){
  101. if(pci->mem[i].size > size)
  102. size = pci->mem[i].size;
  103. goto havesize;
  104. }
  105. }
  106. /* no pci - heuristic guess */
  107. if(size < 4*1024*1024)
  108. size = 4*1024*1024;
  109. else
  110. size = ROUND(size, 1024*1024);
  111. havesize:
  112. vgalinearaddr(scr, paddr, size);
  113. }
  114. VGAdev vgavesadev = {
  115. "vesa",
  116. 0,
  117. 0,
  118. 0,
  119. vesalinear,
  120. 0,
  121. 0,
  122. 0,
  123. 0,
  124. 0,
  125. };