go32.pp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272
  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. {$S-}{no stack check, used by DPMIEXCP !! }
  14. {$i os.inc}
  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 inportb(port : word) : byte;
  132. function inportw(port : word) : word;
  133. function inportl(port : word) : longint;
  134. procedure outportb(port : word;data : byte);
  135. procedure outportw(port : word;data : word);
  136. procedure outportl(port : word;data : longint);
  137. function get_run_mode : word;
  138. {$ifndef V0_6}
  139. function transfer_buffer : longint;
  140. function tb_size : longint;
  141. procedure copytodos(var addr; len : longint);
  142. procedure copyfromdos(var addr; len : longint);
  143. {$endif not VER0_6}
  144. procedure dpmi_dosmemput(seg : word;ofs : word;var data;count : longint);
  145. procedure dpmi_dosmemget(seg : word;ofs : word;var data;count : longint);
  146. procedure dpmi_dosmemmove(sseg,sofs,dseg,dofs : word;count : longint);
  147. procedure dpmi_dosmemfillchar(seg,ofs : word;count : longint;c : char);
  148. procedure dpmi_dosmemfillword(seg,ofs : word;count : longint;w : word);
  149. const
  150. { this procedures are assigned to the procedure which are needed }
  151. { for the current mode to access DOS memory }
  152. { It's strongly recommended to use this procedures! }
  153. dosmemput : procedure(seg : word;ofs : word;var data;count : longint)=dpmi_dosmemput;
  154. dosmemget : procedure(seg : word;ofs : word;var data;count : longint)=dpmi_dosmemget;
  155. dosmemmove : procedure(sseg,sofs,dseg,dofs : word;count : longint)=dpmi_dosmemmove;
  156. dosmemfillchar : procedure(seg,ofs : word;count : longint;c : char)=dpmi_dosmemfillchar;
  157. dosmemfillword : procedure(seg,ofs : word;count : longint;w : word)=dpmi_dosmemfillword;
  158. {$ifdef SUPPORT_PORT}
  159. type
  160. tport = class
  161. procedure writeport(p : word;data : byte);
  162. function readport(p : word) : byte;
  163. property pp[w : word] : byte read readport write writeport;default;
  164. end;
  165. tportw = class
  166. procedure writeport(p : word;data : word);
  167. function readport(p : word) : word;
  168. property pp[w : word] : word read readport write writeport;default;
  169. end;
  170. tportl = class
  171. procedure writeport(p : word;data : longint);
  172. function readport(p : word) : longint;
  173. property pp[w : word] : longint read readport write writeport;default;
  174. end;
  175. var
  176. { we don't need to initialize port, because neither member
  177. variables nor virtual methods are accessed
  178. }
  179. port,portb : tport;
  180. portw : tportw;
  181. portl : tportl;
  182. {$endif SUPPORT_PORT}
  183. implementation
  184. {$ifndef go32v2}
  185. { the following procedures copy from and to DOS memory without DPMI,
  186. these are not necessary for go32v2, becuase that requires dpmi (PFV) }
  187. procedure raw_dosmemput(seg : word;ofs : word;var data;count : longint);
  188. begin
  189. move(data,pointer($e0000000+seg*16+ofs)^,count);
  190. end;
  191. procedure raw_dosmemget(seg : word;ofs : word;var data;count : longint);
  192. begin
  193. move(pointer($e0000000+seg*16+ofs)^,data,count);
  194. end;
  195. procedure raw_dosmemmove(sseg,sofs,dseg,dofs : word;count : longint);
  196. begin
  197. move(pointer($e0000000+sseg*16+sofs)^,pointer($e0000000+dseg*16+dofs)^,count);
  198. end;
  199. procedure raw_dosmemfillchar(seg,ofs : word;count : longint;c : char);
  200. begin
  201. fillchar(pointer($e0000000+seg*16+ofs)^,count,c);
  202. end;
  203. procedure raw_dosmemfillword(seg,ofs : word;count : longint;w : word);
  204. begin
  205. fillword(pointer($e0000000+seg*16+ofs)^,count,w);
  206. end;
  207. {$endif}
  208. { the following procedures copy from and to DOS memory using DPMI }
  209. procedure dpmi_dosmemput(seg : word;ofs : word;var data;count : longint);
  210. begin
  211. seg_move(get_ds,longint(@data),dosmemselector,seg*16+ofs,count);
  212. end;
  213. procedure dpmi_dosmemget(seg : word;ofs : word;var data;count : longint);
  214. begin
  215. seg_move(dosmemselector,seg*16+ofs,get_ds,longint(@data),count);
  216. end;
  217. procedure dpmi_dosmemmove(sseg,sofs,dseg,dofs : word;count : longint);
  218. begin
  219. seg_move(dosmemselector,sseg*16+sofs,dosmemselector,dseg*16+dofs,count);
  220. end;
  221. procedure dpmi_dosmemfillchar(seg,ofs : word;count : longint;c : char);
  222. begin
  223. seg_fillchar(dosmemselector,seg*16+ofs,count,c);
  224. end;
  225. procedure dpmi_dosmemfillword(seg,ofs : word;count : longint;w : word);
  226. begin
  227. seg_fillword(dosmemselector,seg*16+ofs,count,w);
  228. end;
  229. function global_dos_alloc(bytes : longint) : longint;
  230. begin
  231. asm
  232. movl bytes,%ebx
  233. orl $0x10,%ebx // round up
  234. shrl $0x4,%ebx // convert to Paragraphs
  235. movl $0x100,%eax // function 0x100
  236. int $0x31
  237. shll $0x10,%eax // return Segment in hi(Result)
  238. movw %dx,%ax // return Selector in lo(Result)
  239. movl %eax,__result
  240. end;
  241. end;
  242. function global_dos_free(selector : word) : boolean;
  243. begin
  244. asm
  245. movw Selector,%dx
  246. movl $0x101,%eax
  247. int $0x31
  248. setnc %al
  249. movb %al,__RESULT
  250. end;
  251. end;
  252. function realintr(intnr : word;var regs : trealregs) : boolean;
  253. begin
  254. regs.realsp:=0;
  255. regs.realss:=0;
  256. asm
  257. movw intnr,%bx
  258. xorl %ecx,%ecx
  259. movl regs,%edi
  260. { es is always equal ds }
  261. movl $0x300,%eax
  262. int $0x31
  263. setnc %al
  264. movb %al,__RESULT
  265. end;
  266. end;
  267. procedure seg_fillchar(seg : word;ofs : longint;count : longint;c : char);
  268. begin
  269. asm
  270. movl ofs,%edi
  271. movl count,%ecx
  272. movb c,%dl
  273. { load es with selector }
  274. pushw %es
  275. movw seg,%ax
  276. movw %ax,%es
  277. { fill eax with duplicated c }
  278. { so we can use stosl }
  279. movb %dl,%dh
  280. movw %dx,%ax
  281. shll $16,%eax
  282. movw %dx,%ax
  283. movl %ecx,%edx
  284. shrl $2,%ecx
  285. cld
  286. rep
  287. stosl
  288. movl %edx,%ecx
  289. andl $3,%ecx
  290. rep
  291. stosb
  292. popw %es
  293. end ['EAX','ECX','EDX','EDI'];
  294. end;
  295. procedure seg_fillword(seg : word;ofs : longint;count : longint;w : word);
  296. begin
  297. asm
  298. movl ofs,%edi
  299. movl count,%ecx
  300. movw w,%dx
  301. { load segment }
  302. pushw %es
  303. movw seg,%ax
  304. movw %ax,%es
  305. { fill eax }
  306. movw %dx,%ax
  307. shll $16,%eax
  308. movw %dx,%ax
  309. movl %ecx,%edx
  310. shrl $1,%ecx
  311. cld
  312. rep
  313. stosl
  314. movl %edx,%ecx
  315. andl $1,%ecx
  316. rep
  317. stosw
  318. popw %es
  319. end ['EAX','ECX','EDX','EDI'];
  320. end;
  321. procedure seg_move(sseg : word;source : longint;dseg : word;dest : longint;count : longint);
  322. begin
  323. if count=0 then
  324. exit;
  325. if (sseg<>dseg) or ((sseg=dseg) and (source>dest)) then
  326. asm
  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. end ['ESI','EDI','ECX','EAX']
  348. else if (source<dest) then
  349. { copy backward for overlapping }
  350. asm
  351. pushw %es
  352. pushw %ds
  353. std
  354. movl count,%ecx
  355. movl source,%esi
  356. movl dest,%edi
  357. movw dseg,%ax
  358. movw %ax,%es
  359. movw sseg,%ax
  360. movw %ax,%ds
  361. addl %ecx,%esi
  362. addl %ecx,%edi
  363. movl %ecx,%eax
  364. andl $3,%ecx
  365. orl %ecx,%ecx
  366. jz .LSEG_MOVE1
  367. { calculate esi and edi}
  368. decl %esi
  369. decl %edi
  370. rep
  371. movsb
  372. incl %esi
  373. incl %edi
  374. .LSEG_MOVE1:
  375. subl $4,%esi
  376. subl $4,%edi
  377. movl %eax,%ecx
  378. shrl $2,%ecx
  379. rep
  380. movsl
  381. cld
  382. popw %ds
  383. popw %es
  384. end ['ESI','EDI','ECX'];
  385. end;
  386. procedure outportb(port : word;data : byte);
  387. begin
  388. asm
  389. movw port,%dx
  390. movb data,%al
  391. outb %al,%dx
  392. end ['EAX','EDX'];
  393. end;
  394. procedure outportw(port : word;data : word);
  395. begin
  396. asm
  397. movw port,%dx
  398. movw data,%ax
  399. outw %ax,%dx
  400. end ['EAX','EDX'];
  401. end;
  402. procedure outportl(port : word;data : longint);
  403. begin
  404. asm
  405. movw port,%dx
  406. movl data,%eax
  407. outl %eax,%dx
  408. end ['EAX','EDX'];
  409. end;
  410. function inportb(port : word) : byte;
  411. begin
  412. asm
  413. movw port,%dx
  414. inb %dx,%al
  415. movb %al,__RESULT
  416. end ['EAX','EDX'];
  417. end;
  418. function inportw(port : word) : word;
  419. begin
  420. asm
  421. movw port,%dx
  422. inw %dx,%ax
  423. movw %ax,__RESULT
  424. end ['EAX','EDX'];
  425. end;
  426. function inportl(port : word) : longint;
  427. begin
  428. asm
  429. movw port,%dx
  430. inl %dx,%eax
  431. movl %eax,__RESULT
  432. end ['EAX','EDX'];
  433. end;
  434. function get_cs : word;
  435. begin
  436. asm
  437. movw %cs,%ax
  438. movw %ax,__RESULT;
  439. end;
  440. end;
  441. function get_ss : word;
  442. begin
  443. asm
  444. movw %ss,%ax
  445. movw %ax,__RESULT;
  446. end;
  447. end;
  448. function get_ds : word;
  449. begin
  450. asm
  451. movw %ds,%ax
  452. movw %ax,__RESULT;
  453. end;
  454. end;
  455. procedure test_int31(flag : longint);[alias : 'test_int31'];
  456. begin
  457. asm
  458. pushl %ebx
  459. movw $0,U_GO32_INT31ERROR
  460. movl flag,%ebx
  461. testb $1,%bl
  462. jz 1f
  463. movw %ax,U_GO32_INT31ERROR
  464. xorl %eax,%eax
  465. jmp 2f
  466. 1:
  467. movl $1,%eax
  468. 2:
  469. popl %ebx
  470. end;
  471. end;
  472. function set_pm_interrupt(vector : byte;const intaddr : tseginfo) : boolean;
  473. begin
  474. asm
  475. movl intaddr,%eax
  476. movl (%eax),%edx
  477. movw 4(%eax),%cx
  478. movl $0x205,%eax
  479. movb vector,%bl
  480. int $0x31
  481. pushf
  482. call test_int31
  483. movb %al,__RESULT
  484. end;
  485. end;
  486. function set_rm_interrupt(vector : byte;const intaddr : tseginfo) : boolean;
  487. begin
  488. asm
  489. movl intaddr,%eax
  490. movw (%eax),%dx
  491. movw 4(%eax),%cx
  492. movl $0x201,%eax
  493. movb vector,%bl
  494. int $0x31
  495. pushf
  496. call test_int31
  497. movb %al,__RESULT
  498. end;
  499. end;
  500. function set_pm_exception_handler(e : byte;const intaddr : tseginfo) : boolean;
  501. begin
  502. asm
  503. movl intaddr,%eax
  504. movl (%eax),%edx
  505. movw 4(%eax),%cx
  506. movl $0x212,%eax
  507. movb e,%bl
  508. int $0x31
  509. pushf
  510. call test_int31
  511. movb %al,__RESULT
  512. end;
  513. end;
  514. function set_exception_handler(e : byte;const intaddr : tseginfo) : boolean;
  515. begin
  516. asm
  517. movl intaddr,%eax
  518. movl (%eax),%edx
  519. movw 4(%eax),%cx
  520. movl $0x203,%eax
  521. movb e,%bl
  522. int $0x31
  523. pushf
  524. call test_int31
  525. movb %al,__RESULT
  526. end;
  527. end;
  528. function get_pm_exception_handler(e : byte;var intaddr : tseginfo) : boolean;
  529. begin
  530. asm
  531. movl $0x210,%eax
  532. movb e,%bl
  533. int $0x31
  534. pushf
  535. call test_int31
  536. movb %al,__RESULT
  537. movl intaddr,%eax
  538. movl %edx,(%eax)
  539. movw %cx,4(%eax)
  540. end;
  541. end;
  542. function get_exception_handler(e : byte;var intaddr : tseginfo) : boolean;
  543. begin
  544. asm
  545. movl $0x202,%eax
  546. movb e,%bl
  547. int $0x31
  548. pushf
  549. call test_int31
  550. movb %al,__RESULT
  551. movl intaddr,%eax
  552. movl %edx,(%eax)
  553. movw %cx,4(%eax)
  554. end;
  555. end;
  556. function get_pm_interrupt(vector : byte;var intaddr : tseginfo) : boolean;
  557. begin
  558. asm
  559. movb vector,%bl
  560. movl $0x204,%eax
  561. int $0x31
  562. pushf
  563. call test_int31
  564. movb %al,__RESULT
  565. movl intaddr,%eax
  566. movl %edx,(%eax)
  567. movw %cx,4(%eax)
  568. end;
  569. end;
  570. function get_rm_interrupt(vector : byte;var intaddr : tseginfo) : boolean;
  571. begin
  572. asm
  573. movb vector,%bl
  574. movl $0x200,%eax
  575. int $0x31
  576. pushf
  577. call test_int31
  578. movb %al,__RESULT
  579. movl intaddr,%eax
  580. movzwl %dx,%edx
  581. movl %edx,(%eax)
  582. movw %cx,4(%eax)
  583. end;
  584. end;
  585. function free_rm_callback(var intaddr : tseginfo) : boolean;
  586. begin
  587. asm
  588. movl intaddr,%eax
  589. movw (%eax),%dx
  590. movw 4(%eax),%cx
  591. movl $0x304,%eax
  592. int $0x31
  593. pushf
  594. call test_int31
  595. movb %al,__RESULT
  596. end;
  597. end;
  598. { here we must use ___v2prt0_ds_alias instead of from v2prt0.s
  599. because the exception processor sets the ds limit to $fff
  600. at hardware exceptions }
  601. function get_rm_callback(pm_func : pointer;const reg : trealregs;var rmcb : tseginfo) : boolean;
  602. begin
  603. asm
  604. movl pm_func,%esi
  605. movl reg,%edi
  606. pushw %es
  607. {$ifdef GO32V2}
  608. movw ___v2prt0_ds_alias,%ax
  609. {$else GO32V2}
  610. movw %ds,%ax
  611. {$endif GO32V2}
  612. movw %ax,%es
  613. pushw %ds
  614. movw %cs,%ax
  615. movw %ax,%ds
  616. movl $0x303,%eax
  617. int $0x31
  618. popw %ds
  619. popw %es
  620. pushf
  621. call test_int31
  622. movb %al,__RESULT
  623. movl rmcb,%eax
  624. movzwl %dx,%edx
  625. movl %edx,(%eax)
  626. movw %cx,4(%eax)
  627. end;
  628. end;
  629. function allocate_ldt_descriptors(count : word) : word;
  630. begin
  631. asm
  632. movw count,%cx
  633. xorl %eax,%eax
  634. int $0x31
  635. movw %ax,__RESULT
  636. end;
  637. end;
  638. function free_ldt_descriptor(d : word) : boolean;
  639. begin
  640. asm
  641. movw d,%bx
  642. movl $1,%eax
  643. int $0x31
  644. pushf
  645. call test_int31
  646. movb %al,__RESULT
  647. end;
  648. end;
  649. function segment_to_descriptor(seg : word) : word;
  650. begin
  651. asm
  652. movw seg,%bx
  653. movl $2,%eax
  654. int $0x31
  655. movw %ax,__RESULT
  656. end;
  657. end;
  658. function get_next_selector_increment_value : word;
  659. begin
  660. asm
  661. movl $3,%eax
  662. int $0x31
  663. movw %ax,__RESULT
  664. end;
  665. end;
  666. function get_segment_base_address(d : word) : longint;
  667. begin
  668. asm
  669. movw d,%bx
  670. movl $6,%eax
  671. int $0x31
  672. xorl %eax,%eax
  673. movw %dx,%ax
  674. shll $16,%ecx
  675. orl %ecx,%eax
  676. movl %eax,__RESULT
  677. end;
  678. end;
  679. function get_page_size:longint;
  680. begin
  681. asm
  682. movl $0x604,%eax
  683. int $0x31
  684. shll $16,%ebx
  685. movw %cx,%bx
  686. movl %ebx,__RESULT
  687. end;
  688. end;
  689. function request_linear_region(linearaddr, size : longint;
  690. var blockhandle : longint) : boolean;
  691. var
  692. pageofs : longint;
  693. begin
  694. pageofs:=linearaddr and $3ff;
  695. linearaddr:=linearaddr-pageofs;
  696. size:=size+pageofs;
  697. asm
  698. movl $0x504,%eax
  699. movl linearaddr,%ebx
  700. movl size,%ecx
  701. movl $1,%edx
  702. xorl %esi,%esi
  703. int $0x31
  704. pushf
  705. call test_int31
  706. movb %al,__RESULT
  707. movl blockhandle,%eax
  708. movl %esi,(%eax)
  709. movl %ebx,pageofs
  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. movl $0x501,%eax
  718. movl size,%ecx
  719. movl %ecx,%ebx
  720. shrl $16,%ebx
  721. andl $65535,%ecx
  722. int $0x31
  723. jnc .Lallocate_mem_block_err
  724. xorl %ebx,%ebx
  725. xorl %ecx,%ecx
  726. .Lallocate_mem_block_err:
  727. shll $16,%ebx
  728. movw %cx,%bx
  729. shll $16,%esi
  730. movw %di,%si
  731. movl %ebx,__RESULT
  732. end;
  733. end;
  734. function free_memory_block(blockhandle : longint) : boolean;
  735. begin
  736. asm
  737. movl blockhandle,%esi
  738. movl %esi,%edi
  739. shll $16,%esi
  740. movl $0x502,%eax
  741. int $0x31
  742. pushf
  743. call test_int31
  744. movb %al,__RESULT
  745. end;
  746. end;
  747. function lock_linear_region(linearaddr, size : longint) : boolean;
  748. begin
  749. asm
  750. movl $0x600,%eax
  751. movl linearaddr,%ecx
  752. movl %ecx,%ebx
  753. shrl $16,%ebx
  754. movl size,%esi
  755. movl %esi,%edi
  756. shrl $16,%esi
  757. int $0x31
  758. pushf
  759. call test_int31
  760. movb %al,__RESULT
  761. end;
  762. end;
  763. function lock_data(var data;size : longint) : boolean;
  764. var
  765. linearaddr : longint;
  766. begin
  767. if get_run_mode <> 4 then
  768. exit;
  769. linearaddr:=longint(@data)+get_segment_base_address(get_ds);
  770. lock_data:=lock_linear_region(linearaddr,size);
  771. end;
  772. function lock_code(functionaddr : pointer;size : longint) : boolean;
  773. var
  774. linearaddr : longint;
  775. begin
  776. if get_run_mode<>rm_dpmi then
  777. exit;
  778. linearaddr:=longint(functionaddr)+get_segment_base_address(get_cs);
  779. lock_code:=lock_linear_region(linearaddr,size);
  780. end;
  781. function unlock_linear_region(linearaddr,size : longint) : boolean;
  782. begin
  783. asm
  784. movl $0x601,%eax
  785. movl linearaddr,%ecx
  786. movl %ecx,%ebx
  787. shrl $16,%ebx
  788. movl size,%esi
  789. movl %esi,%edi
  790. shrl $16,%esi
  791. int $0x31
  792. pushf
  793. call test_int31
  794. movb %al,__RESULT
  795. end;
  796. end;
  797. function unlock_data(var data;size : longint) : boolean;
  798. var
  799. linearaddr : longint;
  800. begin
  801. if get_run_mode<>rm_dpmi then
  802. exit;
  803. linearaddr:=longint(@data)+get_segment_base_address(get_ds);
  804. unlock_data:=unlock_linear_region(linearaddr,size);
  805. end;
  806. function unlock_code(functionaddr : pointer;size : longint) : boolean;
  807. var
  808. linearaddr : longint;
  809. begin
  810. if get_run_mode <>rm_dpmi then
  811. exit;
  812. linearaddr:=longint(functionaddr)+get_segment_base_address(get_cs);
  813. unlock_code:=unlock_linear_region(linearaddr,size);
  814. end;
  815. function set_segment_base_address(d : word;s : longint) : boolean;
  816. begin
  817. asm
  818. movw d,%bx
  819. leal s,%eax
  820. movw (%eax),%dx
  821. movw 2(%eax),%cx
  822. movl $7,%eax
  823. int $0x31
  824. pushf
  825. call test_int31
  826. movb %al,__RESULT
  827. end;
  828. end;
  829. function set_descriptor_access_right(d : word;w : word) : longint;
  830. begin
  831. asm
  832. movw d,%bx
  833. movw w,%cx
  834. movl $9,%eax
  835. int $0x31
  836. pushf
  837. call test_int31
  838. movw %ax,__RESULT
  839. end;
  840. end;
  841. function set_segment_limit(d : word;s : longint) : boolean;
  842. begin
  843. asm
  844. movw d,%bx
  845. leal s,%eax
  846. movw (%eax),%dx
  847. movw 2(%eax),%cx
  848. movl $8,%eax
  849. int $0x31
  850. pushf
  851. call test_int31
  852. movb %al,__RESULT
  853. end;
  854. end;
  855. function get_descriptor_access_right(d : word) : longint;
  856. begin
  857. asm
  858. movzwl d,%eax
  859. lar %eax,%eax
  860. jz .L_ok
  861. xorl %eax,%eax
  862. .L_ok:
  863. movl %eax,__RESULT
  864. end;
  865. end;
  866. function get_segment_limit(d : word) : longint;
  867. begin
  868. asm
  869. movzwl d,%eax
  870. lsl %eax,%eax
  871. jz .L_ok2
  872. xorl %eax,%eax
  873. .L_ok2:
  874. movl %eax,__RESULT
  875. end;
  876. end;
  877. function create_code_segment_alias_descriptor(seg : word) : word;
  878. begin
  879. asm
  880. movw seg,%bx
  881. movl $0xa,%eax
  882. int $0x31
  883. pushf
  884. call test_int31
  885. movw %ax,__RESULT
  886. end;
  887. end;
  888. function get_meminfo(var meminfo : tmeminfo) : boolean;
  889. begin
  890. asm
  891. movl meminfo,%edi
  892. movl $0x500,%eax
  893. int $0x31
  894. pushf
  895. movb %al,__RESULT
  896. call test_int31
  897. end;
  898. end;
  899. function get_linear_addr(phys_addr : longint;size : longint) : longint;
  900. begin
  901. asm
  902. movl phys_addr,%ebx
  903. movl %ebx,%ecx
  904. shrl $16,%ebx
  905. movl size,%esi
  906. movl %esi,%edi
  907. shrl $16,%esi
  908. movl $0x800,%eax
  909. int $0x31
  910. pushf
  911. call test_int31
  912. shll $16,%ebx
  913. movw %cx,%bx
  914. movl %ebx,__RESULT
  915. end;
  916. end;
  917. procedure disable;assembler;
  918. asm
  919. cli
  920. end;
  921. procedure enable;assembler;
  922. asm
  923. sti
  924. end;
  925. function get_run_mode : word;
  926. begin
  927. asm
  928. movw _run_mode,%ax
  929. movw %ax,__RESULT
  930. end ['EAX'];
  931. end;
  932. function map_device_in_memory_block(handle,offset,pagecount,device:longint):boolean;
  933. begin
  934. asm
  935. movl device,%edx
  936. movl handle,%esi
  937. xorl %ebx,%ebx
  938. movl pagecount,%ecx
  939. movl $0x0508,%eax
  940. int $0x31
  941. pushf
  942. setnc %al
  943. movb %al,__RESULT
  944. call test_int31
  945. end;
  946. end;
  947. function get_core_selector : word;
  948. begin
  949. asm
  950. movw _core_selector,%ax
  951. movw %ax,__RESULT
  952. end;
  953. end;
  954. {$ifndef V0_6}
  955. function transfer_buffer : longint;
  956. begin
  957. transfer_buffer := go32_info_block.linear_address_of_transfer_buffer;
  958. end;
  959. function tb_size : longint;
  960. begin
  961. tb_size := go32_info_block.size_of_transfer_buffer;
  962. end;
  963. procedure copytodos(var addr; len : longint);
  964. begin
  965. if len>tb_size then runerror(217);
  966. {$ifdef GO32V2}
  967. seg_move(get_ds,longint(@addr),dosmemselector,transfer_buffer,len);
  968. {$else GO32V2}
  969. move(addr,pointer(transfer_buffer)^,len);
  970. {$endif GO32V2}
  971. end;
  972. procedure copyfromdos(var addr; len : longint);
  973. begin
  974. if len > tb_size then runerror(217);
  975. {$ifdef GO32V2}
  976. seg_move(dosmemselector,transfer_buffer,get_ds,longint(@addr),len);
  977. {$else GO32V2}
  978. move(pointer(transfer_buffer)^,addr,len);
  979. {$endif GO32V2}
  980. end;
  981. {$endif not V0_6}
  982. {$ifdef SUPPORT_PORT}
  983. { to give easy port access }
  984. procedure tport.writeport(p : word;data : byte);
  985. begin
  986. outportb(p,data);
  987. end;
  988. function tport.readport(p : word) : byte;
  989. begin
  990. readport:=inportb(p);
  991. end;
  992. procedure tportw.writeport(p : word;data : word);
  993. begin
  994. outportw(p,data);
  995. end;
  996. function tportw.readport(p : word) : word;
  997. begin
  998. readport:=inportw(p);
  999. end;
  1000. procedure tportl.writeport(p : word;data : longint);
  1001. begin
  1002. outportl(p,data);
  1003. end;
  1004. function tportl.readport(p : word) : longint;
  1005. begin
  1006. readport:=inportl(p);
  1007. end;
  1008. {$endif SUPPORT_PORT}
  1009. begin
  1010. int31error:=0;
  1011. {$ifndef go32v2}
  1012. if not (get_run_mode=rm_dpmi) then
  1013. begin
  1014. dosmemget:=@raw_dosmemget;
  1015. dosmemput:=@raw_dosmemput;
  1016. dosmemmove:=@raw_dosmemmove;
  1017. dosmemfillchar:=@raw_dosmemfillchar;
  1018. dosmemfillword:=@raw_dosmemfillword;
  1019. end
  1020. else
  1021. {$endif}
  1022. begin
  1023. dosmemselector:=get_core_selector;
  1024. end;
  1025. end.
  1026. {
  1027. $Log$
  1028. Revision 1.4 1998-04-24 08:26:50 pierre
  1029. * had to rename property from p to pp to
  1030. avoid duplicate identifier error in
  1031. implementation of readport and writeport
  1032. that have p as argument
  1033. Revision 1.3 1998/04/12 22:35:29 florian
  1034. + support of port-array added
  1035. Revision 1.2 1998/03/29 17:26:20 florian
  1036. * small improvements
  1037. Revision 1.1.1.1 1998/03/25 11:18:41 root
  1038. * Restored version
  1039. Revision 1.8 1998/03/24 15:54:14 peter
  1040. - raw_ functions are not necessary for go32v2, $ifdef'd them
  1041. Revision 1.7 1998/03/24 09:33:59 peter
  1042. + new trealregs from the mailinglist
  1043. + 2 new functions get_page_size, map_device_in_mem_block
  1044. Revision 1.6 1998/02/01 09:32:21 florian
  1045. * some clean up
  1046. Revision 1.5 1998/01/26 11:56:27 michael
  1047. + Added log at the end
  1048. revision 1.4
  1049. date: 1997/12/12 13:14:37; author: pierre; state: Exp; lines: +2 -1
  1050. + added handling of swap_vectors if under exceptions
  1051. i.e. swapvector is not dummy under go32v2
  1052. * bug in output, exceptions where not allways reset correctly
  1053. now the code in dpmiexcp is called from v2prt0.as exit routine
  1054. * in crt.pp corrected init_delay calibration loop
  1055. and added it for go32v2 also (was disabled before due to crashes !!)
  1056. the previous code did a wrong assumption on the time need to call
  1057. get_ticks compared to an internal loop without call
  1058. ----------------------------
  1059. revision 1.3
  1060. date: 1997/12/11 11:50:37; author: pierre; state: Exp; lines: +2 -2
  1061. * bug in get_linear_addr corrected
  1062. thanks to Raul who found this bug.
  1063. ----------------------------
  1064. revision 1.2
  1065. date: 1997/12/01 12:15:46; author: michael; state: Exp; lines: +10 -3
  1066. + added copyright reference in header.
  1067. ----------------------------
  1068. revision 1.1
  1069. date: 1997/11/27 08:33:50; author: michael; state: Exp;
  1070. Initial revision
  1071. ----------------------------
  1072. revision 1.1.1.1
  1073. date: 1997/11/27 08:33:50; author: michael; state: Exp; lines: +0 -0
  1074. FPC RTL CVS start
  1075. =============================================================================
  1076. History:
  1077. 6th november 1996:
  1078. + dosmem* implemented
  1079. }