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

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

Changes to XTIDE Universal BIOS:

  • Restore IdeTransfer.asm to r169 since recent optimizations broke at least drive identification.
File size: 11.7 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    .wBlocksLeft            resb    2
8    .wBlockSize             resb    2   ; Block size in WORDs (256...32768)
9    .wDataPort              resb    2
10    .bSectorsInLastBlock:   resb    1
11                            resb    1   ; Offset 7 = IDEPACK.bDeviceControl
12    .fnXfer                 resb    2   ; Offset to transfer function
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 destination buffer or source data
25;       DS:DI:  Ptr to DPT (in RAMVARS segment)
26;       SS:BP:  Ptr to IDEPACK
27;   Returns:
28;       AH:     INT 13h Error Code
29;       CF:     Cleared if success, Set if error
30;   Corrupts registers:
31;       AL, BX, CX, DX, SI, ES
32;--------------------------------------------------------------------
33ALIGN JUMP_ALIGN
34IdeTransfer_StartWithCommandInAL:
35    mov     ah, [bp+IDEPACK.bSectorCountHighExt]
36
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    jnz     SHORT .PrepareToWriteDataFromESSI
40    cmp     al, COMMAND_WRITE_MULTIPLE
41    je      SHORT .PrepareToWriteDataFromESSI
42
43    ; Prepare to read data to ESSI
44    mov     bx, g_rgfnPioRead
45    mov     al, [bp+IDEPACK.bSectorCount]
46    call    InitializePiovarsInSSBPwithSectorCountInAX
47    xchg    si, di
48    call    Registers_NormalizeESDI
49    jmp     SHORT ReadFromDrive
50
51ALIGN JUMP_ALIGN
52.PrepareToWriteDataFromESSI:
53    mov     bx, g_rgfnPioWrite
54    mov     al, [bp+IDEPACK.bSectorCount]
55    call    InitializePiovarsInSSBPwithSectorCountInAX
56    call    Registers_NormalizeESSI
57    ; Fall to WriteToDrive
58
59
60;--------------------------------------------------------------------
61; WriteToDrive
62;   Parameters:
63;       DS:DI:  Ptr to DPT (in RAMVARS segment)
64;       ES:SI:  Normalized ptr to buffer containing data
65;       SS:BP:  Ptr to PIOVARS
66;   Returns:
67;       AH:     BIOS Error code
68;       CF:     0 if transfer succesfull
69;               1 if any error
70;   Corrupts registers:
71;       AL, BX, CX, DX, SI, ES
72;--------------------------------------------------------------------
73WriteToDrive:
74    ; Always poll when writing first block (IRQs are generated for following blocks)
75    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
76    call    IdeWait_PollStatusFlagInBLwithTimeoutInBH
77    jc      SHORT .ReturnWithTransferErrorInAH
78ALIGN JUMP_ALIGN
79.WriteNextBlock:
80    mov     dx, [bp+PIOVARS.wDataPort]
81    dec     WORD [bp+PIOVARS.wBlocksLeft]       ; Transferring last (possibly partial) block?
82    jz      SHORT .XferLastBlock                ;  If so, jump to transfer
83    mov     cx, [bp+PIOVARS.wBlockSize]         ; Load block size in WORDs
84    call    [bp+PIOVARS.fnXfer]                 ; Transfer full block
85
86    ; Normalize pointer when necessary
87    mov     ax, si
88    shr     ax, 1                               ; WORD offset
89    add     ax, [bp+PIOVARS.wBlockSize]
90    jns     SHORT .WaitUntilReadyToTransferNextBlock
91    call    Registers_NormalizeESSI
92
93ALIGN JUMP_ALIGN
94.WaitUntilReadyToTransferNextBlock:
95%ifdef USE_186
96    push    .WriteNextBlock
97    jmp     IdeWait_IRQorDRQ
98%else
99    call    IdeWait_IRQorDRQ
100    jnc     SHORT .WriteNextBlock
101%endif
102.ReturnWithTransferErrorInAH:
103    ret
104
105ALIGN JUMP_ALIGN
106.XferLastBlock:
107    xor     cx, cx
108    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRDY)
109    mov     ch, [bp+PIOVARS.bSectorsInLastBlock]; CX = Partial block size in WORDs
110%ifdef USE_186
111    push    IdeWait_IRQorStatusFlagInBLwithTimeoutInBH
112    jmp     [bp+PIOVARS.fnXfer]
113%else
114    call    [bp+PIOVARS.fnXfer]                 ; Transfer possibly partial block
115    jmp     IdeWait_IRQorStatusFlagInBLwithTimeoutInBH  ; Check for errors
116%endif
117
118
119;--------------------------------------------------------------------
120; ReadFromDrive
121;   Parameters:
122;       ES:DI:  Normalized ptr to buffer to recieve data
123;       DS:SI:  Ptr to DPT (in RAMVARS segment)
124;       SS:BP:  Ptr to PIOVARS
125;   Returns:
126;       DS:DI:  Ptr to DPT (in RAMVARS segment)
127;       AH:     BIOS Error code
128;       CF:     0 if transfer succesfull
129;               1 if any error
130;   Corrupts registers:
131;       AL, BX, CX, DX, SI, ES
132;--------------------------------------------------------------------
133ALIGN JUMP_ALIGN
134ReadFromDrive:
135    ; Wait until drive is ready to transfer
136    xchg    di, si                              ; DS:DI now points DPT
137    call    IdeWait_IRQorDRQ                    ; Wait until ready to transfer
138    jc      SHORT WriteToDrive.ReturnWithTransferErrorInAH
139    xchg    si, di                              ; ES:DI now points buffer
140
141    ; Transfer full or last (possible partial) block
142    mov     dx, [bp+PIOVARS.wDataPort]
143    dec     WORD [bp+PIOVARS.wBlocksLeft]
144    jz      SHORT .XferLastBlock
145    mov     cx, [bp+PIOVARS.wBlockSize]         ; Load block size in WORDs
146    call    [bp+PIOVARS.fnXfer]                 ; Transfer full block
147
148    ; Normalize pointer when necessary
149    mov     ax, di
150    shr     ax, 1                               ; WORD offset
151    add     ax, [bp+PIOVARS.wBlockSize]
152    jns     SHORT ReadFromDrive
153%ifdef USE_186
154    push    ReadFromDrive
155    jmp     Registers_NormalizeESDI
156%else
157    call    Registers_NormalizeESDI
158    jmp     SHORT ReadFromDrive                 ; Loop while blocks left
159%endif
160
161
162ALIGN JUMP_ALIGN
163.XferLastBlock:
164    xor     cx, cx
165    mov     ch, [bp+PIOVARS.bSectorsInLastBlock]; CX = Partial block size in WORDs
166    call    [bp+PIOVARS.fnXfer]                 ; Transfer possibly partial block
167    mov     di, si                              ; DS:DI now points DPT
168    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRDY)
169    jmp     IdeWait_PollStatusFlagInBLwithTimeoutInBH
170
171
172;--------------------------------------------------------------------
173; InitializePiovarsInSSBPwithSectorCountInAX
174;   Parameters:
175;       AX:     Number of sectors to transfer (1...65535)
176;       BX:     Offset to transfer function lookup table
177;       DS:DI:  Ptr to DPT (in RAMVARS segment)
178;       SS:BP:  Ptr to PIOVARS
179;   Returns:
180;       Nothing
181;   Corrupts registers:
182;       AX, BX, CX, DX
183;--------------------------------------------------------------------
184ALIGN JUMP_ALIGN
185InitializePiovarsInSSBPwithSectorCountInAX:
186    ; Store number of blocks to transfer
187    eMOVZX  cx, BYTE [di+DPT_ATA.bSetBlock]     ; Block size in sectors
188    xor     dx, dx      ; DX:AX = Sectors to transfer (1...65535)
189    div     cx          ; AX = Full blocks to transfer
190    test    dx, dx
191    mov     dh, cl      ; DH = Full block size if no partial blocks to transfer
192    jz      SHORT .NoPartialBlocksToTransfer
193    inc     ax          ; Partial block
194    mov     dh, dl      ; DH = Size of partial block in sectors
195.NoPartialBlocksToTransfer:
196    mov     [bp+PIOVARS.wBlocksLeft], ax
197    mov     [bp+PIOVARS.bSectorsInLastBlock], dh
198
199    ; Store block size in WORDs
200    xchg    ch, cl      ; CX = Block size in WORDs
201    mov     [bp+PIOVARS.wBlockSize], cx
202
203    ; Get transfer function based on bus type
204    xchg    ax, bx                              ; Lookup table offset to AX
205    eMOVZX  bx, BYTE [di+DPT.bIdevarsOffset]    ; CS:BX now points to IDEVARS
206    mov     dx, [cs:bx+IDEVARS.wPort]           ; Load IDE Data port address
207    mov     bl, [cs:bx+IDEVARS.bDevice]         ; Load device type to BX
208    add     bx, ax
209    mov     ax, [cs:bx]                         ; Load offset to transfer function
210    mov     [bp+PIOVARS.wDataPort], dx
211    mov     [bp+PIOVARS.fnXfer], ax
212    ret
213
214
215;--------------------------------------------------------------------
216; DualByteReadForXtide      Dual port 8-bit XTIDE PIO read transfer
217; SingleByteRead            Single port 8-bit PIO read transfer
218; WordReadForXTIDEmod       8088/8086 compatible 16-bit IDE PIO read transfer
219; WordReadForXTplusAndAT    Normal 16-bit IDE PIO read transfer
220; DWordRead                 VLB/PCI 32-bit IDE PIO read transfer
221;   Parameters:
222;       CX:     Block size in WORDs
223;       DX:     IDE Data port address
224;       ES:DI:  Normalized ptr to buffer to recieve data
225;   Returns:
226;       Nothing
227;   Corrupts registers:
228;       AX, BX, CX
229;--------------------------------------------------------------------
230ALIGN JUMP_ALIGN
231DualByteReadForXtide:
232%ifdef USE_186
233    shr     cx, 2       ; Smaller but slower on 186/286
234%else
235    times 2 shr cx, 1   ; Loop unrolling
236%endif
237    mov     bx, 8       ; Bit mask for toggling data low/high reg
238ALIGN JUMP_ALIGN
239.InswLoop:
240    XTIDE_INSW
241    XTIDE_INSW
242    XTIDE_INSW
243    XTIDE_INSW
244    loop    .InswLoop
245    ret
246
247;----
248ALIGN JUMP_ALIGN
249SingleByteRead:
250%ifdef USE_186  ; INS instruction available
251    shl     cx, 1       ; WORD count to BYTE count
252    rep insb
253%else           ; If 8088/8086
254    shr     cx, 1       ; WORD count to DWORD count
255ALIGN JUMP_ALIGN
256.InsdLoop:
257    in      al, dx
258    stosb               ; Store to [ES:DI]
259    in      al, dx
260    stosb
261    in      al, dx
262    stosb
263    in      al, dx
264    stosb
265    loop    .InsdLoop
266%endif
267    ret
268
269;----
270%ifndef USE_186
271ALIGN JUMP_ALIGN
272WordReadForXTIDEmod:
273    times 2 shr cx, 1   ; WORD count to QWORD count
274ALIGN JUMP_ALIGN
275.ReadNextQword:
276    in      ax, dx      ; Read 1st WORD
277    stosw               ; Store 1st WORD to [ES:DI]
278    in      ax, dx
279    stosw               ; 2nd
280    in      ax, dx
281    stosw               ; 3rd
282    in      ax, dx
283    stosw               ; 4th
284    loop    .ReadNextQword
285    ret
286%endif
287
288;----
289ALIGN JUMP_ALIGN
290WordReadForXTplusAndAT:
291    rep
292    db      6Dh         ; INSW (we want this in XT build)
293    ret
294
295;----
296ALIGN JUMP_ALIGN
297DWordRead:
298    shr     cx, 1       ; WORD count to DWORD count
299    rep
300    db      66h         ; Override operand size to 32-bit
301    db      6Dh         ; INSW/INSD
302    ret
303
304
305;--------------------------------------------------------------------
306; DualByteWriteForXtide     Dual port 8-bit XTIDE PIO write transfer
307; SingleByteWrite           Single port 8-bit PIO write transfer
308; WordWriteForXTIDEmod      8088/8086 compatible 16-bit IDE PIO read transfer
309; WordWrite                 Normal 16-bit IDE PIO write transfer
310; DWordWrite                VLB/PCI 32-bit IDE PIO write transfer
311;   Parameters:
312;       CX:     Block size in WORDs
313;       DX:     IDE Data port address
314;       ES:SI:  Normalized ptr to buffer containing data
315;   Returns:
316;       Nothing
317;   Corrupts registers:
318;       AX, CX
319;--------------------------------------------------------------------
320ALIGN JUMP_ALIGN
321DualByteWriteForXtide:
322    push    ds
323    push    bx
324%ifdef USE_186
325    shr     cx, 2       ; Smaller but slower on 186/286
326%else
327    times 2 shr cx, 1   ; Loop unrolling
328%endif
329    mov     bx, 8       ; Bit mask for toggling data low/high reg
330    push    es          ; Copy ES...
331    pop     ds          ; ...to DS
332ALIGN JUMP_ALIGN
333.OutswLoop:
334    XTIDE_OUTSW
335    XTIDE_OUTSW
336    XTIDE_OUTSW
337    XTIDE_OUTSW
338    loop    .OutswLoop
339    pop     bx
340    pop     ds
341    ret
342
343;----
344ALIGN JUMP_ALIGN
345SingleByteWrite:
346%ifdef USE_186  ; OUTS instruction available
347    shl     cx, 1       ; WORD count to BYTE count
348    eSEG    es          ; Source is ES segment
349    rep outsb
350%else           ; If 8088/8086
351    shr     cx, 1       ; WORD count to DWORD count
352    push    ds          ; Store DS
353    push    es          ; Copy ES...
354    pop     ds          ; ...to DS
355ALIGN JUMP_ALIGN
356.OutsdLoop:
357    lodsb               ; Load from [DS:SI] to AL
358    out     dx, al
359    lodsb
360    out     dx, al
361    lodsb
362    out     dx, al
363    lodsb
364    out     dx, al
365    loop    .OutsdLoop
366    pop     ds          ; Restore DS
367%endif
368    ret
369
370;---
371ALIGN JUMP_ALIGN
372WordWriteForXTIDEmod:
373    push    ds
374%ifdef USE_186
375    shr     cx, 2       ; Smaller but slower on 186/286
376%else
377    times 2 shr cx, 1   ; Loop unrolling
378%endif
379    push    es          ; Copy ES...
380    pop     ds          ; ...to DS
381ALIGN JUMP_ALIGN
382.WriteNextQword:
383    XTIDE_MOD_OUTSW
384    XTIDE_MOD_OUTSW
385    XTIDE_MOD_OUTSW
386    XTIDE_MOD_OUTSW
387    loop    .WriteNextQword
388    pop     ds
389    ret
390
391;----
392ALIGN JUMP_ALIGN
393WordWrite:
394    eSEG    es          ; Source is ES segment
395    rep
396    db      6Fh         ; OUTSW (we want this in XT build)
397    ret
398
399ALIGN JUMP_ALIGN
400DWordWrite:
401    shr     cx, 1       ; WORD count to DWORD count
402    eSEG    es          ; Source is ES segment
403    rep
404    db      66h         ; Override operand size to 32-bit
405    db      6Fh         ; OUTSW/OUTSD
406    ret
407
408
409
410; Lookup tables to get transfer function based on bus type
411ALIGN WORD_ALIGN
412g_rgfnPioRead:
413    dw      DualByteReadForXtide    ; DEVICE_8BIT_DUAL_PORT_XTIDE
414%ifdef USE_186
415    dw      WordReadForXTplusAndAT  ; DEVICE_XTIDE_WITH_REVERSED_A3_AND_A0
416%else
417    dw      WordReadForXTIDEmod
418%endif
419    dw      SingleByteRead          ; DEVICE_8BIT_SINGLE_PORT
420    dw      WordReadForXTplusAndAT  ; DEVICE_16BIT_ATA
421    dw      DWordRead               ; DEVICE_32BIT_ATA
422
423g_rgfnPioWrite:
424    dw      DualByteWriteForXtide   ; DEVICE_8BIT_DUAL_PORT_XTIDE
425    dw      WordWriteForXTIDEmod    ; DEVICE_XTIDE_WITH_REVERSED_A3_AND_A0
426    dw      SingleByteWrite         ; DEVICE_8BIT_SINGLE_PORT
427    dw      WordWrite               ; DEVICE_16BIT_ATA
428    dw      DWordWrite              ; DEVICE_32BIT_ATA
Note: See TracBrowser for help on using the repository browser.