[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-discuss] Unable to use DMA of PCI IDE bus master

From: Jakob Bohm
Subject: Re: [Qemu-discuss] Unable to use DMA of PCI IDE bus master
Date: Thu, 23 Jun 2016 16:22:46 +0200
User-agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:45.0) Gecko/20100101 Thunderbird/45.1.1

On 23/06/2016 09:02, Yanjun Yang wrote:

I was trying to use DMA to transfer a sector of data from hardisk to memory.  The attached
 code works under VirtualBox (change bmcr address to D000) but not under newer version
of qemu.  An old version of qemu (1.1.2 from Debian wheezy) behave as I expected. Other
version I tested are from stable branch, 2.6.50 from Arch Linux, they both give all
zero result.

The following code was compiled by Jwasm(MASM compatible) under dos. It'll display the
first sector of data from disk on screen.  I don't know whether there is bugs in my code or
I miss a configuration of qemu.

To test my code, I just used a clean install of FreeDos, and run the executable compiled by
Jwasm. I didn't use any special qemu command line switch, just "qemu-system-x86_64 dos.cow"
and run the executable inside the emulated dos environment.

Any comment will be appreciated. Thanks in advance.

Which (virtual) hardware disk controller and (if applicable) mainboard
chipset does this assume?

Is this the hardware emulated by default by the qemu command you ran?

Are you trying to access the ISA-bus compatible DMA controller at I/O
port 0x0040 using the obscure fact that older ISA machines only
decoded the low 10 bits of the I/O port address?

========== code attached below ===========

STACK segment para stack 'STACK'
    db 512 dup(0)
STACK ends

BMCR_BASE       equ    0c040h       ; Bus Master Control Register base address
BM_COMMAND_REG  equ    BMCR_BASE    ; Command
BM_STATUS_REG   equ    BMCR_BASE + 2  ; Status
BM_PRD_ADDR_REG equ    BMCR_BASE + 4  ; Physical Region Descriptor address
PIO_BASE_ADDR1  equ    01f0h
PIO_BASE_ADDR2  equ    03f6h
SEC_NUM         equ    1
LBASECTOR       equ    0

DATA segment use16 para 'DATA'
    align 2
Buf         db      512 * SEC_NUM DUP (0)   ; DMA Buffer
BufLen      equ     $ - Buf
    align 4
PRD_Buf     dd      0           ; Physical Region Descriptor Buffer
            dd      0
DATA ends

EchoCH   macro   ascii
    mov     ah, 2
    mov     dl, ascii
    int     21h

outx macro reg, val
    mov     dx, reg
    mov     al, val
    out     dx, al

inx  macro reg
    mov     dx, reg
    in      al, dx

CODE segment use16
    assume cs:CODE,ds:DATA,ss:STACK

    mov     ax, DATA
    mov     ds, ax
    outx    BM_COMMAND_REG, 00h     ; start/STOP = 0, reset BM status
    outx    BM_STATUS_REG, 00000110B; clear interrupt and error flag
    ; create PRD
    mov     ax, ds
    movzx   eax, ax
    shl     eax, 4                  ; eax=base for data segment
    add     eax, offset Buf         ; eax=base for PRD_Bufj
    mov     PRD_Buf, eax               ; Physical address
    mov     word ptr [PRD_Buf+4], BufLen ; Byte count [15:1]
    mov     word ptr [PRD_Buf+6], 8000h  ; EOT=1
    mov     ax, ds
    movzx   eax, ax
    shl     eax, 4
    add     eax, offset PRD_Buf
    mov     dx, BM_PRD_ADDR_REG
    out     dx, eax                 ; PRD address
    outx    BM_COMMAND_REG, 08h     ; R/W=1, read from disk
    call    WaitDevice
    outx    PIO_BASE_ADDR1+6, 00h   ; Dev=0
    call    WaitDevice
    ;outx    PIO_BASE_ADDR2, 00      ; enable interrupt
    outx    PIO_BASE_ADDR1 + 1, 00h              ; =00
    outx    PIO_BASE_ADDR1 + 2, SEC_NUM          ; sector num
    outx    PIO_BASE_ADDR1 + 3, LBASECTOR
    outx    PIO_BASE_ADDR1 + 4, LBASECTOR/256
    outx    PIO_BASE_ADDR1 + 5, LBASECTOR/65536
    outx    PIO_BASE_ADDR1 + 6, 01000000B OR (LBASECTOR/256/256/256)
    outx    PIO_BASE_ADDR1 + 7, 0C8h             ; 0C8h=READ DMA
    outx    BM_COMMAND_REG, 09h     ; R/W=1, START/STOP=1, start DMA
    inx     BM_STATUS_REG
    and     al, 00000100B
    JZ      @B
    outx    BM_STATUS_REG, 00000100B
    outx    BM_COMMAND_REG, 00h     ; START/STOP = 0, stop DMA
    call    ShowBuf
    mov     ax,4C00h
    int     21h

    ; Wait until BSY=0,DRQ=0
WaitDevice  proc
    inx     PIO_BASE_ADDR1 + 7
    and     al, 10001000b
    jnz     @B
WaitDevice  endp

;Show what's in the buffer
ShowBuf     proc
    lea     si, Buf
    mov     bp, BufLen / 16
    mov     cx,16
    push    ax
    shr     al, 4
    call    ToAscii
    EchoCH  al
    pop     ax
    call    ToAscii
    EchoCH  al
    EchoCH  ' '
    loop    NextCh
    EchoCH  0dh
    EchoCH  0ah
    dec     bp
    jnz     NextLine
ShowBuf     endp

ToAscii     proc
    and     al, 0fh
    cmp     al, 10
    jae     @F
    add     al,'0'
@@: add     al,'A' - 10
ToAscii     endp

CODE ends
end start


Jakob Bohm, CIO, Partner, WiseMo A/S.  https://www.wisemo.com
Transformervej 29, 2860 Søborg, Denmark.  Direct +45 31 13 16 10
This public discussion message is non-binding and may contain errors.
WiseMo - Remote Service Management for PCs, Phones and Embedded 

reply via email to

[Prev in Thread] Current Thread [Next in Thread]