Changeset 478 in xtideuniversalbios


Ignore:
Timestamp:
Oct 20, 2012, 7:37:28 PM (11 years ago)
Author:
aitotat@…
google:author:
aitotat@gmail.com
Message:

Changes to XTIDE Universal BIOS:

  • Fixes to DMA transfers but it still does not work.
File:
1 edited

Legend:

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

    r477 r478  
    104104    mov     ah, CHANNEL_3 | WRITE | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE
    105105    call    StartDMAtransferForXTCFwithDmaModeInAH
    106     jc      SHORT ReturnNumberOfSectorsXferred
     106    call    UpdateVariablesForSecondPageIfRequired
     107    jc      SHORT ReturnNumberOfSectorsXferred      ; Second page not needed
    107108
    108109    ; Transfer second DMA page if necessary (always less than 64k)
    109     call    UpdateVariablesForSecondPageIfRequired
    110     jc      SHORT SecondDmaPageIsNotRequired
    111110    mov     ah, CHANNEL_3 | WRITE | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE
    112111    call    StartDMAtransferForXTCFwithDmaModeInAH
    113     jc      SHORT ReturnNumberOfSectorsXferred
    114     ; Fall to BothDmaPagesTransferredSuccessfully
    115 
    116 BothDmaPagesTransferredSuccessfully:
     112    ; Fall to BothDmaPagesTransferred
     113
     114BothDmaPagesTransferred:
    117115    inc     cx          ; Never overflows since second page always less than 64k
    118116    shr     cx, 1       ; BYTEs to WORDs
    119117    add     [bp+DMAVARS.wTotalWordsXferred], cx
    120 SecondDmaPageIsNotRequired:
    121     xor     ah, ah
    122118ReturnNumberOfSectorsXferred:
     119    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_BSY)
     120    call    IdeWait_PollStatusFlagInBLwithTimeoutInBH
     121    jc      SHORT .ErrorInTransfer
    123122    mov     cx, [bp+DMAVARS.wTotalWordsXferred]
    124123    xchg    cl, ch      ; WORDs to sectors
     124    ret
     125
     126.ErrorInTransfer:
     127    mov     cx, 0       ; No way to know how many bytes got xferred
    125128    ret
    126129
     
    141144;       AL, BX, DX
    142145;--------------------------------------------------------------------
     146ALIGN JUMP_ALIGN
    143147WriteBlockToXTCF:
    144148    ; Transfer first DMA page
    145149    mov     ah, CHANNEL_3 | READ | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE
    146150    call    StartDMAtransferForXTCFwithDmaModeInAH
    147     jc      SHORT ReturnNumberOfSectorsXferred
     151    call    UpdateVariablesForSecondPageIfRequired
     152    jc      SHORT ReturnNumberOfSectorsXferred      ; Second page not needed
    148153
    149154    ; Transfer second DMA page if necessary (always less than 64k)
    150     call    UpdateVariablesForSecondPageIfRequired
    151     jc      SHORT SecondDmaPageIsNotRequired
    152155    mov     ah, CHANNEL_3 | READ | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE
    153156    call    StartDMAtransferForXTCFwithDmaModeInAH
    154     jc      SHORT ReturnNumberOfSectorsXferred
    155     jmp     SHORT BothDmaPagesTransferredSuccessfully
     157    jmp     SHORT BothDmaPagesTransferred
    156158
    157159
     
    163165;       DS:DI:  Ptr to DPT (in RAMVARS segment)
    164166;   Returns:
    165 ;       AH:     BIOS Error code
    166 ;       CF:     0 if transfer successful
    167 ;               1 if any error
     167;       Nothing
    168168;   Corrupts registers:
    169 ;       AL, BX, DX
    170 ;--------------------------------------------------------------------
     169;       AL, DX
     170;--------------------------------------------------------------------
     171ALIGN JUMP_ALIGN
    171172StartDMAtransferForXTCFwithDmaModeInAH:
    172173    push    cx
     
    210211    ; total block requests.  The 8237 is programmed with the actual byte
    211212    ; 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
     213    add     cx, BYTE 1 + 15     ; Number of BYTEs to xfer + 15 (bit 16 in CF)
    216214    rcr     cx, 1
    217215    eSHR_IM cx, 3               ; CX = Number of 16 byte blocks
     
    220218
    221219.MoreToDo:                      ; at this point, cx must be >0
    222     mov     al, 0x40            ; 0x40 = Raise DRQ and clear XT-CFv2 transfer counter
     220    mov     al, 40h             ; 0x40 = Raise DRQ and clear XT-CFv2 transfer counter
    223221.NextDemandBlock:
    224222    out     dx, al              ; get up to 16 bytes from XT-CF card
     
    234232
    235233.EndDMA:
    236     mov     al, 0x10            ;
     234    mov     al, 10h             ;
    237235    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
    242236    pop     cx
    243237    ret
     
    256250;       AX, (CX)
    257251;--------------------------------------------------------------------
     252ALIGN JUMP_ALIGN
    258253UpdateVariablesForSecondPageIfRequired:
    259254    inc     cx                          ; BYTEs in first page
     
    281276.OnePageWasEnough:
    282277    ret
     278
     279
     280
     281
     282%if 0
     283;--------------------------------------------------------------------
     284ALIGN JUMP_ALIGN
     285ReadBlockFromXTCF:
     286;   Parameters:
     287;       CX:     Block size in 512 byte sectors (1..64)
     288;       DX:     IDE Data port address
     289;       ES:DI:      Normalized ptr to buffer to receive data
     290;   Returns:
     291;       Nothing
     292;   Corrupts registers:
     293;       AX, BX, CX
     294
     295    ; use config register to see what we're doing:
     296    ; < A0 = DMA via ch.3
     297    ; > A0 = mem-mapped IO (word-length)
     298    ;
     299   
     300    or      dl, 0x1f    ; XT-CF board control register address (base + 1fh)
     301    in      al, dx      ; get control register
     302    cmp     al, 0xA0    ; test al against 0xA0:
     303    jae .MemMapIO       ; - use memory-mapped IO if >=A0h
     304    or      al, al      ; test al against 0 (quicker than cmp):
     305    jz  .PortIO         ; - use port-based IO (the default) if it was zero
     306                    ; otherwise, 0 < al < A0h, so fall to DMA mode
     307
     308.DMAIO:
     309    ; work out how much we're transferring.  We can't cross a physical 64KB boundary
     310    ; but since the max transfer size is 64KB, we only ever need to do one or two DMA operations
     311   
     312    ; first, normalise the pointer - we need ES to be a physical page address
     313   
     314    mov     ax, es
     315    mov     ch, cl          ; max sectors is 128; also sectors << 8 = words, and we need cl...
     316    mov     cl, 4           ; ... for the rotate parameter
     317    rol     ax, cl          ; ax = es rol 4
     318    mov     bx, ax          ; bx = ax = es rol 4
     319    and     al, 0xf0        ; ax (15..4) now has es (11..0)
     320    and     bx, 0x000f      ; bx (3..0) now has es (15..12)
     321    add     di, ax          ; add offset portion of es (in ax) to di...
     322    adc     bl, 0           ; ... and if it overflowed, increment bl
     323    mov     es, bx          ; es now has physical segment address >> 12
     324
     325    ; now check how much we can transfer without crossing a physical page boundary
     326    mov     bx, di          ;
     327    not     bx          ; 65535 - di = number of bytes we could transfer -1 now in bx
     328    xor     cl, cl          ; zero cl; cx now has transfer size in words
     329    shl     cx, 1           ; words to bytes; CX has total byte count
     330    dec     cx          ; calling DMA with 0 implies 1 byte transferred (so max is 64k exactly)
     331    cmp     bx, cx          ; can we do it in one hit?
     332    jae .LastDMA
     333
     334    ; at this point, the (bytes-1) for this transfer are in bx, total byte count -1 in cx
     335    ; and we need to do 2 DMA operations as the buffer straddles a physical 64k boundary
     336   
     337    sub     cx, bx          ; cx has bytes for 2nd transfer (as (x-1)-(y-1) = x-y)
     338    dec     cx          ; cx has bytes-1 for 2nd transfer
     339    xchg        bx, cx          ; bx = bytes-1 for 2nd transfer; cx = bytes-1 for this transfer
     340    mov     ah, 0x07        ; request a read DMA transfer
     341    call    DemandBasedTransferWithBytesInCX
     342
     343    ; DMA 1 of 2 done - set up registers for second transfer
     344    mov     cx, bx          ; bytes-1 for the 2nd transfer back in cx
     345    ; 1st transfer is done, now for the second
     346ALIGN JUMP_ALIGN
     347.LastDMA:
     348    ; at this point, (bytes-1) for this transfer are in CX
     349    mov     ah, 0x07        ; request a read DMA transfer
     350    call    DemandBasedTransferWithBytesInCX
     351
     352    ; transfer is done, set ES back to a physical segment address
     353    mov     ax, es          ;
     354    mov     cl, 4           ;
     355    ror     ax, cl          ; ax = es ror 4.  Since ES was >> 12 (for DMA controller) so
     356    mov     es, ax          ; now it's back to normal format
     357   
     358    ; pointer format restored - we're done
     359    and     dl, 0xE0        ; restore register values
     360    ret
     361
     362
     363;--------------------------------------------------------------------
     364ALIGN JUMP_ALIGN
     365WriteBlockToXTCF:
     366    ; use config register to see what we're doing:
     367    ; 0 = not set; use byte-length port-IO
     368    ; < A0 = DMA via ch.3
     369    ; > A0 = mem-mapped IO (word-length)
     370    ;
     371   
     372    or      dl, 0x1f    ; XT-CF board control register address (base + 1fh)
     373    in      al, dx      ; get control register
     374    cmp     al, 0xA0    ; test al against 0xA0:
     375    jae .MemMapIO       ; - use memory-mapped IO if >=A0h
     376    or      al, al      ; test al against 0 (quicker than cmp):
     377    jz  .PortIO         ; - use port-based IO (the default) if it was zero
     378                    ; otherwise, 0 < al < A0h, so fall to DMA mode
     379
     380.DMAIO:
     381    ; work out how much we're transferring.  We can't cross a physical 64KB boundary
     382    ; but since the max transfer size is 64KB, we only ever need to do one or two DMA operations
     383
     384    push        di          ; save di...
     385    mov     di, si          ; ...and move si to di (for DMA routine)
     386   
     387    ; first, normalise the pointer - we need ES to be a physical page address
     388   
     389    mov     ax, es
     390    mov     ch, cl          ; max sectors is 64; also sectors << 8 = words, and we need cl...
     391    mov     cl, 4           ; ... for the rotate parameter
     392    rol     ax, cl          ; ax = es rol 4
     393    mov     bx, ax          ; bx = ax = es rol 4
     394    and     al, 0xf0        ; ax (15..4) now has es (11..0)
     395    and     bx, 0x000f      ; bx (3..0) now has es (15..12)
     396    add     di, ax          ; add offset portion of es (in ax) to si...
     397    adc     bl, 0           ; ... and if it overflowed, increment bl
     398    mov     es, bx          ; es now has physical segment address >> 12
     399
     400    ; now check how much we can transfer without crossing a physical page boundary
     401    mov     bx, di          ;
     402    not     bx          ; 65535 - di = number of bytes we could transfer -1 now in bx
     403    xor     cl, cl          ; zero cl; cx now has transfer size in words
     404    shl     cx, 1           ; words to bytes; CX has total byte count
     405    dec     cx          ; calling DMA with 0 implies 1 byte transferred (so max is 64k exactly)
     406    cmp     bx, cx          ; can we do it in one hit?
     407    jae .LastDMA
     408
     409    ; at this point, the (bytes-1) for this transfer are in bx, total byte count -1 in cx
     410    ; and we need to do 2 DMA operations as the buffer straddles a physical 64k boundary
     411   
     412    sub     cx, bx          ; cx has bytes for 2nd transfer (as (x-1)-(y-1) = x-y)
     413    dec     cx          ; cx has bytes-1 for 2nd transfer
     414    xchg        bx, cx          ; bx = bytes-1 for 2nd transfer; cx = bytes-1 for this transfer
     415    mov     ah, 0x0b        ; request a write DMA transfer
     416    call    DemandBasedTransferWithBytesInCX
     417
     418    ; DMA 1 of 2 done - set up registers for second transfer
     419    mov     cx, bx          ; bytes-1 for the 2nd transfer back in cx
     420    ; 1st transfer is done, now for the second
     421ALIGN JUMP_ALIGN
     422.LastDMA:
     423    ; at this point, (bytes-1) for this transfer are in CX
     424    mov     ah, 0x0b        ; request a write DMA transfer
     425    call    DemandBasedTransferWithBytesInCX
     426
     427    ; transfer is done, set ES back to a physical segment address
     428    mov     ax, es          ;
     429    mov     cl, 4           ;
     430    ror     ax, cl          ; ax = es ror 4.  Since ES was >> 12 (for DMA controller) so
     431    mov     es, ax          ; now it's back to normal format
     432
     433    mov     si, di          ; move di (used by DMA routine) back to si
     434   
     435    ; pointers updated - we're done
     436    pop     di          ;
     437    and     dl, 0xE0        ; restore register values
     438    ret
     439
     440
     441; -------------------------------------------------------------------------------------------------------------
     442;
     443; DemandBasedTransferWithBytesInCX
     444; ================================
     445;
     446; DMA Transfer function:
     447; - AH = 0x07 for read from media - demand/inc/non-auto-init/write(to memory)/ch3
     448; - AH = 0x0b for write to media  - demand/inc/non-auto-init/read(from memory)/ch3
     449; - byte count -1 in CX
     450; - XT-CF control register in DX
     451; - physical segment address in ES *but* high four bits in low four bits (i.e. shr 12)
     452; - buffer offset (from physical segment) in DI
     453;
     454; Note - cannot cross a physical segment boundary, but ES will be updated (maintaining the >>12
     455;        format) if after the last byte has been transferred the pointer needs to be updated to
     456;        the next physical segment.
     457;
     458; Preserves:    BX, DX
     459; Corrupts:     AX, CX
     460; Updates:  ES, DI
     461;
     462; -------------------------------------------------------------------------------------------------------------
     463
     464ALIGN JUMP_ALIGN
     465DemandBasedTransferWithBytesInCX:
     466    cli                 ; clear interrupts while we set up the actual DMA transfer
     467    mov     al, 0x07        ; mask (4) + channel (3)
     468    out     0x0a, al        ; send to DMA mask register
     469    mov     al, ah          ; retrieve the transfer mode passed in...
     470    out     0x0b, al        ; and send mode to DMA mode register
     471    out     0x0c, al        ; clear DMA byte-order flip-flop (write any value)
     472    mov     ax, di          ; di has buffer offset
     473    out     0x06, al        ;
     474    mov     al, ah          ;
     475    out     0x06, al        ; send offset to DMA controller address port for ch.3
     476    mov     ax, es          ; es has physical segment address >> 12
     477    out     0x82, al        ; send the relavent 4-bits to DMA controller page for ch.3
     478    out     0x0c, al        ; clear DMA byte-order flip-flop (write any value)
     479    mov     ax, cx          ; byte count to AX
     480    out     0x07, al        ; send low-byte of transfer size in bytes...
     481    mov     al, ah          ; mov high byte to low byte...
     482    out     0x07, al        ; ...and high byte to DMA controller count port for ch.3
     483    mov     al, 0x03        ; clear bit mask (0) + channel (3)
     484    out     0x0a, al        ; send to DMA mask register - enable the DMA!
     485    sti                 ; enable interrutps; let the CPU see to anything outstanding
     486
     487    mov     ax, es          ; update ES:DI (values have been loaded into DMA controller)
     488    inc     cx          ; CX back to actual bytes
     489    add     di, cx          ; add bytes to DI...
     490    adc     ax, 0           ; ...and if it overflowed, increment...
     491    mov     es, ax          ; ...ES
     492
     493    add     cx, 15          ; XT-CFv2 will present data in 16-byte blocks, but byte count may not
     494    shr     cx, 1           ; be divisable by 16 due to boundary crossing.  So catch any < 16-byte
     495    shr     cx, 1           ; block by adding 15, then dividing bytes (in CX) by 16 to get the
     496    shr     cx, 1           ; total block requests.  The 8237 is programmed with the actual byte
     497    shr     cx, 1           ; count and will end the transfer by asserting TC when done.
     498
     499.MoreToDo:                  ; at this point, cx must be >0
     500    mov     al, 0x40        ; 0x40 = Raise DRQ and clear XT-CFv2 transfer counter
     501.NextDemandBlock:
     502    out     dx, al          ; get up to 16 bytes from XT-CF card
     503    loop    .NextDemandBlock        ; decrement CX and loop if <> 0
     504                        ; (Loop provides a wait-state between 16-byte blocks; do not unroll)
     505.CleanUp:
     506    ; check the transfer is actually done - in case another DMA operation messed things up
     507    inc     cx          ; set up CX, in case we need to do an extra iteration
     508    in      al, 0x08        ; get DMA status register
     509    and     al, 0x08        ; test DMA ch.3 TC bit
     510    jz  .MoreToDo           ; it wasn't set so get more bytes
     511.EndDMA:
     512    mov     al, 0x10        ;
     513    out     dx, al          ; set back to DMA enabled status
     514    ret
     515   
     516%endif ; 0
     517
     518
     519
Note: See TracChangeset for help on using the changeset viewer.