Changeset 479 in xtideuniversalbios


Ignore:
Timestamp:
Oct 21, 2012, 5:59:26 PM (11 years ago)
Author:
aitotat@…
google:author:
aitotat@gmail.com
Message:

Changes to XTIDE Universal BIOS:

  • Simplified non-working DMA code (same problem continues).
Location:
trunk/XTIDE_Universal_BIOS
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/XTIDE_Universal_BIOS/Inc/Controllers/XTCF.inc

    r473 r479  
    4545; 8-bit PIO transfers (port I/O) are used if Control Register is zero.
    4646; Any other value means DMA transfers (using DMA channel 3).
    47 XTCF_8BIT_PIO_MODE                  EQU     0
    48 XTCF_MEMORY_MAPPED_MODE             EQU     0A0h
     47XTCF_8BIT_PIO_MODE                      EQU     0
     48XTCF_DMA_MODE                           EQU     10h
     49XTCF_MEMORY_MAPPED_MODE                 EQU     0A0h
     50RAISE_DRQ_AND_CLEAR_XTCF_XFER_COUNTER   EQU     40h
    4951
    5052
  • trunk/XTIDE_Universal_BIOS/Inc/DmaController.inc

    r477 r479  
    8787
    8888
    89 ; Status Registers
     89; Status Registers (reading will clear Terminal Count flags)
    9090STATUS_REGISTER_DMA8_in         EQU     COMMAND_REGISTER_DMA8_out
    9191    FLG_CH1_HAS_REACHED_TERMINAL_COUNT      EQU     (1<<1)
  • trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeDmaTransfer.asm

    r478 r479  
    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,
     23    .wTotalBytesXferred         resb    2   ; 0-1,
     24    .wBytesLeftToXfer           resb    2   ; 2-3, 0 = 65536
    2525    .bbbPhysicalAddress         resb    3   ; 4-6,
    2626                                resb    1   ; 7, IDEPACK.bDeviceControl
     
    5050    ; Initialize DMAVARS
    5151    xor     cx, cx
    52     mov     [bp+DMAVARS.wTotalWordsXferred], cx
     52    mov     [bp+DMAVARS.wTotalBytesXferred], cx
    5353    mov     ch, [bp+IDEPACK.bSectorCount]   ; CX = WORDs to transfer
    5454    shl     cx, 1                           ; WORDs to BYTEs, 0 = 65536
    55     dec     cx
    56     mov     [bp+DMAVARS.wBytesLeftToXferLessOne], cx
     55    mov     [bp+DMAVARS.wBytesLeftToXfer], cx
    5756
    5857    ; Convert Segment:Offset type pointer to physical address
     
    6059    mov     cx, es
    6160%rep 4
    62     shl cx, 1
    63     rcl bx, 1
     61    shl     cx, 1
     62    rcl     bx, 1
    6463%endrep
    6564    add     cx, si
     
    6867    mov     [bp+DMAVARS.bbbPhysicalAddress+2], bl
    6968
    70     ; Calculate bytes for first page - 1
     69    ; Calculate bytes for first page
    7170    neg     cx  ; Max number of bytes for first page, 0 = 65536
    72     dec     cx
    73     MIN_U   cx, [bp+DMAVARS.wBytesLeftToXferLessOne]
     71    MIN_U   cx, [bp+DMAVARS.wBytesLeftToXfer]
    7472
    7573    ; Are we reading or writing?
     74    mov     bl, CHANNEL_3 | READ | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE   ; Assume write command
    7675    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
     76    jnz     SHORT TransferBlockToOrFromXTCF
    7877    cmp     al, COMMAND_WRITE_MULTIPLE
    79     je      SHORT WriteBlockToXTCF
    80     ; Fall to ReadBlockFromXTCF
    81 
    82 
    83 ;--------------------------------------------------------------------
    84 ; ReadBlockFromXTCF
     78    je      SHORT TransferBlockToOrFromXTCF
     79
     80    ; Read command
     81    mov     bl, CHANNEL_3 | WRITE | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE
     82    ; Fall to TransferBlockToOrFromXTCF
     83
     84
     85;--------------------------------------------------------------------
     86; TransferBlockToOrFromXTCF
    8587;   Parameters:
    86 ;       CX:     Bytes in first page - 1
     88;       BX:     Mode byte for DMA Mode Register
     89;       CX:     Bytes in first page
    8790;       DS:DI:  Ptr to DPT (in RAMVARS segment)
    8891;       SS:BP:  Ptr to DMAVARS
     
    9699;       AL, BX, DX
    97100;--------------------------------------------------------------------
    98 ReadBlockFromXTCF:
     101TransferBlockToOrFromXTCF:
    99102    ; 8-bit DMA transfers must be done withing 64k physical page.
    100103    ; We support maximum of 128 sectors (65536 bytes) per one INT 13h call
     
    102105
    103106    ; Transfer first DMA page
    104     mov     ah, CHANNEL_3 | WRITE | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE
    105     call    StartDMAtransferForXTCFwithDmaModeInAH
    106     call    UpdateVariablesForSecondPageIfRequired
    107     jc      SHORT ReturnNumberOfSectorsXferred      ; Second page not needed
     107    call    StartDMAtransferForXTCFwithDmaModeInBL
     108    jcxz    .ReturnNumberOfSectorsXferred           ; One page was enough (128 sectors)
     109    mov     [bp+DMAVARS.wTotalBytesXferred], cx     ; Store total BYTEs transferred so far
     110
     111    ; Get bytes left to transfer for second DMA page
     112    mov     ax, [bp+DMAVARS.wBytesLeftToXfer]
     113    sub     ax, cx
     114    jz      SHORT .ReturnNumberOfSectorsXferred     ; Transfer was within 64k page
     115
     116    ; Increment address
     117    xchg    cx, ax
     118    add     [bp+DMAVARS.bbbPhysicalAddress], ax
     119    adc     [bp+DMAVARS.bbbPhysicalAddress+2], bh   ; Never sets CF
    108120
    109121    ; Transfer second DMA page if necessary (always less than 64k)
    110     mov     ah, CHANNEL_3 | WRITE | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE
    111     call    StartDMAtransferForXTCFwithDmaModeInAH
    112     ; Fall to BothDmaPagesTransferred
    113 
    114 BothDmaPagesTransferred:
    115     inc     cx          ; Never overflows since second page always less than 64k
    116     shr     cx, 1       ; BYTEs to WORDs
    117     add     [bp+DMAVARS.wTotalWordsXferred], cx
    118 ReturnNumberOfSectorsXferred:
     122    call    StartDMAtransferForXTCFwithDmaModeInBL
     123    add     [bp+DMAVARS.wTotalBytesXferred], cx
     124
     125.ReturnNumberOfSectorsXferred:
     126    ; Check errors
    119127    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_BSY)
    120128    call    IdeWait_PollStatusFlagInBLwithTimeoutInBH
    121129    jc      SHORT .ErrorInTransfer
    122     mov     cx, [bp+DMAVARS.wTotalWordsXferred]
    123     xchg    cl, ch      ; WORDs to sectors
     130
     131    ; Return number of sectors transferred
     132    mov     cx, [bp+DMAVARS.wTotalBytesXferred]
     133    jcxz    .FullPageOf128SectorsXferred
     134%ifdef USE_186
     135    shr     cx, 9       ; BYTEs to sectors
     136%else
     137    xchg    cl, ch      ; BYTEs to WORDs
     138    shr     cx, 1       ; WORDs to sectors
     139%endif
     140    clc
     141    ret
     142
     143.FullPageOf128SectorsXferred:
     144    mov     cx, 128
    124145    ret
    125146
    126147.ErrorInTransfer:
    127     mov     cx, 0       ; No way to know how many bytes got xferred
    128     ret
    129 
    130 
    131 ;--------------------------------------------------------------------
    132 ; WriteBlockToXTCF
     148    mov     cx, 0       ; No way to know how many sectors got transferred
     149    ret
     150
     151
     152;--------------------------------------------------------------------
     153; StartDMAtransferForXTCFwithDmaModeInBL
    133154;   Parameters:
    134 ;       CX:     Bytes in first page - 1
     155;       BL:     Byte for DMA Mode Register
     156;       CX:     Number of BYTEs to transfer
    135157;       DS:DI:  Ptr to DPT (in RAMVARS segment)
    136158;       SS:BP:  Ptr to DMAVARS
    137 ;   Returns:
    138 ;       DS:DI:  Ptr to DPT (in RAMVARS segment)
    139 ;       AH:     BIOS Error code
    140 ;       CX:     Number of successfully transferred sectors
    141 ;       CF:     0 if transfer successful
    142 ;               1 if any error
    143 ;   Corrupts registers:
    144 ;       AL, BX, DX
    145 ;--------------------------------------------------------------------
    146 ALIGN JUMP_ALIGN
    147 WriteBlockToXTCF:
    148     ; Transfer first DMA page
    149     mov     ah, CHANNEL_3 | READ | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE
    150     call    StartDMAtransferForXTCFwithDmaModeInAH
    151     call    UpdateVariablesForSecondPageIfRequired
    152     jc      SHORT ReturnNumberOfSectorsXferred      ; Second page not needed
    153 
    154     ; Transfer second DMA page if necessary (always less than 64k)
    155     mov     ah, CHANNEL_3 | READ | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE
    156     call    StartDMAtransferForXTCFwithDmaModeInAH
    157     jmp     SHORT BothDmaPagesTransferred
    158 
    159 
    160 ;--------------------------------------------------------------------
    161 ; StartDMAtransferForXTCFwithDmaModeInAH
    162 ;   Parameters:
    163 ;       AH:     Byte for DMA Mode Register
    164 ;       CX:     Number of BYTEs to transfer - 1
    165 ;       DS:DI:  Ptr to DPT (in RAMVARS segment)
    166159;   Returns:
    167160;       Nothing
     
    170163;--------------------------------------------------------------------
    171164ALIGN JUMP_ALIGN
    172 StartDMAtransferForXTCFwithDmaModeInAH:
    173     push    cx
    174 
     165StartDMAtransferForXTCFwithDmaModeInBL:
    175166    ; Program 8-bit DMA Controller
    176 
    177167    ; Disable Interrupts and DMA Channel 3 during DMA setup
    178168    cli                                     ; Disable interrupts
     
    181171
    182172    ; Set DMA Mode (read or write using channel 3)
    183     mov     al, ah
     173    mov     al, bl
    184174    out     MODE_REGISTER_DMA8_out, al
    185175
     
    196186    out     CLEAR_FLIPFLOP_DMA8_out, al     ; Reset flip-flop to low byte
    197187    mov     ax, cx
     188    dec     ax                              ; DMA controller is programmed for one byte less
    198189    out     BASE_AND_CURRENT_COUNT_REGISTER_DMA8_CH3_out, al    ; Low byte
    199190    mov     al, ah
     
    206197
    207198
    208     ; XT-CFv2 will present data in 16-byte blocks, but byte count may not
    209     ; be divisable by 16 due to boundary crossing.  So catch any < 16-byte
    210     ; block by adding 15, then dividing bytes (in CX) by 16 to get the
    211     ; total block requests.  The 8237 is programmed with the actual byte
    212     ; count and will end the transfer by asserting TC when done.
    213     add     cx, BYTE 1 + 15     ; Number of BYTEs to xfer + 15 (bit 16 in CF)
    214     rcr     cx, 1
    215     eSHR_IM cx, 3               ; CX = Number of 16 byte blocks
     199    ; XT-CF transfers 16 bytes at a time. We need to manually
     200    ; start transfer for every block.
    216201    mov     dx, [di+DPT.wBasePort]
    217202    add     dl, XTCF_CONTROL_REGISTER
    218 
    219 .MoreToDo:                      ; at this point, cx must be >0
    220     mov     al, 40h             ; 0x40 = Raise DRQ and clear XT-CFv2 transfer counter
    221 .NextDemandBlock:
    222     out     dx, al              ; get up to 16 bytes from XT-CF card
    223     loop    .NextDemandBlock    ; decrement CX and loop if <> 0
    224                                 ; (Loop provides a wait-state between 16-byte blocks; do not unroll)
    225 
    226 .CleanUp:
    227     ; check the transfer is actually done - in case another DMA operation messed things up
    228     inc     cx                                      ; set up CX, in case we need to do an extra iteration
    229     in      al, STATUS_REGISTER_DMA8_in             ; get DMA status register
    230     test    al, FLG_CH3_HAS_REACHED_TERMINAL_COUNT  ; test DMA ch.3 TC bit
    231     jz      SHORT .MoreToDo                         ; it wasn't set so get more bytes
    232 
    233 .EndDMA:
    234     mov     al, 10h             ;
    235     out     dx, al              ; set back to DMA enabled status
    236     pop     cx
    237     ret
    238 
    239 
    240 ;--------------------------------------------------------------------
    241 ; UpdateVariablesForSecondPageIfRequired
    242 ;   Parameters:
    243 ;       CX:     Number of BYTEs in first page - 1
    244 ;       SS:BP:  Ptr to DMAVARS
    245 ;   Returns:
    246 ;       CX:     Bytes left to transfer - 1 (if CF = 0)
    247 ;       CF:     0 if second DMA transfer required
    248 ;               1 if one DMA transfer was enough
    249 ;   Corrupts registers:
    250 ;       AX, (CX)
    251 ;--------------------------------------------------------------------
    252203ALIGN JUMP_ALIGN
    253 UpdateVariablesForSecondPageIfRequired:
    254     inc     cx                          ; BYTEs in first page
    255     jcxz    .FullPageXferred            ; 0 = 65536
    256 
    257     ; Store total WORDs transferred so far
    258     mov     ax, cx
    259     shr     ax, 1                       ; BYTEs to WORDs
    260     mov     [bp+DMAVARS.wTotalWordsXferred], ax
    261 
    262     ; Get bytes left to transfer for second DMA page
    263     mov     ax, [bp+DMAVARS.wBytesLeftToXferLessOne]
    264     sub     ax, cx
    265     jb      SHORT .OnePageWasEnough
    266 
    267     ; Increment address
    268     add     [bp+DMAVARS.bbbPhysicalAddress], cx
    269     adc     BYTE [bp+DMAVARS.bbbPhysicalAddress+2], 0   ; Never sets CF
    270     xchg    cx, ax
    271     ret
    272 
    273 .FullPageXferred:
    274     mov     WORD [bp+DMAVARS.wTotalWordsXferred], 65536 / 2
    275     stc
    276 .OnePageWasEnough:
    277     ret
    278 
    279 
    280 
    281 
    282 %if 0
    283 ;--------------------------------------------------------------------
    284 ALIGN JUMP_ALIGN
    285 ReadBlockFromXTCF:
    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
    346 ALIGN 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 ;--------------------------------------------------------------------
    364 ALIGN JUMP_ALIGN
    365 WriteBlockToXTCF:
    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
    421 ALIGN 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 
    464 ALIGN JUMP_ALIGN
    465 DemandBasedTransferWithBytesInCX:
    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 
     204.TransferNextBlock:
     205    mov     al, RAISE_DRQ_AND_CLEAR_XTCF_XFER_COUNTER
     206    cli                                 ; We want no ISR to read DMA Status Register before we do
     207    out     dx, al                      ; Transfer up to 16 bytes to/from XT-CF card
     208    ; * Here XT-CF sets CPU to wait states during transfer *
     209    in      al, STATUS_REGISTER_DMA8_in
     210    sti
     211    test    al, FLG_CH3_HAS_REACHED_TERMINAL_COUNT
     212    jz      SHORT .TransferNextBlock    ; All bytes transferred?
     213
     214    ; Restore XT-CF to normal operation
     215    mov     al, XTCF_DMA_MODE
     216    out     dx, al
     217    ret
Note: See TracChangeset for help on using the changeset viewer.