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

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

Changes to all parts of the project:

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