source: xtideuniversalbios/trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeTransfer.asm @ 361

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

Changes to XTIDE Universal BIOS:

  • Added untested support for Fast XTIDE (CPLD v2 project).
  • Removed 8-bit single port device since there does not seem to be any need for one.
File size: 11.2 KB
Line 
1; Project name  :   XTIDE Universal BIOS
2; Description   :   IDE Device transfer functions.
3
4; Structure containing variables for PIO transfer functions.
5; This struct must not be larger than IDEPACK without INTPACK.
6struc PIOVARS
7    .wWordsInBlock          resb    2   ; 0, Block size in WORDs
8    .wWordsLeft             resb    2   ; 2, WORDs left to transfer
9    .wWordsDone             resb    2   ; 4, Number of sectors xferred
10                            resb    1   ; 6,
11                            resb    1   ; 7, IDEPACK.bDeviceControl
12    .wDataPort              resb    2   ; 8, IDE Data Port
13    .fnXfer                 resb    2   ; 10, Offset to transfer function
14endstruc
15
16
17; Section containing code
18SECTION .text
19
20;--------------------------------------------------------------------
21; IdeTransfer_StartWithCommandInAL
22;   Parameters:
23;       AL:     IDE command that was used to start the transfer
24;               (all PIO read and write commands including Identify Device)
25;       ES:SI:  Ptr to normalized data buffer
26;       DS:DI:  Ptr to DPT (in RAMVARS segment)
27;       SS:BP:  Ptr to IDEPACK
28;   Returns:
29;       AH:     INT 13h Error Code
30;       CX:     Number of successfully transferred sectors
31;       CF:     Cleared if success, Set if error
32;   Corrupts registers:
33;       AL, BX, DX, SI, ES
34;--------------------------------------------------------------------
35ALIGN JUMP_ALIGN
36IdeTransfer_StartWithCommandInAL:
37    ; Are we reading or writing?
38    test    al, 16  ; Bit 4 is cleared on all the read commands but set on 3 of the 4 write commands
39    mov     ah, [bp+IDEPACK.bSectorCount]
40    jnz     SHORT WriteToDrive
41    cmp     al, COMMAND_WRITE_MULTIPLE
42    je      SHORT WriteToDrive
43    ; Fall to ReadFromDrive
44
45;--------------------------------------------------------------------
46; ReadFromDrive
47;   Parameters:
48;       AH:     Number of sectors to transfer (1...128)
49;       ES:SI:  Normalized ptr to buffer to receive data
50;       DS:DI:  Ptr to DPT (in RAMVARS segment)
51;       SS:BP:  Ptr to PIOVARS
52;   Returns:
53;       DS:DI:  Ptr to DPT (in RAMVARS segment)
54;       AH:     BIOS Error code
55;       CX:     Number of successfully transferred sectors
56;       CF:     0 if transfer successful
57;               1 if any error
58;   Corrupts registers:
59;       AL, BX, DX, SI, ES
60;--------------------------------------------------------------------
61ReadFromDrive:
62    ; Prepare to read data to ESSI
63    mov     bx, g_rgfnPioRead
64    call    InitializePiovarsInSSBPwithSectorCountInAH
65
66    ; Wait until drive is ready to transfer
67    call    IdeWait_IRQorDRQ                    ; Wait until ready to transfer
68    jc      SHORT ReturnWithTransferErrorInAH
69    xchg    si, di                              ; ES:DI now points buffer
70
71    mov     cx, [bp+PIOVARS.wWordsInBlock]
72
73ALIGN JUMP_ALIGN
74.ReadNextBlockFromDrive:
75    mov     dx, [bp+PIOVARS.wDataPort]
76    cmp     [bp+PIOVARS.wWordsLeft], cx
77    jbe     SHORT .ReadLastBlockFromDrive
78    call    [bp+PIOVARS.fnXfer]
79
80    ; Wait until ready for next block and check for errors
81    xchg    di, si                              ; DS:DI now points DPT
82    call    IdeWait_IRQorDRQ                    ; Wait until ready to transfer
83    jc      SHORT ReturnWithTransferErrorInAH
84    xchg    si, di                              ; ES:DI now points buffer
85
86    ; Increment number of successfully read WORDs
87    mov     cx, [bp+PIOVARS.wWordsInBlock]
88    sub     [bp+PIOVARS.wWordsLeft], cx
89    add     [bp+PIOVARS.wWordsDone], cx
90    jmp     SHORT .ReadNextBlockFromDrive
91
92ALIGN JUMP_ALIGN
93.ReadLastBlockFromDrive:
94    mov     cx, [bp+PIOVARS.wWordsLeft]
95    call    [bp+PIOVARS.fnXfer]                 ; Transfer possibly partial block
96
97    ; Check for errors in last block
98    mov     di, si                              ; DS:DI now points DPT
99CheckErrorsAfterTransferringLastBlock:
100    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRDY)
101    call    IdeWait_PollStatusFlagInBLwithTimeoutInBH
102
103    ; Return number of successfully read sectors
104ReturnWithTransferErrorInAH:
105    mov     cx, [bp+PIOVARS.wWordsDone]
106    jc      SHORT .ConvertTransferredWordsInCXtoSectors
107    add     cx, [bp+PIOVARS.wWordsLeft]         ; Never sets CF
108.ConvertTransferredWordsInCXtoSectors:
109    xchg    cl, ch
110    ret
111
112
113;--------------------------------------------------------------------
114; WriteToDrive
115;   Parameters:
116;       AH:     Number of sectors to transfer (1...128)
117;       DS:DI:  Ptr to DPT (in RAMVARS segment)
118;       ES:SI:  Normalized ptr to buffer containing data
119;       SS:BP:  Ptr to PIOVARS
120;   Returns:
121;       AH:     BIOS Error code
122;       CX:     Number of successfully transferred sectors
123;       CF:     0 if transfer successful
124;               1 if any error
125;   Corrupts registers:
126;       AL, BX, DX, SI, ES
127;--------------------------------------------------------------------
128ALIGN JUMP_ALIGN
129WriteToDrive:
130    ; Prepare to write data from ESSI
131    mov     bx, g_rgfnPioWrite
132    call    InitializePiovarsInSSBPwithSectorCountInAH
133
134    ; Always poll when writing first block (IRQs are generated for following blocks)
135    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
136    call    IdeWait_PollStatusFlagInBLwithTimeoutInBH
137    jc      SHORT ReturnWithTransferErrorInAH
138
139    mov     cx, [bp+PIOVARS.wWordsInBlock]
140
141ALIGN JUMP_ALIGN
142.WriteNextBlockToDrive:
143    mov     dx, [bp+PIOVARS.wDataPort]
144    cmp     [bp+PIOVARS.wWordsLeft], cx
145    jbe     SHORT .WriteLastBlockToDrive
146    call    [bp+PIOVARS.fnXfer]
147
148    ; Wait until ready for next block and check for errors
149    call    IdeWait_IRQorDRQ                    ; Wait until ready to transfer
150    jc      SHORT ReturnWithTransferErrorInAH
151
152    ; Increment number of successfully written WORDs
153    mov     cx, [bp+PIOVARS.wWordsInBlock]
154    sub     [bp+PIOVARS.wWordsLeft], cx
155    add     [bp+PIOVARS.wWordsDone], cx
156    jmp     SHORT .WriteNextBlockToDrive
157
158ALIGN JUMP_ALIGN
159.WriteLastBlockToDrive:
160    mov     cx, [bp+PIOVARS.wWordsLeft]
161%ifdef USE_186
162    push    CheckErrorsAfterTransferringLastBlock
163    jmp     [bp+PIOVARS.fnXfer]                 ; Transfer possibly partial block
164%else
165    call    [bp+PIOVARS.fnXfer]                 ; Transfer possibly partial block
166    jmp     SHORT CheckErrorsAfterTransferringLastBlock
167%endif
168
169
170;--------------------------------------------------------------------
171; InitializePiovarsInSSBPwithSectorCountInAH
172;   Parameters:
173;       AH:     Number of sectors to transfer (1...128)
174;       BX:     Offset to transfer function lookup table
175;       DS:DI:  Ptr to DPT (in RAMVARS segment)
176;       SS:BP:  Ptr to PIOVARS
177;   Returns:
178;       Nothing
179;   Corrupts registers:
180;       AX, BX, DX
181;--------------------------------------------------------------------
182ALIGN JUMP_ALIGN
183InitializePiovarsInSSBPwithSectorCountInAH:
184    ; Store sizes
185    xor     al, al
186    mov     [bp+PIOVARS.wWordsLeft], ax
187    mov     ah, [di+DPT_ATA.bSetBlock]
188    mov     [bp+PIOVARS.wWordsInBlock], ax
189    cbw
190    mov     [bp+PIOVARS.wWordsDone], ax         ; Zero
191
192    ; Get transfer function based on bus type
193    xchg    ax, bx                              ; Lookup table offset to AX
194    mov     bl, [di+DPT.bIdevarsOffset]         ; CS:BX now points to IDEVARS
195    mov     dx, [cs:bx+IDEVARS.wPort]           ; Load IDE Data port address
196    mov     bl, [cs:bx+IDEVARS.bDevice]         ; Load device type to BX
197    add     bx, ax
198    mov     [bp+PIOVARS.wDataPort], dx
199    mov     ax, [cs:bx]                         ; Load offset to transfer function
200    mov     [bp+PIOVARS.fnXfer], ax
201    ret
202
203
204;--------------------------------------------------------------------
205; ReadBlockFromXtideRev1        XTIDE rev 1
206; ReadBlockFromXtideRev2        XTIDE rev 2 or rev 1 with swapped A0 and A3 (chuck-mod)
207; ReadBlockFrom16bitDataPort    Normal 16-bit IDE
208; ReadBlockFrom32bitDataPort    VLB/PCI 32-bit IDE
209;   Parameters:
210;       CX:     Block size in WORDs
211;       DX:     IDE Data port address
212;       ES:DI:  Normalized ptr to buffer to receive data
213;   Returns:
214;       Nothing
215;   Corrupts registers:
216;       AX, BX, CX
217;--------------------------------------------------------------------
218ALIGN JUMP_ALIGN
219ReadBlockFromXtideRev1:
220    eSHR_IM cx, 2       ; Loop unrolling
221    mov     bx, 8       ; Bit mask for toggling data low/high reg
222ALIGN JUMP_ALIGN
223.InswLoop:
224    XTIDE_INSW
225    XTIDE_INSW
226    XTIDE_INSW
227    XTIDE_INSW
228    loop    .InswLoop
229    ret
230
231;--------------------------------------------------------------------
232%ifndef USE_186         ; 8086/8088 compatible WORD read
233ALIGN JUMP_ALIGN
234ReadBlockFromXtideRev2:
235    times 2 shr cx, 1   ; WORD count to QWORD count
236ALIGN JUMP_ALIGN
237.ReadNextQword:
238    in      ax, dx      ; Read 1st WORD
239    stosw               ; Store 1st WORD to [ES:DI]
240    in      ax, dx
241    stosw               ; 2nd
242    in      ax, dx
243    stosw               ; 3rd
244    in      ax, dx
245    stosw               ; 4th
246    loop    .ReadNextQword
247    ret
248%endif
249
250;--------------------------------------------------------------------
251ALIGN JUMP_ALIGN
252ReadBlockFrom16bitDataPort:
253    rep
254    db      6Dh         ; INSW (we want this in XT build)
255    ret
256
257;--------------------------------------------------------------------
258ALIGN JUMP_ALIGN
259ReadBlockFrom32bitDataPort:
260    shr     cx, 1       ; WORD count to DWORD count
261    rep
262    db      66h         ; Override operand size to 32-bit
263    db      6Dh         ; INSW/INSD
264    ret
265
266
267;--------------------------------------------------------------------
268; WriteBlockToXtideRev1         XTIDE rev 1
269; WriteBlockToXtideRev2         XTIDE rev 2 or rev 1 with swapped A0 and A3 (chuck-mod)
270; WriteBlockToFastXtide         Fast XTIDE (CPLD v2 project)
271; WriteBlockTo16bitDataPort     Normal 16-bit IDE
272; WriteBlockTo32bitDataPort     VLB/PCI 32-bit IDE
273;   Parameters:
274;       CX:     Block size in WORDs
275;       DX:     IDE Data port address
276;       ES:SI:  Normalized ptr to buffer containing data
277;   Returns:
278;       Nothing
279;   Corrupts registers:
280;       AX, CX
281;--------------------------------------------------------------------
282ALIGN JUMP_ALIGN
283WriteBlockToXtideRev1:
284    push    ds
285    push    bx
286    eSHR_IM cx, 2       ; Loop unrolling
287    mov     bx, 8       ; Bit mask for toggling data low/high reg
288    push    es          ; Copy ES...
289    pop     ds          ; ...to DS
290ALIGN JUMP_ALIGN
291.OutswLoop:
292    XTIDE_OUTSW
293    XTIDE_OUTSW
294    XTIDE_OUTSW
295    XTIDE_OUTSW
296    loop    .OutswLoop
297    pop     bx
298    pop     ds
299    ret
300
301;--------------------------------------------------------------------
302ALIGN JUMP_ALIGN
303WriteBlockToXtideRev2:
304    push    ds
305    eSHR_IM cx, 2       ; Loop unrolling
306    push    es          ; Copy ES...
307    pop     ds          ; ...to DS
308ALIGN JUMP_ALIGN
309.WriteNextQword:
310    XTIDE_MOD_OUTSW
311    XTIDE_MOD_OUTSW
312    XTIDE_MOD_OUTSW
313    XTIDE_MOD_OUTSW
314    loop    .WriteNextQword
315    pop     ds
316    ret
317
318;--------------------------------------------------------------------
319%ifndef USE_186         ; 8086/8088 compatible WORD write
320ALIGN JUMP_ALIGN
321WriteBlockToFastXtide:
322    times 2 shr cx, 1   ; WORD count to QWORD count
323    push    ds
324    push    es
325    pop     ds
326ALIGN JUMP_ALIGN
327.ReadNextQword:
328    lodsw               ; Load 1st WORD from [DS:SI]
329    out     dx, ax      ; Write 1st WORD
330    lodsw
331    out     dx, ax      ; 2nd
332    lodsw
333    out     dx, ax      ; 3rd
334    lodsw
335    out     dx, ax      ; 4th
336    loop    .ReadNextQword
337    pop     ds
338    ret
339%endif
340
341;--------------------------------------------------------------------
342ALIGN JUMP_ALIGN
343WriteBlockTo16bitDataPort:
344    es                  ; Source is ES segment
345    rep
346    db      6Fh         ; OUTSW (we want this in XT build)
347    ret
348
349;--------------------------------------------------------------------
350ALIGN JUMP_ALIGN
351WriteBlockTo32bitDataPort:
352    shr     cx, 1       ; WORD count to DWORD count
353    es                  ; Source is ES segment
354    rep
355    db      66h         ; Override operand size to 32-bit
356    db      6Fh         ; OUTSW/OUTSD
357    ret
358
359
360
361; Lookup tables to get transfer function based on bus type
362ALIGN WORD_ALIGN
363g_rgfnPioRead:
364    dw      ReadBlockFromXtideRev1      ; DEVICE_XTIDE_REV1
365%ifdef USE_186
366    dw      ReadBlockFrom16bitDataPort  ; DEVICE_XTIDE_REV2
367    dw      ReadBlockFrom16bitDataPort  ; DEVICE_FAST_XTIDE
368%else
369    dw      ReadBlockFromXtideRev2      ; DEVICE_XTIDE_REV2
370    dw      ReadBlockFromXtideRev2      ; DEVICE_FAST_XTIDE
371%endif
372    dw      ReadBlockFrom16bitDataPort  ; DEVICE_16BIT_ATA
373    dw      ReadBlockFrom32bitDataPort  ; DEVICE_32BIT_ATA
374
375g_rgfnPioWrite:
376    dw      WriteBlockToXtideRev1       ; DEVICE_XTIDE_REV1
377    dw      WriteBlockToXtideRev2       ; DEVICE_XTIDE_REV2
378%ifdef USE_186
379    dw      WriteBlockTo16bitDataPort   ; DEVICE_FAST_XTIDE
380%else
381    dw      WriteBlockToFastXtide       ; DEVICE_FAST_XTIDE
382%endif
383    dw      WriteBlockTo16bitDataPort   ; DEVICE_16BIT_ATA
384    dw      WriteBlockTo32bitDataPort   ; DEVICE_32BIT_ATA
Note: See TracBrowser for help on using the repository browser.