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

Last change on this file since 152 was 152, checked in by aitotat, 13 years ago

Changes to XTIDE Universal BIOS:

  • XTIDE mod should now be supported (untested).
  • Interrupt Service Routine no longer requires variable from RAMVARS.
  • Some small improvements.
File size: 11.4 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    cmp     al, COMMAND_WRITE_MULTIPLE
38    je      SHORT .PrepareToWriteDataFromESSI
39    cmp     al, COMMAND_WRITE_MULTIPLE_EXT
40    je      SHORT .PrepareToWriteDataFromESSI
41    cmp     al, COMMAND_WRITE_SECTORS
42    je      SHORT .PrepareToWriteDataFromESSI
43    cmp     al, COMMAND_WRITE_SECTORS_EXT
44    je      SHORT .PrepareToWriteDataFromESSI
45
46    ; Prepare to read data to ESSI
47    mov     bx, g_rgfnPioRead
48    mov     al, [bp+IDEPACK.bSectorCount]
49    call    InitializePiovarsInSSBPwithSectorCountInAX
50    xchg    si, di
51    call    Registers_NormalizeESDI
52    jmp     SHORT ReadFromDrive
53
54ALIGN JUMP_ALIGN
55.PrepareToWriteDataFromESSI:
56    mov     bx, g_rgfnPioWrite
57    mov     al, [bp+IDEPACK.bSectorCount]
58    call    InitializePiovarsInSSBPwithSectorCountInAX
59    call    Registers_NormalizeESSI
60    ; Fall to WriteToDrive
61
62
63;--------------------------------------------------------------------
64; WriteToDrive
65;   Parameters:
66;       DS:DI:  Ptr to DPT (in RAMVARS segment)
67;       ES:SI:  Normalized ptr to buffer containing data
68;       SS:BP:  Ptr to PIOVARS
69;   Returns:
70;       AH:     BIOS Error code
71;       CF:     0 if transfer succesfull
72;               1 if any error
73;   Corrupts registers:
74;       AL, BX, CX, DX, SI, ES
75;--------------------------------------------------------------------
76WriteToDrive:
77    ; Always poll when writing first block (IRQs are generated for following blocks)
78    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
79    call    IdeWait_PollStatusFlagInBLwithTimeoutInBH
80    jc      SHORT .ReturnWithTransferErrorInAH
81ALIGN JUMP_ALIGN
82.WriteNextBlock:
83    mov     dx, [bp+PIOVARS.wDataPort]
84    dec     WORD [bp+PIOVARS.wBlocksLeft]       ; Transferring last (possibly partial) block?
85    jz      SHORT .XferLastBlock                ;  If so, jump to transfer
86    mov     cx, [bp+PIOVARS.wBlockSize]         ; Load block size in WORDs
87    call    [bp+PIOVARS.fnXfer]                 ; Transfer full block
88
89    ; Normalize pointer when necessary
90    mov     ax, si
91    shr     ax, 1                               ; WORD offset
92    add     ax, [bp+PIOVARS.wBlockSize]
93    jns     SHORT .WaitUntilReadyToTransferNextBlock
94    call    Registers_NormalizeESSI
95
96ALIGN JUMP_ALIGN
97.WaitUntilReadyToTransferNextBlock:
98%ifdef USE_186
99    push    .WriteNextBlock
100    jmp     IdeWait_IRQorDRQ
101%else
102    call    IdeWait_IRQorDRQ
103    jnc     SHORT .WriteNextBlock
104%endif
105.ReturnWithTransferErrorInAH:
106    ret
107
108ALIGN JUMP_ALIGN
109.XferLastBlock:
110    xor     cx, cx
111    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRDY)
112    mov     ch, [bp+PIOVARS.bSectorsInLastBlock]; CX = Partial block size in WORDs
113%ifdef USE_186
114    push    IdeWait_IRQorStatusFlagInBLwithTimeoutInBH
115    jmp     [bp+PIOVARS.fnXfer]
116%else
117    call    [bp+PIOVARS.fnXfer]                 ; Transfer possibly partial block
118    jmp     IdeWait_IRQorStatusFlagInBLwithTimeoutInBH  ; Check for errors
119%endif
120
121
122;--------------------------------------------------------------------
123; ReadFromDrive
124;   Parameters:
125;       ES:DI:  Normalized ptr to buffer to recieve data
126;       DS:SI:  Ptr to DPT (in RAMVARS segment)
127;       SS:BP:  Ptr to PIOVARS
128;   Returns:
129;       DS:DI:  Ptr to DPT (in RAMVARS segment)
130;       AH:     BIOS Error code
131;       CF:     0 if transfer succesfull
132;               1 if any error
133;   Corrupts registers:
134;       AL, BX, CX, DX, SI, ES
135;--------------------------------------------------------------------
136ALIGN JUMP_ALIGN
137ReadFromDrive:
138    ; Wait until drive is ready to transfer
139    xchg    di, si                              ; DS:DI now points DPT
140    call    IdeWait_IRQorDRQ                    ; Wait until ready to transfer
141    jc      SHORT WriteToDrive.ReturnWithTransferErrorInAH
142    xchg    si, di                              ; ES:DI now points buffer
143
144    ; Transfer full or last (possible partial) block
145    mov     dx, [bp+PIOVARS.wDataPort]
146    dec     WORD [bp+PIOVARS.wBlocksLeft]
147    jz      SHORT .XferLastBlock
148    mov     cx, [bp+PIOVARS.wBlockSize]         ; Load block size in WORDs
149    call    [bp+PIOVARS.fnXfer]                 ; Transfer full block
150
151    ; Normalize pointer when necessary
152    mov     ax, di
153    shr     ax, 1                               ; WORD offset
154    add     ax, [bp+PIOVARS.wBlockSize]
155    jns     SHORT ReadFromDrive
156    call    Registers_NormalizeESDI
157    jmp     SHORT ReadFromDrive                 ; Loop while blocks left
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 (0=65536)
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
186    test    ax, ax
187    eCMOVZ  dl, 1       ; DX:AX = Sectors to transfer (1...65536)
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
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    times 2 shr cx, 1   ; Loop unrolling
232    mov     bx, 8       ; Bit mask for toggling data low/high reg
233ALIGN JUMP_ALIGN
234.InswLoop:
235    XTIDE_INSW
236    XTIDE_INSW
237    XTIDE_INSW
238    XTIDE_INSW
239    loop    .InswLoop
240    ret
241
242;----
243ALIGN JUMP_ALIGN
244SingleByteRead:
245%ifdef USE_186  ; INS instruction available
246    shl     cx, 1       ; WORD count to BYTE count
247    rep insb
248%else           ; If 8088/8086
249    shr     cx, 1       ; WORD count to DWORD count
250ALIGN JUMP_ALIGN
251.InsdLoop:
252    in      al, dx
253    stosb               ; Store to [ES:DI]
254    in      al, dx
255    stosb
256    in      al, dx
257    stosb
258    in      al, dx
259    stosb
260    loop    .InsdLoop
261%endif
262    ret
263
264;----
265%ifndef USE_186
266ALIGN JUMP_ALIGN
267WordReadForXTIDEmod:
268    times 2 shr cx, 1   ; WORD count to QWORD count
269ALIGN JUMP_ALIGN
270.ReadNextQword:
271    in      ax, dx      ; Read 1st WORD
272    stosw               ; Store 1st WORD to [ES:DI]
273    in      ax, dx
274    stosw               ; 2nd
275    in      ax, dx
276    stosw               ; 3rd
277    in      ax, dx
278    stosw               ; 4th
279    loop    .ReadNextQword
280    ret
281%endif
282
283;----
284ALIGN JUMP_ALIGN
285WordReadForXTplusAndAT:
286    rep
287    db      6Dh         ; INSW (we want this in XT build)
288    ret
289
290;----
291ALIGN JUMP_ALIGN
292DWordRead:
293    shr     cx, 1       ; WORD count to DWORD count
294    rep
295    db      66h         ; Override operand size to 32-bit
296    db      6Dh         ; INSW/INSD
297    ret
298
299
300;--------------------------------------------------------------------
301; DualByteWriteForXtide     Dual port 8-bit XTIDE PIO write transfer
302; SingleByteWrite           Single port 8-bit PIO write transfer
303; WordWriteForXTIDEmod      8088/8086 compatible 16-bit IDE PIO read transfer
304; WordWrite                 Normal 16-bit IDE PIO write transfer
305; DWordWrite                VLB/PCI 32-bit IDE PIO write transfer
306;   Parameters:
307;       CX:     Block size in WORDs
308;       DX:     IDE Data port address
309;       ES:SI:  Normalized ptr to buffer containing data
310;   Returns:
311;       Nothing
312;   Corrupts registers:
313;       AX, CX
314;--------------------------------------------------------------------
315ALIGN JUMP_ALIGN
316DualByteWriteForXtide:
317    push    ds
318    push    bx
319    times 2 shr cx, 1   ; Loop unrolling
320    mov     bx, 8       ; Bit mask for toggling data low/high reg
321    push    es          ; Copy ES...
322    pop     ds          ; ...to DS
323ALIGN JUMP_ALIGN
324.OutswLoop:
325    XTIDE_OUTSW
326    XTIDE_OUTSW
327    XTIDE_OUTSW
328    XTIDE_OUTSW
329    loop    .OutswLoop
330    pop     bx
331    pop     ds
332    ret
333
334;----
335ALIGN JUMP_ALIGN
336SingleByteWrite:
337%ifdef USE_186  ; OUTS instruction available
338    shl     cx, 1       ; WORD count to BYTE count
339    eSEG    es          ; Source is ES segment
340    rep outsb
341%else           ; If 8088/8086
342    shr     cx, 1       ; WORD count to DWORD count
343    push    ds          ; Store DS
344    push    es          ; Copy ES...
345    pop     ds          ; ...to DS
346ALIGN JUMP_ALIGN
347.OutsdLoop:
348    lodsb               ; Load from [DS:SI] to AL
349    out     dx, al
350    lodsb
351    out     dx, al
352    lodsb
353    out     dx, al
354    lodsb
355    out     dx, al
356    loop    .OutsdLoop
357    pop     ds          ; Restore DS
358%endif
359    ret
360
361;---
362ALIGN JUMP_ALIGN
363WordWriteForXTIDEmod:
364    push    ds
365    times 2 shr cx, 1   ; Loop unrolling
366    push    es          ; Copy ES...
367    pop     ds          ; ...to DS
368ALIGN JUMP_ALIGN
369.WriteNextQword:
370    XTIDE_MOD_OUTSW
371    XTIDE_MOD_OUTSW
372    XTIDE_MOD_OUTSW
373    XTIDE_MOD_OUTSW
374    loop    .WriteNextQword
375    pop     ds
376    ret
377
378;----
379ALIGN JUMP_ALIGN
380WordWrite:
381    eSEG    es          ; Source is ES segment
382    rep
383    db      6Fh         ; OUTSW
384    ret
385
386ALIGN JUMP_ALIGN
387DWordWrite:
388    shr     cx, 1       ; WORD count to DWORD count
389    eSEG    es          ; Source is ES segment
390    rep
391    db      66h         ; Override operand size to 32-bit
392    db      6Fh         ; OUTSW/OUTSD
393    ret
394
395
396
397; Lookup tables to get transfer function based on bus type
398ALIGN WORD_ALIGN
399g_rgfnPioRead:
400    dw      DualByteReadForXtide    ; DEVICE_8BIT_DUAL_PORT_XTIDE
401%ifdef USE_186
402    dw      WordReadForXTplusAndAT  ; DEVICE_XTIDE_WITH_REVERSED_A3_AND_A0
403%else
404    dw      WordReadForXTIDEmod
405%endif
406    dw      SingleByteRead          ; DEVICE_8BIT_SINGLE_PORT
407    dw      WordReadForXTplusAndAT  ; DEVICE_16BIT_ATA
408    dw      DWordRead               ; DEVICE_32BIT_ATA
409
410g_rgfnPioWrite:
411    dw      DualByteWriteForXtide   ; DEVICE_8BIT_DUAL_PORT_XTIDE
412    dw      WordWriteForXTIDEmod    ; DEVICE_XTIDE_WITH_REVERSED_A3_AND_A0
413    dw      SingleByteWrite         ; DEVICE_8BIT_SINGLE_PORT
414    dw      WordWrite               ; DEVICE_16BIT_ATA
415    dw      DWordWrite              ; DEVICE_32BIT_ATA
Note: See TracBrowser for help on using the repository browser.