go32.pp 31 KB

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