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

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

Changes:

  • Added some missing PIO mode timings to ATA_ID.inc (based on info from http://www.singlix.net/specs/cfspc4_0.pdf)
  • Updated Configuration_FullMode.txt but it may need additional changes as the Tandy info doesn't match the wiki.
  • Optimizations.
  • Excluded some unused code from XTIDECFG.
File size: 11.4 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    .wDataPort              resb    2   ; 0, IDE Data Port
8    .fnXfer                 resb    2   ; 2, Offset to transfer function
9    .wSectorsInBlock        resb    2   ; 4, Block size in sectors
10    .bSectorsLeft           resb    1   ; 6, Sectors left to transfer
11                            resb    1   ; 7, IDEPACK.bDeviceControl
12    .bSectorsDone           resb    1   ; 8, Number of sectors xferred
13endstruc
14
15
16; Section containing code
17SECTION .text
18
19;--------------------------------------------------------------------
20; IdeTransfer_StartWithCommandInAL
21;   Parameters:
22;       AL:     IDE command that was used to start the transfer
23;               (all PIO read and write commands including Identify Device)
24;       ES:SI:  Ptr to normalized data buffer
25;       DS:DI:  Ptr to DPT (in RAMVARS segment)
26;       SS:BP:  Ptr to IDEPACK
27;   Returns:
28;       AH:     INT 13h Error Code
29;       CX:     Number of successfully transferred sectors
30;       CF:     Cleared if success, Set if error
31;   Corrupts registers:
32;       AL, BX, DX, SI, ES
33;--------------------------------------------------------------------
34ALIGN JUMP_ALIGN
35IdeTransfer_StartWithCommandInAL:
36    ; Are we reading or writing?
37    test    al, 16  ; Bit 4 is cleared on all the read commands but set on 3 of the 4 write commands
38    mov     ah, [bp+IDEPACK.bSectorCount]
39    jnz     SHORT WriteToDrive
40    cmp     al, COMMAND_WRITE_MULTIPLE
41    je      SHORT WriteToDrive
42    ; Fall to ReadFromDrive
43
44;--------------------------------------------------------------------
45; ReadFromDrive
46;   Parameters:
47;       AH:     Number of sectors to transfer (1...128)
48;       ES:SI:  Normalized ptr to buffer to receive data
49;       DS:DI:  Ptr to DPT (in RAMVARS segment)
50;       SS:BP:  Ptr to PIOVARS
51;   Returns:
52;       DS:DI:  Ptr to DPT (in RAMVARS segment)
53;       AH:     BIOS Error code
54;       CX:     Number of successfully transferred sectors
55;       CF:     0 if transfer successful
56;               1 if any error
57;   Corrupts registers:
58;       AL, BX, DX, SI, ES
59;--------------------------------------------------------------------
60ReadFromDrive:
61    ; Prepare to read data to ESSI
62    mov     bx, g_rgfnPioRead
63    call    InitializePiovarsInSSBPwithSectorCountInAH
64
65    ; Wait until drive is ready to transfer
66    call    IdeWait_IRQorDRQ                    ; Wait until ready to transfer
67    jc      SHORT ReturnWithTransferErrorInAH
68    xchg    si, di                              ; ES:DI now points buffer
69
70    mov     cx, [bp+PIOVARS.wSectorsInBlock]    ; Max 128
71
72ALIGN JUMP_ALIGN
73.ReadNextBlockFromDrive:
74    mov     dx, [bp+PIOVARS.wDataPort]
75    cmp     [bp+PIOVARS.bSectorsLeft], cl
76    jbe     SHORT .ReadLastBlockFromDrive
77    call    [bp+PIOVARS.fnXfer]
78
79    ; Wait until ready for next block and check for errors
80    xchg    di, si                              ; DS:DI now points DPT
81    call    IdeWait_IRQorDRQ                    ; Wait until ready to transfer
82    jc      SHORT ReturnWithTransferErrorInAH
83    xchg    si, di                              ; ES:DI now points buffer
84
85    ; Increment number of successfully read sectors
86    mov     cx, [bp+PIOVARS.wSectorsInBlock]
87    sub     [bp+PIOVARS.bSectorsLeft], cl
88    add     [bp+PIOVARS.bSectorsDone], cl
89    jmp     SHORT .ReadNextBlockFromDrive
90
91ALIGN JUMP_ALIGN
92.ReadLastBlockFromDrive:
93    mov     cl, [bp+PIOVARS.bSectorsLeft]       ; CH is already zero
94    call    [bp+PIOVARS.fnXfer]                 ; Transfer possibly partial block
95
96    ; Check for errors in last block
97    mov     di, si                              ; DS:DI now points DPT
98CheckErrorsAfterTransferringLastBlock:
99    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRDY)
100    call    IdeWait_PollStatusFlagInBLwithTimeoutInBH
101
102    ; Return number of successfully read sectors
103ReturnWithTransferErrorInAH:
104%ifdef USE_386
105    movzx   cx, [bp+PIOVARS.bSectorsDone]
106%else
107    mov     cl, [bp+PIOVARS.bSectorsDone]
108    mov     ch, 0                               ; Preserve CF
109%endif
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.wSectorsInBlock]    ; Max 128
140
141ALIGN JUMP_ALIGN
142.WriteNextBlockToDrive:
143    mov     dx, [bp+PIOVARS.wDataPort]
144    cmp     [bp+PIOVARS.bSectorsLeft], cl
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 sectors
153    mov     cx, [bp+PIOVARS.wSectorsInBlock]
154    sub     [bp+PIOVARS.bSectorsLeft], cl
155    add     [bp+PIOVARS.bSectorsDone], cl
156    jmp     SHORT .WriteNextBlockToDrive
157
158ALIGN JUMP_ALIGN
159.WriteLastBlockToDrive:
160    mov     cl, [bp+PIOVARS.bSectorsLeft]       ; CH is already zero
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    mov     [bp+PIOVARS.bSectorsLeft], ah
186    eMOVZX  ax, [di+DPT_ATA.bBlockSize]
187    mov     [bp+PIOVARS.wSectorsInBlock], ax
188    mov     [bp+PIOVARS.bSectorsDone], ah       ; Zero
189
190    ; Get transfer function based on bus type
191    xchg    ax, bx                              ; Lookup table offset to AX
192    mov     bl, [di+DPT.bIdevarsOffset]         ; CS:BX now points to IDEVARS
193    mov     dx, [cs:bx+IDEVARS.wPort]           ; Load IDE Data port address
194%ifdef MODULE_ADVANCED_ATA
195    mov     bl, [di+DPT_ADVANCED_ATA.bDevice]
196%else
197    mov     bl, [cs:bx+IDEVARS.bDevice]         ; Load device type to BX
198%endif
199    add     bx, ax
200
201    mov     [bp+PIOVARS.wDataPort], dx
202    mov     ax, [cs:bx]                         ; Load offset to transfer function
203    mov     [bp+PIOVARS.fnXfer], ax
204    ret
205
206
207;--------------------------------------------------------------------
208; ReadBlockFromXtideRev1        XTIDE rev 1
209; ReadBlockFromXtideRev2        XTIDE rev 2 or rev 1 with swapped A0 and A3 (chuck-mod)
210; ReadBlockFrom16bitDataPort    Normal 16-bit IDE
211; ReadBlockFrom32bitDataPort    VLB/PCI 32-bit IDE
212;   Parameters:
213;       CX:     Block size in 512 byte sectors
214;       DX:     IDE Data port address
215;       ES:DI:  Normalized ptr to buffer to receive data
216;   Returns:
217;       Nothing
218;   Corrupts registers:
219;       AX, BX, CX
220;--------------------------------------------------------------------
221ALIGN JUMP_ALIGN
222ReadBlockFromXtideRev1:
223    UNROLL_SECTORS_IN_CX_TO_QWORDS
224    mov     bl, 8       ; Bit mask for toggling data low/high reg
225ALIGN JUMP_ALIGN
226.InswLoop:
227    XTIDE_INSW
228    XTIDE_INSW
229    XTIDE_INSW
230    XTIDE_INSW
231    loop    .InswLoop
232    ret
233
234;--------------------------------------------------------------------
235%ifndef USE_186         ; 8086/8088 compatible WORD read
236ALIGN JUMP_ALIGN
237ReadBlockFromXtideRev2:
238    UNROLL_SECTORS_IN_CX_TO_QWORDS
239ALIGN JUMP_ALIGN
240.ReadNextQword:
241    in      ax, dx      ; Read 1st WORD
242    stosw               ; Store 1st WORD to [ES:DI]
243    in      ax, dx
244    stosw               ; 2nd
245    in      ax, dx
246    stosw               ; 3rd
247    in      ax, dx
248    stosw               ; 4th
249    loop    .ReadNextQword
250    ret
251%endif
252
253;--------------------------------------------------------------------
254ALIGN JUMP_ALIGN
255ReadBlockFrom16bitDataPort:
256    xchg    cl, ch      ; Sectors to WORDs
257    rep
258    db      6Dh         ; INSW (we want this in XT build)
259    ret
260
261;--------------------------------------------------------------------
262ALIGN JUMP_ALIGN
263ReadBlockFrom32bitDataPort:
264    db      0C1h        ; SHL
265    db      0E1h        ; CX
266    db      7           ; 7 (Sectors to DWORDs)
267    rep
268    db      66h         ; Override operand size to 32-bit
269    db      6Dh         ; INSW/INSD
270    ret
271
272
273;--------------------------------------------------------------------
274; WriteBlockToXtideRev1         XTIDE rev 1
275; WriteBlockToXtideRev2         XTIDE rev 2 or rev 1 with swapped A0 and A3 (chuck-mod)
276; WriteBlockToFastXtide         Fast XTIDE (CPLD v2 project)
277; WriteBlockTo16bitDataPort     Normal 16-bit IDE
278; WriteBlockTo32bitDataPort     VLB/PCI 32-bit IDE
279;   Parameters:
280;       CX:     Block size in 512-byte sectors
281;       DX:     IDE Data port address
282;       ES:SI:  Normalized ptr to buffer containing data
283;   Returns:
284;       Nothing
285;   Corrupts registers:
286;       AX, CX
287;--------------------------------------------------------------------
288ALIGN JUMP_ALIGN
289WriteBlockToXtideRev1:
290    push    ds
291    push    bx
292    UNROLL_SECTORS_IN_CX_TO_QWORDS
293    mov     bl, 8       ; Bit mask for toggling data low/high reg
294    push    es          ; Copy ES...
295    pop     ds          ; ...to DS
296ALIGN JUMP_ALIGN
297.OutswLoop:
298    XTIDE_OUTSW
299    XTIDE_OUTSW
300    XTIDE_OUTSW
301    XTIDE_OUTSW
302    loop    .OutswLoop
303    pop     bx
304    pop     ds
305    ret
306
307;--------------------------------------------------------------------
308ALIGN JUMP_ALIGN
309WriteBlockToXtideRev2:
310    UNROLL_SECTORS_IN_CX_TO_QWORDS
311    push    ds
312    push    es          ; Copy ES...
313    pop     ds          ; ...to DS
314ALIGN JUMP_ALIGN
315.WriteNextQword:
316    XTIDE_MOD_OUTSW
317    XTIDE_MOD_OUTSW
318    XTIDE_MOD_OUTSW
319    XTIDE_MOD_OUTSW
320    loop    .WriteNextQword
321    pop     ds
322    ret
323
324;--------------------------------------------------------------------
325%ifndef USE_186         ; 8086/8088 compatible WORD write
326ALIGN JUMP_ALIGN
327WriteBlockToFastXtide:
328    UNROLL_SECTORS_IN_CX_TO_QWORDS
329    push    ds
330    push    es
331    pop     ds
332ALIGN JUMP_ALIGN
333.ReadNextQword:
334    lodsw               ; Load 1st WORD from [DS:SI]
335    out     dx, ax      ; Write 1st WORD
336    lodsw
337    out     dx, ax      ; 2nd
338    lodsw
339    out     dx, ax      ; 3rd
340    lodsw
341    out     dx, ax      ; 4th
342    loop    .ReadNextQword
343    pop     ds
344    ret
345%endif
346
347;--------------------------------------------------------------------
348ALIGN JUMP_ALIGN
349WriteBlockTo16bitDataPort:
350    xchg    cl, ch      ; Sectors to WORDs
351    es                  ; Source is ES segment
352    rep
353    db      6Fh         ; OUTSW (we want this in XT build)
354    ret
355
356;--------------------------------------------------------------------
357ALIGN JUMP_ALIGN
358WriteBlockTo32bitDataPort:
359    db      0C1h        ; SHL
360    db      0E1h        ; CX
361    db      7           ; 7 (Sectors to DWORDs)
362    es                  ; Source is ES segment
363    rep
364    db      66h         ; Override operand size to 32-bit
365    db      6Fh         ; OUTSW/OUTSD
366    ret
367
368
369
370; Lookup tables to get transfer function based on bus type
371ALIGN WORD_ALIGN
372g_rgfnPioRead:
373    dw      ReadBlockFromXtideRev1      ; DEVICE_XTIDE_REV1
374%ifdef USE_186
375    dw      ReadBlockFrom16bitDataPort  ; DEVICE_XTIDE_REV2
376    dw      ReadBlockFrom16bitDataPort  ; DEVICE_FAST_XTIDE
377%else
378    dw      ReadBlockFromXtideRev2      ; DEVICE_XTIDE_REV2
379    dw      ReadBlockFromXtideRev2      ; DEVICE_FAST_XTIDE
380%endif
381    dw      ReadBlockFrom16bitDataPort  ; DEVICE_16BIT_ATA
382    dw      ReadBlockFrom32bitDataPort  ; DEVICE_32BIT_ATA
383
384g_rgfnPioWrite:
385    dw      WriteBlockToXtideRev1       ; DEVICE_XTIDE_REV1
386    dw      WriteBlockToXtideRev2       ; DEVICE_XTIDE_REV2
387%ifdef USE_186
388    dw      WriteBlockTo16bitDataPort   ; DEVICE_FAST_XTIDE
389%else
390    dw      WriteBlockToFastXtide       ; DEVICE_FAST_XTIDE
391%endif
392    dw      WriteBlockTo16bitDataPort   ; DEVICE_16BIT_ATA
393    dw      WriteBlockTo32bitDataPort   ; DEVICE_32BIT_ATA
Note: See TracBrowser for help on using the repository browser.