3 This file is part of the Free Pascal run time library
.
4 and implements some stuff
for protected mode programming
5 Copyright (c
) 1999-2000 by the Free Pascal development team
.
7 See the file COPYING
.FPC
, included
in this distribution
,
8 for details about the copyright
.
10 This program is distributed
in the hope that it will be useful
,
11 but WITHOUT ANY WARRANTY
; without even the implied warranty of
12 MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE
.
14 **********************************************************************}
18 {$ifdef SUPPORT_PORTS
}
20 {$endif SUPPORT_PORTS
}
21 {$S-,R-
,I-
,Q-
} {no stack check
, used by DPMIEXCP
!! }
26 { contants
for the run modes returned by get_run_mode
}
28 rm_raw
= 1; { raw (without HIMEM
) }
29 rm_xms
= 2; { XMS (for example with HIMEM
, without EMM386
) }
30 rm_vcpi
= 3; { VCPI (for example HIMEM
and EMM386
) }
31 rm_dpmi
= 4; { DPMI (for example DOS box
or 386Max
) }
48 available_lockable_pages
,
51 available_physical_pages
,
54 max_pages_in_paging_file
,
67 1: { 32-bit
} (EDI
, ESI
, EBP
, Res
, EBX
, EDX
, ECX
, EAX
: longint
;
68 Flags
, ES
, DS
, FS
, GS
, IP
, CS
, SP
, SS
: word
);
69 2: { 16-bit
} (DI
, DI2
, SI
, SI2
, BP
, BP2
, R1
, R2
: word
;
70 BX
, BX2
, DX
, DX2
, CX
, CX2
, AX
, AX2
: word
);
71 3: { 8-bit
} (stuff
: array
[1..4] of longint
;
72 BL
, BH
, BL2
, BH2
, DL
, DH
, DL2
, DH2
,
73 CL
, CH
, CL2
, CH2
, AL
, AH
, AL2
, AH2
: byte
);
74 4: { Compat
} (RealEDI
, RealESI
, RealEBP
, RealRES
,
75 RealEBX
, RealEDX
, RealECX
, RealEAX
: longint
;
77 RealES
, RealDS
, RealFS
, RealGS
,
78 RealIP
, RealCS
, RealSP
, RealSS
: word
);
81 registers
= trealregs
;
83 { this works only with real DPMI
}
84 function
allocate_ldt_descriptors(count
: word
) : word
;
85 function
free_ldt_descriptor(d
: word
) : boolean
;
86 function
segment_to_descriptor(seg
: word
) : word
;
87 function get_next_selector_increment_value
: word
;
88 function
get_segment_base_address(d
: word
) : longint
;
89 function
set_segment_base_address(d
: word
;s
: longint
) : boolean
;
90 function
set_segment_limit(d
: word
;s
: longint
) : boolean
;
91 function
set_descriptor_access_right(d
: word
;w
: word
) : longint
;
92 function
create_code_segment_alias_descriptor(seg
: word
) : word
;
93 function
get_linear_addr(phys_addr
: longint
;size
: longint
) : longint
;
94 function
get_segment_limit(d
: word
) : longint
;
95 function
get_descriptor_access_right(d
: word
) : longint
;
96 function get_page_size
:longint;
97 function
map_device_in_memory_block(handle
,offset
,pagecount
,device
:longint):boolean;
98 function
realintr(intnr
: word
;var regs
: trealregs
) : boolean
;
100 { is needed
for functions which need a real mode buffer
}
101 function
global_dos_alloc(bytes
: longint
) : longint
;
102 function
global_dos_free(selector
: word
) : boolean
;
105 { selector
for the DOS
memory (only usable
if in DPMI mode
) }
106 dosmemselector
: word
;
107 { result of dpmi call
}
110 { this procedure copies
data where the source
and destination
}
111 { are specified by
48 bit pointers
}
112 { Note
: the procedure checks only
for overlapping
if }
113 { source selector
=destination selector
}
114 procedure
seg_move(sseg
: word
;source
: longint
;dseg
: word
;dest
: longint
;count
: longint
);
116 { fills a memory area specified by a
48 bit pointer with c
}
117 procedure
seg_fillchar(seg
: word
;ofs
: longint
;count
: longint
;c
: char
);
118 procedure
seg_fillword(seg
: word
;ofs
: longint
;count
: longint
;w
: word
);
120 {************************************}
121 { this works with all PM interfaces
: }
122 {************************************}
124 function
get_meminfo(var meminfo
: tmeminfo
) : boolean
;
125 function
get_pm_interrupt(vector
: byte
;var intaddr
: tseginfo
) : boolean
;
126 function
set_pm_interrupt(vector
: byte
;const intaddr
: tseginfo
) : boolean
;
127 function
get_rm_interrupt(vector
: byte
;var intaddr
: tseginfo
) : boolean
;
128 function
set_rm_interrupt(vector
: byte
;const intaddr
: tseginfo
) : boolean
;
129 function
get_exception_handler(e
: byte
;var intaddr
: tseginfo
) : boolean
;
130 function
set_exception_handler(e
: byte
;const intaddr
: tseginfo
) : boolean
;
131 function
get_pm_exception_handler(e
: byte
;var intaddr
: tseginfo
) : boolean
;
132 function
set_pm_exception_handler(e
: byte
;const intaddr
: tseginfo
) : boolean
;
133 function
free_rm_callback(var intaddr
: tseginfo
) : boolean
;
134 function
get_rm_callback(pm_func
: pointer
;const reg
: trealregs
;var rmcb
: tseginfo
) : boolean
;
135 function get_cs
: word
;
136 function get_ds
: word
;
137 function get_ss
: word
;
139 { locking functions
}
140 function
allocate_memory_block(size
:longint):longint;
141 function
free_memory_block(blockhandle
: longint
) : boolean
;
142 function
request_linear_region(linearaddr
, size
: longint
;
143 var blockhandle
: longint
) : boolean
;
144 function
lock_linear_region(linearaddr
, size
: longint
) : boolean
;
145 function
lock_data(var
data;size
: longint
) : boolean
;
146 function
lock_code(functionaddr
: pointer
;size
: longint
) : boolean
;
147 function
unlock_linear_region(linearaddr
, size
: longint
) : boolean
;
148 function
unlock_data(var
data;size
: longint
) : boolean
;
149 function
unlock_code(functionaddr
: pointer
;size
: longint
) : boolean
;
151 { disables
and enables interrupts
}
155 function
inportb(port
: word
) : byte
;
156 function
inportw(port
: word
) : word
;
157 function
inportl(port
: word
) : longint
;
159 procedure
outportb(port
: word
;data : byte
);
160 procedure
outportw(port
: word
;data : word
);
161 procedure
outportl(port
: word
;data : longint
);
162 function get_run_mode
: word
;
164 function transfer_buffer
: longint
;
165 function tb_segment
: longint
;
166 function tb_offset
: longint
;
167 function tb_size
: longint
;
168 procedure
copytodos(var addr
; len
: longint
);
169 procedure
copyfromdos(var addr
; len
: longint
);
171 procedure
dpmi_dosmemput(seg
: word
;ofs
: word
;var
data;count
: longint
);
172 procedure
dpmi_dosmemget(seg
: word
;ofs
: word
;var
data;count
: longint
);
173 procedure
dpmi_dosmemmove(sseg
,sofs
,dseg
,dofs
: word
;count
: longint
);
174 procedure
dpmi_dosmemfillchar(seg
,ofs
: word
;count
: longint
;c
: char
);
175 procedure
dpmi_dosmemfillword(seg
,ofs
: word
;count
: longint
;w
: word
);
178 {$ifdef SUPPORT_PORTS
}
181 procedure
writeport(p
: word
;data : byte
);
182 function
readport(p
: word
) : byte
;
183 property pp
[w
: word
] : byte read readport write writeport
;default
;
187 procedure
writeport(p
: word
;data : word
);
188 function
readport(p
: word
) : word
;
189 property pp
[w
: word
] : word read readport write writeport
;default
;
193 procedure
writeport(p
: word
;data : longint
);
194 function
readport(p
: word
) : longint
;
195 property pp
[w
: word
] : longint read readport write writeport
;default
;
198 { we don
't need to initialize port, because neither member
199 variables nor virtual methods are accessed }
204 {$endif SUPPORT_PORTS}
207 { this procedures are assigned to the procedure which are needed }
208 { for the current mode to access DOS memory }
209 { It's strongly recommended to use this procedures
! }
210 dosmemput
: procedure(seg
: word
;ofs
: word
;var
data;count
: longint
)=dpmi_dosmemput
;
211 dosmemget
: procedure(seg
: word
;ofs
: word
;var
data;count
: longint
)=dpmi_dosmemget
;
212 dosmemmove
: procedure(sseg
,sofs
,dseg
,dofs
: word
;count
: longint
)=dpmi_dosmemmove
;
213 dosmemfillchar
: procedure(seg
,ofs
: word
;count
: longint
;c
: char
)=dpmi_dosmemfillchar
;
214 dosmemfillword
: procedure(seg
,ofs
: word
;count
: longint
;w
: word
)=dpmi_dosmemfillword
;
221 { the following procedures copy from
and to DOS memory using DPMI
}
222 procedure
dpmi_dosmemput(seg
: word
;ofs
: word
;var
data;count
: longint
);
225 seg_move(get_ds
,longint(@data),dosmemselector
,seg
*16+ofs
,count
);
228 procedure
dpmi_dosmemget(seg
: word
;ofs
: word
;var
data;count
: longint
);
231 seg_move(dosmemselector
,seg
*16+ofs
,get_ds
,longint(@data),count
);
234 procedure
dpmi_dosmemmove(sseg
,sofs
,dseg
,dofs
: word
;count
: longint
);
237 seg_move(dosmemselector
,sseg
*16+sofs
,dosmemselector
,dseg
*16+dofs
,count
);
240 procedure
dpmi_dosmemfillchar(seg
,ofs
: word
;count
: longint
;c
: char
);
243 seg_fillchar(dosmemselector
,seg
*16+ofs
,count
,c
);
246 procedure
dpmi_dosmemfillword(seg
,ofs
: word
;count
: longint
;w
: word
);
249 seg_fillword(dosmemselector
,seg
*16+ofs
,count
,w
);
253 procedure
test_int31(flag
: longint
);
271 function
global_dos_alloc(bytes
: longint
) : longint
;
276 addl
$0xf,%ebx
// round up
277 shrl
$0x4,%ebx
// convert to Paragraphs
278 movl
$0x100,%eax
// function
0x100
285 shll
$0x10,%eax
// return Segment
in hi(Result
)
286 movw
%dx
,%ax
// return Selector
in lo(Result
)
292 function
global_dos_free(selector
: word
) : boolean
;
304 function
realintr(intnr
: word
;var regs
: trealregs
) : boolean
;
313 { es is always equal ds
}
321 procedure
seg_fillchar(seg
: word
;ofs
: longint
;count
: longint
;c
: char
);
328 { load es with selector
}
332 { fill eax with duplicated c
}
333 { so we can use stosl
}
348 end ['EAX','ECX','EDX','EDI'];
351 procedure
seg_fillword(seg
: word
;ofs
: longint
;count
: longint
;w
: word
);
376 end ['EAX','ECX','EDX','EDI'];
379 procedure
seg_move(sseg
: word
;source
: longint
;dseg
: word
;dest
: longint
;count
: longint
);
384 if (sseg
<>dseg
) or ((sseg
=dseg
) and (source
>dest
)) then
406 end ['ESI','EDI','ECX','EAX']
407 else if (source
<dest
) then
408 { copy backward
for overlapping
}
427 { calculate esi
and edi
}
444 end ['ESI','EDI','ECX'];
447 procedure
outportb(port
: word
;data : byte
);
457 procedure
outportw(port
: word
;data : word
);
467 procedure
outportl(port
: word
;data : longint
);
477 function
inportb(port
: word
) : byte
;
487 function
inportw(port
: word
) : word
;
497 function
inportl(port
: word
) : longint
;
508 {$ifdef SUPPORT_PORTS
}
509 { to give easy port access like tp with port
[] }
511 procedure tport
.writeport(p
: word
;data : byte
);assembler
;
519 function tport
.readport(p
: word
) : byte
;assembler
;
526 procedure tportw
.writeport(p
: word
;data : word
);assembler
;
534 function tportw
.readport(p
: word
) : word
;assembler
;
541 procedure tportl
.writeport(p
: word
;data : longint
);assembler
;
549 function tportl
.readport(p
: word
) : longint
;assembler
;
555 {$endif SUPPORT_PORTS
}
557 function get_cs
: word
;assembler
;
563 function get_ss
: word
;assembler
;
569 function get_ds
: word
;assembler
;
575 function
set_pm_interrupt(vector
: byte
;const intaddr
: tseginfo
) : boolean
;
591 function
set_rm_interrupt(vector
: byte
;const intaddr
: tseginfo
) : boolean
;
607 function
set_pm_exception_handler(e
: byte
;const intaddr
: tseginfo
) : boolean
;
623 function
set_exception_handler(e
: byte
;const intaddr
: tseginfo
) : boolean
;
639 function
get_pm_exception_handler(e
: byte
;var intaddr
: tseginfo
) : boolean
;
655 function
get_exception_handler(e
: byte
;var intaddr
: tseginfo
) : boolean
;
671 function
get_pm_interrupt(vector
: byte
;var intaddr
: tseginfo
) : boolean
;
687 function
get_rm_interrupt(vector
: byte
;var intaddr
: tseginfo
) : boolean
;
704 function
free_rm_callback(var intaddr
: tseginfo
) : boolean
;
718 { here we must use ___v2prt0_ds_alias instead of from v2prt0
.s
719 because the exception processor sets the ds limit to
$fff
720 at hardware exceptions
}
723 ___v2prt0_ds_alias
: word
; external name
'___v2prt0_ds_alias';
725 function
get_rm_callback(pm_func
: pointer
;const reg
: trealregs
;var rmcb
: tseginfo
) : boolean
;
731 movw ___v2prt0_ds_alias
,%ax
750 function
allocate_ldt_descriptors(count
: word
) : word
;
761 function
free_ldt_descriptor(d
: word
) : boolean
;
774 function
segment_to_descriptor(seg
: word
) : word
;
785 function get_next_selector_increment_value
: word
;
795 function
get_segment_base_address(d
: word
) : longint
;
810 function get_page_size
:longint;
821 function
request_linear_region(linearaddr
, size
: longint
;
822 var blockhandle
: longint
) : boolean
;
827 pageofs
:=linearaddr
and $3ff;
828 linearaddr
:=linearaddr-pageofs
;
840 movl blockhandle
,%eax
844 if pageofs
<>linearaddr
then
845 request_linear_region
:=false;
848 function
allocate_memory_block(size
:longint):longint;
857 jnc
.Lallocate_mem_block_err
860 .Lallocate_mem_block_err
:
869 function
free_memory_block(blockhandle
: longint
) : boolean
;
872 movl blockhandle
,%esi
883 function
lock_linear_region(linearaddr
, size
: longint
) : boolean
;
901 function
lock_data(var
data;size
: longint
) : boolean
;
904 linearaddr
: longint
;
907 if get_run_mode
<>rm_dpmi
then
909 linearaddr
:=longint(@data)+get_segment_base_address(get_ds
);
910 lock_data
:=lock_linear_region(linearaddr
,size
);
913 function
lock_code(functionaddr
: pointer
;size
: longint
) : boolean
;
916 linearaddr
: longint
;
919 if get_run_mode
<>rm_dpmi
then
921 linearaddr
:=longint(functionaddr
)+get_segment_base_address(get_cs
);
922 lock_code
:=lock_linear_region(linearaddr
,size
);
925 function
unlock_linear_region(linearaddr
,size
: longint
) : boolean
;
943 function
unlock_data(var
data;size
: longint
) : boolean
;
946 linearaddr
: longint
;
948 if get_run_mode
<>rm_dpmi
then
950 linearaddr
:=longint(@data)+get_segment_base_address(get_ds
);
951 unlock_data
:=unlock_linear_region(linearaddr
,size
);
954 function
unlock_code(functionaddr
: pointer
;size
: longint
) : boolean
;
957 linearaddr
: longint
;
959 if get_run_mode
<>rm_dpmi
then
961 linearaddr
:=longint(functionaddr
)+get_segment_base_address(get_cs
);
962 unlock_code
:=unlock_linear_region(linearaddr
,size
);
965 function
set_segment_base_address(d
: word
;s
: longint
) : boolean
;
981 function
set_descriptor_access_right(d
: word
;w
: word
) : longint
;
995 function
set_segment_limit(d
: word
;s
: longint
) : boolean
;
1011 function
get_descriptor_access_right(d
: word
) : longint
;
1023 function
get_segment_limit(d
: word
) : longint
;
1036 function
create_code_segment_alias_descriptor(seg
: word
) : word
;
1049 function
get_meminfo(var meminfo
: tmeminfo
) : boolean
;
1062 function
get_linear_addr(phys_addr
: longint
;size
: longint
) : longint
;
1082 procedure disable
;assembler
;
1088 procedure enable
;assembler
;
1096 _run_mode
: word
;external name
'_run_mode';
1098 function get_run_mode
: word
;
1101 get_run_mode
:=_run_mode
;
1104 function
map_device_in_memory_block(handle
,offset
,pagecount
,device
:longint):boolean;
1120 {*****************************************************************************
1122 *****************************************************************************}
1124 function transfer_buffer
: longint
;
1126 transfer_buffer
:= go32_info_block
.linear_address_of_transfer_buffer
;
1130 function tb_segment
: longint
;
1132 tb_segment
:=go32_info_block
.linear_address_of_transfer_buffer shr
4;
1136 function tb_offset
: longint
;
1138 tb_offset
:=go32_info_block
.linear_address_of_transfer_buffer
and $f;
1142 function tb_size
: longint
;
1144 tb_size
:= go32_info_block
.size_of_transfer_buffer
;
1148 procedure
copytodos(var addr
; len
: longint
);
1152 seg_move(get_ds
,longint(@addr),dosmemselector
,transfer_buffer
,len
);
1156 procedure
copyfromdos(var addr
; len
: longint
);
1160 seg_move(dosmemselector
,transfer_buffer
,get_ds
,longint(@addr),len
);
1165 _core_selector
: word
;external name
'_core_selector';
1169 dosmemselector
:=_core_selector
;
1174 Revision
1.1 2002/02/19 08:25:09 sasu
1177 Revision
1.1 2000/07/13 06:30:37 michael
1180 Revision
1.8 2000/02/09 16:59:28 peter
1183 Revision
1.7 2000/01/07 16:41:31 daniel
1186 Revision
1.6 2000/01/07 16:32:23 daniel
1187 * copyright
2000 added
1189 Revision
1.5 1999/09/09 07:13:29 pierre
1190 - Port
[] moved to ports
.pp unit
1191 * global_dos_alloc returns zero
and set int31error