xf86int10.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885
  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 "xf86.h"
  10. #include "compiler.h"
  11. #define _INT10_PRIVATE
  12. #include "xf86int10.h"
  13. #include "int10Defines.h"
  14. #include "Pci.h"
  15. #define REG pInt
  16. xf86Int10InfoPtr Int10Current = NULL;
  17. static int int1A_handler(xf86Int10InfoPtr pInt);
  18. #ifndef _PC
  19. static int int42_handler(xf86Int10InfoPtr pInt);
  20. #endif
  21. static int intE6_handler(xf86Int10InfoPtr pInt);
  22. static struct pci_device *findPci(xf86Int10InfoPtr pInt, unsigned short bx);
  23. static CARD32 pciSlotBX(const struct pci_device *pvp);
  24. int
  25. int_handler(xf86Int10InfoPtr pInt)
  26. {
  27. int num = pInt->num;
  28. int ret = 0;
  29. switch (num) {
  30. #ifndef _PC
  31. case 0x10:
  32. case 0x42:
  33. case 0x6D:
  34. if (getIntVect(pInt, num) == I_S_DEFAULT_INT_VECT)
  35. ret = int42_handler(pInt);
  36. break;
  37. #endif
  38. case 0x1A:
  39. ret = int1A_handler(pInt);
  40. break;
  41. case 0xe6:
  42. ret = intE6_handler(pInt);
  43. break;
  44. default:
  45. break;
  46. }
  47. if (!ret)
  48. ret = run_bios_int(num, pInt);
  49. if (!ret) {
  50. xf86DrvMsg(pInt->pScrn->scrnIndex, X_ERROR, "Halting on int 0x%2.2x!\n", num);
  51. dump_registers(pInt);
  52. stack_trace(pInt);
  53. }
  54. return ret;
  55. }
  56. #ifndef _PC
  57. /*
  58. * This is derived from a number of PC system BIOS'es. The intent here is to
  59. * provide very primitive video support, before an EGA/VGA BIOS installs its
  60. * own interrupt vector. Here, "Ignored" calls should remain so. "Not
  61. * Implemented" denotes functionality that can be implemented should the need
  62. * arise. What are "Not Implemented" throughout are video memory accesses.
  63. * Also, very little input validity checking is done here.
  64. */
  65. static int
  66. int42_handler(xf86Int10InfoPtr pInt)
  67. {
  68. switch (X86_AH) {
  69. case 0x00:
  70. /* Set Video Mode */
  71. /* Enter: AL = video mode number */
  72. /* Leave: Nothing */
  73. /* Implemented (except for clearing the screen) */
  74. { /* Localise */
  75. unsigned int ioport;
  76. int i;
  77. CARD16 int1d, regvals, tmp;
  78. CARD8 mode, cgamode, cgacolour;
  79. /*
  80. * Ignore all mode numbers but 0x00-0x13. Some systems also ignore
  81. * 0x0B and 0x0C, but don't do that here.
  82. */
  83. if (X86_AL > 0x13)
  84. break;
  85. /*
  86. * You didn't think that was really the mode set, did you? There
  87. * are only so many slots in the video parameter table...
  88. */
  89. mode = X86_AL;
  90. ioport = 0x03D4;
  91. switch (MEM_RB(pInt, 0x0410) & 0x30) {
  92. case 0x30: /* MDA */
  93. mode = 0x07; /* Force mode to 0x07 */
  94. ioport = 0x03B4;
  95. break;
  96. case 0x10: /* CGA 40x25 */
  97. if (mode >= 0x07)
  98. mode = 0x01;
  99. break;
  100. case 0x20: /* CGA 80x25 (MCGA?) */
  101. if (mode >= 0x07)
  102. mode = 0x03;
  103. break;
  104. case 0x00: /* EGA/VGA */
  105. if (mode >= 0x07) /* Don't try MDA timings */
  106. mode = 0x01; /* !?!?! */
  107. break;
  108. }
  109. /* Locate data in video parameter table */
  110. int1d = MEM_RW(pInt, 0x1d << 2);
  111. regvals = ((mode >> 1) << 4) + int1d;
  112. cgacolour = 0x30;
  113. if (mode == 0x06) {
  114. regvals -= 0x10;
  115. cgacolour = 0x3F;
  116. }
  117. /** Update BIOS Data Area **/
  118. /* Video mode */
  119. MEM_WB(pInt, 0x0449, mode);
  120. /* Columns */
  121. tmp = MEM_RB(pInt, mode + int1d + 0x48);
  122. MEM_WW(pInt, 0x044A, tmp);
  123. /* Page length */
  124. tmp = MEM_RW(pInt, (mode & 0x06) + int1d + 0x40);
  125. MEM_WW(pInt, 0x044C, tmp);
  126. /* Start Address */
  127. MEM_WW(pInt, 0x044E, 0);
  128. /* Cursor positions, one for each display page */
  129. for (i = 0x0450; i < 0x0460; i += 2)
  130. MEM_WW(pInt, i, 0);
  131. /* Cursor start & end scanlines */
  132. tmp = MEM_RB(pInt, regvals + 0x0B);
  133. MEM_WB(pInt, 0x0460, tmp);
  134. tmp = MEM_RB(pInt, regvals + 0x0A);
  135. MEM_WB(pInt, 0x0461, tmp);
  136. /* Current display page number */
  137. MEM_WB(pInt, 0x0462, 0);
  138. /* CRTC I/O address */
  139. MEM_WW(pInt, 0x0463, ioport);
  140. /* CGA Mode register value */
  141. cgamode = MEM_RB(pInt, mode + int1d + 0x50);
  142. MEM_WB(pInt, 0x0465, cgamode);
  143. /* CGA Colour register value */
  144. MEM_WB(pInt, 0x0466, cgacolour);
  145. /* Rows */
  146. MEM_WB(pInt, 0x0484, (25 - 1));
  147. /* Program the mode */
  148. pci_io_write8(pInt->io, ioport + 4, cgamode & 0x37); /* Turn off screen */
  149. for (i = 0; i < 0x10; i++) {
  150. tmp = MEM_RB(pInt, regvals + i);
  151. pci_io_write8(pInt->io, ioport, i);
  152. pci_io_write8(pInt->io, ioport + 1, tmp);
  153. }
  154. pci_io_write8(pInt->io, ioport + 5, cgacolour); /* Select colour mode */
  155. pci_io_write8(pInt->io, ioport + 4, cgamode); /* Turn on screen */
  156. }
  157. break;
  158. case 0x01:
  159. /* Set Cursor Type */
  160. /* Enter: CH = starting line for cursor */
  161. /* CL = ending line for cursor */
  162. /* Leave: Nothing */
  163. /* Implemented */
  164. { /* Localise */
  165. unsigned int ioport = MEM_RW(pInt, 0x0463);
  166. MEM_WB(pInt, 0x0460, X86_CL);
  167. MEM_WB(pInt, 0x0461, X86_CH);
  168. pci_io_write8(pInt->io, ioport, 0x0A);
  169. pci_io_write8(pInt->io, ioport + 1, X86_CH);
  170. pci_io_write8(pInt->io, ioport, 0x0B);
  171. pci_io_write8(pInt->io, ioport + 1, X86_CL);
  172. }
  173. break;
  174. case 0x02:
  175. /* Set Cursor Position */
  176. /* Enter: BH = display page number */
  177. /* DH = row */
  178. /* DL = column */
  179. /* Leave: Nothing */
  180. /* Implemented */
  181. { /* Localise */
  182. unsigned int ioport;
  183. CARD16 offset;
  184. MEM_WB(pInt, (X86_BH << 1) + 0x0450, X86_DL);
  185. MEM_WB(pInt, (X86_BH << 1) + 0x0451, X86_DH);
  186. if (X86_BH != MEM_RB(pInt, 0x0462))
  187. break;
  188. offset = (X86_DH * MEM_RW(pInt, 0x044A)) + X86_DL;
  189. offset += MEM_RW(pInt, 0x044E) << 1;
  190. ioport = MEM_RW(pInt, 0x0463);
  191. pci_io_write8(pInt->io, ioport, 0x0E);
  192. pci_io_write8(pInt->io, ioport + 1, offset >> 8);
  193. pci_io_write8(pInt->io, ioport, 0x0F);
  194. pci_io_write8(pInt->io, ioport + 1, offset & 0xFF);
  195. }
  196. break;
  197. case 0x03:
  198. /* Get Cursor Position */
  199. /* Enter: BH = display page number */
  200. /* Leave: CH = starting line for cursor */
  201. /* CL = ending line for cursor */
  202. /* DH = row */
  203. /* DL = column */
  204. /* Implemented */
  205. { /* Localise */
  206. X86_CL = MEM_RB(pInt, 0x0460);
  207. X86_CH = MEM_RB(pInt, 0x0461);
  208. X86_DL = MEM_RB(pInt, (X86_BH << 1) + 0x0450);
  209. X86_DH = MEM_RB(pInt, (X86_BH << 1) + 0x0451);
  210. }
  211. break;
  212. case 0x04:
  213. /* Get Light Pen Position */
  214. /* Enter: Nothing */
  215. /* Leave: AH = 0x01 (down/triggered) or 0x00 (not) */
  216. /* BX = pixel column */
  217. /* CX = pixel row */
  218. /* DH = character row */
  219. /* DL = character column */
  220. /* Not Implemented */
  221. { /* Localise */
  222. xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_NOT_IMPLEMENTED, 2,
  223. "int 0x%2.2x(AH=0x04) -- Get Light Pen Position\n",
  224. pInt->num);
  225. if (xf86GetVerbosity() > 3) {
  226. dump_registers(pInt);
  227. stack_trace(pInt);
  228. }
  229. X86_AH = X86_BX = X86_CX = X86_DX = 0;
  230. }
  231. break;
  232. case 0x05:
  233. /* Set Display Page */
  234. /* Enter: AL = display page number */
  235. /* Leave: Nothing */
  236. /* Implemented */
  237. { /* Localise */
  238. unsigned int ioport = MEM_RW(pInt, 0x0463);
  239. CARD16 start;
  240. CARD8 x, y;
  241. /* Calculate new start address */
  242. MEM_WB(pInt, 0x0462, X86_AL);
  243. start = X86_AL * MEM_RW(pInt, 0x044C);
  244. MEM_WW(pInt, 0x044E, start);
  245. start <<= 1;
  246. /* Update start address */
  247. pci_io_write8(pInt->io, ioport, 0x0C);
  248. pci_io_write8(pInt->io, ioport + 1, start >> 8);
  249. pci_io_write8(pInt->io, ioport, 0x0D);
  250. pci_io_write8(pInt->io, ioport + 1, start & 0xFF);
  251. /* Switch cursor position */
  252. y = MEM_RB(pInt, (X86_AL << 1) + 0x0450);
  253. x = MEM_RB(pInt, (X86_AL << 1) + 0x0451);
  254. start += (y * MEM_RW(pInt, 0x044A)) + x;
  255. /* Update cursor position */
  256. pci_io_write8(pInt->io, ioport, 0x0E);
  257. pci_io_write8(pInt->io, ioport + 1, start >> 8);
  258. pci_io_write8(pInt->io, ioport, 0x0F);
  259. pci_io_write8(pInt->io, ioport + 1, start & 0xFF);
  260. }
  261. break;
  262. case 0x06:
  263. /* Initialise or Scroll Window Up */
  264. /* Enter: AL = lines to scroll up */
  265. /* BH = attribute for blank */
  266. /* CH = upper y of window */
  267. /* CL = left x of window */
  268. /* DH = lower y of window */
  269. /* DL = right x of window */
  270. /* Leave: Nothing */
  271. /* Not Implemented */
  272. { /* Localise */
  273. xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_NOT_IMPLEMENTED, 2,
  274. "int 0x%2.2x(AH=0x06) -- Initialise or Scroll Window Up\n",
  275. pInt->num);
  276. xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_NOT_IMPLEMENTED, 3,
  277. " AL=0x%2.2x, BH=0x%2.2x,"
  278. " CH=0x%2.2x, CL=0x%2.2x, DH=0x%2.2x, DL=0x%2.2x\n",
  279. X86_AL, X86_BH, X86_CH, X86_CL, X86_DH, X86_DL);
  280. if (xf86GetVerbosity() > 3) {
  281. dump_registers(pInt);
  282. stack_trace(pInt);
  283. }
  284. }
  285. break;
  286. case 0x07:
  287. /* Initialise or Scroll Window Down */
  288. /* Enter: AL = lines to scroll down */
  289. /* BH = attribute for blank */
  290. /* CH = upper y of window */
  291. /* CL = left x of window */
  292. /* DH = lower y of window */
  293. /* DL = right x of window */
  294. /* Leave: Nothing */
  295. /* Not Implemented */
  296. { /* Localise */
  297. xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_NOT_IMPLEMENTED, 2,
  298. "int 0x%2.2x(AH=0x07) -- Initialise or Scroll Window Down\n",
  299. pInt->num);
  300. xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_NOT_IMPLEMENTED, 3,
  301. " AL=0x%2.2x, BH=0x%2.2x,"
  302. " CH=0x%2.2x, CL=0x%2.2x, DH=0x%2.2x, DL=0x%2.2x\n",
  303. X86_AL, X86_BH, X86_CH, X86_CL, X86_DH, X86_DL);
  304. if (xf86GetVerbosity() > 3) {
  305. dump_registers(pInt);
  306. stack_trace(pInt);
  307. }
  308. }
  309. break;
  310. case 0x08:
  311. /* Read Character and Attribute at Cursor */
  312. /* Enter: BH = display page number */
  313. /* Leave: AH = attribute */
  314. /* AL = character */
  315. /* Not Implemented */
  316. { /* Localise */
  317. xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_NOT_IMPLEMENTED, 2,
  318. "int 0x%2.2x(AH=0x08) -- Read Character and Attribute at"
  319. " Cursor\n", pInt->num);
  320. xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_NOT_IMPLEMENTED, 3,
  321. "BH=0x%2.2x\n", X86_BH);
  322. if (xf86GetVerbosity() > 3) {
  323. dump_registers(pInt);
  324. stack_trace(pInt);
  325. }
  326. X86_AX = 0;
  327. }
  328. break;
  329. case 0x09:
  330. /* Write Character and Attribute at Cursor */
  331. /* Enter: AL = character */
  332. /* BH = display page number */
  333. /* BL = attribute (text) or colour (graphics) */
  334. /* CX = replication count */
  335. /* Leave: Nothing */
  336. /* Not Implemented */
  337. { /* Localise */
  338. xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_NOT_IMPLEMENTED, 2,
  339. "int 0x%2.2x(AH=0x09) -- Write Character and Attribute at"
  340. " Cursor\n", pInt->num);
  341. xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_NOT_IMPLEMENTED, 3,
  342. "AL=0x%2.2x, BH=0x%2.2x, BL=0x%2.2x, CX=0x%4.4x\n",
  343. X86_AL, X86_BH, X86_BL, X86_CX);
  344. if (xf86GetVerbosity() > 3) {
  345. dump_registers(pInt);
  346. stack_trace(pInt);
  347. }
  348. }
  349. break;
  350. case 0x0a:
  351. /* Write Character at Cursor */
  352. /* Enter: AL = character */
  353. /* BH = display page number */
  354. /* BL = colour */
  355. /* CX = replication count */
  356. /* Leave: Nothing */
  357. /* Not Implemented */
  358. { /* Localise */
  359. xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_NOT_IMPLEMENTED, 2,
  360. "int 0x%2.2x(AH=0x0A) -- Write Character at Cursor\n",
  361. pInt->num);
  362. xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_NOT_IMPLEMENTED, 3,
  363. "AL=0x%2.2x, BH=0x%2.2x, BL=0x%2.2x, CX=0x%4.4x\n",
  364. X86_AL, X86_BH, X86_BL, X86_CX);
  365. if (xf86GetVerbosity() > 3) {
  366. dump_registers(pInt);
  367. stack_trace(pInt);
  368. }
  369. }
  370. break;
  371. case 0x0b:
  372. /* Set Palette, Background or Border */
  373. /* Enter: BH = 0x00 or 0x01 */
  374. /* BL = colour or palette (respectively) */
  375. /* Leave: Nothing */
  376. /* Implemented */
  377. { /* Localise */
  378. unsigned int ioport = MEM_RW(pInt, 0x0463) + 5;
  379. CARD8 cgacolour = MEM_RB(pInt, 0x0466);
  380. if (X86_BH) {
  381. cgacolour &= 0xDF;
  382. cgacolour |= (X86_BL & 0x01) << 5;
  383. }
  384. else {
  385. cgacolour &= 0xE0;
  386. cgacolour |= X86_BL & 0x1F;
  387. }
  388. MEM_WB(pInt, 0x0466, cgacolour);
  389. pci_io_write8(pInt->io, ioport, cgacolour);
  390. }
  391. break;
  392. case 0x0c:
  393. /* Write Graphics Pixel */
  394. /* Enter: AL = pixel value */
  395. /* BH = display page number */
  396. /* CX = column */
  397. /* DX = row */
  398. /* Leave: Nothing */
  399. /* Not Implemented */
  400. { /* Localise */
  401. xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_NOT_IMPLEMENTED, 2,
  402. "int 0x%2.2x(AH=0x0C) -- Write Graphics Pixel\n",
  403. pInt->num);
  404. xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_NOT_IMPLEMENTED, 3,
  405. "AL=0x%2.2x, BH=0x%2.2x, CX=0x%4.4x, DX=0x%4.4x\n",
  406. X86_AL, X86_BH, X86_CX, X86_DX);
  407. if (xf86GetVerbosity() > 3) {
  408. dump_registers(pInt);
  409. stack_trace(pInt);
  410. }
  411. }
  412. break;
  413. case 0x0d:
  414. /* Read Graphics Pixel */
  415. /* Enter: BH = display page number */
  416. /* CX = column */
  417. /* DX = row */
  418. /* Leave: AL = pixel value */
  419. /* Not Implemented */
  420. { /* Localise */
  421. xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_NOT_IMPLEMENTED, 2,
  422. "int 0x%2.2x(AH=0x0D) -- Read Graphics Pixel\n",
  423. pInt->num);
  424. xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_NOT_IMPLEMENTED, 3,
  425. "BH=0x%2.2x, CX=0x%4.4x, DX=0x%4.4x\n", X86_BH, X86_CX,
  426. X86_DX);
  427. if (xf86GetVerbosity() > 3) {
  428. dump_registers(pInt);
  429. stack_trace(pInt);
  430. }
  431. X86_AL = 0;
  432. }
  433. break;
  434. case 0x0e:
  435. /* Write Character in Teletype Mode */
  436. /* Enter: AL = character */
  437. /* BH = display page number */
  438. /* BL = foreground colour */
  439. /* Leave: Nothing */
  440. /* Not Implemented */
  441. /* WARNING: Emulation of BEL characters will require */
  442. /* emulation of RTC and PC speaker I/O. */
  443. /* Also, this recurses through int 0x10 */
  444. /* which might or might not have been */
  445. /* installed yet. */
  446. { /* Localise */
  447. xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_NOT_IMPLEMENTED, 2,
  448. "int 0x%2.2x(AH=0x0E) -- Write Character in Teletype Mode\n",
  449. pInt->num);
  450. xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_NOT_IMPLEMENTED, 3,
  451. "AL=0x%2.2x, BH=0x%2.2x, BL=0x%2.2x\n",
  452. X86_AL, X86_BH, X86_BL);
  453. if (xf86GetVerbosity() > 3) {
  454. dump_registers(pInt);
  455. stack_trace(pInt);
  456. }
  457. }
  458. break;
  459. case 0x0f:
  460. /* Get Video Mode */
  461. /* Enter: Nothing */
  462. /* Leave: AH = number of columns */
  463. /* AL = video mode number */
  464. /* BH = display page number */
  465. /* Implemented */
  466. { /* Localise */
  467. X86_AH = MEM_RW(pInt, 0x044A);
  468. X86_AL = MEM_RB(pInt, 0x0449);
  469. X86_BH = MEM_RB(pInt, 0x0462);
  470. }
  471. break;
  472. case 0x10:
  473. /* Colour Control (subfunction in AL) */
  474. /* Enter: Various */
  475. /* Leave: Various */
  476. /* Ignored */
  477. break;
  478. case 0x11:
  479. /* Font Control (subfunction in AL) */
  480. /* Enter: Various */
  481. /* Leave: Various */
  482. /* Ignored */
  483. break;
  484. case 0x12:
  485. /* Miscellaneous (subfunction in BL) */
  486. /* Enter: Various */
  487. /* Leave: Various */
  488. /* Ignored. Previous code here optionally allowed */
  489. /* the enabling and disabling of VGA, but no system */
  490. /* BIOS I've come across actually implements it. */
  491. break;
  492. case 0x13:
  493. /* Write String in Teletype Mode */
  494. /* Enter: AL = write mode */
  495. /* BL = attribute (if (AL & 0x02) == 0) */
  496. /* CX = string length */
  497. /* DH = row */
  498. /* DL = column */
  499. /* ES:BP = string segment:offset */
  500. /* Leave: Nothing */
  501. /* Not Implemented */
  502. /* WARNING: Emulation of BEL characters will require */
  503. /* emulation of RTC and PC speaker I/O. */
  504. /* Also, this recurses through int 0x10 */
  505. /* which might or might not have been */
  506. /* installed yet. */
  507. { /* Localise */
  508. xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_NOT_IMPLEMENTED, 2,
  509. "int 0x%2.2x(AH=0x13) -- Write String in Teletype Mode\n",
  510. pInt->num);
  511. xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_NOT_IMPLEMENTED, 3,
  512. "AL=0x%2.2x, BL=0x%2.2x, CX=0x%4.4x,"
  513. " DH=0x%2.2x, DL=0x%2.2x, ES:BP=0x%4.4x:0x%4.4x\n",
  514. X86_AL, X86_BL, X86_CX, X86_DH, X86_DL, X86_ES, X86_BP);
  515. if (xf86GetVerbosity() > 3) {
  516. dump_registers(pInt);
  517. stack_trace(pInt);
  518. }
  519. }
  520. break;
  521. default:
  522. /* Various extensions */
  523. /* Enter: Various */
  524. /* Leave: Various */
  525. /* Ignored */
  526. break;
  527. }
  528. return 1;
  529. }
  530. #endif
  531. #define SUCCESSFUL 0x00
  532. #define DEVICE_NOT_FOUND 0x86
  533. #define BAD_REGISTER_NUMBER 0x87
  534. #ifdef SHOW_ALL_DEVICES
  535. /**
  536. * These functions are meant to be used by the PCI BIOS emulation. Some
  537. * BIOSes need to see if there are \b other chips of the same type around so
  538. * by setting \c exclude one PCI device can be explicitely excluded, if
  539. * required.
  540. */
  541. static struct pci_device *
  542. do_find(const struct pci_id_match *m, char n, const struct pci_device *exclude)
  543. {
  544. struct pci_device *dev;
  545. struct pci_device_iterator *iter;
  546. n++;
  547. iter = pci_id_match_iterator_create(m);
  548. while ((dev = pci_device_next(iter)) != NULL) {
  549. if ((dev != exclude) && !(--n)) {
  550. break;
  551. }
  552. }
  553. pci_iterator_destroy(iter);
  554. return dev;
  555. }
  556. static struct pci_device *
  557. find_pci_device_vendor(CARD16 vendorID, CARD16 deviceID,
  558. char n, const struct pci_device *exclude)
  559. {
  560. struct pci_id_match m;
  561. m.vendor_id = vendorID;
  562. m.device_id = deviceID;
  563. m.subvendor_id = PCI_MATCH_ANY;
  564. m.subdevice_id = PCI_MATCH_ANY;
  565. m.device_class = 0;
  566. m.device_class_mask = 0;
  567. return do_find(&m, n, exclude);
  568. }
  569. static struct pci_device *
  570. find_pci_class(CARD8 intf, CARD8 subClass, CARD16 _class,
  571. char n, const struct pci_device *exclude)
  572. {
  573. struct pci_id_match m;
  574. m.vendor_id = PCI_MATCH_ANY;
  575. m.device_id = PCI_MATCH_ANY;
  576. m.subvendor_id = PCI_MATCH_ANY;
  577. m.subdevice_id = PCI_MATCH_ANY;
  578. m.device_class = (((uint32_t) _class) << 16)
  579. | (((uint32_t) subClass) << 8) | intf;
  580. m.device_class_mask = 0x00ffffff;
  581. return do_find(&m, n, exclude);
  582. }
  583. #endif
  584. /*
  585. * Return the last bus number in the same domain as dev. Only look at the
  586. * one domain since this is going into %cl, and VGA I/O is per-domain anyway.
  587. */
  588. static int
  589. int1A_last_bus_number(struct pci_device *dev)
  590. {
  591. struct pci_device *d;
  592. struct pci_slot_match m = { dev->domain,
  593. PCI_MATCH_ANY,
  594. PCI_MATCH_ANY,
  595. PCI_MATCH_ANY
  596. };
  597. struct pci_device_iterator *iter;
  598. int i = 0;
  599. iter = pci_slot_match_iterator_create(&m);
  600. while ((d = pci_device_next(iter)))
  601. if (d->bus > i)
  602. i = d->bus;
  603. pci_iterator_destroy(iter);
  604. return i;
  605. }
  606. static int
  607. int1A_handler(xf86Int10InfoPtr pInt)
  608. {
  609. struct pci_device *const pvp = xf86GetPciInfoForEntity(pInt->entityIndex);
  610. struct pci_device *dev;
  611. if (pvp == NULL)
  612. return 0; /* oops */
  613. #ifdef PRINT_INT
  614. ErrorF("int 0x1a: ax=0x%x bx=0x%x cx=0x%x dx=0x%x di=0x%x es=0x%x\n",
  615. X86_EAX, X86_EBX, X86_ECX, X86_EDX, X86_EDI, X86_ESI);
  616. #endif
  617. switch (X86_AX) {
  618. case 0xb101:
  619. X86_EAX &= 0xFF00; /* no config space/special cycle support */
  620. X86_EDX = 0x20494350; /* " ICP" */
  621. X86_EBX = 0x0210; /* Version 2.10 */
  622. X86_ECX &= 0xFF00;
  623. X86_ECX |= int1A_last_bus_number(pvp);
  624. X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
  625. #ifdef PRINT_INT
  626. ErrorF("ax=0x%x dx=0x%x bx=0x%x cx=0x%x flags=0x%x\n",
  627. X86_EAX, X86_EDX, X86_EBX, X86_ECX, X86_EFLAGS);
  628. #endif
  629. return 1;
  630. case 0xb102:
  631. if ((X86_DX == pvp->vendor_id)
  632. && (X86_CX == pvp->device_id)
  633. && (X86_ESI == 0)) {
  634. X86_EAX = X86_AL | (SUCCESSFUL << 8);
  635. X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
  636. X86_EBX = pciSlotBX(pvp);
  637. }
  638. #ifdef SHOW_ALL_DEVICES
  639. else if ((dev = find_pci_device_vendor(X86_EDX, X86_ECX, X86_ESI, pvp))) {
  640. X86_EAX = X86_AL | (SUCCESSFUL << 8);
  641. X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
  642. X86_EBX = pciSlotBX(dev);
  643. }
  644. #endif
  645. else {
  646. X86_EAX = X86_AL | (DEVICE_NOT_FOUND << 8);
  647. X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
  648. }
  649. #ifdef PRINT_INT
  650. ErrorF("ax=0x%x bx=0x%x flags=0x%x\n", X86_EAX, X86_EBX, X86_EFLAGS);
  651. #endif
  652. return 1;
  653. case 0xb103:
  654. if ((X86_ECX & 0x00FFFFFF) == pvp->device_class) {
  655. X86_EAX = X86_AL | (SUCCESSFUL << 8);
  656. X86_EBX = pciSlotBX(pvp);
  657. X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
  658. }
  659. #ifdef SHOW_ALL_DEVICES
  660. else if ((dev = find_pci_class(X86_CL, X86_CH,
  661. (X86_ECX & 0xffff0000) >> 16,
  662. X86_ESI, pvp))) {
  663. X86_EAX = X86_AL | (SUCCESSFUL << 8);
  664. X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
  665. X86_EBX = pciSlotBX(dev);
  666. }
  667. #endif
  668. else {
  669. X86_EAX = X86_AL | (DEVICE_NOT_FOUND << 8);
  670. X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
  671. }
  672. #ifdef PRINT_INT
  673. ErrorF("ax=0x%x flags=0x%x\n", X86_EAX, X86_EFLAGS);
  674. #endif
  675. return 1;
  676. case 0xb108:
  677. if ((dev = findPci(pInt, X86_EBX)) != NULL) {
  678. pci_device_cfg_read_u8(dev, &X86_CL, X86_DI);
  679. X86_EAX = X86_AL | (SUCCESSFUL << 8);
  680. X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
  681. }
  682. else {
  683. X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8);
  684. X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
  685. }
  686. #ifdef PRINT_INT
  687. ErrorF("ax=0x%x cx=0x%x flags=0x%x\n", X86_EAX, X86_ECX, X86_EFLAGS);
  688. #endif
  689. return 1;
  690. case 0xb109:
  691. if ((dev = findPci(pInt, X86_EBX)) != NULL) {
  692. pci_device_cfg_read_u16(dev, &X86_CX, X86_DI);
  693. X86_EAX = X86_AL | (SUCCESSFUL << 8);
  694. X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
  695. }
  696. else {
  697. X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8);
  698. X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
  699. }
  700. #ifdef PRINT_INT
  701. ErrorF("ax=0x%x cx=0x%x flags=0x%x\n", X86_EAX, X86_ECX, X86_EFLAGS);
  702. #endif
  703. return 1;
  704. case 0xb10a:
  705. if ((dev = findPci(pInt, X86_EBX)) != NULL) {
  706. pci_device_cfg_read_u32(dev, &X86_ECX, X86_DI);
  707. X86_EAX = X86_AL | (SUCCESSFUL << 8);
  708. X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
  709. }
  710. else {
  711. X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8);
  712. X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
  713. }
  714. #ifdef PRINT_INT
  715. ErrorF("ax=0x%x cx=0x%x flags=0x%x\n", X86_EAX, X86_ECX, X86_EFLAGS);
  716. #endif
  717. return 1;
  718. case 0xb10b:
  719. if ((dev = findPci(pInt, X86_EBX)) != NULL) {
  720. pci_device_cfg_write_u8(dev, X86_CL, X86_DI);
  721. X86_EAX = X86_AL | (SUCCESSFUL << 8);
  722. X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
  723. }
  724. else {
  725. X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8);
  726. X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
  727. }
  728. #ifdef PRINT_INT
  729. ErrorF("ax=0x%x flags=0x%x\n", X86_EAX, X86_EFLAGS);
  730. #endif
  731. return 1;
  732. case 0xb10c:
  733. if ((dev = findPci(pInt, X86_EBX)) != NULL) {
  734. pci_device_cfg_write_u16(dev, X86_CX, X86_DI);
  735. X86_EAX = X86_AL | (SUCCESSFUL << 8);
  736. X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
  737. }
  738. else {
  739. X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8);
  740. X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
  741. }
  742. #ifdef PRINT_INT
  743. ErrorF("ax=0x%x flags=0x%x\n", X86_EAX, X86_EFLAGS);
  744. #endif
  745. return 1;
  746. case 0xb10d:
  747. if ((dev = findPci(pInt, X86_EBX)) != NULL) {
  748. pci_device_cfg_write_u32(dev, X86_ECX, X86_DI);
  749. X86_EAX = X86_AL | (SUCCESSFUL << 8);
  750. X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
  751. }
  752. else {
  753. X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8);
  754. X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
  755. }
  756. #ifdef PRINT_INT
  757. ErrorF("ax=0x%x flags=0x%x\n", X86_EAX, X86_EFLAGS);
  758. #endif
  759. return 1;
  760. default:
  761. xf86DrvMsgVerb(pInt->pScrn->scrnIndex, X_NOT_IMPLEMENTED, 2,
  762. "int 0x1a subfunction\n");
  763. dump_registers(pInt);
  764. if (xf86GetVerbosity() > 3)
  765. stack_trace(pInt);
  766. return 0;
  767. }
  768. }
  769. static struct pci_device *
  770. findPci(xf86Int10InfoPtr pInt, unsigned short bx)
  771. {
  772. const unsigned bus = (bx >> 8) & 0x00FF;
  773. const unsigned dev = (bx >> 3) & 0x001F;
  774. const unsigned func = (bx) & 0x0007;
  775. return pci_device_find_by_slot(pInt->dev->domain, bus, dev, func);
  776. }
  777. static CARD32
  778. pciSlotBX(const struct pci_device *pvp)
  779. {
  780. return ((pvp->bus << 8) & 0x00FF00) | (pvp->dev << 3) | (pvp->func);
  781. }
  782. /*
  783. * handle initialization
  784. */
  785. static int
  786. intE6_handler(xf86Int10InfoPtr pInt)
  787. {
  788. struct pci_device *pvp;
  789. if ((pvp = xf86GetPciInfoForEntity(pInt->entityIndex)))
  790. X86_AX = (pvp->bus << 8) | (pvp->dev << 3) | (pvp->func & 0x7);
  791. pushw(pInt, X86_CS);
  792. pushw(pInt, X86_IP);
  793. X86_CS = pInt->BIOSseg;
  794. X86_EIP = 0x0003;
  795. X86_ES = 0; /* standard pc es */
  796. return 1;
  797. }