Let me try to clarify the situation a little.

There is an 80188 running on the board that contains the dual-ported memory
and the 80188 is not using a 32-bit flat memory model, it uses
segment:offset addressing (because that's all it can do).  On this board,
there are pointers to other locations on the board.  These addresses have
the form 0x1000:xxxx because the board's architecture (as the 80188 sees it)
places it there.

To the PC, this is an ISA board and the memory (for a Linux host) is at
0x000Dxxxx.  The driver in the PC has to read some data from a fixed address
in DPM.  Part of that data is a pointer (placed into the Dual-Ported memory
by the 80188) which points to other data that the PC needs to access.  These
addresses are always in the form 0x1000:xxxx because they are computed by
the 80188 on the board.

The PC needs to compute the equivalent 32-bit address to get the data
pointed to.  That is, it has to translate the address 0x1000:xxxx to
0x000Dxxxx.  There's a quick way to do that, namely
                0x000D000L + (long)( 16-bit word that forms the offset part
of the SEG:OFF address )

That's not to hard, although it's not really elegant. it can be hidden by a
preprocessor function.

Similarly, the PC has to write some data to the board and then write to the
board a pointer (in segment:offset format) relating to the data it just
wrote.  This means that the PC has to take a pointer from the board to an
area, say 0x1000:1234 for concreteness, and translate it to its own address
space, giving 0x000D1234.  Then it has to write a series of things at that
address and then put at another (fixed) location the address of the end of
the string of data it just wrote.  This means, for example,  that it has to
take an address in its space
                0x000D3456 + strlen( data ) + 1  (assume this computes to:
0x000D3478)
and translate it into the SEG:OFF format expected by the 80188.  And it has
to use the segment that the 80188 sees that data at.  Therefore, in this
example we need to take 0x000D3478 and transform it into 0x1000:3478.  

That's the part that's not obvious (to me) and while I can certainly create
several hacks that would produce the results, I wanted to know if there were
existing functions (or something that someone else has already written and
tested) that might do the job more elegantly.

BTW, in a 16-bit MS-DOS compiler (say, Borland C++ v3.1 or v4.5) we would
write
        board_ptr = MK_FP( 0x1000 , FP_OFF( pc_pointer) );
to substitute a different segment address for the one already in a pointer.
That's fairly neat and I know that the compiler produces very compact code
(one load-store pair and one store-immediate). 

        Norm



> -----Original Message-----
> From: Kulwinder Atwal [SMTP:[EMAIL PROTECTED]]
> Sent: Wednesday, March 29, 2000 6:34 PM
> To:   Norm Dresner; [EMAIL PROTECTED]
> Subject:      Re: [rtl] Segment/Offset - pointer conversion for accessing
> an ISA board
> 
> Kulwinder Atwal wrote:
> > 
> > To translate DPM memory is a straight forward procedure:
> > 
> > #define DPM_OFFSET 0xC000
> 
> Change this to:
> 
> #define DPM_OFFSET 0xC0000000
> 
> and you can use the 32 bit flat memory model like RTL and not worry
> about segments and offsets in 4 GB space. 
> 
> - Kal.
> 
> > 
> > #define DPM_TO_CPU (addr) (addr += DPM_OFFSET)
> > 
> > #define CPU_TO_DPM (addr) (addr -= DPM_OFFSET)
> > 
> > - Kal.
> > 
> > Norm Dresner wrote:
> > >
> > > Back in MS-DOS days, we had functions provided with the compiler to do
> the
> > > conversions between a pointer and a segment:offset description of an
> address:
> > >         void                    *MK_FP( ushort seg , ushort off );
> > >         unsigned short  FP_SEG( void *pointer );
> > >         unsigned short  FP_OFF( void *pointer );
> > >
> > > I have the need to do computation like this when accessing an ISA
> board
> > > (1st 1M of memory) and when translating the addresses from the
> dual-ported
> > > RAM from what's seen by the CPU on the board to what's seen by the PC
> (On
> > > the board, the DPM looks like it starts at  0x1000:0 while on the PC
> it's
> > > at 0xD000:0).
> > >
> > > Obviously I could roll my own replacements but before I start doing
> that I
> > > was wondering if it had already been done -- and probably more
> elegantly
> > > (and even more correctly) than I could do (at least the first time I
> do it).
> > >
> > > Thanks
> > >         Norm
> > >
> > > -- [rtl] ---
> > > To unsubscribe:
> > > echo "unsubscribe rtl" | mail [EMAIL PROTECTED] OR
> > > echo "unsubscribe rtl <Your_email>" | mail [EMAIL PROTECTED]
> > > ---
> > > For more information on Real-Time Linux see:
> > > http://www.rtlinux.org/rtlinux/
> > -- [rtl] ---
> > To unsubscribe:
> > echo "unsubscribe rtl" | mail [EMAIL PROTECTED] OR
> > echo "unsubscribe rtl <Your_email>" | mail [EMAIL PROTECTED]
> > ---
> > For more information on Real-Time Linux see:
> > http://www.rtlinux.org/rtlinux/
> -- [rtl] ---
> To unsubscribe:
> echo "unsubscribe rtl" | mail [EMAIL PROTECTED] OR
> echo "unsubscribe rtl <Your_email>" | mail [EMAIL PROTECTED]
> ---
> For more information on Real-Time Linux see:
> http://www.rtlinux.org/rtlinux/
-- [rtl] ---
To unsubscribe:
echo "unsubscribe rtl" | mail [EMAIL PROTECTED] OR
echo "unsubscribe rtl <Your_email>" | mail [EMAIL PROTECTED]
---
For more information on Real-Time Linux see:
http://www.rtlinux.org/rtlinux/

Reply via email to