go32.pp 33 KB

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