Ignore:
Timestamp:
Oct 20, 2012, 5:04:32 PM (12 years ago)
Author:
aitotat@…
google:author:
aitotat@gmail.com
Message:

Changes to XTIDE Universal BIOS:

  • Added non-working DMA transfer code.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeDmaTransfer.asm

    r474 r477  
    2121; This struct must not be larger than IDEPACK without INTPACK.
    2222struc DMAVARS   ; Must not be larger than 9 bytes! See IDEPACK in RamVars.inc.
     23    .wTotalWordsXferred         resb    2   ; 0-1,
     24    .wBytesLeftToXferLessOne    resb    2   ; 2-3,
     25    .bbbPhysicalAddress         resb    3   ; 4-6,
     26                                resb    1   ; 7, IDEPACK.bDeviceControl
    2327endstruc
    2428
     
    3236;       AL:     IDE command that was used to start the transfer
    3337;               (all PIO read and write commands including Identify Device)
    34 ;       ES:SI:  Ptr to normalized data buffer
     38;       ES:SI:  Ptr to data buffer (not normalized)
    3539;       DS:DI:  Ptr to DPT (in RAMVARS segment)
    3640;       SS:BP:  Ptr to IDEPACK
     
    4044;       CF:     Cleared if success, Set if error
    4145;   Corrupts registers:
    42 ;       AL, BX, DX, SI, ES
     46;       AL, BX, DX
    4347;--------------------------------------------------------------------
    4448ALIGN JUMP_ALIGN
    4549IdeDmaTransfer_StartWithCommandInAL:
     50    ; Initialize DMAVARS
     51    xor     cx, cx
     52    mov     [bp+DMAVARS.wTotalWordsXferred], cx
     53    mov     ch, [bp+IDEPACK.bSectorCount]   ; CX = WORDs to transfer
     54    shl     cx, 1                           ; WORDs to BYTEs, 0 = 65536
     55    dec     cx
     56    mov     [bp+DMAVARS.wBytesLeftToXferLessOne], cx
     57
     58    ; Convert Segment:Offset type pointer to physical address
     59    xor     bx, bx
     60    mov     cx, es
     61%rep 4
     62    shl cx, 1
     63    rcl bx, 1
     64%endrep
     65    add     cx, si
     66    adc     bl, bh
     67    mov     [bp+DMAVARS.bbbPhysicalAddress], cx
     68    mov     [bp+DMAVARS.bbbPhysicalAddress+2], bl
     69
     70    ; Calculate bytes for first page - 1
     71    neg     cx  ; Max number of bytes for first page, 0 = 65536
     72    dec     cx
     73    MIN_U   cx, [bp+DMAVARS.wBytesLeftToXferLessOne]
     74
     75    ; Are we reading or writing?
     76    test    al, 16  ; Bit 4 is cleared on all the read commands but set on 3 of the 4 write commands
     77    jnz     SHORT WriteBlockToXTCF
     78    cmp     al, COMMAND_WRITE_MULTIPLE
     79    je      SHORT WriteBlockToXTCF
     80    ; Fall to ReadBlockFromXTCF
     81
     82
     83;--------------------------------------------------------------------
     84; ReadBlockFromXTCF
     85;   Parameters:
     86;       CX:     Bytes in first page - 1
     87;       DS:DI:  Ptr to DPT (in RAMVARS segment)
     88;       SS:BP:  Ptr to DMAVARS
     89;   Returns:
     90;       DS:DI:  Ptr to DPT (in RAMVARS segment)
     91;       AH:     BIOS Error code
     92;       CX:     Number of successfully transferred sectors
     93;       CF:     0 if transfer successful
     94;               1 if any error
     95;   Corrupts registers:
     96;       AL, BX, DX
     97;--------------------------------------------------------------------
     98ReadBlockFromXTCF:
     99    ; 8-bit DMA transfers must be done withing 64k physical page.
     100    ; We support maximum of 128 sectors (65536 bytes) per one INT 13h call
     101    ; so we might need to separate transfer to 2 separate DMA operations.
     102
     103    ; Transfer first DMA page
     104    mov     ah, CHANNEL_3 | WRITE | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE
     105    call    StartDMAtransferForXTCFwithDmaModeInAH
     106    jc      SHORT ReturnNumberOfSectorsXferred
     107
     108    ; Transfer second DMA page if necessary (always less than 64k)
     109    call    UpdateVariablesForSecondPageIfRequired
     110    jc      SHORT SecondDmaPageIsNotRequired
     111    mov     ah, CHANNEL_3 | WRITE | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE
     112    call    StartDMAtransferForXTCFwithDmaModeInAH
     113    jc      SHORT ReturnNumberOfSectorsXferred
     114    ; Fall to BothDmaPagesTransferredSuccessfully
     115
     116BothDmaPagesTransferredSuccessfully:
     117    inc     cx          ; Never overflows since second page always less than 64k
     118    shr     cx, 1       ; BYTEs to WORDs
     119    add     [bp+DMAVARS.wTotalWordsXferred], cx
     120SecondDmaPageIsNotRequired:
     121    xor     ah, ah
     122ReturnNumberOfSectorsXferred:
     123    mov     cx, [bp+DMAVARS.wTotalWordsXferred]
     124    xchg    cl, ch      ; WORDs to sectors
     125    ret
     126
     127
     128;--------------------------------------------------------------------
     129; WriteBlockToXTCF
     130;   Parameters:
     131;       CX:     Bytes in first page - 1
     132;       DS:DI:  Ptr to DPT (in RAMVARS segment)
     133;       SS:BP:  Ptr to DMAVARS
     134;   Returns:
     135;       DS:DI:  Ptr to DPT (in RAMVARS segment)
     136;       AH:     BIOS Error code
     137;       CX:     Number of successfully transferred sectors
     138;       CF:     0 if transfer successful
     139;               1 if any error
     140;   Corrupts registers:
     141;       AL, BX, DX
     142;--------------------------------------------------------------------
     143WriteBlockToXTCF:
     144    ; Transfer first DMA page
     145    mov     ah, CHANNEL_3 | READ | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE
     146    call    StartDMAtransferForXTCFwithDmaModeInAH
     147    jc      SHORT ReturnNumberOfSectorsXferred
     148
     149    ; Transfer second DMA page if necessary (always less than 64k)
     150    call    UpdateVariablesForSecondPageIfRequired
     151    jc      SHORT SecondDmaPageIsNotRequired
     152    mov     ah, CHANNEL_3 | READ | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE
     153    call    StartDMAtransferForXTCFwithDmaModeInAH
     154    jc      SHORT ReturnNumberOfSectorsXferred
     155    jmp     SHORT BothDmaPagesTransferredSuccessfully
     156
     157
     158;--------------------------------------------------------------------
     159; StartDMAtransferForXTCFwithDmaModeInAH
     160;   Parameters:
     161;       AH:     Byte for DMA Mode Register
     162;       CX:     Number of BYTEs to transfer - 1
     163;       DS:DI:  Ptr to DPT (in RAMVARS segment)
     164;   Returns:
     165;       AH:     BIOS Error code
     166;       CF:     0 if transfer successful
     167;               1 if any error
     168;   Corrupts registers:
     169;       AL, BX, DX
     170;--------------------------------------------------------------------
     171StartDMAtransferForXTCFwithDmaModeInAH:
     172    push    cx
     173
     174    ; Program 8-bit DMA Controller
     175
     176    ; Disable Interrupts and DMA Channel 3 during DMA setup
     177    cli                                     ; Disable interrupts
     178    mov     al, SET_CH3_MASK_BIT
     179    out     MASK_REGISTER_DMA8_out, al      ; Disable DMA Channel 3
     180
     181    ; Set DMA Mode (read or write using channel 3)
     182    mov     al, ah
     183    out     MODE_REGISTER_DMA8_out, al
     184
     185    ; Set address to DMA controller
     186    out     CLEAR_FLIPFLOP_DMA8_out, al     ; Reset flip-flop to low byte
     187    mov     ax, [bp+DMAVARS.bbbPhysicalAddress]
     188    out     BASE_AND_CURRENT_ADDRESS_REGISTER_DMA8_CH3_out, al  ; Low byte
     189    mov     al, ah
     190    out     BASE_AND_CURRENT_ADDRESS_REGISTER_DMA8_CH3_out, al  ; High byte
     191    mov     al, [bp+DMAVARS.bbbPhysicalAddress+2]
     192    out     PAGE_DMA8_CH_3, al
     193
     194    ; Set number of bytes to transfer (DMA controller must be programmed number of bytes - 1)
     195    out     CLEAR_FLIPFLOP_DMA8_out, al     ; Reset flip-flop to low byte
     196    mov     ax, cx
     197    out     BASE_AND_CURRENT_COUNT_REGISTER_DMA8_CH3_out, al    ; Low byte
     198    mov     al, ah
     199    out     BASE_AND_CURRENT_COUNT_REGISTER_DMA8_CH3_out, al    ; High byte
     200
     201    ; Enable DMA Channel 3
     202    mov     al, CLEAR_CH3_MASK_BIT
     203    out     MASK_REGISTER_DMA8_out, al      ; Enable DMA Channel 3
     204    sti                                     ; Enable interrupts
     205
     206
     207    ; XT-CFv2 will present data in 16-byte blocks, but byte count may not
     208    ; be divisable by 16 due to boundary crossing.  So catch any < 16-byte
     209    ; block by adding 15, then dividing bytes (in CX) by 16 to get the
     210    ; total block requests.  The 8237 is programmed with the actual byte
     211    ; count and will end the transfer by asserting TC when done.
     212    xor     ax, ax
     213    add     cx, BYTE 1 + 15     ; Number of BYTEs to xfer + 15
     214    adc     al, ah
     215    shr     ax, 1
     216    rcr     cx, 1
     217    eSHR_IM cx, 3               ; CX = Number of 16 byte blocks
     218    mov     dx, [di+DPT.wBasePort]
     219    add     dl, XTCF_CONTROL_REGISTER
     220
     221.MoreToDo:                      ; at this point, cx must be >0
     222    mov     al, 0x40            ; 0x40 = Raise DRQ and clear XT-CFv2 transfer counter
     223.NextDemandBlock:
     224    out     dx, al              ; get up to 16 bytes from XT-CF card
     225    loop    .NextDemandBlock    ; decrement CX and loop if <> 0
     226                                ; (Loop provides a wait-state between 16-byte blocks; do not unroll)
     227
     228.CleanUp:
     229    ; check the transfer is actually done - in case another DMA operation messed things up
     230    inc     cx                                      ; set up CX, in case we need to do an extra iteration
     231    in      al, STATUS_REGISTER_DMA8_in             ; get DMA status register
     232    test    al, FLG_CH3_HAS_REACHED_TERMINAL_COUNT  ; test DMA ch.3 TC bit
     233    jz      SHORT .MoreToDo                         ; it wasn't set so get more bytes
     234
     235.EndDMA:
     236    mov     al, 0x10            ;
     237    out     dx, al              ; set back to DMA enabled status
     238
     239    ; Check IDE Status Register for errors
     240    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_BSY)
     241    call    IdeWait_PollStatusFlagInBLwithTimeoutInBH
     242    pop     cx
     243    ret
     244
     245
     246;--------------------------------------------------------------------
     247; UpdateVariablesForSecondPageIfRequired
     248;   Parameters:
     249;       CX:     Number of BYTEs in first page - 1
     250;       SS:BP:  Ptr to DMAVARS
     251;   Returns:
     252;       CX:     Bytes left to transfer - 1 (if CF = 0)
     253;       CF:     0 if second DMA transfer required
     254;               1 if one DMA transfer was enough
     255;   Corrupts registers:
     256;       AX, (CX)
     257;--------------------------------------------------------------------
     258UpdateVariablesForSecondPageIfRequired:
     259    inc     cx                          ; BYTEs in first page
     260    jcxz    .FullPageXferred            ; 0 = 65536
     261
     262    ; Store total WORDs transferred so far
     263    mov     ax, cx
     264    shr     ax, 1                       ; BYTEs to WORDs
     265    mov     [bp+DMAVARS.wTotalWordsXferred], ax
     266
     267    ; Get bytes left to transfer for second DMA page
     268    mov     ax, [bp+DMAVARS.wBytesLeftToXferLessOne]
     269    sub     ax, cx
     270    jb      SHORT .OnePageWasEnough
     271
     272    ; Increment address
     273    add     [bp+DMAVARS.bbbPhysicalAddress], cx
     274    adc     BYTE [bp+DMAVARS.bbbPhysicalAddress+2], 0   ; Never sets CF
     275    xchg    cx, ax
     276    ret
     277
     278.FullPageXferred:
     279    mov     WORD [bp+DMAVARS.wTotalWordsXferred], 65536 / 2
     280    stc
     281.OnePageWasEnough:
     282    ret
Note: See TracChangeset for help on using the changeset viewer.