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

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

Changes to XTIDE Universal BIOS:

  • Errors from AH=9h are stored to DPTs again.
  • XT build fits in 8k again.
File size: 11.3 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    mov     cl, [bp+PIOVARS.bSectorsDone]
105    mov     ch, 0                               ; Preserve CF
106    ret
107
108
109;--------------------------------------------------------------------
110; WriteToDrive
111;   Parameters:
112;       AH:     Number of sectors to transfer (1...128)
113;       DS:DI:  Ptr to DPT (in RAMVARS segment)
114;       ES:SI:  Normalized ptr to buffer containing data
115;       SS:BP:  Ptr to PIOVARS
116;   Returns:
117;       AH:     BIOS Error code
118;       CX:     Number of successfully transferred sectors
119;       CF:     0 if transfer successful
120;               1 if any error
121;   Corrupts registers:
122;       AL, BX, DX, SI, ES
123;--------------------------------------------------------------------
124ALIGN JUMP_ALIGN
125WriteToDrive:
126    ; Prepare to write data from ESSI
127    mov     bx, g_rgfnPioWrite
128    call    InitializePiovarsInSSBPwithSectorCountInAH
129
130    ; Always poll when writing first block (IRQs are generated for following blocks)
131    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
132    call    IdeWait_PollStatusFlagInBLwithTimeoutInBH
133    jc      SHORT ReturnWithTransferErrorInAH
134
135    mov     cx, [bp+PIOVARS.wSectorsInBlock]    ; Max 128
136
137ALIGN JUMP_ALIGN
138.WriteNextBlockToDrive:
139    mov     dx, [bp+PIOVARS.wDataPort]
140    cmp     [bp+PIOVARS.bSectorsLeft], cl
141    jbe     SHORT .WriteLastBlockToDrive
142    call    [bp+PIOVARS.fnXfer]
143
144    ; Wait until ready for next block and check for errors
145    call    IdeWait_IRQorDRQ                    ; Wait until ready to transfer
146    jc      SHORT ReturnWithTransferErrorInAH
147
148    ; Increment number of successfully written sectors
149    mov     cx, [bp+PIOVARS.wSectorsInBlock]
150    sub     [bp+PIOVARS.bSectorsLeft], cl
151    add     [bp+PIOVARS.bSectorsDone], cl
152    jmp     SHORT .WriteNextBlockToDrive
153
154ALIGN JUMP_ALIGN
155.WriteLastBlockToDrive:
156    mov     cl, [bp+PIOVARS.bSectorsLeft]       ; CH is already zero
157%ifdef USE_186
158    push    CheckErrorsAfterTransferringLastBlock
159    jmp     [bp+PIOVARS.fnXfer]                 ; Transfer possibly partial block
160%else
161    call    [bp+PIOVARS.fnXfer]                 ; Transfer possibly partial block
162    jmp     SHORT CheckErrorsAfterTransferringLastBlock
163%endif
164
165
166;--------------------------------------------------------------------
167; InitializePiovarsInSSBPwithSectorCountInAH
168;   Parameters:
169;       AH:     Number of sectors to transfer (1...128)
170;       BX:     Offset to transfer function lookup table
171;       DS:DI:  Ptr to DPT (in RAMVARS segment)
172;       SS:BP:  Ptr to PIOVARS
173;   Returns:
174;       Nothing
175;   Corrupts registers:
176;       AX, BX, DX
177;--------------------------------------------------------------------
178ALIGN JUMP_ALIGN
179InitializePiovarsInSSBPwithSectorCountInAH:
180    ; Store sizes
181    mov     [bp+PIOVARS.bSectorsLeft], ah
182    eMOVZX  ax, BYTE [di+DPT_ATA.bBlockSize]
183    mov     [bp+PIOVARS.wSectorsInBlock], ax
184    mov     [bp+PIOVARS.bSectorsDone], ah       ; Zero
185
186    ; Get transfer function based on bus type
187    xchg    ax, bx                              ; Lookup table offset to AX
188    mov     bl, [di+DPT.bIdevarsOffset]         ; CS:BX now points to IDEVARS
189    mov     dx, [cs:bx+IDEVARS.wPort]           ; Load IDE Data port address
190%ifdef MODULE_ADVANCED_ATA
191    mov     bl, [di+DPT_ADVANCED_ATA.bDevice]
192%else
193    mov     bl, [cs:bx+IDEVARS.bDevice]         ; Load device type to BX
194%endif
195    add     bx, ax
196
197    mov     [bp+PIOVARS.wDataPort], dx
198    mov     ax, [cs:bx]                         ; Load offset to transfer function
199    mov     [bp+PIOVARS.fnXfer], ax
200    ret
201
202
203;--------------------------------------------------------------------
204; ReadBlockFromXtideRev1        XTIDE rev 1
205; ReadBlockFromXtideRev2        XTIDE rev 2 or rev 1 with swapped A0 and A3 (chuck-mod)
206; ReadBlockFrom16bitDataPort    Normal 16-bit IDE
207; ReadBlockFrom32bitDataPort    VLB/PCI 32-bit IDE
208;   Parameters:
209;       CX:     Block size in 512 byte sectors
210;       DX:     IDE Data port address
211;       ES:DI:  Normalized ptr to buffer to receive data
212;   Returns:
213;       Nothing
214;   Corrupts registers:
215;       AX, BX, CX
216;--------------------------------------------------------------------
217ALIGN JUMP_ALIGN
218ReadBlockFromXtideRev1:
219    UNROLL_SECTORS_IN_CX_TO_QWORDS
220    mov     bx, 8       ; Bit mask for toggling data low/high reg
221ALIGN JUMP_ALIGN
222.InswLoop:
223    XTIDE_INSW
224    XTIDE_INSW
225    XTIDE_INSW
226    XTIDE_INSW
227    loop    .InswLoop
228    ret
229
230;--------------------------------------------------------------------
231%ifndef USE_186         ; 8086/8088 compatible WORD read
232ALIGN JUMP_ALIGN
233ReadBlockFromXtideRev2:
234    UNROLL_SECTORS_IN_CX_TO_QWORDS
235ALIGN JUMP_ALIGN
236.ReadNextQword:
237    in      ax, dx      ; Read 1st WORD
238    stosw               ; Store 1st WORD to [ES:DI]
239    in      ax, dx
240    stosw               ; 2nd
241    in      ax, dx
242    stosw               ; 3rd
243    in      ax, dx
244    stosw               ; 4th
245    loop    .ReadNextQword
246    ret
247%endif
248
249;--------------------------------------------------------------------
250ALIGN JUMP_ALIGN
251ReadBlockFrom16bitDataPort:
252    xchg    cl, ch      ; Sectors to WORDs
253    rep
254    db      6Dh         ; INSW (we want this in XT build)
255    ret
256
257;--------------------------------------------------------------------
258ALIGN JUMP_ALIGN
259ReadBlockFrom32bitDataPort:
260    db      0C1h        ; SHL
261    db      0E1h        ; CX
262    db      7           ; 7 (Sectors to DWORDs)
263    rep
264    db      66h         ; Override operand size to 32-bit
265    db      6Dh         ; INSW/INSD
266    ret
267
268
269;--------------------------------------------------------------------
270; WriteBlockToXtideRev1         XTIDE rev 1
271; WriteBlockToXtideRev2         XTIDE rev 2 or rev 1 with swapped A0 and A3 (chuck-mod)
272; WriteBlockToFastXtide         Fast XTIDE (CPLD v2 project)
273; WriteBlockTo16bitDataPort     Normal 16-bit IDE
274; WriteBlockTo32bitDataPort     VLB/PCI 32-bit IDE
275;   Parameters:
276;       CX:     Block size in 512-byte sectors
277;       DX:     IDE Data port address
278;       ES:SI:  Normalized ptr to buffer containing data
279;   Returns:
280;       Nothing
281;   Corrupts registers:
282;       AX, CX
283;--------------------------------------------------------------------
284ALIGN JUMP_ALIGN
285WriteBlockToXtideRev1:
286    push    ds
287    push    bx
288    UNROLL_SECTORS_IN_CX_TO_QWORDS
289    mov     bx, 8       ; Bit mask for toggling data low/high reg
290    push    es          ; Copy ES...
291    pop     ds          ; ...to DS
292ALIGN JUMP_ALIGN
293.OutswLoop:
294    XTIDE_OUTSW
295    XTIDE_OUTSW
296    XTIDE_OUTSW
297    XTIDE_OUTSW
298    loop    .OutswLoop
299    pop     bx
300    pop     ds
301    ret
302
303;--------------------------------------------------------------------
304ALIGN JUMP_ALIGN
305WriteBlockToXtideRev2:
306    UNROLL_SECTORS_IN_CX_TO_QWORDS
307    push    ds
308    push    es          ; Copy ES...
309    pop     ds          ; ...to DS
310ALIGN JUMP_ALIGN
311.WriteNextQword:
312    XTIDE_MOD_OUTSW
313    XTIDE_MOD_OUTSW
314    XTIDE_MOD_OUTSW
315    XTIDE_MOD_OUTSW
316    loop    .WriteNextQword
317    pop     ds
318    ret
319
320;--------------------------------------------------------------------
321%ifndef USE_186         ; 8086/8088 compatible WORD write
322ALIGN JUMP_ALIGN
323WriteBlockToFastXtide:
324    UNROLL_SECTORS_IN_CX_TO_QWORDS
325    push    ds
326    push    es
327    pop     ds
328ALIGN JUMP_ALIGN
329.ReadNextQword:
330    lodsw               ; Load 1st WORD from [DS:SI]
331    out     dx, ax      ; Write 1st WORD
332    lodsw
333    out     dx, ax      ; 2nd
334    lodsw
335    out     dx, ax      ; 3rd
336    lodsw
337    out     dx, ax      ; 4th
338    loop    .ReadNextQword
339    pop     ds
340    ret
341%endif
342
343;--------------------------------------------------------------------
344ALIGN JUMP_ALIGN
345WriteBlockTo16bitDataPort:
346    xchg    cl, ch      ; Sectors to WORDs
347    es                  ; Source is ES segment
348    rep
349    db      6Fh         ; OUTSW (we want this in XT build)
350    ret
351
352;--------------------------------------------------------------------
353ALIGN JUMP_ALIGN
354WriteBlockTo32bitDataPort:
355    db      0C1h        ; SHL
356    db      0E1h        ; CX
357    db      7           ; 7 (Sectors to DWORDs)
358    es                  ; Source is ES segment
359    rep
360    db      66h         ; Override operand size to 32-bit
361    db      6Fh         ; OUTSW/OUTSD
362    ret
363
364
365
366; Lookup tables to get transfer function based on bus type
367ALIGN WORD_ALIGN
368g_rgfnPioRead:
369    dw      ReadBlockFromXtideRev1      ; DEVICE_XTIDE_REV1
370%ifdef USE_186
371    dw      ReadBlockFrom16bitDataPort  ; DEVICE_XTIDE_REV2
372    dw      ReadBlockFrom16bitDataPort  ; DEVICE_FAST_XTIDE
373%else
374    dw      ReadBlockFromXtideRev2      ; DEVICE_XTIDE_REV2
375    dw      ReadBlockFromXtideRev2      ; DEVICE_FAST_XTIDE
376%endif
377    dw      ReadBlockFrom16bitDataPort  ; DEVICE_16BIT_ATA
378    dw      ReadBlockFrom32bitDataPort  ; DEVICE_32BIT_ATA
379
380g_rgfnPioWrite:
381    dw      WriteBlockToXtideRev1       ; DEVICE_XTIDE_REV1
382    dw      WriteBlockToXtideRev2       ; DEVICE_XTIDE_REV2
383%ifdef USE_186
384    dw      WriteBlockTo16bitDataPort   ; DEVICE_FAST_XTIDE
385%else
386    dw      WriteBlockToFastXtide       ; DEVICE_FAST_XTIDE
387%endif
388    dw      WriteBlockTo16bitDataPort   ; DEVICE_16BIT_ATA
389    dw      WriteBlockTo32bitDataPort   ; DEVICE_32BIT_ATA
Note: See TracBrowser for help on using the repository browser.