generic.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  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 <unistd.h>
  11. #include "xf86.h"
  12. #include "xf86_OSproc.h"
  13. #include "compiler.h"
  14. #define _INT10_PRIVATE
  15. #include "xf86int10.h"
  16. #include "int10Defines.h"
  17. #include "Pci.h"
  18. #define ALLOC_ENTRIES(x) ((V_RAM / x) - 1)
  19. static uint8_t read_b(xf86Int10InfoPtr pInt, int addr);
  20. static uint16_t read_w(xf86Int10InfoPtr pInt, int addr);
  21. static uint32_t read_l(xf86Int10InfoPtr pInt, int addr);
  22. static void write_b(xf86Int10InfoPtr pInt, int addr, uint8_t val);
  23. static void write_w(xf86Int10InfoPtr pInt, int addr, uint16_t val);
  24. static void write_l(xf86Int10InfoPtr pInt, int addr, uint32_t val);
  25. /*
  26. * the emulator cannot pass a pointer to the current xf86Int10InfoRec
  27. * to the memory access functions therefore store it here.
  28. */
  29. typedef struct {
  30. int shift;
  31. int entries;
  32. void *base;
  33. void *vRam;
  34. int highMemory;
  35. void *sysMem;
  36. char *alloc;
  37. } genericInt10Priv;
  38. #define INTPriv(x) ((genericInt10Priv*)x->private)
  39. int10MemRec genericMem = {
  40. read_b,
  41. read_w,
  42. read_l,
  43. write_b,
  44. write_w,
  45. write_l
  46. };
  47. static void MapVRam(xf86Int10InfoPtr pInt);
  48. static void UnmapVRam(xf86Int10InfoPtr pInt);
  49. #ifdef _PC
  50. #define GET_HIGH_BASE(x) (((V_BIOS + (x) + getpagesize() - 1)/getpagesize()) \
  51. * getpagesize())
  52. #endif
  53. static void *sysMem = NULL;
  54. xf86Int10InfoPtr
  55. xf86ExtendedInitInt10(int entityIndex, int Flags)
  56. {
  57. xf86Int10InfoPtr pInt;
  58. void *base = 0;
  59. void *vbiosMem = 0;
  60. void *options = NULL;
  61. legacyVGARec vga;
  62. ScrnInfoPtr pScrn;
  63. pScrn = xf86FindScreenForEntity(entityIndex);
  64. options = xf86HandleInt10Options(pScrn, entityIndex);
  65. if (int10skip(options)) {
  66. free(options);
  67. return NULL;
  68. }
  69. pInt = (xf86Int10InfoPtr) xnfcalloc(1, sizeof(xf86Int10InfoRec));
  70. pInt->entityIndex = entityIndex;
  71. if (!xf86Int10ExecSetup(pInt))
  72. goto error0;
  73. pInt->mem = &genericMem;
  74. pInt->private = (void *) xnfcalloc(1, sizeof(genericInt10Priv));
  75. INTPriv(pInt)->alloc = (void *) xnfcalloc(1, ALLOC_ENTRIES(getpagesize()));
  76. pInt->pScrn = pScrn;
  77. base = INTPriv(pInt)->base = xnfalloc(SYS_BIOS);
  78. /* FIXME: Shouldn't this be a failure case? Leaving dev as NULL seems like
  79. * FIXME: an error
  80. */
  81. pInt->dev = xf86GetPciInfoForEntity(entityIndex);
  82. /*
  83. * we need to map video RAM MMIO as some chipsets map mmio
  84. * registers into this range.
  85. */
  86. MapVRam(pInt);
  87. #ifdef _PC
  88. if (!sysMem)
  89. pci_device_map_legacy(pInt->dev, V_BIOS, BIOS_SIZE + SYS_BIOS - V_BIOS,
  90. PCI_DEV_MAP_FLAG_WRITABLE, &sysMem);
  91. INTPriv(pInt)->sysMem = sysMem;
  92. if (xf86ReadBIOS(0, 0, base, LOW_PAGE_SIZE) < 0) {
  93. xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot read int vect\n");
  94. goto error1;
  95. }
  96. /*
  97. * Retrieve everything between V_BIOS and SYS_BIOS as some system BIOSes
  98. * have executable code there.
  99. */
  100. memset((char *) base + V_BIOS, 0, SYS_BIOS - V_BIOS);
  101. INTPriv(pInt)->highMemory = V_BIOS;
  102. if (xf86IsEntityPrimary(entityIndex) && !(initPrimary(options))) {
  103. if (!xf86int10GetBiosSegment(pInt, (unsigned char *) sysMem - V_BIOS))
  104. goto error1;
  105. set_return_trap(pInt);
  106. pInt->Flags = Flags & (SET_BIOS_SCRATCH | RESTORE_BIOS_SCRATCH);
  107. if (!(pInt->Flags & SET_BIOS_SCRATCH))
  108. pInt->Flags &= ~RESTORE_BIOS_SCRATCH;
  109. xf86Int10SaveRestoreBIOSVars(pInt, TRUE);
  110. }
  111. else {
  112. const BusType location_type = xf86int10GetBiosLocationType(pInt);
  113. int bios_location = V_BIOS;
  114. reset_int_vect(pInt);
  115. set_return_trap(pInt);
  116. switch (location_type) {
  117. case BUS_PCI:{
  118. int err;
  119. struct pci_device *rom_device =
  120. xf86GetPciInfoForEntity(pInt->entityIndex);
  121. vbiosMem = (unsigned char *) base + bios_location;
  122. err = pci_device_read_rom(rom_device, vbiosMem);
  123. if (err) {
  124. xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot read V_BIOS (3) %s\n",
  125. strerror(err));
  126. goto error1;
  127. }
  128. INTPriv(pInt)->highMemory = GET_HIGH_BASE(rom_device->rom_size);
  129. break;
  130. }
  131. default:
  132. goto error1;
  133. }
  134. pInt->BIOSseg = V_BIOS >> 4;
  135. pInt->num = 0xe6;
  136. LockLegacyVGA(pInt, &vga);
  137. xf86ExecX86int10(pInt);
  138. UnlockLegacyVGA(pInt, &vga);
  139. }
  140. #else
  141. if (!sysMem) {
  142. sysMem = xnfalloc(BIOS_SIZE);
  143. setup_system_bios(sysMem);
  144. }
  145. INTPriv(pInt)->sysMem = sysMem;
  146. setup_int_vect(pInt);
  147. set_return_trap(pInt);
  148. /* Retrieve the entire legacy video BIOS segment. This can be upto
  149. * 128KiB.
  150. */
  151. vbiosMem = (char *) base + V_BIOS;
  152. memset(vbiosMem, 0, 2 * V_BIOS_SIZE);
  153. if (pci_device_read_rom(pInt->dev, vbiosMem) != 0
  154. || pInt->dev->rom_size < V_BIOS_SIZE) {
  155. xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
  156. "Unable to retrieve all of segment 0x0C0000.\n");
  157. }
  158. /*
  159. * If this adapter is the primary, use its post-init BIOS (if we can find
  160. * it).
  161. */
  162. {
  163. int bios_location = V_BIOS;
  164. Bool done = FALSE;
  165. vbiosMem = (unsigned char *) base + bios_location;
  166. if (xf86IsEntityPrimary(entityIndex)) {
  167. if (int10_check_bios(pScrn->scrnIndex, bios_location >> 4, vbiosMem))
  168. done = TRUE;
  169. else
  170. xf86DrvMsg(pScrn->scrnIndex, X_INFO,
  171. "No legacy BIOS found -- trying PCI\n");
  172. }
  173. if (!done) {
  174. int err;
  175. struct pci_device *rom_device =
  176. xf86GetPciInfoForEntity(pInt->entityIndex);
  177. err = pci_device_read_rom(rom_device, vbiosMem);
  178. if (err) {
  179. xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Cannot read V_BIOS (5) %s\n",
  180. strerror(err));
  181. goto error1;
  182. }
  183. }
  184. }
  185. pInt->BIOSseg = V_BIOS >> 4;
  186. pInt->num = 0xe6;
  187. LockLegacyVGA(pInt, &vga);
  188. xf86ExecX86int10(pInt);
  189. UnlockLegacyVGA(pInt, &vga);
  190. #endif
  191. free(options);
  192. return pInt;
  193. error1:
  194. free(base);
  195. UnmapVRam(pInt);
  196. free(INTPriv(pInt)->alloc);
  197. free(pInt->private);
  198. error0:
  199. free(pInt);
  200. free(options);
  201. return NULL;
  202. }
  203. static void
  204. MapVRam(xf86Int10InfoPtr pInt)
  205. {
  206. int pagesize = getpagesize();
  207. int size = ((VRAM_SIZE + pagesize - 1) / pagesize) * pagesize;
  208. pci_device_map_legacy(pInt->dev, V_RAM, size, PCI_DEV_MAP_FLAG_WRITABLE,
  209. &(INTPriv(pInt)->vRam));
  210. pInt->io = pci_legacy_open_io(pInt->dev, 0, 64 * 1024);
  211. }
  212. static void
  213. UnmapVRam(xf86Int10InfoPtr pInt)
  214. {
  215. int pagesize = getpagesize();
  216. int size = ((VRAM_SIZE + pagesize - 1) / pagesize) * pagesize;
  217. pci_device_unmap_legacy(pInt->dev, INTPriv(pInt)->vRam, size);
  218. pci_device_close_io(pInt->dev, pInt->io);
  219. pInt->io = NULL;
  220. }
  221. Bool
  222. MapCurrentInt10(xf86Int10InfoPtr pInt)
  223. {
  224. /* nothing to do here */
  225. return TRUE;
  226. }
  227. void
  228. xf86FreeInt10(xf86Int10InfoPtr pInt)
  229. {
  230. if (!pInt)
  231. return;
  232. #if defined (_PC)
  233. xf86Int10SaveRestoreBIOSVars(pInt, FALSE);
  234. #endif
  235. if (Int10Current == pInt)
  236. Int10Current = NULL;
  237. free(INTPriv(pInt)->base);
  238. UnmapVRam(pInt);
  239. free(INTPriv(pInt)->alloc);
  240. free(pInt->private);
  241. free(pInt);
  242. }
  243. void *
  244. xf86Int10AllocPages(xf86Int10InfoPtr pInt, int num, int *off)
  245. {
  246. int pagesize = getpagesize();
  247. int num_pages = ALLOC_ENTRIES(pagesize);
  248. int i, j;
  249. for (i = 0; i < (num_pages - num); i++) {
  250. if (INTPriv(pInt)->alloc[i] == 0) {
  251. for (j = i; j < (num + i); j++)
  252. if (INTPriv(pInt)->alloc[j] != 0)
  253. break;
  254. if (j == (num + i))
  255. break;
  256. i += num;
  257. }
  258. }
  259. if (i == (num_pages - num))
  260. return NULL;
  261. for (j = i; j < (i + num); j++)
  262. INTPriv(pInt)->alloc[j] = 1;
  263. *off = (i + 1) * pagesize;
  264. return (char *) INTPriv(pInt)->base + *off;
  265. }
  266. void
  267. xf86Int10FreePages(xf86Int10InfoPtr pInt, void *pbase, int num)
  268. {
  269. int pagesize = getpagesize();
  270. int first =
  271. (((char *) pbase - (char *) INTPriv(pInt)->base) / pagesize) - 1;
  272. int i;
  273. for (i = first; i < (first + num); i++)
  274. INTPriv(pInt)->alloc[i] = 0;
  275. }
  276. #define OFF(addr) ((addr) & 0xffff)
  277. #if defined _PC
  278. #define HIGH_OFFSET (INTPriv(pInt)->highMemory)
  279. #define HIGH_BASE V_BIOS
  280. #else
  281. #define HIGH_OFFSET SYS_BIOS
  282. #define HIGH_BASE SYS_BIOS
  283. #endif
  284. #define SYS(addr) ((addr) >= HIGH_OFFSET)
  285. #define V_ADDR(addr) \
  286. (SYS(addr) ? ((char*)INTPriv(pInt)->sysMem) + (addr - HIGH_BASE) \
  287. : (((char*)(INTPriv(pInt)->base) + addr)))
  288. #define VRAM_ADDR(addr) (addr - V_RAM)
  289. #define VRAM_BASE (INTPriv(pInt)->vRam)
  290. #define VRAM(addr) ((addr >= V_RAM) && (addr < (V_RAM + VRAM_SIZE)))
  291. #define V_ADDR_RB(addr) \
  292. (VRAM(addr)) ? MMIO_IN8((uint8_t*)VRAM_BASE,VRAM_ADDR(addr)) \
  293. : *(uint8_t*) V_ADDR(addr)
  294. #define V_ADDR_RW(addr) \
  295. (VRAM(addr)) ? MMIO_IN16((uint16_t*)VRAM_BASE,VRAM_ADDR(addr)) \
  296. : ldw_u((void *)V_ADDR(addr))
  297. #define V_ADDR_RL(addr) \
  298. (VRAM(addr)) ? MMIO_IN32((uint32_t*)VRAM_BASE,VRAM_ADDR(addr)) \
  299. : ldl_u((void *)V_ADDR(addr))
  300. #define V_ADDR_WB(addr,val) \
  301. if(VRAM(addr)) \
  302. MMIO_OUT8((uint8_t*)VRAM_BASE,VRAM_ADDR(addr),val); \
  303. else \
  304. *(uint8_t*) V_ADDR(addr) = val;
  305. #define V_ADDR_WW(addr,val) \
  306. if(VRAM(addr)) \
  307. MMIO_OUT16((uint16_t*)VRAM_BASE,VRAM_ADDR(addr),val); \
  308. else \
  309. stw_u((val),(void *)(V_ADDR(addr)));
  310. #define V_ADDR_WL(addr,val) \
  311. if (VRAM(addr)) \
  312. MMIO_OUT32((uint32_t*)VRAM_BASE,VRAM_ADDR(addr),val); \
  313. else \
  314. stl_u(val,(void *)(V_ADDR(addr)));
  315. static uint8_t
  316. read_b(xf86Int10InfoPtr pInt, int addr)
  317. {
  318. return V_ADDR_RB(addr);
  319. }
  320. static uint16_t
  321. read_w(xf86Int10InfoPtr pInt, int addr)
  322. {
  323. #if X_BYTE_ORDER == X_LITTLE_ENDIAN
  324. if (OFF(addr + 1) > 0)
  325. return V_ADDR_RW(addr);
  326. #endif
  327. return V_ADDR_RB(addr) | (V_ADDR_RB(addr + 1) << 8);
  328. }
  329. static uint32_t
  330. read_l(xf86Int10InfoPtr pInt, int addr)
  331. {
  332. #if X_BYTE_ORDER == X_LITTLE_ENDIAN
  333. if (OFF(addr + 3) > 2)
  334. return V_ADDR_RL(addr);
  335. #endif
  336. return V_ADDR_RB(addr) |
  337. (V_ADDR_RB(addr + 1) << 8) |
  338. (V_ADDR_RB(addr + 2) << 16) | (V_ADDR_RB(addr + 3) << 24);
  339. }
  340. static void
  341. write_b(xf86Int10InfoPtr pInt, int addr, uint8_t val)
  342. {
  343. V_ADDR_WB(addr, val);
  344. }
  345. static void
  346. write_w(xf86Int10InfoPtr pInt, int addr, CARD16 val)
  347. {
  348. #if X_BYTE_ORDER == X_LITTLE_ENDIAN
  349. if (OFF(addr + 1) > 0) {
  350. V_ADDR_WW(addr, val);
  351. }
  352. #endif
  353. V_ADDR_WB(addr, val);
  354. V_ADDR_WB(addr + 1, val >> 8);
  355. }
  356. static void
  357. write_l(xf86Int10InfoPtr pInt, int addr, uint32_t val)
  358. {
  359. #if X_BYTE_ORDER == X_LITTLE_ENDIAN
  360. if (OFF(addr + 3) > 2) {
  361. V_ADDR_WL(addr, val);
  362. }
  363. #endif
  364. V_ADDR_WB(addr, val);
  365. V_ADDR_WB(addr + 1, val >> 8);
  366. V_ADDR_WB(addr + 2, val >> 16);
  367. V_ADDR_WB(addr + 3, val >> 24);
  368. }
  369. void *
  370. xf86int10Addr(xf86Int10InfoPtr pInt, uint32_t addr)
  371. {
  372. return V_ADDR(addr);
  373. }