helper_exec.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767
  1. /*
  2. * XFree86 int10 module
  3. * execute BIOS int 10h calls in x86 real mode environment
  4. * Copyright 1999 Egbert Eich
  5. *
  6. * Part of this code was inspired by the VBIOS POSTing code in DOSEMU
  7. * developed by the "DOSEMU-Development-Team"
  8. */
  9. /*
  10. * To debug port accesses define PRINT_PORT to 1.
  11. * Note! You also have to comment out ioperm()
  12. * in xf86EnableIO(). Otherwise we won't trap
  13. * on PIO.
  14. */
  15. #ifdef HAVE_XORG_CONFIG_H
  16. #include <xorg-config.h>
  17. #endif
  18. #define PRINT_PORT 0
  19. #include <unistd.h>
  20. #include <X11/Xos.h>
  21. #include "xf86.h"
  22. #include "xf86_OSproc.h"
  23. #include "compiler.h"
  24. #define _INT10_PRIVATE
  25. #include "int10Defines.h"
  26. #include "xf86int10.h"
  27. #include "Pci.h"
  28. #ifdef _X86EMU
  29. #include "x86emu/x86emui.h"
  30. #else
  31. #define DEBUG_IO_TRACE() 0
  32. #endif
  33. #include <pciaccess.h>
  34. static int pciCfg1in(uint16_t addr, uint32_t *val);
  35. static int pciCfg1out(uint16_t addr, uint32_t val);
  36. static int pciCfg1inw(uint16_t addr, uint16_t *val);
  37. static int pciCfg1outw(uint16_t addr, uint16_t val);
  38. static int pciCfg1inb(uint16_t addr, uint8_t *val);
  39. static int pciCfg1outb(uint16_t addr, uint8_t val);
  40. #if defined (_PC)
  41. static void SetResetBIOSVars(xf86Int10InfoPtr pInt, Bool set);
  42. #endif
  43. #define REG pInt
  44. int
  45. setup_int(xf86Int10InfoPtr pInt)
  46. {
  47. if (pInt != Int10Current) {
  48. if (!MapCurrentInt10(pInt))
  49. return -1;
  50. Int10Current = pInt;
  51. }
  52. X86_EAX = (uint32_t) pInt->ax;
  53. X86_EBX = (uint32_t) pInt->bx;
  54. X86_ECX = (uint32_t) pInt->cx;
  55. X86_EDX = (uint32_t) pInt->dx;
  56. X86_ESI = (uint32_t) pInt->si;
  57. X86_EDI = (uint32_t) pInt->di;
  58. X86_EBP = (uint32_t) pInt->bp;
  59. X86_ESP = 0x1000;
  60. X86_SS = pInt->stackseg >> 4;
  61. X86_EIP = 0x0600;
  62. X86_CS = 0x0; /* address of 'hlt' */
  63. X86_DS = 0x40; /* standard pc ds */
  64. X86_ES = pInt->es;
  65. X86_FS = 0;
  66. X86_GS = 0;
  67. X86_EFLAGS = X86_IF_MASK | X86_IOPL_MASK;
  68. #if defined (_PC)
  69. if (pInt->Flags & SET_BIOS_SCRATCH)
  70. SetResetBIOSVars(pInt, TRUE);
  71. #endif
  72. OsBlockSignals();
  73. return 0;
  74. }
  75. void
  76. finish_int(xf86Int10InfoPtr pInt, int sig)
  77. {
  78. OsReleaseSignals();
  79. pInt->ax = (uint32_t) X86_EAX;
  80. pInt->bx = (uint32_t) X86_EBX;
  81. pInt->cx = (uint32_t) X86_ECX;
  82. pInt->dx = (uint32_t) X86_EDX;
  83. pInt->si = (uint32_t) X86_ESI;
  84. pInt->di = (uint32_t) X86_EDI;
  85. pInt->es = (uint16_t) X86_ES;
  86. pInt->bp = (uint32_t) X86_EBP;
  87. pInt->flags = (uint32_t) X86_FLAGS;
  88. #if defined (_PC)
  89. if (pInt->Flags & RESTORE_BIOS_SCRATCH)
  90. SetResetBIOSVars(pInt, FALSE);
  91. #endif
  92. }
  93. /* general software interrupt handler */
  94. uint32_t
  95. getIntVect(xf86Int10InfoPtr pInt, int num)
  96. {
  97. return MEM_RW(pInt, num << 2) + (MEM_RW(pInt, (num << 2) + 2) << 4);
  98. }
  99. void
  100. pushw(xf86Int10InfoPtr pInt, uint16_t val)
  101. {
  102. X86_ESP -= 2;
  103. MEM_WW(pInt, ((uint32_t) X86_SS << 4) + X86_SP, val);
  104. }
  105. int
  106. run_bios_int(int num, xf86Int10InfoPtr pInt)
  107. {
  108. uint32_t eflags;
  109. #ifndef _PC
  110. /* check if bios vector is initialized */
  111. if (MEM_RW(pInt, (num << 2) + 2) == (SYS_BIOS >> 4)) { /* SYS_BIOS_SEG ? */
  112. if (num == 21 && X86_AH == 0x4e) {
  113. xf86DrvMsg(pInt->pScrn->scrnIndex, X_NOTICE,
  114. "Failing Find-Matching-File on non-PC"
  115. " (int 21, func 4e)\n");
  116. X86_AX = 2;
  117. SET_FLAG(F_CF);
  118. return 1;
  119. }
  120. else {
  121. xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_NOT_IMPLEMENTED, 2,
  122. "Ignoring int 0x%02x call\n", num);
  123. if (xf86GetVerbosity() > 3) {
  124. dump_registers(pInt);
  125. stack_trace(pInt);
  126. }
  127. return 1;
  128. }
  129. }
  130. #endif
  131. #ifdef PRINT_INT
  132. ErrorF("calling card BIOS at: ");
  133. #endif
  134. eflags = X86_EFLAGS;
  135. #if 0
  136. eflags = eflags | IF_MASK;
  137. X86_EFLAGS = X86_EFLAGS & ~(VIF_MASK | TF_MASK | IF_MASK | NT_MASK);
  138. #endif
  139. pushw(pInt, eflags);
  140. pushw(pInt, X86_CS);
  141. pushw(pInt, X86_IP);
  142. X86_CS = MEM_RW(pInt, (num << 2) + 2);
  143. X86_IP = MEM_RW(pInt, num << 2);
  144. #ifdef PRINT_INT
  145. ErrorF("0x%x:%lx\n", X86_CS, X86_EIP);
  146. #endif
  147. return 1;
  148. }
  149. /* Debugging stuff */
  150. void
  151. dump_code(xf86Int10InfoPtr pInt)
  152. {
  153. int i;
  154. uint32_t lina = SEG_ADR((uint32_t), X86_CS, IP);
  155. xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_INFO, 3, "code at 0x%8.8" PRIx32 ":\n",
  156. (unsigned) lina);
  157. for (i = 0; i < 0x10; i++)
  158. xf86ErrorFVerb(3, " %2.2x", MEM_RB(pInt, lina + i));
  159. xf86ErrorFVerb(3, "\n");
  160. for (; i < 0x20; i++)
  161. xf86ErrorFVerb(3, " %2.2x", MEM_RB(pInt, lina + i));
  162. xf86ErrorFVerb(3, "\n");
  163. }
  164. void
  165. dump_registers(xf86Int10InfoPtr pInt)
  166. {
  167. xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_INFO, 3,
  168. "EAX=0x%8.8lx, EBX=0x%8.8lx, ECX=0x%8.8lx, EDX=0x%8.8lx\n",
  169. (unsigned long) X86_EAX, (unsigned long) X86_EBX,
  170. (unsigned long) X86_ECX, (unsigned long) X86_EDX);
  171. xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_INFO, 3,
  172. "ESP=0x%8.8lx, EBP=0x%8.8lx, ESI=0x%8.8lx, EDI=0x%8.8lx\n",
  173. (unsigned long) X86_ESP, (unsigned long) X86_EBP,
  174. (unsigned long) X86_ESI, (unsigned long) X86_EDI);
  175. xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_INFO, 3,
  176. "CS=0x%4.4x, SS=0x%4.4x,"
  177. " DS=0x%4.4x, ES=0x%4.4x, FS=0x%4.4x, GS=0x%4.4x\n",
  178. X86_CS, X86_SS, X86_DS, X86_ES, X86_FS, X86_GS);
  179. xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_INFO, 3,
  180. "EIP=0x%8.8lx, EFLAGS=0x%8.8lx\n",
  181. (unsigned long) X86_EIP, (unsigned long) X86_EFLAGS);
  182. }
  183. void
  184. stack_trace(xf86Int10InfoPtr pInt)
  185. {
  186. int i = 0;
  187. unsigned long stack = SEG_ADR((uint32_t), X86_SS, SP);
  188. unsigned long tail = (uint32_t) ((X86_SS << 4) + 0x1000);
  189. if (stack >= tail)
  190. return;
  191. xf86MsgVerb(X_INFO, 3, "stack at 0x%8.8lx:\n", stack);
  192. for (; stack < tail; stack++) {
  193. xf86ErrorFVerb(3, " %2.2x", MEM_RB(pInt, stack));
  194. i = (i + 1) % 0x10;
  195. if (!i)
  196. xf86ErrorFVerb(3, "\n");
  197. }
  198. if (i)
  199. xf86ErrorFVerb(3, "\n");
  200. }
  201. int
  202. port_rep_inb(xf86Int10InfoPtr pInt,
  203. uint16_t port, uint32_t base, int d_f, uint32_t count)
  204. {
  205. register int inc = d_f ? -1 : 1;
  206. uint32_t dst = base;
  207. if (PRINT_PORT && DEBUG_IO_TRACE())
  208. ErrorF(" rep_insb(%#x) %" PRIu32 " bytes at %8.8" PRIx32 " %s\n",
  209. port, (unsigned) count, (unsigned) base, d_f ? "up" : "down");
  210. while (count--) {
  211. MEM_WB(pInt, dst, x_inb(port));
  212. dst += inc;
  213. }
  214. return dst - base;
  215. }
  216. int
  217. port_rep_inw(xf86Int10InfoPtr pInt,
  218. uint16_t port, uint32_t base, int d_f, uint32_t count)
  219. {
  220. register int inc = d_f ? -2 : 2;
  221. uint32_t dst = base;
  222. if (PRINT_PORT && DEBUG_IO_TRACE())
  223. ErrorF(" rep_insw(%#x) %" PRIu32 " bytes at %8.8" PRIx32 " %s\n",
  224. port, (unsigned) count, (unsigned) base, d_f ? "up" : "down");
  225. while (count--) {
  226. MEM_WW(pInt, dst, x_inw(port));
  227. dst += inc;
  228. }
  229. return dst - base;
  230. }
  231. int
  232. port_rep_inl(xf86Int10InfoPtr pInt,
  233. uint16_t port, uint32_t base, int d_f, uint32_t count)
  234. {
  235. register int inc = d_f ? -4 : 4;
  236. uint32_t dst = base;
  237. if (PRINT_PORT && DEBUG_IO_TRACE())
  238. ErrorF(" rep_insl(%#x) %" PRIu32 " bytes at %8.8" PRIx32 " %s\n",
  239. port, (unsigned) count, (unsigned) base, d_f ? "up" : "down");
  240. while (count--) {
  241. MEM_WL(pInt, dst, x_inl(port));
  242. dst += inc;
  243. }
  244. return dst - base;
  245. }
  246. int
  247. port_rep_outb(xf86Int10InfoPtr pInt,
  248. uint16_t port, uint32_t base, int d_f, uint32_t count)
  249. {
  250. register int inc = d_f ? -1 : 1;
  251. uint32_t dst = base;
  252. if (PRINT_PORT && DEBUG_IO_TRACE())
  253. ErrorF(" rep_outb(%#x) %" PRIu32 " bytes at %8.8" PRIx32 " %s\n",
  254. port, (unsigned) count, (unsigned) base, d_f ? "up" : "down");
  255. while (count--) {
  256. x_outb(port, MEM_RB(pInt, dst));
  257. dst += inc;
  258. }
  259. return dst - base;
  260. }
  261. int
  262. port_rep_outw(xf86Int10InfoPtr pInt,
  263. uint16_t port, uint32_t base, int d_f, uint32_t count)
  264. {
  265. register int inc = d_f ? -2 : 2;
  266. uint32_t dst = base;
  267. if (PRINT_PORT && DEBUG_IO_TRACE())
  268. ErrorF(" rep_outw(%#x) %" PRIu32 " bytes at %8.8" PRIx32 " %s\n",
  269. port, (unsigned) count, (unsigned) base, d_f ? "up" : "down");
  270. while (count--) {
  271. x_outw(port, MEM_RW(pInt, dst));
  272. dst += inc;
  273. }
  274. return dst - base;
  275. }
  276. int
  277. port_rep_outl(xf86Int10InfoPtr pInt,
  278. uint16_t port, uint32_t base, int d_f, uint32_t count)
  279. {
  280. register int inc = d_f ? -4 : 4;
  281. uint32_t dst = base;
  282. if (PRINT_PORT && DEBUG_IO_TRACE())
  283. ErrorF(" rep_outl(%#x) %" PRIu32 " bytes at %8.8" PRIx32 " %s\n",
  284. port, (unsigned) count, (unsigned) base, d_f ? "up" : "down");
  285. while (count--) {
  286. x_outl(port, MEM_RL(pInt, dst));
  287. dst += inc;
  288. }
  289. return dst - base;
  290. }
  291. uint8_t
  292. x_inb(uint16_t port)
  293. {
  294. uint8_t val;
  295. if (port == 0x40) {
  296. Int10Current->inb40time++;
  297. val = (uint8_t) (Int10Current->inb40time >>
  298. ((Int10Current->inb40time & 1) << 3));
  299. if (PRINT_PORT && DEBUG_IO_TRACE())
  300. ErrorF(" inb(%#x) = %2.2x\n", port, val);
  301. #ifdef __NOT_YET__
  302. }
  303. else if (port < 0x0100) { /* Don't interfere with mainboard */
  304. val = 0;
  305. xf86DrvMsgVerb(Int10Current->pScrn->scrnIndex, X_NOT_IMPLEMENTED, 2,
  306. "inb 0x%4.4x\n", port);
  307. if (xf86GetVerbosity() > 3) {
  308. dump_registers(Int10Current);
  309. stack_trace(Int10Current);
  310. }
  311. #endif /* __NOT_YET__ */
  312. }
  313. else if (!pciCfg1inb(port, &val)) {
  314. val = pci_io_read8(Int10Current->io, port);
  315. if (PRINT_PORT && DEBUG_IO_TRACE())
  316. ErrorF(" inb(%#x) = %2.2x\n", port, val);
  317. }
  318. return val;
  319. }
  320. uint16_t
  321. x_inw(uint16_t port)
  322. {
  323. uint16_t val;
  324. if (port == 0x5c) {
  325. struct timeval tv;
  326. /*
  327. * Emulate a PC's timer. Typical resolution is 3.26 usec.
  328. * Approximate this by dividing by 3.
  329. */
  330. X_GETTIMEOFDAY(&tv);
  331. val = (uint16_t) (tv.tv_usec / 3);
  332. }
  333. else if (!pciCfg1inw(port, &val)) {
  334. val = pci_io_read16(Int10Current->io, port);
  335. if (PRINT_PORT && DEBUG_IO_TRACE())
  336. ErrorF(" inw(%#x) = %4.4x\n", port, val);
  337. }
  338. return val;
  339. }
  340. void
  341. x_outb(uint16_t port, uint8_t val)
  342. {
  343. if ((port == 0x43) && (val == 0)) {
  344. struct timeval tv;
  345. /*
  346. * Emulate a PC's timer 0. Such timers typically have a resolution of
  347. * some .838 usec per tick, but this can only provide 1 usec per tick.
  348. * (Not that this matters much, given inherent emulation delays.) Use
  349. * the bottom bit as a byte select. See inb(0x40) above.
  350. */
  351. X_GETTIMEOFDAY(&tv);
  352. Int10Current->inb40time = (uint16_t) (tv.tv_usec | 1);
  353. if (PRINT_PORT && DEBUG_IO_TRACE())
  354. ErrorF(" outb(%#x, %2.2x)\n", port, val);
  355. #ifdef __NOT_YET__
  356. }
  357. else if (port < 0x0100) { /* Don't interfere with mainboard */
  358. xf86DrvMsgVerb(Int10Current->pScrn->scrnIndex, X_NOT_IMPLEMENTED, 2,
  359. "outb 0x%4.4x,0x%2.2x\n", port, val);
  360. if (xf86GetVerbosity() > 3) {
  361. dump_registers(Int10Current);
  362. stack_trace(Int10Current);
  363. }
  364. #endif /* __NOT_YET__ */
  365. }
  366. else if (!pciCfg1outb(port, val)) {
  367. if (PRINT_PORT && DEBUG_IO_TRACE())
  368. ErrorF(" outb(%#x, %2.2x)\n", port, val);
  369. pci_io_write8(Int10Current->io, port, val);
  370. }
  371. }
  372. void
  373. x_outw(uint16_t port, uint16_t val)
  374. {
  375. if (!pciCfg1outw(port, val)) {
  376. if (PRINT_PORT && DEBUG_IO_TRACE())
  377. ErrorF(" outw(%#x, %4.4x)\n", port, val);
  378. pci_io_write16(Int10Current->io, port, val);
  379. }
  380. }
  381. uint32_t
  382. x_inl(uint16_t port)
  383. {
  384. uint32_t val;
  385. if (!pciCfg1in(port, &val)) {
  386. val = pci_io_read32(Int10Current->io, port);
  387. if (PRINT_PORT && DEBUG_IO_TRACE())
  388. ErrorF(" inl(%#x) = %8.8" PRIx32 "\n", port, (unsigned) val);
  389. }
  390. return val;
  391. }
  392. void
  393. x_outl(uint16_t port, uint32_t val)
  394. {
  395. if (!pciCfg1out(port, val)) {
  396. if (PRINT_PORT && DEBUG_IO_TRACE())
  397. ErrorF(" outl(%#x, %8.8" PRIx32 ")\n", port, (unsigned) val);
  398. pci_io_write32(Int10Current->io, port, val);
  399. }
  400. }
  401. uint8_t
  402. Mem_rb(uint32_t addr)
  403. {
  404. return (*Int10Current->mem->rb) (Int10Current, addr);
  405. }
  406. uint16_t
  407. Mem_rw(uint32_t addr)
  408. {
  409. return (*Int10Current->mem->rw) (Int10Current, addr);
  410. }
  411. uint32_t
  412. Mem_rl(uint32_t addr)
  413. {
  414. return (*Int10Current->mem->rl) (Int10Current, addr);
  415. }
  416. void
  417. Mem_wb(uint32_t addr, uint8_t val)
  418. {
  419. (*Int10Current->mem->wb) (Int10Current, addr, val);
  420. }
  421. void
  422. Mem_ww(uint32_t addr, uint16_t val)
  423. {
  424. (*Int10Current->mem->ww) (Int10Current, addr, val);
  425. }
  426. void
  427. Mem_wl(uint32_t addr, uint32_t val)
  428. {
  429. (*Int10Current->mem->wl) (Int10Current, addr, val);
  430. }
  431. static uint32_t PciCfg1Addr = 0;
  432. #define PCI_DOM_FROM_TAG(tag) (((tag) >> 24) & (PCI_DOM_MASK))
  433. #define PCI_BUS_FROM_TAG(tag) (((tag) >> 16) & (PCI_DOMBUS_MASK))
  434. #define PCI_DEV_FROM_TAG(tag) (((tag) & 0x0000f800u) >> 11)
  435. #define PCI_FUNC_FROM_TAG(tag) (((tag) & 0x00000700u) >> 8)
  436. #define PCI_OFFSET(x) ((x) & 0x000000ff)
  437. #define PCI_TAG(x) ((x) & 0x7fffff00)
  438. static struct pci_device *
  439. pci_device_for_cfg_address(uint32_t addr)
  440. {
  441. struct pci_device *dev = NULL;
  442. uint32_t tag = PCI_TAG(addr);
  443. struct pci_slot_match slot_match = {
  444. .domain = PCI_DOM_FROM_TAG(tag),
  445. .bus = PCI_BUS_NO_DOMAIN(PCI_BUS_FROM_TAG(tag)),
  446. .dev = PCI_DEV_FROM_TAG(tag),
  447. .func = PCI_FUNC_FROM_TAG(tag),
  448. .match_data = 0
  449. };
  450. struct pci_device_iterator *iter =
  451. pci_slot_match_iterator_create(&slot_match);
  452. if (iter)
  453. dev = pci_device_next(iter);
  454. pci_iterator_destroy(iter);
  455. return dev;
  456. }
  457. static int
  458. pciCfg1in(uint16_t addr, uint32_t *val)
  459. {
  460. if (addr == 0xCF8) {
  461. *val = PciCfg1Addr;
  462. return 1;
  463. }
  464. if (addr == 0xCFC) {
  465. pci_device_cfg_read_u32(pci_device_for_cfg_address(PciCfg1Addr),
  466. (uint32_t *) val, PCI_OFFSET(PciCfg1Addr));
  467. if (PRINT_PORT && DEBUG_IO_TRACE())
  468. ErrorF(" cfg_inl(%#" PRIx32 ") = %8.8" PRIx32 "\n", (unsigned) PciCfg1Addr,
  469. (unsigned) *val);
  470. return 1;
  471. }
  472. return 0;
  473. }
  474. static int
  475. pciCfg1out(uint16_t addr, uint32_t val)
  476. {
  477. if (addr == 0xCF8) {
  478. PciCfg1Addr = val;
  479. return 1;
  480. }
  481. if (addr == 0xCFC) {
  482. if (PRINT_PORT && DEBUG_IO_TRACE())
  483. ErrorF(" cfg_outl(%#" PRIx32 ", %8.8" PRIx32 ")\n", (unsigned) PciCfg1Addr,
  484. (unsigned) val);
  485. pci_device_cfg_write_u32(pci_device_for_cfg_address(PciCfg1Addr), val,
  486. PCI_OFFSET(PciCfg1Addr));
  487. return 1;
  488. }
  489. return 0;
  490. }
  491. static int
  492. pciCfg1inw(uint16_t addr, uint16_t *val)
  493. {
  494. int shift;
  495. if ((addr >= 0xCF8) && (addr <= 0xCFB)) {
  496. shift = (addr - 0xCF8) * 8;
  497. *val = (PciCfg1Addr >> shift) & 0xffff;
  498. return 1;
  499. }
  500. if ((addr >= 0xCFC) && (addr <= 0xCFF)) {
  501. const unsigned offset = addr - 0xCFC;
  502. pci_device_cfg_read_u16(pci_device_for_cfg_address(PciCfg1Addr),
  503. val, PCI_OFFSET(PciCfg1Addr) + offset);
  504. if (PRINT_PORT && DEBUG_IO_TRACE())
  505. ErrorF(" cfg_inw(%#" PRIx32 ") = %4.4x\n", (unsigned) (PciCfg1Addr + offset),
  506. (unsigned) *val);
  507. return 1;
  508. }
  509. return 0;
  510. }
  511. static int
  512. pciCfg1outw(uint16_t addr, uint16_t val)
  513. {
  514. int shift;
  515. if ((addr >= 0xCF8) && (addr <= 0xCFB)) {
  516. shift = (addr - 0xCF8) * 8;
  517. PciCfg1Addr &= ~(0xffff << shift);
  518. PciCfg1Addr |= ((uint32_t) val) << shift;
  519. return 1;
  520. }
  521. if ((addr >= 0xCFC) && (addr <= 0xCFF)) {
  522. const unsigned offset = addr - 0xCFC;
  523. if (PRINT_PORT && DEBUG_IO_TRACE())
  524. ErrorF(" cfg_outw(%#" PRIx32 ", %4.4x)\n", (unsigned) (PciCfg1Addr + offset),
  525. (unsigned) val);
  526. pci_device_cfg_write_u16(pci_device_for_cfg_address(PciCfg1Addr), val,
  527. PCI_OFFSET(PciCfg1Addr) + offset);
  528. return 1;
  529. }
  530. return 0;
  531. }
  532. static int
  533. pciCfg1inb(uint16_t addr, uint8_t *val)
  534. {
  535. int shift;
  536. if ((addr >= 0xCF8) && (addr <= 0xCFB)) {
  537. shift = (addr - 0xCF8) * 8;
  538. *val = (PciCfg1Addr >> shift) & 0xff;
  539. return 1;
  540. }
  541. if ((addr >= 0xCFC) && (addr <= 0xCFF)) {
  542. const unsigned offset = addr - 0xCFC;
  543. pci_device_cfg_read_u8(pci_device_for_cfg_address(PciCfg1Addr),
  544. val, PCI_OFFSET(PciCfg1Addr) + offset);
  545. if (PRINT_PORT && DEBUG_IO_TRACE())
  546. ErrorF(" cfg_inb(%#" PRIx32 ") = %2.2x\n", (unsigned) (PciCfg1Addr + offset),
  547. (unsigned) *val);
  548. return 1;
  549. }
  550. return 0;
  551. }
  552. static int
  553. pciCfg1outb(uint16_t addr, uint8_t val)
  554. {
  555. int shift;
  556. if ((addr >= 0xCF8) && (addr <= 0xCFB)) {
  557. shift = (addr - 0xCF8) * 8;
  558. PciCfg1Addr &= ~(0xff << shift);
  559. PciCfg1Addr |= ((uint32_t) val) << shift;
  560. return 1;
  561. }
  562. if ((addr >= 0xCFC) && (addr <= 0xCFF)) {
  563. const unsigned offset = addr - 0xCFC;
  564. if (PRINT_PORT && DEBUG_IO_TRACE())
  565. ErrorF(" cfg_outb(%#" PRIx32 ", %2.2x)\n", (unsigned) (PciCfg1Addr + offset),
  566. (unsigned) val);
  567. pci_device_cfg_write_u8(pci_device_for_cfg_address(PciCfg1Addr), val,
  568. PCI_OFFSET(PciCfg1Addr) + offset);
  569. return 1;
  570. }
  571. return 0;
  572. }
  573. uint8_t
  574. bios_checksum(const uint8_t *start, int size)
  575. {
  576. uint8_t sum = 0;
  577. while (size-- > 0)
  578. sum += *start++;
  579. return sum;
  580. }
  581. /*
  582. * Lock/Unlock legacy VGA. Some Bioses try to be very clever and make
  583. * an attempt to detect a legacy ISA card. If they find one they might
  584. * act very strange: for example they might configure the card as a
  585. * monochrome card. This might cause some drivers to choke.
  586. * To avoid this we attempt legacy VGA by writing to all know VGA
  587. * disable registers before we call the BIOS initialization and
  588. * restore the original values afterwards. In beween we hold our
  589. * breath. To get to a (possibly exising) ISA card need to disable
  590. * our current PCI card.
  591. */
  592. /*
  593. * This is just for booting: we just want to catch pure
  594. * legacy vga therefore we don't worry about mmio etc.
  595. * This stuff should really go into vgaHW.c. However then
  596. * the driver would have to load the vga-module prior to
  597. * doing int10.
  598. */
  599. void
  600. LockLegacyVGA(xf86Int10InfoPtr pInt, legacyVGAPtr vga)
  601. {
  602. vga->save_msr = pci_io_read8(pInt->io, 0x03CC);
  603. vga->save_vse = pci_io_read8(pInt->io, 0x03C3);
  604. #ifndef __ia64__
  605. vga->save_46e8 = pci_io_read8(pInt->io, 0x46E8);
  606. #endif
  607. vga->save_pos102 = pci_io_read8(pInt->io, 0x0102);
  608. pci_io_write8(pInt->io, 0x03C2, ~(uint8_t) 0x03 & vga->save_msr);
  609. pci_io_write8(pInt->io, 0x03C3, ~(uint8_t) 0x01 & vga->save_vse);
  610. #ifndef __ia64__
  611. pci_io_write8(pInt->io, 0x46E8, ~(uint8_t) 0x08 & vga->save_46e8);
  612. #endif
  613. pci_io_write8(pInt->io, 0x0102, ~(uint8_t) 0x01 & vga->save_pos102);
  614. }
  615. void
  616. UnlockLegacyVGA(xf86Int10InfoPtr pInt, legacyVGAPtr vga)
  617. {
  618. pci_io_write8(pInt->io, 0x0102, vga->save_pos102);
  619. #ifndef __ia64__
  620. pci_io_write8(pInt->io, 0x46E8, vga->save_46e8);
  621. #endif
  622. pci_io_write8(pInt->io, 0x03C3, vga->save_vse);
  623. pci_io_write8(pInt->io, 0x03C2, vga->save_msr);
  624. }
  625. #if defined (_PC)
  626. static void
  627. SetResetBIOSVars(xf86Int10InfoPtr pInt, Bool set)
  628. {
  629. int pagesize = getpagesize();
  630. unsigned char *base;
  631. int i;
  632. if (pci_device_map_legacy
  633. (pInt->dev, 0, pagesize, PCI_DEV_MAP_FLAG_WRITABLE, (void **) &base))
  634. return; /* eek */
  635. if (set) {
  636. for (i = BIOS_SCRATCH_OFF; i < BIOS_SCRATCH_END; i++)
  637. MEM_WW(pInt, i, *(base + i));
  638. }
  639. else {
  640. for (i = BIOS_SCRATCH_OFF; i < BIOS_SCRATCH_END; i++)
  641. *(base + i) = MEM_RW(pInt, i);
  642. }
  643. pci_device_unmap_legacy(pInt->dev, base, pagesize);
  644. }
  645. void
  646. xf86Int10SaveRestoreBIOSVars(xf86Int10InfoPtr pInt, Bool save)
  647. {
  648. int pagesize = getpagesize();
  649. unsigned char *base;
  650. int i;
  651. if (!xf86IsEntityPrimary(pInt->entityIndex)
  652. || (!save && !pInt->BIOSScratch))
  653. return;
  654. if (pci_device_map_legacy
  655. (pInt->dev, 0, pagesize, PCI_DEV_MAP_FLAG_WRITABLE, (void **) &base))
  656. return; /* eek */
  657. base += BIOS_SCRATCH_OFF;
  658. if (save) {
  659. if ((pInt->BIOSScratch = xnfalloc(BIOS_SCRATCH_LEN)))
  660. for (i = 0; i < BIOS_SCRATCH_LEN; i++)
  661. *(((char *) pInt->BIOSScratch + i)) = *(base + i);
  662. }
  663. else {
  664. if (pInt->BIOSScratch) {
  665. for (i = 0; i < BIOS_SCRATCH_LEN; i++)
  666. *(base + i) = *(pInt->BIOSScratch + i);
  667. free(pInt->BIOSScratch);
  668. pInt->BIOSScratch = NULL;
  669. }
  670. }
  671. pci_device_unmap_legacy(pInt->dev, base - BIOS_SCRATCH_OFF, pagesize);
  672. }
  673. #endif
  674. xf86Int10InfoPtr
  675. xf86InitInt10(int entityIndex)
  676. {
  677. return xf86ExtendedInitInt10(entityIndex, 0);
  678. }