source: xtideuniversalbios/trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeDmaTransfer.asm @ 477

Last change on this file since 477 was 477, checked in by aitotat@…, 12 years ago

Changes to XTIDE Universal BIOS:

  • Added non-working DMA transfer code.
File size: 9.6 KB
Line 
1; Project name  :   XTIDE Universal BIOS
2; Description   :   IDE Device DMA transfer functions.
3
4;
5; XTIDE Universal BIOS and Associated Tools
6; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
7;
8; This program is free software; you can redistribute it and/or modify
9; it under the terms of the GNU General Public License as published by
10; the Free Software Foundation; either version 2 of the License, or
11; (at your option) any later version.
12;
13; This program is distributed in the hope that it will be useful,
14; but WITHOUT ANY WARRANTY; without even the implied warranty of
15; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16; GNU General Public License for more details.
17; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
18;
19
20; Structure containing variables for DMA transfer functions.
21; This struct must not be larger than IDEPACK without INTPACK.
22struc 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
27endstruc
28
29
30; Section containing code
31SECTION .text
32
33;--------------------------------------------------------------------
34; IdeDmaTransfer_StartWithCommandInAL
35;   Parameters:
36;       AL:     IDE command that was used to start the transfer
37;               (all PIO read and write commands including Identify Device)
38;       ES:SI:  Ptr to data buffer (not normalized)
39;       DS:DI:  Ptr to DPT (in RAMVARS segment)
40;       SS:BP:  Ptr to IDEPACK
41;   Returns:
42;       AH:     INT 13h Error Code
43;       CX:     Number of successfully transferred sectors
44;       CF:     Cleared if success, Set if error
45;   Corrupts registers:
46;       AL, BX, DX
47;--------------------------------------------------------------------
48ALIGN JUMP_ALIGN
49IdeDmaTransfer_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 TracBrowser for help on using the repository browser.