go32.pp 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360
  1. {
  2. This file is part of the Free Pascal run time library.
  3. and implements some stuff for protected mode programming
  4. Copyright (c) 1999-2000 by the Free Pascal development team.
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit go32;
  12. {$S-,R-,I-,Q-} {no stack check, used by DPMIEXCP !! }
  13. {$inline ON}
  14. interface
  15. const
  16. { contants for the run modes returned by get_run_mode }
  17. rm_unknown = 0;
  18. rm_raw = 1; { raw (without HIMEM) }
  19. rm_xms = 2; { XMS (for example with HIMEM, without EMM386) }
  20. rm_vcpi = 3; { VCPI (for example HIMEM and EMM386) }
  21. rm_dpmi = 4; { DPMI (for example DOS box or 386Max) }
  22. { flags }
  23. carryflag = $001;
  24. parityflag = $004;
  25. auxcarryflag = $010;
  26. zeroflag = $040;
  27. signflag = $080;
  28. trapflag = $100;
  29. interruptflag = $200;
  30. directionflag = $400;
  31. overflowflag = $800;
  32. type
  33. tmeminfo = record
  34. available_memory,
  35. available_pages,
  36. available_lockable_pages,
  37. linear_space,
  38. unlocked_pages,
  39. available_physical_pages,
  40. total_physical_pages,
  41. free_linear_space,
  42. max_pages_in_paging_file,
  43. reserved0,
  44. reserved1,
  45. reserved2 : longint;
  46. end;
  47. tseginfo = record
  48. offset : pointer;
  49. segment : word;
  50. end;
  51. trealregs = record
  52. case integer of
  53. 1: { 32-bit } (EDI, ESI, EBP, Res, EBX, EDX, ECX, EAX: longint;
  54. Flags, ES, DS, FS, GS, IP, CS, SP, SS: word);
  55. 2: { 16-bit } (DI, DI2, SI, SI2, BP, BP2, R1, R2: word;
  56. BX, BX2, DX, DX2, CX, CX2, AX, AX2: word);
  57. 3: { 8-bit } (stuff: array[1..4] of longint;
  58. BL, BH, BL2, BH2, DL, DH, DL2, DH2,
  59. CL, CH, CL2, CH2, AL, AH, AL2, AH2: byte);
  60. 4: { Compat } (RealEDI, RealESI, RealEBP, RealRES,
  61. RealEBX, RealEDX, RealECX, RealEAX: longint;
  62. RealFlags,
  63. RealES, RealDS, RealFS, RealGS,
  64. RealIP, RealCS, RealSP, RealSS: word);
  65. end;
  66. registers = trealregs;
  67. tdpmiversioninfo = record
  68. major, minor: byte;
  69. flags: word;
  70. cpu: byte;
  71. master_pic, slave_pic: byte;
  72. end;
  73. { this works only with real DPMI }
  74. function allocate_ldt_descriptors(count : word) : word;
  75. function free_ldt_descriptor(d : word) : boolean;
  76. function segment_to_descriptor(seg : word) : word;
  77. function get_next_selector_increment_value : word;
  78. function get_segment_base_address(d : word) : dword;
  79. function set_segment_base_address(d : word;s : dword) : boolean;
  80. function set_segment_limit(d : word;s : dword): boolean;
  81. function set_descriptor_access_right(d : word;w : word) : boolean;
  82. function create_code_segment_alias_descriptor(seg : word) : word;
  83. function get_linear_addr(phys_addr : dword;size : longint) : dword;
  84. function free_linear_addr_mapping(linear_addr: dword): boolean;
  85. function get_segment_limit(d : word) : dword;
  86. function get_descriptor_access_right(d : word) : longint;
  87. function get_page_size:longint;
  88. function map_device_in_memory_block(handle,offset,pagecount,device:dword):boolean;
  89. function get_page_attributes(handle, offset, pagecount: dword; buf: pointer): boolean;
  90. function set_page_attributes(handle, offset, pagecount: dword; buf: pointer): boolean;
  91. function realintr(intnr : word;var regs : trealregs) : boolean;
  92. function get_dpmi_version(var version: tdpmiversioninfo): boolean;
  93. { is needed for functions which need a real mode buffer }
  94. function global_dos_alloc(bytes : longint) : longint;
  95. function global_dos_free(selector : word) : boolean;
  96. var
  97. { selector for the DOS memory (only usable if in DPMI mode) }
  98. dosmemselector : word;
  99. { result of dpmi call }
  100. int31error : word;
  101. { this procedure copies data where the source and destination }
  102. { are specified by 48 bit pointers }
  103. { Note: the procedure checks only for overlapping if }
  104. { source selector=destination selector }
  105. procedure seg_move(sseg : word;source : longint;dseg : word;dest : longint;count : longint);
  106. { fills a memory area specified by a 48 bit pointer with c }
  107. procedure seg_fillchar(seg : word;ofs : longint;count : longint;c : char);
  108. procedure seg_fillword(seg : word;ofs : longint;count : longint;w : word);
  109. {************************************}
  110. { this works with all PM interfaces: }
  111. {************************************}
  112. function get_meminfo(var meminfo : tmeminfo) : boolean;
  113. function get_pm_interrupt(vector : byte;var intaddr : tseginfo) : boolean;
  114. function set_pm_interrupt(vector : byte;const intaddr : tseginfo) : boolean;
  115. function get_rm_interrupt(vector : byte;var intaddr : tseginfo) : boolean;
  116. function set_rm_interrupt(vector : byte;const intaddr : tseginfo) : boolean;
  117. function get_exception_handler(e : byte;var intaddr : tseginfo) : boolean;
  118. function set_exception_handler(e : byte;const intaddr : tseginfo) : boolean;
  119. function get_pm_exception_handler(e : byte;var intaddr : tseginfo) : boolean;
  120. function set_pm_exception_handler(e : byte;const intaddr : tseginfo) : boolean;
  121. function free_rm_callback(var intaddr : tseginfo) : boolean;
  122. function get_rm_callback(pm_func : pointer;const reg : trealregs;var rmcb : tseginfo) : boolean;
  123. function get_cs : word;
  124. function get_ds : word;
  125. function get_ss : word;
  126. { locking functions }
  127. function allocate_memory_block(size:longint):longint;
  128. function free_memory_block(blockhandle : longint) : boolean;
  129. function request_linear_region(linearaddr, size : longint;
  130. var blockhandle : longint) : boolean;
  131. function lock_linear_region(linearaddr, size : longint) : boolean;
  132. function lock_data(var data;size : longint) : boolean;
  133. function lock_code(functionaddr : pointer;size : longint) : boolean;
  134. function unlock_linear_region(linearaddr, size : longint) : boolean;
  135. function unlock_data(var data;size : longint) : boolean;
  136. function unlock_code(functionaddr : pointer;size : longint) : boolean;
  137. {$ifdef VER3_0}
  138. { disables and enables interrupts }
  139. procedure disable;
  140. procedure enable;
  141. function inportb(port : word) : byte;
  142. function inportw(port : word) : word;
  143. function inportl(port : word) : longint;
  144. procedure outportb(port : word;data : byte);
  145. procedure outportw(port : word;data : word);
  146. procedure outportl(port : word;data : longint);
  147. {$else VER3_0}
  148. { disables and enables interrupts }
  149. procedure disable;inline;
  150. procedure enable;inline;
  151. function inportb(port : word) : byte;inline;
  152. function inportw(port : word) : word;inline;
  153. function inportl(port : word) : longint;inline;
  154. procedure outportb(port : word;data : byte);inline;
  155. procedure outportw(port : word;data : word);inline;
  156. procedure outportl(port : word;data : longint);inline;
  157. {$endif VER3_0}
  158. function get_run_mode : word;
  159. function transfer_buffer : longint;
  160. function tb_segment : longint;
  161. function tb_offset : longint;
  162. function tb_size : longint;
  163. procedure copytodos(var addr; len : longint);
  164. procedure copyfromdos(var addr; len : longint);
  165. procedure dpmi_dosmemput(seg : word;ofs : word;var data;count : longint);
  166. procedure dpmi_dosmemget(seg : word;ofs : word;var data;count : longint);
  167. procedure dpmi_dosmemmove(sseg,sofs,dseg,dofs : word;count : longint);
  168. procedure dpmi_dosmemfillchar(seg,ofs : word;count : longint;c : char);
  169. procedure dpmi_dosmemfillword(seg,ofs : word;count : longint;w : word);
  170. const
  171. { this procedures are assigned to the procedure which are needed }
  172. { for the current mode to access DOS memory }
  173. { It's strongly recommended to use this procedures! }
  174. dosmemput : procedure(seg : word;ofs : word;var data;count : longint)=@dpmi_dosmemput;
  175. dosmemget : procedure(seg : word;ofs : word;var data;count : longint)=@dpmi_dosmemget;
  176. dosmemmove : procedure(sseg,sofs,dseg,dofs : word;count : longint)=@dpmi_dosmemmove;
  177. dosmemfillchar : procedure(seg,ofs : word;count : longint;c : char)=@dpmi_dosmemfillchar;
  178. dosmemfillword : procedure(seg,ofs : word;count : longint;w : word)=@dpmi_dosmemfillword;
  179. implementation
  180. {$asmmode ATT}
  181. { the following procedures copy from and to DOS memory using DPMI }
  182. procedure dpmi_dosmemput(seg : word;ofs : word;var data;count : longint);
  183. begin
  184. seg_move(get_ds,longint(@data),dosmemselector,seg*16+ofs,count);
  185. end;
  186. procedure dpmi_dosmemget(seg : word;ofs : word;var data;count : longint);
  187. begin
  188. seg_move(dosmemselector,seg*16+ofs,get_ds,longint(@data),count);
  189. end;
  190. procedure dpmi_dosmemmove(sseg,sofs,dseg,dofs : word;count : longint);
  191. begin
  192. seg_move(dosmemselector,sseg*16+sofs,dosmemselector,dseg*16+dofs,count);
  193. end;
  194. procedure dpmi_dosmemfillchar(seg,ofs : word;count : longint;c : char);
  195. begin
  196. seg_fillchar(dosmemselector,seg*16+ofs,count,c);
  197. end;
  198. procedure dpmi_dosmemfillword(seg,ofs : word;count : longint;w : word);
  199. begin
  200. seg_fillword(dosmemselector,seg*16+ofs,count,w);
  201. end;
  202. procedure test_int31(flag : longint); stdcall; { stack-args! }
  203. begin
  204. asm
  205. pushl %ebx
  206. movw $0,INT31ERROR
  207. movl flag,%ebx
  208. testb $1,%bl
  209. jz .Lti31_1
  210. movw %ax,INT31ERROR
  211. xorl %eax,%eax
  212. jmp .Lti31_2
  213. .Lti31_1:
  214. movl $1,%eax
  215. .Lti31_2:
  216. popl %ebx
  217. end;
  218. end;
  219. function global_dos_alloc(bytes : longint) : longint;
  220. begin
  221. asm
  222. pushl %ebx
  223. movl bytes,%ebx
  224. addl $0xf,%ebx // round up
  225. shrl $0x4,%ebx // convert to Paragraphs
  226. movl $0x100,%eax // function 0x100
  227. int $0x31
  228. jnc .LDos_OK
  229. movw %ax,INT31ERROR
  230. xorl %eax,%eax
  231. jmp .LDos_end
  232. .LDos_OK:
  233. shll $0x10,%eax // return Segment in hi(Result)
  234. movw %dx,%ax // return Selector in lo(Result)
  235. .LDos_end:
  236. movl %eax,__result
  237. popl %ebx
  238. end;
  239. end;
  240. function global_dos_free(selector : word) : boolean;
  241. begin
  242. asm
  243. movw Selector,%dx
  244. movl $0x101,%eax
  245. int $0x31
  246. setnc %al
  247. movb %al,__RESULT
  248. end;
  249. end;
  250. function realintr(intnr : word;var regs : trealregs) : boolean;
  251. begin
  252. regs.realsp:=0;
  253. regs.realss:=0;
  254. regs.realres:=0; { play it safe }
  255. asm
  256. { save all used registers to avoid crash under NTVDM }
  257. { when spawning a 32-bit DPMI application }
  258. pushl %edi
  259. pushl %ebx
  260. pushw %fs
  261. movw intnr,%bx
  262. xorl %ecx,%ecx
  263. movl regs,%edi
  264. { es is always equal ds }
  265. movl $0x300,%eax
  266. int $0x31
  267. popw %fs
  268. setnc %al
  269. movb %al,__RESULT
  270. popl %ebx
  271. popl %edi
  272. end;
  273. end;
  274. procedure seg_fillchar(seg : word;ofs : longint;count : longint;c : char);
  275. begin
  276. asm
  277. pushl %edi
  278. movl ofs,%edi
  279. movl count,%ecx
  280. movb c,%dl
  281. { load es with selector }
  282. pushw %es
  283. movw seg,%ax
  284. movw %ax,%es
  285. { fill eax with duplicated c }
  286. { so we can use stosl }
  287. movb %dl,%dh
  288. movw %dx,%ax
  289. shll $16,%eax
  290. movw %dx,%ax
  291. movl %ecx,%edx
  292. shrl $2,%ecx
  293. cld
  294. rep
  295. stosl
  296. movl %edx,%ecx
  297. andl $3,%ecx
  298. rep
  299. stosb
  300. popw %es
  301. popl %edi
  302. end;
  303. end;
  304. procedure seg_fillword(seg : word;ofs : longint;count : longint;w : word);
  305. begin
  306. asm
  307. pushl %edi
  308. movl ofs,%edi
  309. movl count,%ecx
  310. movw w,%dx
  311. { load segment }
  312. pushw %es
  313. movw seg,%ax
  314. movw %ax,%es
  315. { fill eax }
  316. movw %dx,%ax
  317. shll $16,%eax
  318. movw %dx,%ax
  319. movl %ecx,%edx
  320. shrl $1,%ecx
  321. cld
  322. rep
  323. stosl
  324. movl %edx,%ecx
  325. andl $1,%ecx
  326. rep
  327. stosw
  328. popw %es
  329. popl %edi
  330. end;
  331. end;
  332. procedure seg_move(sseg : word;source : longint;dseg : word;dest : longint;count : longint);
  333. begin
  334. if count=0 then
  335. exit;
  336. if (sseg<>dseg) or ((sseg=dseg) and (source>dest)) then
  337. asm
  338. pushl %esi
  339. pushl %edi
  340. pushw %es
  341. pushw %ds
  342. cld
  343. movl count,%ecx
  344. movl source,%esi
  345. movl dest,%edi
  346. movw dseg,%ax
  347. movw %ax,%es
  348. movw sseg,%ax
  349. movw %ax,%ds
  350. movl %ecx,%eax
  351. shrl $2,%ecx
  352. rep
  353. movsl
  354. movl %eax,%ecx
  355. andl $3,%ecx
  356. rep
  357. movsb
  358. popw %ds
  359. popw %es
  360. popl %edi
  361. popl %esi
  362. end ['ECX','EAX']
  363. else if (source<dest) then
  364. { copy backward for overlapping }
  365. asm
  366. pushl %esi
  367. pushl %edi
  368. pushw %es
  369. pushw %ds
  370. std
  371. movl count,%ecx
  372. movl source,%esi
  373. movl dest,%edi
  374. movw dseg,%ax
  375. movw %ax,%es
  376. movw sseg,%ax
  377. movw %ax,%ds
  378. addl %ecx,%esi
  379. addl %ecx,%edi
  380. movl %ecx,%eax
  381. andl $3,%ecx
  382. orl %ecx,%ecx
  383. jz .LSEG_MOVE1
  384. { calculate esi and edi}
  385. decl %esi
  386. decl %edi
  387. rep
  388. movsb
  389. incl %esi
  390. incl %edi
  391. .LSEG_MOVE1:
  392. subl $4,%esi
  393. subl $4,%edi
  394. movl %eax,%ecx
  395. shrl $2,%ecx
  396. rep
  397. movsl
  398. cld
  399. popw %ds
  400. popw %es
  401. popl %edi
  402. popl %esi
  403. end ['ECX','EAX'];
  404. end;
  405. {$ifdef VER3_0}
  406. procedure outportb(port : word;data : byte);
  407. begin
  408. asm
  409. movw port,%dx
  410. movb data,%al
  411. outb %al,%dx
  412. end ['EAX','EDX'];
  413. end;
  414. procedure outportw(port : word;data : word);
  415. begin
  416. asm
  417. movw port,%dx
  418. movw data,%ax
  419. outw %ax,%dx
  420. end ['EAX','EDX'];
  421. end;
  422. procedure outportl(port : word;data : longint);
  423. begin
  424. asm
  425. movw port,%dx
  426. movl data,%eax
  427. outl %eax,%dx
  428. end ['EAX','EDX'];
  429. end;
  430. function inportb(port : word) : byte;
  431. begin
  432. asm
  433. movw port,%dx
  434. inb %dx,%al
  435. movb %al,__RESULT
  436. end ['EAX','EDX'];
  437. end;
  438. function inportw(port : word) : word;
  439. begin
  440. asm
  441. movw port,%dx
  442. inw %dx,%ax
  443. movw %ax,__RESULT
  444. end ['EAX','EDX'];
  445. end;
  446. function inportl(port : word) : longint;
  447. begin
  448. asm
  449. movw port,%dx
  450. inl %dx,%eax
  451. movl %eax,__RESULT
  452. end ['EAX','EDX'];
  453. end;
  454. {$else VER3_0}
  455. procedure outportb(port : word;data : byte);inline;
  456. begin
  457. fpc_x86_outportb(port,data);
  458. end;
  459. procedure outportw(port : word;data : word);inline;
  460. begin
  461. fpc_x86_outportw(port,data);
  462. end;
  463. procedure outportl(port : word;data : longint);inline;
  464. begin
  465. fpc_x86_outportl(port,data);
  466. end;
  467. function inportb(port : word) : byte;inline;
  468. begin
  469. inportb:=fpc_x86_inportb(port);
  470. end;
  471. function inportw(port : word) : word;inline;
  472. begin
  473. inportw:=fpc_x86_inportw(port);
  474. end;
  475. function inportl(port : word) : longint;inline;
  476. begin
  477. inportl:=fpc_x86_inportl(port);
  478. end;
  479. {$endif VER3_0}
  480. function get_cs : word;assembler;
  481. asm
  482. movw %cs,%ax
  483. end;
  484. function get_ss : word;assembler;
  485. asm
  486. movw %ss,%ax
  487. end;
  488. function get_ds : word;assembler;
  489. asm
  490. movw %ds,%ax
  491. end;
  492. function set_pm_interrupt(vector : byte;const intaddr : tseginfo) : boolean;
  493. begin
  494. asm
  495. pushl %ebx
  496. movl intaddr,%eax
  497. movl (%eax),%edx
  498. movw 4(%eax),%cx
  499. movl $0x205,%eax
  500. movb vector,%bl
  501. int $0x31
  502. pushf
  503. call test_int31
  504. movb %al,__RESULT
  505. popl %ebx
  506. end;
  507. end;
  508. function set_rm_interrupt(vector : byte;const intaddr : tseginfo) : boolean;
  509. begin
  510. asm
  511. pushl %ebx
  512. movl intaddr,%eax
  513. movw (%eax),%dx
  514. movw 4(%eax),%cx
  515. movl $0x201,%eax
  516. movb vector,%bl
  517. int $0x31
  518. pushf
  519. call test_int31
  520. movb %al,__RESULT
  521. popl %ebx
  522. end;
  523. end;
  524. function set_pm_exception_handler(e : byte;const intaddr : tseginfo) : boolean;
  525. begin
  526. asm
  527. pushl %ebx
  528. movl intaddr,%eax
  529. movl (%eax),%edx
  530. movw 4(%eax),%cx
  531. movl $0x212,%eax
  532. movb e,%bl
  533. int $0x31
  534. pushf
  535. call test_int31
  536. movb %al,__RESULT
  537. popl %ebx
  538. end;
  539. end;
  540. function set_exception_handler(e : byte;const intaddr : tseginfo) : boolean;
  541. begin
  542. asm
  543. pushl %ebx
  544. movl intaddr,%eax
  545. movl (%eax),%edx
  546. movw 4(%eax),%cx
  547. movl $0x203,%eax
  548. movb e,%bl
  549. int $0x31
  550. pushf
  551. call test_int31
  552. movb %al,__RESULT
  553. popl %ebx
  554. end;
  555. end;
  556. function get_pm_exception_handler(e : byte;var intaddr : tseginfo) : boolean;
  557. begin
  558. asm
  559. pushl %ebx
  560. movl $0x210,%eax
  561. movb e,%bl
  562. int $0x31
  563. pushf
  564. call test_int31
  565. movb %al,__RESULT
  566. movl intaddr,%eax
  567. movl %edx,(%eax)
  568. movw %cx,4(%eax)
  569. popl %ebx
  570. end;
  571. end;
  572. function get_exception_handler(e : byte;var intaddr : tseginfo) : boolean;
  573. begin
  574. asm
  575. pushl %ebx
  576. movl $0x202,%eax
  577. movb e,%bl
  578. int $0x31
  579. pushf
  580. call test_int31
  581. movb %al,__RESULT
  582. movl intaddr,%eax
  583. movl %edx,(%eax)
  584. movw %cx,4(%eax)
  585. popl %ebx
  586. end;
  587. end;
  588. function get_pm_interrupt(vector : byte;var intaddr : tseginfo) : boolean;
  589. begin
  590. asm
  591. pushl %ebx
  592. movb vector,%bl
  593. movl $0x204,%eax
  594. int $0x31
  595. pushf
  596. call test_int31
  597. movb %al,__RESULT
  598. movl intaddr,%eax
  599. movl %edx,(%eax)
  600. movw %cx,4(%eax)
  601. popl %ebx
  602. end;
  603. end;
  604. function get_rm_interrupt(vector : byte;var intaddr : tseginfo) : boolean;
  605. begin
  606. asm
  607. pushl %ebx
  608. movb vector,%bl
  609. movl $0x200,%eax
  610. int $0x31
  611. pushf
  612. call test_int31
  613. movb %al,__RESULT
  614. movl intaddr,%eax
  615. movzwl %dx,%edx
  616. movl %edx,(%eax)
  617. movw %cx,4(%eax)
  618. popl %ebx
  619. end;
  620. end;
  621. function free_rm_callback(var intaddr : tseginfo) : boolean;
  622. begin
  623. asm
  624. movl intaddr,%eax
  625. movw (%eax),%dx
  626. movw 4(%eax),%cx
  627. movl $0x304,%eax
  628. int $0x31
  629. pushf
  630. call test_int31
  631. movb %al,__RESULT
  632. end;
  633. end;
  634. { here we must use ___v2prt0_ds_alias instead of from v2prt0.s
  635. because the exception processor sets the ds limit to $fff
  636. at hardware exceptions }
  637. var
  638. ___v2prt0_ds_alias : word; external name '___v2prt0_ds_alias';
  639. function get_rm_callback(pm_func : pointer;const reg : trealregs;var rmcb : tseginfo) : boolean;
  640. begin
  641. asm
  642. pushl %esi
  643. pushl %edi
  644. movl pm_func,%esi
  645. movl reg,%edi
  646. pushw %es
  647. movw ___v2prt0_ds_alias,%ax
  648. movw %ax,%es
  649. pushw %ds
  650. movw %cs,%ax
  651. movw %ax,%ds
  652. movl $0x303,%eax
  653. int $0x31
  654. popw %ds
  655. popw %es
  656. pushf
  657. call test_int31
  658. movb %al,__RESULT
  659. movl rmcb,%eax
  660. movzwl %dx,%edx
  661. movl %edx,(%eax)
  662. movw %cx,4(%eax)
  663. popl %edi
  664. popl %esi
  665. end;
  666. end;
  667. function allocate_ldt_descriptors(count : word) : word;
  668. begin
  669. asm
  670. movw count,%cx
  671. xorl %eax,%eax
  672. int $0x31
  673. movw %ax,__RESULT
  674. end;
  675. end;
  676. function free_ldt_descriptor(d : word) : boolean;
  677. begin
  678. asm
  679. pushl %ebx
  680. movw d,%bx
  681. movl $1,%eax
  682. int $0x31
  683. pushf
  684. call test_int31
  685. movb %al,__RESULT
  686. popl %ebx
  687. end;
  688. end;
  689. function segment_to_descriptor(seg : word) : word;
  690. begin
  691. asm
  692. pushl %ebx
  693. movw seg,%bx
  694. movl $2,%eax
  695. int $0x31
  696. movw %ax,__RESULT
  697. popl %ebx
  698. end;
  699. end;
  700. function get_next_selector_increment_value : word;
  701. begin
  702. asm
  703. movl $3,%eax
  704. int $0x31
  705. movw %ax,__RESULT
  706. end;
  707. end;
  708. function get_segment_base_address(d : word) : dword;
  709. begin
  710. asm
  711. pushl %ebx
  712. movw d,%bx
  713. movl $6,%eax
  714. int $0x31
  715. xorl %eax,%eax
  716. movw %dx,%ax
  717. shll $16,%ecx
  718. orl %ecx,%eax
  719. movl %eax,__RESULT
  720. popl %ebx
  721. end;
  722. end;
  723. function get_page_size:longint;
  724. begin
  725. asm
  726. pushl %ebx
  727. movl $0x604,%eax
  728. int $0x31
  729. shll $16,%ebx
  730. movw %cx,%bx
  731. movl %ebx,__RESULT
  732. popl %ebx
  733. end;
  734. end;
  735. function request_linear_region(linearaddr, size : longint;
  736. var blockhandle : longint) : boolean;
  737. var
  738. pageofs : longint;
  739. begin
  740. pageofs:=linearaddr and $3ff;
  741. linearaddr:=linearaddr-pageofs;
  742. size:=size+pageofs;
  743. asm
  744. pushl %ebx
  745. pushl %esi
  746. movl $0x504,%eax
  747. movl linearaddr,%ebx
  748. movl size,%ecx
  749. movl $1,%edx
  750. xorl %esi,%esi
  751. int $0x31
  752. pushf
  753. call test_int31
  754. movb %al,__RESULT
  755. movl blockhandle,%eax
  756. movl %esi,(%eax)
  757. movl %ebx,pageofs
  758. popl %esi
  759. popl %ebx
  760. end;
  761. if pageofs<>linearaddr then
  762. request_linear_region:=false;
  763. end;
  764. function allocate_memory_block(size:longint):longint;
  765. begin
  766. asm
  767. pushl %ebx
  768. pushl %esi
  769. movl $0x501,%eax
  770. movl size,%ecx
  771. movl %ecx,%ebx
  772. shrl $16,%ebx
  773. andl $65535,%ecx
  774. int $0x31
  775. jnc .Lallocate_mem_block_err
  776. xorl %ebx,%ebx
  777. xorl %ecx,%ecx
  778. .Lallocate_mem_block_err:
  779. shll $16,%ebx
  780. movw %cx,%bx
  781. shll $16,%esi
  782. movw %di,%si
  783. movl %ebx,__RESULT
  784. popl %esi
  785. popl %ebx
  786. end;
  787. end;
  788. function free_memory_block(blockhandle : longint) : boolean;
  789. begin
  790. asm
  791. pushl %edi
  792. pushl %esi
  793. movl blockhandle,%esi
  794. movl %esi,%edi
  795. shll $16,%esi
  796. movl $0x502,%eax
  797. int $0x31
  798. pushf
  799. call test_int31
  800. movb %al,__RESULT
  801. popl %esi
  802. popl %edi
  803. end;
  804. end;
  805. function lock_linear_region(linearaddr, size : longint) : boolean;
  806. begin
  807. asm
  808. pushl %ebx
  809. pushl %edi
  810. pushl %esi
  811. movl $0x600,%eax
  812. movl linearaddr,%ecx
  813. movl %ecx,%ebx
  814. shrl $16,%ebx
  815. movl size,%esi
  816. movl %esi,%edi
  817. shrl $16,%esi
  818. int $0x31
  819. pushf
  820. call test_int31
  821. movb %al,__RESULT
  822. popl %esi
  823. popl %edi
  824. popl %ebx
  825. end;
  826. end;
  827. function lock_data(var data;size : longint) : boolean;
  828. var
  829. linearaddr : dword;
  830. begin
  831. if get_run_mode<>rm_dpmi then
  832. exit;
  833. linearaddr:=dword(@data)+get_segment_base_address(get_ds);
  834. lock_data:=lock_linear_region(linearaddr,size);
  835. end;
  836. function lock_code(functionaddr : pointer;size : longint) : boolean;
  837. var
  838. linearaddr : dword;
  839. begin
  840. if get_run_mode<>rm_dpmi then
  841. exit;
  842. linearaddr:=dword(functionaddr)+get_segment_base_address(get_cs);
  843. lock_code:=lock_linear_region(linearaddr,size);
  844. end;
  845. function unlock_linear_region(linearaddr,size : longint) : boolean;
  846. begin
  847. asm
  848. pushl %ebx
  849. pushl %edi
  850. pushl %esi
  851. movl $0x601,%eax
  852. movl linearaddr,%ecx
  853. movl %ecx,%ebx
  854. shrl $16,%ebx
  855. movl size,%esi
  856. movl %esi,%edi
  857. shrl $16,%esi
  858. int $0x31
  859. pushf
  860. call test_int31
  861. movb %al,__RESULT
  862. popl %esi
  863. popl %edi
  864. popl %ebx
  865. end;
  866. end;
  867. function unlock_data(var data;size : longint) : boolean;
  868. var
  869. linearaddr : dword;
  870. begin
  871. if get_run_mode<>rm_dpmi then
  872. exit;
  873. linearaddr:=dword(@data)+get_segment_base_address(get_ds);
  874. unlock_data:=unlock_linear_region(linearaddr,size);
  875. end;
  876. function unlock_code(functionaddr : pointer;size : longint) : boolean;
  877. var
  878. linearaddr : dword;
  879. begin
  880. if get_run_mode<>rm_dpmi then
  881. exit;
  882. linearaddr:=dword(functionaddr)+get_segment_base_address(get_cs);
  883. unlock_code:=unlock_linear_region(linearaddr,size);
  884. end;
  885. function set_segment_base_address(d : word;s : dword) : boolean;
  886. begin
  887. asm
  888. pushl %ebx
  889. movw d,%bx
  890. leal s,%eax
  891. movw (%eax),%dx
  892. movw 2(%eax),%cx
  893. movl $7,%eax
  894. int $0x31
  895. pushf
  896. call test_int31
  897. movb %al,__RESULT
  898. popl %ebx
  899. end;
  900. end;
  901. function set_descriptor_access_right(d : word;w : word) : boolean;
  902. begin
  903. asm
  904. pushl %ebx
  905. movw d,%bx
  906. movw w,%cx
  907. movl $9,%eax
  908. int $0x31
  909. pushf
  910. call test_int31
  911. movb %al,__RESULT
  912. popl %ebx
  913. end;
  914. end;
  915. function set_segment_limit(d : word;s : dword) : boolean;
  916. begin
  917. asm
  918. pushl %ebx
  919. movw d,%bx
  920. leal s,%eax
  921. movw (%eax),%dx
  922. movw 2(%eax),%cx
  923. movl $8,%eax
  924. int $0x31
  925. pushf
  926. call test_int31
  927. movb %al,__RESULT
  928. popl %ebx
  929. end;
  930. end;
  931. function get_descriptor_access_right(d : word) : longint;
  932. begin
  933. asm
  934. movzwl d,%eax
  935. lar %eax,%eax
  936. jz .L_ok
  937. xorl %eax,%eax
  938. .L_ok:
  939. movl %eax,__RESULT
  940. end;
  941. end;
  942. function get_segment_limit(d : word) : dword;
  943. begin
  944. asm
  945. movzwl d,%eax
  946. lsl %eax,%eax
  947. jz .L_ok2
  948. xorl %eax,%eax
  949. .L_ok2:
  950. movl %eax,__RESULT
  951. end;
  952. end;
  953. function create_code_segment_alias_descriptor(seg : word) : word;
  954. begin
  955. asm
  956. pushl %ebx
  957. movw seg,%bx
  958. movl $0xa,%eax
  959. int $0x31
  960. pushf
  961. call test_int31
  962. movw %ax,__RESULT
  963. popl %ebx
  964. end;
  965. end;
  966. function get_meminfo(var meminfo : tmeminfo) : boolean;
  967. begin
  968. asm
  969. pushl %edi
  970. movl meminfo,%edi
  971. movl $0x500,%eax
  972. int $0x31
  973. pushf
  974. movb %al,__RESULT
  975. call test_int31
  976. popl %edi
  977. end;
  978. end;
  979. function get_linear_addr(phys_addr : dword;size : longint) : dword;
  980. begin
  981. asm
  982. pushl %ebx
  983. pushl %edi
  984. pushl %esi
  985. movl phys_addr,%ebx
  986. movl %ebx,%ecx
  987. shrl $16,%ebx
  988. movl size,%esi
  989. movl %esi,%edi
  990. shrl $16,%esi
  991. movl $0x800,%eax
  992. int $0x31
  993. pushf
  994. call test_int31
  995. shll $16,%ebx
  996. movw %cx,%bx
  997. movl %ebx,__RESULT
  998. popl %esi
  999. popl %edi
  1000. popl %ebx
  1001. end;
  1002. end;
  1003. function free_linear_addr_mapping(linear_addr: dword): boolean;
  1004. begin
  1005. asm
  1006. pushl %ebx
  1007. pushl %ecx
  1008. movl linear_addr,%ebx
  1009. movl %ebx,%ecx
  1010. shrl $16,%ebx
  1011. movl $0x801,%eax
  1012. int $0x31
  1013. pushf
  1014. call test_int31
  1015. movb %al,__RESULT
  1016. popl %ecx
  1017. popl %ebx
  1018. end;
  1019. end;
  1020. {$ifdef VER3_0}
  1021. procedure disable;assembler;
  1022. asm
  1023. cli
  1024. end;
  1025. procedure enable;assembler;
  1026. asm
  1027. sti
  1028. end;
  1029. {$else VER3_0}
  1030. procedure disable;inline;
  1031. begin
  1032. fpc_x86_cli;
  1033. end;
  1034. procedure enable;inline;
  1035. begin
  1036. fpc_x86_sti;
  1037. end;
  1038. {$endif VER3_0}
  1039. var
  1040. _run_mode : word;external name '_run_mode';
  1041. function get_run_mode : word;
  1042. begin
  1043. get_run_mode:=_run_mode;
  1044. end;
  1045. function map_device_in_memory_block(handle,offset,pagecount,device:dword):boolean;
  1046. begin
  1047. asm
  1048. pushl %ebx
  1049. pushl %edi
  1050. pushl %esi
  1051. movl device,%edx
  1052. movl handle,%esi
  1053. movl offset,%ebx
  1054. movl pagecount,%ecx
  1055. movl $0x0508,%eax
  1056. int $0x31
  1057. pushf
  1058. call test_int31
  1059. movb %al,__RESULT
  1060. popl %esi
  1061. popl %edi
  1062. popl %ebx
  1063. end;
  1064. end;
  1065. function get_page_attributes(handle, offset, pagecount: dword; buf: pointer): boolean;
  1066. begin
  1067. asm
  1068. pushl %ebx
  1069. pushl %ecx
  1070. pushl %edx
  1071. pushl %esi
  1072. pushw %es
  1073. pushw %ds
  1074. popw %es
  1075. movl buf,%edx
  1076. movl handle,%esi
  1077. movl offset,%ebx
  1078. movl pagecount,%ecx
  1079. movl $0x0506,%eax
  1080. int $0x31
  1081. pushf
  1082. call test_int31
  1083. movb %al,__RESULT
  1084. popw %es
  1085. popl %esi
  1086. popl %edx
  1087. popl %ecx
  1088. popl %ebx
  1089. end;
  1090. end;
  1091. function set_page_attributes(handle, offset, pagecount: dword; buf: pointer): boolean;
  1092. begin
  1093. asm
  1094. pushl %ebx
  1095. pushl %ecx
  1096. pushl %edx
  1097. pushl %esi
  1098. pushw %es
  1099. pushw %ds
  1100. popw %es
  1101. movl buf,%edx
  1102. movl handle,%esi
  1103. movl offset,%ebx
  1104. movl pagecount,%ecx
  1105. movl $0x0507,%eax
  1106. int $0x31
  1107. pushf
  1108. call test_int31
  1109. movb %al,__RESULT
  1110. popw %es
  1111. popl %esi
  1112. popl %edx
  1113. popl %ecx
  1114. popl %ebx
  1115. end;
  1116. end;
  1117. function get_dpmi_version(var version: tdpmiversioninfo): boolean;
  1118. var
  1119. _version, _flags, _cpu, _pic: word;
  1120. begin
  1121. asm
  1122. movl $0x0400,%eax
  1123. int $0x31
  1124. pushf
  1125. movw %ax,_version
  1126. movw %bx,_flags
  1127. movw %cx,_cpu
  1128. movw %dx,_pic
  1129. call test_int31
  1130. movb %al,__RESULT
  1131. end ['EAX','EBX','ECX','EDX'];
  1132. if get_dpmi_version then
  1133. begin
  1134. FillChar(version, SizeOf(version), 0);
  1135. version.major := _version shr 8;
  1136. version.minor := _version and $ff;
  1137. version.flags := _flags;
  1138. version.cpu := _cpu and $ff;
  1139. version.master_pic := _pic shr 8;
  1140. version.slave_pic := _pic and $ff;
  1141. end;
  1142. end;
  1143. {*****************************************************************************
  1144. Transfer Buffer
  1145. *****************************************************************************}
  1146. function transfer_buffer : longint;
  1147. begin
  1148. transfer_buffer := go32_info_block.linear_address_of_transfer_buffer;
  1149. end;
  1150. function tb_segment : longint;
  1151. begin
  1152. tb_segment:=go32_info_block.linear_address_of_transfer_buffer shr 4;
  1153. end;
  1154. function tb_offset : longint;
  1155. begin
  1156. tb_offset:=go32_info_block.linear_address_of_transfer_buffer and $f;
  1157. end;
  1158. function tb_size : longint;
  1159. begin
  1160. tb_size := go32_info_block.size_of_transfer_buffer;
  1161. end;
  1162. procedure copytodos(var addr; len : longint);
  1163. begin
  1164. if len>tb_size then
  1165. runerror(217);
  1166. seg_move(get_ds,longint(@addr),dosmemselector,transfer_buffer,len);
  1167. end;
  1168. procedure copyfromdos(var addr; len : longint);
  1169. begin
  1170. if len>tb_size then
  1171. runerror(217);
  1172. seg_move(dosmemselector,transfer_buffer,get_ds,longint(@addr),len);
  1173. end;
  1174. var
  1175. _core_selector : word;external name '_core_selector';
  1176. begin
  1177. int31error:=0;
  1178. dosmemselector:=_core_selector;
  1179. end.