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

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

Changes to XTIDE Universal BIOS:

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