go32.pp 35 KB

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