go32.pp 32 KB

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