helper_mem.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /*
  2. * XFree86 int10 module
  3. * execute BIOS int 10h calls in x86 real mode environment
  4. * Copyright 1999 Egbert Eich
  5. */
  6. #ifdef HAVE_XORG_CONFIG_H
  7. #include <xorg-config.h>
  8. #endif
  9. #include <string.h>
  10. #include <stdlib.h>
  11. #include "xf86.h"
  12. #include "xf86_OSproc.h"
  13. #include "compiler.h"
  14. #include "xf86Pci.h"
  15. #define _INT10_PRIVATE
  16. #if 0
  17. #include "int10Defines.h"
  18. #endif
  19. #include "xf86int10.h"
  20. #define REG pInt
  21. typedef enum {
  22. OPT_NOINT10,
  23. OPT_INIT_PRIMARY,
  24. } INT10Opts;
  25. static const OptionInfoRec INT10Options[] = {
  26. {OPT_NOINT10, "NoINT10", OPTV_BOOLEAN, {0}, FALSE},
  27. {OPT_INIT_PRIMARY, "InitPrimary", OPTV_BOOLEAN, {0}, FALSE},
  28. {-1, NULL, OPTV_NONE, {0}, FALSE},
  29. };
  30. #ifdef DEBUG
  31. void
  32. dprint(unsigned long start, unsigned long size)
  33. {
  34. int i, j;
  35. char *c = (char *) start;
  36. for (j = 0; j < (size >> 4); j++) {
  37. char *d = c;
  38. ErrorF("\n0x%lx: ", (unsigned long) c);
  39. for (i = 0; i < 16; i++)
  40. ErrorF("%2.2x ", (unsigned char) (*(c++)));
  41. c = d;
  42. for (i = 0; i < 16; i++) {
  43. ErrorF("%c", ((((CARD8) (*c)) > 32) && (((CARD8) (*c)) < 128)) ?
  44. (unsigned char) (*(c)) : '.');
  45. c++;
  46. }
  47. }
  48. ErrorF("\n");
  49. }
  50. #endif
  51. #ifndef _PC
  52. /*
  53. * here we are really paranoid about faking a "real"
  54. * BIOS. Most of this information was pulled from
  55. * dosemu.
  56. */
  57. void
  58. setup_int_vect(xf86Int10InfoPtr pInt)
  59. {
  60. int i;
  61. /* let the int vects point to the SYS_BIOS seg */
  62. for (i = 0; i < 0x80; i++) {
  63. MEM_WW(pInt, i << 2, 0);
  64. MEM_WW(pInt, (i << 2) + 2, SYS_BIOS >> 4);
  65. }
  66. reset_int_vect(pInt);
  67. /* font tables default location (int 1F) */
  68. MEM_WW(pInt, 0x1f << 2, 0xfa6e);
  69. /* int 11 default location (Get Equipment Configuration) */
  70. MEM_WW(pInt, 0x11 << 2, 0xf84d);
  71. /* int 12 default location (Get Conventional Memory Size) */
  72. MEM_WW(pInt, 0x12 << 2, 0xf841);
  73. /* int 15 default location (I/O System Extensions) */
  74. MEM_WW(pInt, 0x15 << 2, 0xf859);
  75. /* int 1A default location (RTC, PCI and others) */
  76. MEM_WW(pInt, 0x1a << 2, 0xff6e);
  77. /* int 05 default location (Bound Exceeded) */
  78. MEM_WW(pInt, 0x05 << 2, 0xff54);
  79. /* int 08 default location (Double Fault) */
  80. MEM_WW(pInt, 0x08 << 2, 0xfea5);
  81. /* int 13 default location (Disk) */
  82. MEM_WW(pInt, 0x13 << 2, 0xec59);
  83. /* int 0E default location (Page Fault) */
  84. MEM_WW(pInt, 0x0e << 2, 0xef57);
  85. /* int 17 default location (Parallel Port) */
  86. MEM_WW(pInt, 0x17 << 2, 0xefd2);
  87. /* fdd table default location (int 1e) */
  88. MEM_WW(pInt, 0x1e << 2, 0xefc7);
  89. /* Set Equipment flag to VGA */
  90. i = MEM_RB(pInt, 0x0410) & 0xCF;
  91. MEM_WB(pInt, 0x0410, i);
  92. /* XXX Perhaps setup more of the BDA here. See also int42(0x00). */
  93. }
  94. #endif
  95. int
  96. setup_system_bios(void *base_addr)
  97. {
  98. char *base = (char *) base_addr;
  99. /*
  100. * we trap the "industry standard entry points" to the BIOS
  101. * and all other locations by filling them with "hlt"
  102. * TODO: implement hlt-handler for these
  103. */
  104. memset(base, 0xf4, 0x10000);
  105. /* set bios date */
  106. strcpy(base + 0x0FFF5, "06/11/99");
  107. /* set up eisa ident string */
  108. strcpy(base + 0x0FFD9, "PCI_ISA");
  109. /* write system model id for IBM-AT */
  110. *((unsigned char *) (base + 0x0FFFE)) = 0xfc;
  111. return 1;
  112. }
  113. void
  114. reset_int_vect(xf86Int10InfoPtr pInt)
  115. {
  116. /*
  117. * This table is normally located at 0xF000:0xF0A4. However, int 0x42,
  118. * function 0 (Mode Set) expects it (or a copy) somewhere in the bottom
  119. * 64kB. Note that because this data doesn't survive POST, int 0x42 should
  120. * only be used during EGA/VGA BIOS initialisation.
  121. */
  122. static const CARD8 VideoParms[] = {
  123. /* Timing for modes 0x00 & 0x01 */
  124. 0x38, 0x28, 0x2d, 0x0a, 0x1f, 0x06, 0x19, 0x1c,
  125. 0x02, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
  126. /* Timing for modes 0x02 & 0x03 */
  127. 0x71, 0x50, 0x5a, 0x0a, 0x1f, 0x06, 0x19, 0x1c,
  128. 0x02, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
  129. /* Timing for modes 0x04, 0x05 & 0x06 */
  130. 0x38, 0x28, 0x2d, 0x0a, 0x7f, 0x06, 0x64, 0x70,
  131. 0x02, 0x01, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
  132. /* Timing for mode 0x07 */
  133. 0x61, 0x50, 0x52, 0x0f, 0x19, 0x06, 0x19, 0x19,
  134. 0x02, 0x0d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00,
  135. /* Display page lengths in little endian order */
  136. 0x00, 0x08, /* Modes 0x00 and 0x01 */
  137. 0x00, 0x10, /* Modes 0x02 and 0x03 */
  138. 0x00, 0x40, /* Modes 0x04 and 0x05 */
  139. 0x00, 0x40, /* Modes 0x06 and 0x07 */
  140. /* Number of columns for each mode */
  141. 40, 40, 80, 80, 40, 40, 80, 80,
  142. /* CGA Mode register value for each mode */
  143. 0x2c, 0x28, 0x2d, 0x29, 0x2a, 0x2e, 0x1e, 0x29,
  144. /* Padding */
  145. 0x00, 0x00, 0x00, 0x00
  146. };
  147. int i;
  148. for (i = 0; i < sizeof(VideoParms); i++)
  149. MEM_WB(pInt, i + (0x1000 - sizeof(VideoParms)), VideoParms[i]);
  150. MEM_WW(pInt, 0x1d << 2, 0x1000 - sizeof(VideoParms));
  151. MEM_WW(pInt, (0x1d << 2) + 2, 0);
  152. MEM_WW(pInt, 0x10 << 2, 0xf065);
  153. MEM_WW(pInt, (0x10 << 2) + 2, SYS_BIOS >> 4);
  154. MEM_WW(pInt, 0x42 << 2, 0xf065);
  155. MEM_WW(pInt, (0x42 << 2) + 2, SYS_BIOS >> 4);
  156. MEM_WW(pInt, 0x6D << 2, 0xf065);
  157. MEM_WW(pInt, (0x6D << 2) + 2, SYS_BIOS >> 4);
  158. }
  159. void
  160. set_return_trap(xf86Int10InfoPtr pInt)
  161. {
  162. /*
  163. * Here we set the exit condition: We return when we encounter
  164. * 'hlt' (=0xf4), which we locate at address 0x600 in x86 memory.
  165. */
  166. MEM_WB(pInt, 0x0600, 0xf4);
  167. /*
  168. * Allocate a segment for the stack
  169. */
  170. xf86Int10AllocPages(pInt, 1, &pInt->stackseg);
  171. }
  172. void *
  173. xf86HandleInt10Options(ScrnInfoPtr pScrn, int entityIndex)
  174. {
  175. EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex);
  176. OptionInfoPtr options = NULL;
  177. if (pEnt->device) {
  178. void *configOptions = NULL;
  179. /* Check if xf86CollectOptions() has already been called */
  180. if (((pEnt->index < 0) ||
  181. !pScrn || !(configOptions = pScrn->options)) && pEnt->device)
  182. configOptions = pEnt->device->options;
  183. if (configOptions) {
  184. if (!(options = (OptionInfoPtr) malloc(sizeof(INT10Options))))
  185. return NULL;
  186. (void) memcpy(options, INT10Options, sizeof(INT10Options));
  187. xf86ProcessOptions(pScrn->scrnIndex, configOptions, options);
  188. }
  189. }
  190. free(pEnt);
  191. return options;
  192. }
  193. Bool
  194. int10skip(const void *options)
  195. {
  196. Bool noint10 = FALSE;
  197. if (!options)
  198. return FALSE;
  199. xf86GetOptValBool(options, OPT_NOINT10, &noint10);
  200. return noint10;
  201. }
  202. Bool
  203. int10_check_bios(int scrnIndex, int codeSeg, const unsigned char *vbiosMem)
  204. {
  205. int size;
  206. if ((codeSeg & 0x1f) || /* Not 512-byte aligned otherwise */
  207. ((codeSeg << 4) < V_BIOS) || ((codeSeg << 4) >= SYS_SIZE))
  208. return FALSE;
  209. if ((*vbiosMem != 0x55) || (*(vbiosMem + 1) != 0xAA) || !*(vbiosMem + 2))
  210. return FALSE;
  211. size = *(vbiosMem + 2) * 512;
  212. if ((size + (codeSeg << 4)) > SYS_SIZE)
  213. return FALSE;
  214. if (bios_checksum(vbiosMem, size))
  215. xf86DrvMsg(scrnIndex, X_INFO, "Bad V_BIOS checksum\n");
  216. return TRUE;
  217. }
  218. Bool
  219. initPrimary(const void *options)
  220. {
  221. Bool initPrimary = FALSE;
  222. if (!options)
  223. return FALSE;
  224. xf86GetOptValBool(options, OPT_INIT_PRIMARY, &initPrimary);
  225. return initPrimary;
  226. }
  227. BusType
  228. xf86int10GetBiosLocationType(const xf86Int10InfoPtr pInt)
  229. {
  230. BusType location_type;
  231. EntityInfoPtr pEnt = xf86GetEntityInfo(pInt->entityIndex);
  232. location_type = pEnt->location.type;
  233. free(pEnt);
  234. return location_type;
  235. }
  236. #define CHECK_V_SEGMENT_RANGE(x) \
  237. if (((x) << 4) < V_BIOS) { \
  238. xf86DrvMsg(pInt->pScrn->scrnIndex, X_ERROR, \
  239. "V_BIOS address 0x%lx out of range\n", \
  240. (unsigned long)(x) << 4); \
  241. return FALSE; \
  242. }
  243. Bool
  244. xf86int10GetBiosSegment(xf86Int10InfoPtr pInt, void *base)
  245. {
  246. unsigned i;
  247. int cs = ~0;
  248. int segments[4];
  249. segments[0] = MEM_RW(pInt, (0x10 << 2) + 2);
  250. segments[1] = MEM_RW(pInt, (0x42 << 2) + 2);
  251. segments[2] = V_BIOS >> 4;
  252. segments[3] = ~0;
  253. for (i = 0; segments[i] != ~0; i++) {
  254. unsigned char *vbiosMem;
  255. cs = segments[i];
  256. CHECK_V_SEGMENT_RANGE(cs);
  257. vbiosMem = (unsigned char *) base + (cs << 4);
  258. if (int10_check_bios(pInt->pScrn->scrnIndex, cs, vbiosMem)) {
  259. break;
  260. }
  261. }
  262. if (segments[i] == ~0) {
  263. xf86DrvMsg(pInt->pScrn->scrnIndex, X_ERROR, "No V_BIOS found\n");
  264. return FALSE;
  265. }
  266. xf86DrvMsg(pInt->pScrn->scrnIndex, X_INFO, "Primary V_BIOS segment is: 0x%lx\n",
  267. (unsigned long) cs);
  268. pInt->BIOSseg = cs;
  269. return TRUE;
  270. }