go32.pp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272
  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. { disables and enables interrupts }
  140. procedure disable;inline;
  141. procedure enable;inline;
  142. function inportb(port : word) : byte;inline;
  143. function inportw(port : word) : word;inline;
  144. function inportl(port : word) : longint;inline;
  145. procedure outportb(port : word;data : byte);inline;
  146. procedure outportw(port : word;data : word);inline;
  147. procedure outportl(port : word;data : longint);inline;
  148. function get_run_mode : word;
  149. function transfer_buffer : longint;
  150. function tb_segment : longint;
  151. function tb_offset : longint;
  152. function tb_size : longint;
  153. procedure copytodos(var addr; len : longint);
  154. procedure copyfromdos(var addr; len : longint);
  155. procedure dpmi_dosmemput(seg : word;ofs : word;var data;count : longint);
  156. procedure dpmi_dosmemget(seg : word;ofs : word;var data;count : longint);
  157. procedure dpmi_dosmemmove(sseg,sofs,dseg,dofs : word;count : longint);
  158. procedure dpmi_dosmemfillchar(seg,ofs : word;count : longint;c : AnsiChar);
  159. procedure dpmi_dosmemfillword(seg,ofs : word;count : longint;w : word);
  160. const
  161. { this procedures are assigned to the procedure which are needed }
  162. { for the current mode to access DOS memory }
  163. { It's strongly recommended to use this procedures! }
  164. dosmemput : procedure(seg : word;ofs : word;var data;count : longint)=@dpmi_dosmemput;
  165. dosmemget : procedure(seg : word;ofs : word;var data;count : longint)=@dpmi_dosmemget;
  166. dosmemmove : procedure(sseg,sofs,dseg,dofs : word;count : longint)=@dpmi_dosmemmove;
  167. dosmemfillchar : procedure(seg,ofs : word;count : longint;c : AnsiChar)=@dpmi_dosmemfillchar;
  168. dosmemfillword : procedure(seg,ofs : word;count : longint;w : word)=@dpmi_dosmemfillword;
  169. implementation
  170. {$asmmode ATT}
  171. { the following procedures copy from and to DOS memory using DPMI }
  172. procedure dpmi_dosmemput(seg : word;ofs : word;var data;count : longint);
  173. begin
  174. seg_move(get_ds,longint(@data),dosmemselector,seg*16+ofs,count);
  175. end;
  176. procedure dpmi_dosmemget(seg : word;ofs : word;var data;count : longint);
  177. begin
  178. seg_move(dosmemselector,seg*16+ofs,get_ds,longint(@data),count);
  179. end;
  180. procedure dpmi_dosmemmove(sseg,sofs,dseg,dofs : word;count : longint);
  181. begin
  182. seg_move(dosmemselector,sseg*16+sofs,dosmemselector,dseg*16+dofs,count);
  183. end;
  184. procedure dpmi_dosmemfillchar(seg,ofs : word;count : longint;c : AnsiChar);
  185. begin
  186. seg_fillchar(dosmemselector,seg*16+ofs,count,c);
  187. end;
  188. procedure dpmi_dosmemfillword(seg,ofs : word;count : longint;w : word);
  189. begin
  190. seg_fillword(dosmemselector,seg*16+ofs,count,w);
  191. end;
  192. procedure test_int31(flag : longint); stdcall; { stack-args! }
  193. begin
  194. asm
  195. pushl %ebx
  196. movw $0,INT31ERROR
  197. movl flag,%ebx
  198. testb $1,%bl
  199. jz .Lti31_1
  200. movw %ax,INT31ERROR
  201. xorl %eax,%eax
  202. jmp .Lti31_2
  203. .Lti31_1:
  204. movl $1,%eax
  205. .Lti31_2:
  206. popl %ebx
  207. end;
  208. end;
  209. function global_dos_alloc(bytes : longint) : longint;
  210. begin
  211. asm
  212. pushl %ebx
  213. movl bytes,%ebx
  214. addl $0xf,%ebx // round up
  215. shrl $0x4,%ebx // convert to Paragraphs
  216. movl $0x100,%eax // function 0x100
  217. int $0x31
  218. jnc .LDos_OK
  219. movw %ax,INT31ERROR
  220. xorl %eax,%eax
  221. jmp .LDos_end
  222. .LDos_OK:
  223. shll $0x10,%eax // return Segment in hi(Result)
  224. movw %dx,%ax // return Selector in lo(Result)
  225. .LDos_end:
  226. movl %eax,__result
  227. popl %ebx
  228. end;
  229. end;
  230. function global_dos_free(selector : word) : boolean;
  231. begin
  232. asm
  233. movw Selector,%dx
  234. movl $0x101,%eax
  235. int $0x31
  236. setnc %al
  237. movb %al,__RESULT
  238. end;
  239. end;
  240. function realintr(intnr : word;var regs : trealregs) : boolean;
  241. begin
  242. regs.realsp:=0;
  243. regs.realss:=0;
  244. regs.realres:=0; { play it safe }
  245. asm
  246. { save all used registers to avoid crash under NTVDM }
  247. { when spawning a 32-bit DPMI application }
  248. pushl %edi
  249. pushl %ebx
  250. pushw %fs
  251. movw intnr,%bx
  252. xorl %ecx,%ecx
  253. movl regs,%edi
  254. { es is always equal ds }
  255. movl $0x300,%eax
  256. int $0x31
  257. popw %fs
  258. setnc %al
  259. movb %al,__RESULT
  260. popl %ebx
  261. popl %edi
  262. end;
  263. end;
  264. procedure seg_fillchar(seg : word;ofs : longint;count : longint;c : AnsiChar);
  265. begin
  266. asm
  267. pushl %edi
  268. movl ofs,%edi
  269. movl count,%ecx
  270. movb c,%dl
  271. { load es with selector }
  272. pushw %es
  273. movw seg,%ax
  274. movw %ax,%es
  275. { fill eax with duplicated c }
  276. { so we can use stosl }
  277. movb %dl,%dh
  278. movw %dx,%ax
  279. shll $16,%eax
  280. movw %dx,%ax
  281. movl %ecx,%edx
  282. shrl $2,%ecx
  283. cld
  284. rep
  285. stosl
  286. movl %edx,%ecx
  287. andl $3,%ecx
  288. rep
  289. stosb
  290. popw %es
  291. popl %edi
  292. end;
  293. end;
  294. procedure seg_fillword(seg : word;ofs : longint;count : longint;w : word);
  295. begin
  296. asm
  297. pushl %edi
  298. movl ofs,%edi
  299. movl count,%ecx
  300. movw w,%dx
  301. { load segment }
  302. pushw %es
  303. movw seg,%ax
  304. movw %ax,%es
  305. { fill eax }
  306. movw %dx,%ax
  307. shll $16,%eax
  308. movw %dx,%ax
  309. movl %ecx,%edx
  310. shrl $1,%ecx
  311. cld
  312. rep
  313. stosl
  314. movl %edx,%ecx
  315. andl $1,%ecx
  316. rep
  317. stosw
  318. popw %es
  319. popl %edi
  320. end;
  321. end;
  322. procedure seg_move(sseg : word;source : longint;dseg : word;dest : longint;count : longint);
  323. begin
  324. if count=0 then
  325. exit;
  326. if (sseg<>dseg) or ((sseg=dseg) and (source>dest)) then
  327. asm
  328. pushl %esi
  329. pushl %edi
  330. pushw %es
  331. pushw %ds
  332. cld
  333. movl count,%ecx
  334. movl source,%esi
  335. movl dest,%edi
  336. movw dseg,%ax
  337. movw %ax,%es
  338. movw sseg,%ax
  339. movw %ax,%ds
  340. movl %ecx,%eax
  341. shrl $2,%ecx
  342. rep
  343. movsl
  344. movl %eax,%ecx
  345. andl $3,%ecx
  346. rep
  347. movsb
  348. popw %ds
  349. popw %es
  350. popl %edi
  351. popl %esi
  352. end ['ECX','EAX']
  353. else if (source<dest) then
  354. { copy backward for overlapping }
  355. asm
  356. pushl %esi
  357. pushl %edi
  358. pushw %es
  359. pushw %ds
  360. std
  361. movl count,%ecx
  362. movl source,%esi
  363. movl dest,%edi
  364. movw dseg,%ax
  365. movw %ax,%es
  366. movw sseg,%ax
  367. movw %ax,%ds
  368. addl %ecx,%esi
  369. addl %ecx,%edi
  370. movl %ecx,%eax
  371. andl $3,%ecx
  372. orl %ecx,%ecx
  373. jz .LSEG_MOVE1
  374. { calculate esi and edi}
  375. decl %esi
  376. decl %edi
  377. rep
  378. movsb
  379. incl %esi
  380. incl %edi
  381. .LSEG_MOVE1:
  382. subl $4,%esi
  383. subl $4,%edi
  384. movl %eax,%ecx
  385. shrl $2,%ecx
  386. rep
  387. movsl
  388. cld
  389. popw %ds
  390. popw %es
  391. popl %edi
  392. popl %esi
  393. end ['ECX','EAX'];
  394. end;
  395. procedure outportb(port : word;data : byte);inline;
  396. begin
  397. fpc_x86_outportb(port,data);
  398. end;
  399. procedure outportw(port : word;data : word);inline;
  400. begin
  401. fpc_x86_outportw(port,data);
  402. end;
  403. procedure outportl(port : word;data : longint);inline;
  404. begin
  405. fpc_x86_outportl(port,data);
  406. end;
  407. function inportb(port : word) : byte;inline;
  408. begin
  409. inportb:=fpc_x86_inportb(port);
  410. end;
  411. function inportw(port : word) : word;inline;
  412. begin
  413. inportw:=fpc_x86_inportw(port);
  414. end;
  415. function inportl(port : word) : longint;inline;
  416. begin
  417. inportl:=fpc_x86_inportl(port);
  418. end;
  419. function get_cs : word;assembler;
  420. asm
  421. movw %cs,%ax
  422. end;
  423. function get_ss : word;assembler;
  424. asm
  425. movw %ss,%ax
  426. end;
  427. function get_ds : word;assembler;
  428. asm
  429. movw %ds,%ax
  430. end;
  431. function set_pm_interrupt(vector : byte;const intaddr : tseginfo) : boolean;
  432. begin
  433. asm
  434. pushl %ebx
  435. movl intaddr,%eax
  436. movl (%eax),%edx
  437. movw 4(%eax),%cx
  438. movl $0x205,%eax
  439. movb vector,%bl
  440. int $0x31
  441. pushf
  442. call test_int31
  443. movb %al,__RESULT
  444. popl %ebx
  445. end;
  446. end;
  447. function set_rm_interrupt(vector : byte;const intaddr : tseginfo) : boolean;
  448. begin
  449. asm
  450. pushl %ebx
  451. movl intaddr,%eax
  452. movw (%eax),%dx
  453. movw 4(%eax),%cx
  454. movl $0x201,%eax
  455. movb vector,%bl
  456. int $0x31
  457. pushf
  458. call test_int31
  459. movb %al,__RESULT
  460. popl %ebx
  461. end;
  462. end;
  463. function set_pm_exception_handler(e : byte;const intaddr : tseginfo) : boolean;
  464. begin
  465. asm
  466. pushl %ebx
  467. movl intaddr,%eax
  468. movl (%eax),%edx
  469. movw 4(%eax),%cx
  470. movl $0x212,%eax
  471. movb e,%bl
  472. int $0x31
  473. pushf
  474. call test_int31
  475. movb %al,__RESULT
  476. popl %ebx
  477. end;
  478. end;
  479. function set_exception_handler(e : byte;const intaddr : tseginfo) : boolean;
  480. begin
  481. asm
  482. pushl %ebx
  483. movl intaddr,%eax
  484. movl (%eax),%edx
  485. movw 4(%eax),%cx
  486. movl $0x203,%eax
  487. movb e,%bl
  488. int $0x31
  489. pushf
  490. call test_int31
  491. movb %al,__RESULT
  492. popl %ebx
  493. end;
  494. end;
  495. function get_pm_exception_handler(e : byte;var intaddr : tseginfo) : boolean;
  496. begin
  497. asm
  498. pushl %ebx
  499. movl $0x210,%eax
  500. movb e,%bl
  501. int $0x31
  502. pushf
  503. call test_int31
  504. movb %al,__RESULT
  505. movl intaddr,%eax
  506. movl %edx,(%eax)
  507. movw %cx,4(%eax)
  508. popl %ebx
  509. end;
  510. end;
  511. function get_exception_handler(e : byte;var intaddr : tseginfo) : boolean;
  512. begin
  513. asm
  514. pushl %ebx
  515. movl $0x202,%eax
  516. movb e,%bl
  517. int $0x31
  518. pushf
  519. call test_int31
  520. movb %al,__RESULT
  521. movl intaddr,%eax
  522. movl %edx,(%eax)
  523. movw %cx,4(%eax)
  524. popl %ebx
  525. end;
  526. end;
  527. function get_pm_interrupt(vector : byte;var intaddr : tseginfo) : boolean;
  528. begin
  529. asm
  530. pushl %ebx
  531. movb vector,%bl
  532. movl $0x204,%eax
  533. int $0x31
  534. pushf
  535. call test_int31
  536. movb %al,__RESULT
  537. movl intaddr,%eax
  538. movl %edx,(%eax)
  539. movw %cx,4(%eax)
  540. popl %ebx
  541. end;
  542. end;
  543. function get_rm_interrupt(vector : byte;var intaddr : tseginfo) : boolean;
  544. begin
  545. asm
  546. pushl %ebx
  547. movb vector,%bl
  548. movl $0x200,%eax
  549. int $0x31
  550. pushf
  551. call test_int31
  552. movb %al,__RESULT
  553. movl intaddr,%eax
  554. movzwl %dx,%edx
  555. movl %edx,(%eax)
  556. movw %cx,4(%eax)
  557. popl %ebx
  558. end;
  559. end;
  560. function free_rm_callback(var intaddr : tseginfo) : boolean;
  561. begin
  562. asm
  563. movl intaddr,%eax
  564. movw (%eax),%dx
  565. movw 4(%eax),%cx
  566. movl $0x304,%eax
  567. int $0x31
  568. pushf
  569. call test_int31
  570. movb %al,__RESULT
  571. end;
  572. end;
  573. { here we must use ___v2prt0_ds_alias instead of from v2prt0.s
  574. because the exception processor sets the ds limit to $fff
  575. at hardware exceptions }
  576. var
  577. ___v2prt0_ds_alias : word; external name '___v2prt0_ds_alias';
  578. function get_rm_callback(pm_func : pointer;const reg : trealregs;var rmcb : tseginfo) : boolean;
  579. begin
  580. asm
  581. pushl %esi
  582. pushl %edi
  583. movl pm_func,%esi
  584. movl reg,%edi
  585. pushw %es
  586. movw ___v2prt0_ds_alias,%ax
  587. movw %ax,%es
  588. pushw %ds
  589. movw %cs,%ax
  590. movw %ax,%ds
  591. movl $0x303,%eax
  592. int $0x31
  593. popw %ds
  594. popw %es
  595. pushf
  596. call test_int31
  597. movb %al,__RESULT
  598. movl rmcb,%eax
  599. movzwl %dx,%edx
  600. movl %edx,(%eax)
  601. movw %cx,4(%eax)
  602. popl %edi
  603. popl %esi
  604. end;
  605. end;
  606. function allocate_ldt_descriptors(count : word) : word;
  607. begin
  608. asm
  609. movw count,%cx
  610. xorl %eax,%eax
  611. int $0x31
  612. movw %ax,__RESULT
  613. end;
  614. end;
  615. function free_ldt_descriptor(d : word) : boolean;
  616. begin
  617. asm
  618. pushl %ebx
  619. movw d,%bx
  620. movl $1,%eax
  621. int $0x31
  622. pushf
  623. call test_int31
  624. movb %al,__RESULT
  625. popl %ebx
  626. end;
  627. end;
  628. function segment_to_descriptor(seg : word) : word;
  629. begin
  630. asm
  631. pushl %ebx
  632. movw seg,%bx
  633. movl $2,%eax
  634. int $0x31
  635. movw %ax,__RESULT
  636. popl %ebx
  637. end;
  638. end;
  639. function get_next_selector_increment_value : word;
  640. begin
  641. asm
  642. movl $3,%eax
  643. int $0x31
  644. movw %ax,__RESULT
  645. end;
  646. end;
  647. function get_segment_base_address(d : word) : dword;
  648. begin
  649. asm
  650. pushl %ebx
  651. movw d,%bx
  652. movl $6,%eax
  653. int $0x31
  654. xorl %eax,%eax
  655. movw %dx,%ax
  656. shll $16,%ecx
  657. orl %ecx,%eax
  658. movl %eax,__RESULT
  659. popl %ebx
  660. end;
  661. end;
  662. function get_page_size:longint;
  663. begin
  664. asm
  665. pushl %ebx
  666. movl $0x604,%eax
  667. int $0x31
  668. shll $16,%ebx
  669. movw %cx,%bx
  670. movl %ebx,__RESULT
  671. popl %ebx
  672. end;
  673. end;
  674. function request_linear_region(linearaddr, size : longint;
  675. var blockhandle : longint) : boolean;
  676. var
  677. pageofs : longint;
  678. begin
  679. pageofs:=linearaddr and $3ff;
  680. linearaddr:=linearaddr-pageofs;
  681. size:=size+pageofs;
  682. asm
  683. pushl %ebx
  684. pushl %esi
  685. movl $0x504,%eax
  686. movl linearaddr,%ebx
  687. movl size,%ecx
  688. movl $1,%edx
  689. xorl %esi,%esi
  690. int $0x31
  691. pushf
  692. call test_int31
  693. movb %al,__RESULT
  694. movl blockhandle,%eax
  695. movl %esi,(%eax)
  696. movl %ebx,pageofs
  697. popl %esi
  698. popl %ebx
  699. end;
  700. if pageofs<>linearaddr then
  701. request_linear_region:=false;
  702. end;
  703. function allocate_memory_block(size:longint):longint;
  704. begin
  705. asm
  706. pushl %ebx
  707. pushl %esi
  708. movl $0x501,%eax
  709. movl size,%ecx
  710. movl %ecx,%ebx
  711. shrl $16,%ebx
  712. andl $65535,%ecx
  713. int $0x31
  714. jnc .Lallocate_mem_block_err
  715. xorl %ebx,%ebx
  716. xorl %ecx,%ecx
  717. .Lallocate_mem_block_err:
  718. shll $16,%ebx
  719. movw %cx,%bx
  720. shll $16,%esi
  721. movw %di,%si
  722. movl %ebx,__RESULT
  723. popl %esi
  724. popl %ebx
  725. end;
  726. end;
  727. function free_memory_block(blockhandle : longint) : boolean;
  728. begin
  729. asm
  730. pushl %edi
  731. pushl %esi
  732. movl blockhandle,%esi
  733. movl %esi,%edi
  734. shll $16,%esi
  735. movl $0x502,%eax
  736. int $0x31
  737. pushf
  738. call test_int31
  739. movb %al,__RESULT
  740. popl %esi
  741. popl %edi
  742. end;
  743. end;
  744. function lock_linear_region(linearaddr, size : longint) : boolean;
  745. begin
  746. asm
  747. pushl %ebx
  748. pushl %edi
  749. pushl %esi
  750. movl $0x600,%eax
  751. movl linearaddr,%ecx
  752. movl %ecx,%ebx
  753. shrl $16,%ebx
  754. movl size,%esi
  755. movl %esi,%edi
  756. shrl $16,%esi
  757. int $0x31
  758. pushf
  759. call test_int31
  760. movb %al,__RESULT
  761. popl %esi
  762. popl %edi
  763. popl %ebx
  764. end;
  765. end;
  766. function lock_data(var data;size : longint) : boolean;
  767. var
  768. linearaddr : dword;
  769. begin
  770. if get_run_mode<>rm_dpmi then
  771. exit;
  772. linearaddr:=dword(@data)+get_segment_base_address(get_ds);
  773. lock_data:=lock_linear_region(linearaddr,size);
  774. end;
  775. function lock_code(functionaddr : pointer;size : longint) : boolean;
  776. var
  777. linearaddr : dword;
  778. begin
  779. if get_run_mode<>rm_dpmi then
  780. exit;
  781. linearaddr:=dword(functionaddr)+get_segment_base_address(get_cs);
  782. lock_code:=lock_linear_region(linearaddr,size);
  783. end;
  784. function unlock_linear_region(linearaddr,size : longint) : boolean;
  785. begin
  786. asm
  787. pushl %ebx
  788. pushl %edi
  789. pushl %esi
  790. movl $0x601,%eax
  791. movl linearaddr,%ecx
  792. movl %ecx,%ebx
  793. shrl $16,%ebx
  794. movl size,%esi
  795. movl %esi,%edi
  796. shrl $16,%esi
  797. int $0x31
  798. pushf
  799. call test_int31
  800. movb %al,__RESULT
  801. popl %esi
  802. popl %edi
  803. popl %ebx
  804. end;
  805. end;
  806. function unlock_data(var data;size : longint) : boolean;
  807. var
  808. linearaddr : dword;
  809. begin
  810. if get_run_mode<>rm_dpmi then
  811. exit;
  812. linearaddr:=dword(@data)+get_segment_base_address(get_ds);
  813. unlock_data:=unlock_linear_region(linearaddr,size);
  814. end;
  815. function unlock_code(functionaddr : pointer;size : longint) : boolean;
  816. var
  817. linearaddr : dword;
  818. begin
  819. if get_run_mode<>rm_dpmi then
  820. exit;
  821. linearaddr:=dword(functionaddr)+get_segment_base_address(get_cs);
  822. unlock_code:=unlock_linear_region(linearaddr,size);
  823. end;
  824. function set_segment_base_address(d : word;s : dword) : boolean;
  825. begin
  826. asm
  827. pushl %ebx
  828. movw d,%bx
  829. leal s,%eax
  830. movw (%eax),%dx
  831. movw 2(%eax),%cx
  832. movl $7,%eax
  833. int $0x31
  834. pushf
  835. call test_int31
  836. movb %al,__RESULT
  837. popl %ebx
  838. end;
  839. end;
  840. function set_descriptor_access_right(d : word;w : word) : boolean;
  841. begin
  842. asm
  843. pushl %ebx
  844. movw d,%bx
  845. movw w,%cx
  846. movl $9,%eax
  847. int $0x31
  848. pushf
  849. call test_int31
  850. movb %al,__RESULT
  851. popl %ebx
  852. end;
  853. end;
  854. function set_segment_limit(d : word;s : dword) : boolean;
  855. begin
  856. asm
  857. pushl %ebx
  858. movw d,%bx
  859. leal s,%eax
  860. movw (%eax),%dx
  861. movw 2(%eax),%cx
  862. movl $8,%eax
  863. int $0x31
  864. pushf
  865. call test_int31
  866. movb %al,__RESULT
  867. popl %ebx
  868. end;
  869. end;
  870. function get_descriptor_access_right(d : word) : longint;
  871. begin
  872. asm
  873. movzwl d,%eax
  874. lar %eax,%eax
  875. jz .L_ok
  876. xorl %eax,%eax
  877. .L_ok:
  878. movl %eax,__RESULT
  879. end;
  880. end;
  881. function get_segment_limit(d : word) : dword;
  882. begin
  883. asm
  884. movzwl d,%eax
  885. lsl %eax,%eax
  886. jz .L_ok2
  887. xorl %eax,%eax
  888. .L_ok2:
  889. movl %eax,__RESULT
  890. end;
  891. end;
  892. function create_code_segment_alias_descriptor(seg : word) : word;
  893. begin
  894. asm
  895. pushl %ebx
  896. movw seg,%bx
  897. movl $0xa,%eax
  898. int $0x31
  899. pushf
  900. call test_int31
  901. movw %ax,__RESULT
  902. popl %ebx
  903. end;
  904. end;
  905. function get_meminfo(var meminfo : tmeminfo) : boolean;
  906. begin
  907. asm
  908. pushl %edi
  909. movl meminfo,%edi
  910. movl $0x500,%eax
  911. int $0x31
  912. pushf
  913. movb %al,__RESULT
  914. call test_int31
  915. popl %edi
  916. end;
  917. end;
  918. function get_linear_addr(phys_addr : dword;size : longint) : dword;
  919. begin
  920. asm
  921. pushl %ebx
  922. pushl %edi
  923. pushl %esi
  924. movl phys_addr,%ebx
  925. movl %ebx,%ecx
  926. shrl $16,%ebx
  927. movl size,%esi
  928. movl %esi,%edi
  929. shrl $16,%esi
  930. movl $0x800,%eax
  931. int $0x31
  932. pushf
  933. call test_int31
  934. shll $16,%ebx
  935. movw %cx,%bx
  936. movl %ebx,__RESULT
  937. popl %esi
  938. popl %edi
  939. popl %ebx
  940. end;
  941. end;
  942. function free_linear_addr_mapping(linear_addr: dword): boolean;
  943. begin
  944. asm
  945. pushl %ebx
  946. pushl %ecx
  947. movl linear_addr,%ebx
  948. movl %ebx,%ecx
  949. shrl $16,%ebx
  950. movl $0x801,%eax
  951. int $0x31
  952. pushf
  953. call test_int31
  954. movb %al,__RESULT
  955. popl %ecx
  956. popl %ebx
  957. end;
  958. end;
  959. procedure disable;inline;
  960. begin
  961. fpc_x86_cli;
  962. end;
  963. procedure enable;inline;
  964. begin
  965. fpc_x86_sti;
  966. end;
  967. var
  968. _run_mode : word;external name '_run_mode';
  969. function get_run_mode : word;
  970. begin
  971. get_run_mode:=_run_mode;
  972. end;
  973. function map_device_in_memory_block(handle,offset,pagecount,device:dword):boolean;
  974. begin
  975. asm
  976. pushl %ebx
  977. pushl %edi
  978. pushl %esi
  979. movl device,%edx
  980. movl handle,%esi
  981. movl offset,%ebx
  982. movl pagecount,%ecx
  983. movl $0x0508,%eax
  984. int $0x31
  985. pushf
  986. call test_int31
  987. movb %al,__RESULT
  988. popl %esi
  989. popl %edi
  990. popl %ebx
  991. end;
  992. end;
  993. function get_page_attributes(handle, offset, pagecount: dword; buf: pointer): boolean;
  994. begin
  995. asm
  996. pushl %ebx
  997. pushl %ecx
  998. pushl %edx
  999. pushl %esi
  1000. pushw %es
  1001. pushw %ds
  1002. popw %es
  1003. movl buf,%edx
  1004. movl handle,%esi
  1005. movl offset,%ebx
  1006. movl pagecount,%ecx
  1007. movl $0x0506,%eax
  1008. int $0x31
  1009. pushf
  1010. call test_int31
  1011. movb %al,__RESULT
  1012. popw %es
  1013. popl %esi
  1014. popl %edx
  1015. popl %ecx
  1016. popl %ebx
  1017. end;
  1018. end;
  1019. function set_page_attributes(handle, offset, pagecount: dword; buf: pointer): boolean;
  1020. begin
  1021. asm
  1022. pushl %ebx
  1023. pushl %ecx
  1024. pushl %edx
  1025. pushl %esi
  1026. pushw %es
  1027. pushw %ds
  1028. popw %es
  1029. movl buf,%edx
  1030. movl handle,%esi
  1031. movl offset,%ebx
  1032. movl pagecount,%ecx
  1033. movl $0x0507,%eax
  1034. int $0x31
  1035. pushf
  1036. call test_int31
  1037. movb %al,__RESULT
  1038. popw %es
  1039. popl %esi
  1040. popl %edx
  1041. popl %ecx
  1042. popl %ebx
  1043. end;
  1044. end;
  1045. function get_dpmi_version(var version: tdpmiversioninfo): boolean;
  1046. var
  1047. _version, _flags, _cpu, _pic: word;
  1048. begin
  1049. asm
  1050. movl $0x0400,%eax
  1051. int $0x31
  1052. pushf
  1053. movw %ax,_version
  1054. movw %bx,_flags
  1055. movw %cx,_cpu
  1056. movw %dx,_pic
  1057. call test_int31
  1058. movb %al,__RESULT
  1059. end ['EAX','EBX','ECX','EDX'];
  1060. if get_dpmi_version then
  1061. begin
  1062. FillChar(version, SizeOf(version), 0);
  1063. version.major := _version shr 8;
  1064. version.minor := _version and $ff;
  1065. version.flags := _flags;
  1066. version.cpu := _cpu and $ff;
  1067. version.master_pic := _pic shr 8;
  1068. version.slave_pic := _pic and $ff;
  1069. end;
  1070. end;
  1071. {*****************************************************************************
  1072. Transfer Buffer
  1073. *****************************************************************************}
  1074. function transfer_buffer : longint;
  1075. begin
  1076. transfer_buffer := go32_info_block.linear_address_of_transfer_buffer;
  1077. end;
  1078. function tb_segment : longint;
  1079. begin
  1080. tb_segment:=go32_info_block.linear_address_of_transfer_buffer shr 4;
  1081. end;
  1082. function tb_offset : longint;
  1083. begin
  1084. tb_offset:=go32_info_block.linear_address_of_transfer_buffer and $f;
  1085. end;
  1086. function tb_size : longint;
  1087. begin
  1088. tb_size := go32_info_block.size_of_transfer_buffer;
  1089. end;
  1090. procedure copytodos(var addr; len : longint);
  1091. begin
  1092. if len>tb_size then
  1093. runerror(217);
  1094. seg_move(get_ds,longint(@addr),dosmemselector,transfer_buffer,len);
  1095. end;
  1096. procedure copyfromdos(var addr; len : longint);
  1097. begin
  1098. if len>tb_size then
  1099. runerror(217);
  1100. seg_move(dosmemselector,transfer_buffer,get_ds,longint(@addr),len);
  1101. end;
  1102. var
  1103. _core_selector : word;external name '_core_selector';
  1104. begin
  1105. int31error:=0;
  1106. dosmemselector:=_core_selector;
  1107. end.