Read data at IO Address higher 0xFFFF (32 bit address)

Started by dinhtandl, October 25, 2010, 07:15:22 AM

Previous topic - Next topic

dinhtandl

Dear,

I have a procedure which use to read data at I/O Address but this Address is lower or equal 0xFFFFF (16 bit addresss):


;     _ioread
;
;     This procedure reads data from the io port specified. Data can
;     be a byte, word or long word as specified by the size parameter.
;
;     C Prototype
;
;     short ioread(unsigned long addr, unsigned long * data, short size);
;
;        addr  - io address to write to
;        data  - location where data will be stored.
;        size  - size of data to read in bytes. {1, 2, 4}
;
_ioread    PROC FAR
   push bp
   mov bp,sp

   push ebx             ; save registers
   push edx
   push di
   push es

   ;   get io address and check to make sure it's in range
   mov edx,[bp+6]               ; address
   cmp edx,0000FFFFH
   jg ioread_err_range

   xor eax,eax                  ; prepare to recieve data
   mov bx,[bp+0EH]              ; size

   cmp bx,4                     ; write long word
   jne ioread_check_word
   in eax,dx
   jmp ioread_err_ok

   ioread_check_word:          ; write word
   cmp bx,2
   jne ioread_check_byte
   in ax,dx
   jmp ioread_err_ok

   ioread_check_byte:          ; write byte
   cmp bx,1
   jne ioread_err_range
   in al,dx
   jmp ioread_err_ok

   ioread_err_ok:              ; successful procedure
   mov edx,[bp+0AH]             ; data
   mov di,dx
   shr edx,16
   mov es,dx
   mov es:[di],eax              ; store result
   xor ax,ax
   jmp ioread_omega

   ioread_err_range:           ; range error in procedure
   mov ax,0FFFFH

   ioread_omega:

   pop es               ; restore registers
   pop di
   pop edx
   pop ebx

   mov sp,bp
   pop bp
   ret
_ioread    ENDP


At the current, I want to read data at I/O Address higher 0xFFFF (or 32 bit address), but i can't modify this procedure to execute this function.
Please help me to modify this procedure to read data with 32 bit I/O Address.

sinsi

There are no I/O ports greater then FFFFh, maybe you mean memory-mapped I/O (e.g. PCI bus)?
Light travels faster than sound, that's why some people seem bright until you hear them.

dinhtandl

Thanks sinsi, I thinks so, too.
But i have a problem:
+ I have PCI Express Card.
+ this card has Base Address: 0xE100 0000 (memory-mapped I/O address)
+ Using memory read to read data at this address but i can't read exactly data. (Because i has read data in linux and compare with DOS).
+ This is proceduce to read memory-mapped I/O:


;     _memread
;
;     This procedure reads data from the specified memory location. Data can
;     be a byte, word or long word as specified by the size parameter.
;
;     C Prototype
;
;     short memread(unsigned long addr, unsigned long * data, short size);
;
;        addr  - memory address to read from in SEG:OFF format
;        data  - location where data will be stored in SEG:OFF format.
;        size  - size of data to read in bytes. {1, 2, 4}
;
_memread   PROC FAR
   push bp
   mov bp,sp

   push ebx             ; save registers
   push edx
   push di
   push es

   ;   get memory address
   mov edx,[bp+6]               ; address
   ;   convert address to es:di form
   mov di,dx
   shr edx,16
   mov es,dx

   mov edx,[bp+0AH]             ; data address
   mov bx,[bp+0EH]              ; size

   xor eax,eax                  ; prepare to recieve data

   cmp bx,4                     ; write long word
   jne memread_check_word
   mov eax,es:[di]
   jmp memread_err_ok

   memread_check_word:          ; write word
   cmp bx,2
   jne memread_check_byte
   mov ax,es:[di]
   jmp memread_err_ok

   memread_check_byte:          ; write byte
   cmp bx,1
   jne memread_err_range
   mov al,es:[di]
   jmp memread_err_ok

   memread_err_ok:              ; successful procedure
   mov di,dx
   shr edx,16
   mov es,dx
   mov es:[di],eax              ; store result
   xor ax,ax
   jmp memread_omega

   memread_err_range:           ; range error in procedure
   mov ax,0FFFFH

   memread_omega:

   pop es               ; restore registers
   pop di
   pop edx
   pop ebx

   mov sp,bp
   pop bp
   ret
_memread   ENDP


Please give me some of advises

japheth


> Please give me some of advises

You cannot access extended memory so easy in real-mode. The most common way to read extended memory is INT 15h, ah=87h:

-----------------------------------------------------------------------------------------------------
INT 15 - SYSTEM - COPY EXTENDED MEMORY
   AH = 87h
   CX = number of words to copy (max 8000h)
   ES:SI -> global descriptor table (see #00499)
Return: CF set on error
   CF clear if successful
   AH = status (see #00498)
Notes:   copy is done in protected mode with interrupts disabled by the default
     BIOS handler; many 386 memory managers perform the copy with
     interrupts enabled
   on the PS/2 30-286 & "Tortuga" this function does not use the port 92h
     for A20 control, but instead uses the keyboard controller (8042).
     Reportedly this may cause the system to crash when access to the
     8042 is disabled in password server mode (see also PORT 0064h,#P0398)
   this function is incompatible with the OS/2 compatibility box
SeeAlso: AH=88h,AH=89h,INT 1F/AH=90h

(Table 00498)
Values for extended-memory copy status:
00h   source copied into destination
01h   parity error
02h   interrupt error
03h   address line 20 gating failed
80h   invalid command (PC,PCjr)
86h   unsupported function (XT,PS30)

Format of global descriptor table:
Offset   Size   Description   (Table 00499)
00h 16 BYTEs   zeros (used by BIOS)
10h   WORD   source segment length in bytes (2*CX-1 or greater)
12h  3 BYTEs   24-bit linear source address, low byte first
15h   BYTE   source segment access rights (93h)
16h   WORD   (286) zero
      (386+) extended access rights and high byte of source address
18h   WORD   destination segment length in bytes (2*CX-1 or greater)
1Ah  3 BYTEs   24-bit linear destination address, low byte first
1Dh   BYTE   destination segment access rights (93h)
1Eh   WORD   (286) zero
      (386+) extended access rights and high byte of destin. address
20h 16 BYTEs   zeros (used by BIOS to build CS and SS descriptors)
-----------------------------------------------------------------------------------------------------

As an alternative, one may use "unreal" mode, but this is less flexible because it won't work in v86-mode.





clive

Or use a DOS-Extender, use DPMI or the features of the extender to access whatever memory you want. It is certainly possible to build and test 32-bit drivers, normally hosted by Windows or Linux, under DOS. Booted too DOS mind you, it won't work in the virtual DOS boxes.
It could be a random act of randomness. Those happen a lot as well.

sinsi

Hey japheth, can this function be used to access the APIC from real mode?
Hmm, might give it a try.
Light travels faster than sound, that's why some people seem bright until you hear them.

redskull

This was all recently covered in this thread: http://www.masm32.com/board/index.php?topic=13564.0

Also, like clive said, these suggestions are for REAL real mode, not NTVDM.  Doing it inside a DOS box is much tricker (but in some ways, actually easier).

-r
Strange women, lying in ponds, distributing swords, is no basis for a system of government

dinhtandl

Thanks for all.
hey clive, I use Win98 (support DOS).
I'm newcommer in Assembly Language, please hepl me modify this procedure.
I have tried to read at many high address, so it always return 0xFFFFFFFF (4 bytes).


japheth

Quote from: sinsi on October 25, 2010, 02:34:54 PM
Hey japheth, can this function be used to access the APIC from real mode?
Hmm, might give it a try.

I've once implemented memory access via int 15h, ah=87h in good old FD Debug's DX command.