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

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

Changes to XTIDE Universal BIOS:

  • Redesigned Disk Parameter Tables.
  • Code generalizations for supporting non-IDE devices in the future.
File size: 10.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    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; DualByteRead      Dual port 8-bit XTIDE PIO read transfer
216; WordRead          Normal 16-bit IDE PIO read transfer
217; DWordRead         VLB/PCI 32-bit IDE PIO read transfer
218; SingleByteRead    Single port 8-bit PIO read transfer
219;   Parameters:
220;       CX:     Block size in WORDs
221;       DX:     IDE Data port address
222;       ES:DI:  Normalized ptr to buffer to recieve data
223;   Returns:
224;       Nothing
225;   Corrupts registers:
226;       AX, BX, CX
227;--------------------------------------------------------------------
228ALIGN JUMP_ALIGN
229DualByteRead:
230    times 2 shr cx, 1           ; Loop unrolling
231    mov     bx, 8               ; Bit mask for toggling data low/high reg
232ALIGN JUMP_ALIGN
233.InswLoop:
234    eDUAL_BYTE_PORT_INSW
235    eDUAL_BYTE_PORT_INSW
236    eDUAL_BYTE_PORT_INSW
237    eDUAL_BYTE_PORT_INSW
238    loop    .InswLoop
239    ret
240
241ALIGN JUMP_ALIGN
242WordRead:
243    rep
244    db      6Dh         ; INSW
245    ret
246
247ALIGN JUMP_ALIGN
248DWordRead:
249    shr     cx, 1       ; WORD count to DWORD count
250    rep
251    db      66h         ; Override operand size to 32-bit
252    db      6Dh         ; INSW/INSD
253    ret
254
255ALIGN JUMP_ALIGN
256SingleByteRead:
257%ifdef USE_186  ; INS instruction available
258    shl     cx, 1               ; WORD count to BYTE count
259    rep insb
260%else           ; If 8088/8086
261    shr     cx, 1               ; WORD count to DWORD count
262ALIGN JUMP_ALIGN
263.InsdLoop:
264    in      al, dx
265    stosb                       ; Store to [ES:DI]
266    in      al, dx
267    stosb
268    in      al, dx
269    stosb
270    in      al, dx
271    stosb
272    loop    .InsdLoop
273%endif
274    ret
275
276
277;--------------------------------------------------------------------
278; DualByteWrite     Dual port 8-bit XTIDE PIO write transfer
279; WordWrite         Normal 16-bit IDE PIO write transfer
280; DWordWrite        VLB/PCI 32-bit IDE PIO write transfer
281; SingleByteWrite   Single port 8-bit PIO write transfer
282;   Parameters:
283;       CX:     Block size in WORDs
284;       DX:     IDE Data port address
285;       ES:SI:  Normalized ptr to buffer containing data
286;   Returns:
287;       Nothing
288;   Corrupts registers:
289;       AX, CX
290;--------------------------------------------------------------------
291ALIGN JUMP_ALIGN
292DualByteWrite:
293    push    ds
294    push    bx
295    times 2 shr cx, 1           ; Loop unrolling
296    mov     bx, 8               ; Bit mask for toggling data low/high reg
297    push    es                  ; Copy ES...
298    pop     ds                  ; ...to DS
299ALIGN JUMP_ALIGN
300.OutswLoop:
301    eDUAL_BYTE_PORT_OUTSW
302    eDUAL_BYTE_PORT_OUTSW
303    eDUAL_BYTE_PORT_OUTSW
304    eDUAL_BYTE_PORT_OUTSW
305    loop    .OutswLoop
306    pop     bx
307    pop     ds
308    ret
309
310ALIGN JUMP_ALIGN
311WordWrite:
312    eSEG    es          ; Source is ES segment
313    rep
314    db      6Fh         ; OUTSW
315    ret
316
317ALIGN JUMP_ALIGN
318DWordWrite:
319    shr     cx, 1       ; WORD count to DWORD count
320    eSEG    es          ; Source is ES segment
321    rep
322    db      66h         ; Override operand size to 32-bit
323    db      6Fh         ; OUTSW/OUTSD
324    ret
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
353; Lookup tables to get transfer function based on bus type
354ALIGN WORD_ALIGN
355g_rgfnPioRead:
356    dw      DualByteRead        ; DEVICE_8BIT_DUAL_PORT_XTIDE
357    dw      NULL                ; DEVICE_XTIDE_WITH_REVERSED_A3_AND_A0
358    dw      SingleByteRead      ; DEVICE_8BIT_SINGLE_PORT
359    dw      WordRead            ; DEVICE_16BIT_ATA
360    dw      DWordRead           ; DEVICE_32BIT_ATA
361g_rgfnPioWrite:
362    dw      DualByteWrite       ; DEVICE_8BIT_DUAL_PORT_XTIDE
363    dw      NULL                ; DEVICE_XTIDE_WITH_REVERSED_A3_AND_A0
364    dw      SingleByteWrite     ; DEVICE_8BIT_SINGLE_PORT
365    dw      WordWrite           ; DEVICE_16BIT_ATA
366    dw      DWordWrite          ; DEVICE_32BIT_ATA
Note: See TracBrowser for help on using the repository browser.