Back to home page

DOS ain't dead

Forum index page

Log in | Register

Back to index page
Thread view  Board view
Laaca(R)

Homepage

Czech republic,
12.08.2019, 22:19
 

Need help with DPMI function 301h (Developers)

Hello all!
I need your help with my routine using DPMI function 301h. In my task I want to talk with legacy (non-ACPI) PnP BIOS interface.
I want it to be compilable with TurboPascal-realmode and Freepascal-32bitPM.
The original code is quite bit but I simplified the code to be as small as possible and to use rather assembler that pascal.
In my code I call the PNP-BIOS function 00h - GetNumber_and_size_of_PNP_nodes
(for reference please see specification - relevant pages 26-31)

THIS REALMODE CODE WORKS PERFECT:
(Note: in line "InternalCallPNP($F000,24114,$F000,p1,p2);" just change the magic numbers for numbers you get from scan of your machine - see the 3rd snipet of code)

Program TestPNP;

Procedure InternalCallPNP(seg_entry,offs_entry,ds_seg:word;var param1,param2:word);
var p:pointer;
begin
asm
mov ax,ds_seg
push ax

push $b800 {for simplicity we will not mess with transfer buffers stuff}
push 0 {but we just use some safe realmode address like videobuffer}
push $b800
push 2

push 0

mov ax,offs_entry
mov bx,seg_entry

mov p.word[0],ax
mov p.word[2],bx

call p

pop ax
pop ax
pop ax
pop ax
pop ax
pop ax
end;

param1:=MemW[$B800:0];
param2:=MemW[$B800:2];
end;

var p1,p2:word;
begin
InternalCallPNP($F000,24114,$F000,p1,p2);
writeln('p1: ',p1);
writeln('p2: ',p2);
end.



BUT IN THE CODE BELOW IS THE PROBLEM - this code should be analogical to previous one but works in 32-bit protected mode using Freepascal.
I can not just call the realmode BIOS entrypoint from protected mode so I have to use the emulation via DPMI function 301h. But it does not work at all. In FreeDOS the computer freezes after instruction INT31h and in Windows98 freezes the task.

Program TestPNP;
uses Go32;

Procedure InternalCallPNP(seg_entry,offs_entry,ds_seg:word;var param1,param2:word);
var r:TRealRegs;
begin

FillChar(r,sizeof(TRealRegs),0);
r.cs:=seg_entry;
r.ip:=offs_entry;

asm
mov ax,ds_seg
push ax

push $b800 {for simplicity we will not mess with transfer buffers stuff}
push 0 {but we just use some safe realmode address like videobuffer}
push $b800
push 2

push 0

mov edi,r
mov ebx,0
mov ecx,6
mov eax,301h;
int 31h

pop ax
pop ax
pop ax
pop ax
pop ax
pop ax
end;

param1:=MemW[$B800:0];
param2:=MemW[$B800:2];
end;

var p1,p2:word;
begin
InternalCallPNP($F000,24114,$F000,p1,p2);
writeln('p1: ',p1);
writeln('p2: ',p2);
end.



AND THE LAST PIECE OF CODE - the detection of the PNP BIOS and detection of the entrypoint.
This code works in both Turbopascal and Freepascal. (no problem here)

Function RMString(segm,offs:word;len:byte):string;
var a:longint;
s:string;
begin
s:='';
for a:=0 to len-1 do s:=s+char(Mem[segm:offs+a]);
RMstring:=s;
end;


Function ScanSegment(segm:word;var offs:longint;limit:word;gran:word;const SearchStr:string):boolean;
var l:byte;
begin
l:=Length(SearchStr);
repeat
if RMstring(segm,offs,l)=SearchStr then
begin
ScanSegment:=true;
Exit;
end;
inc(offs,gran);
until offs>limit-gran;
offs:=0;
ScanSegment:=false;
end;


Function Get_PNP_BIOS_Entry_Info(var seg_entry,offs_entry,ds_seg:word):boolean;
var scan_seg:word;
scan_ofs:longint;
begin

scan_seg:=$F000;
scan_ofs:=0;

if not ScanSegment(scan_seg,scan_ofs,$FFFF,16,'$PnP')
then begin
seg_entry:=0;
offs_entry:=0;
ds_seg:=0;
Get_PNP_BIOS_Entry_Info:=false;
end
else begin
ds_seg:=MemW[scan_seg:scan_ofs+27];
offs_entry:=MemW[scan_seg:scan_ofs+13];
seg_entry:=MemW[scan_seg:scan_ofs+15];
Get_PNP_BIOS_Entry_Info:=true;
end;
end;

var s,o,d:word;
begin
if not Get_PNP_BIOS_Entry_Info(s,o,d)
then writeln('No PNP BIOS found!')
else begin
writeln('PNP BIOS found!');
writeln('Entrypoint segment: ',s);
writeln('Entrypoint offset: ',o);
writeln('DS register for routine: ',d);
end;
end.

---
DOS-u-akbar!

RayeR(R)

Homepage

CZ,
15.08.2019, 03:35

@ Laaca
 

Need help with DPMI function 301h

Hi,
I don't know FP specific but do you really need to write it in ASM?
DJGPP has DPMI wrapper C functions like
__dpmi_simulate_real_mode_procedure_retf()
http://www.delorie.com/djgpp/doc/libc/libc_275.html
that should do what you want. Maybe you have to take care about saving and restoring some other registers. Here's some info about DPMI 0301h
http://www.delorie.com/djgpp/doc/dpmi/api/310301.html

---
DOS gives me freedom to unlimited HW access.

Laaca(R)

Homepage

Czech republic,
16.08.2019, 08:09

@ RayeR
 

Need help with DPMI function 301h

> Hi,
> I don't know FP specific but do you really need to write it in ASM?
> DJGPP has DPMI wrapper C functions like
> __dpmi_simulate_real_mode_procedure_retf()
> http://www.delorie.com/djgpp/doc/libc/libc_275.html
> that should do what you want. Maybe you have to take care about saving and
> restoring some other registers. Here's some info about DPMI 0301h
> http://www.delorie.com/djgpp/doc/dpmi/api/310301.html

No, Freepascal does not have equivalent to this function. For DPMI 300h has, for DPMI 301h not. But even if it would be - other problém is; I don't know how to give the parameters via stack with this DJGPP function. I think it is not possible at all. And this PnP standard uses the communication not via registers but via stack.

In my old other project I use the DPMI 301h function without problems but here is not parameters passing through stack (I use it in my port of Digpak/Midpak sound library).

---
DOS-u-akbar!

Laaca(R)

Homepage

Czech republic,
16.08.2019, 08:11

@ Laaca
 

Need help with DPMI function 301h

> > Hi,
> > I don't know FP specific but do you really need to write it in ASM?
> > DJGPP has DPMI wrapper C functions like
> > __dpmi_simulate_real_mode_procedure_retf()
> > http://www.delorie.com/djgpp/doc/libc/libc_275.html
> > that should do what you want. Maybe you have to take care about saving
> and
> > restoring some other registers. Here's some info about DPMI 0301h
> > http://www.delorie.com/djgpp/doc/dpmi/api/310301.html
>

No, Freepascal does not have equivalent to this function. For DPMI 300h
has, for DPMI 301h not. But even if it would be - other problém is; I don't
know how to give the parameters via stack with this DJGPP function. I think
it is not possible at all. And this PnP standard uses the communication not
via registers but via stack.

In my old other project I use the DPMI 301h function without problems but here is not parameters passing through stack (I use it in my port of
Digpak/Midpak sound library).

Rayer, are you able to convert the Freepascal version of code into DJGPP to more people be interrested to analyze the problem?

---
DOS-u-akbar!

marcov(R)

17.08.2019, 23:34

@ Laaca
 

Need help with DPMI function 301h

> push $b800 {for simplicity we will not mess with transfer buffers stuff}
> push 0 {but we just use some safe realmode address like videobuffer}
> push $b800
> push 2
>
> push 0

Push word (pushw) maybe ? In 32-bit mode the default will be a 32-bit push.

Japheth(R)

Homepage

Germany (South),
18.08.2019, 09:56
(edited by Japheth, 18.08.2019, 10:23)

@ Laaca
 

Need help with DPMI function 301h

> I can not just call the realmode BIOS entrypoint from protected mode so I
> have to use the emulation via DPMI function 301h.

Yes

> FillChar(r,sizeof(TRealRegs),0);
> r.cs:=seg_entry;
> r.ip:=offs_entry;

So far it's ok, real-mode CS:IP and SS:SP are set.

> push $b800
> push 0
> push $b800
> push 2
>
> push 0

In 32-bit protected-mode, when you're pushing a constant value, a 32-bit value is pushed! So the code above pushes 5 DWORDS, not 5 WORDS ( as was your intention, probably ).

Simplest workround: replace "push CONST" by "mov ax,CONST" & "push ax".

---
MS-DOS forever!

Back to index page
Thread view  Board view
15889 Postings in 1469 Threads, 269 registered users, 82 users online (0 registered, 82 guests)
DOS ain't dead | Admin contact
RSS Feed
powered by my little forum