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

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

Changes to XTIDE Universal BIOS:

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