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

Last change on this file since 493 was 493, checked in by gregli@…, 11 years ago

Separated MODULE_8BIT_IDE into the basic part used by XTIDE rev 1 and rev 2 which is PIO based, and MODULE_8BIT_IDE_ADVANCED for JRIDE and XTCF support which requires memory mapping and/or DMA. This allows for creating an 8KB image with boot menu support (but no hotkeys) for the XTIDE rev 1. Cleaned up how we reset the drive translation information, ensuring it is properly set between boot attempt on a primary and secondary drive - as a result we clean it when needed, rather than trying to always keep it clean. Also fixed translation bugs in int13h.asm where I had previously missed converting some MODULE_HOTKEYS into MODULE_DRIVEXLATE.

File size: 10.6 KB
Line 
1; Project name  :   XTIDE Universal BIOS
2; Description   :   IDE Device transfer functions.
3
4;
5; XTIDE Universal BIOS and Associated Tools
6; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
7;
8; This program is free software; you can redistribute it and/or modify
9; it under the terms of the GNU General Public License as published by
10; the Free Software Foundation; either version 2 of the License, or
11; (at your option) any later version.
12;
13; This program is distributed in the hope that it will be useful,
14; but WITHOUT ANY WARRANTY; without even the implied warranty of
15; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16; GNU General Public License for more details.
17; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
18;
19
20; Structure containing variables for PIO transfer functions.
21; This struct must not be larger than IDEPACK without INTPACK.
22struc PIOVARS   ; Must not be larger than 9 bytes! See IDEPACK in RamVars.inc.
23    .wDataPort              resb    2   ; 0-1, IDE Data Port
24    .fnXfer                 resb    2   ; 2-3, Offset to transfer function
25    .wSectorsInBlock        resb    2   ; 4-5, Block size in sectors
26    .bSectorsLeft           resb    1   ; 6, Sectors left to transfer
27                            resb    1   ; 7, IDEPACK.bDeviceControl
28    .bSectorsDone           resb    1   ; 8, Number of sectors xferred
29endstruc
30
31
32; Section containing code
33SECTION .text
34
35;--------------------------------------------------------------------
36; IdeTransfer_StartWithCommandInAL
37;   Parameters:
38;       AL:     IDE command that was used to start the transfer
39;               (all PIO read and write commands including Identify Device)
40;       ES:SI:  Ptr to data buffer
41;       DS:DI:  Ptr to DPT (in RAMVARS segment)
42;       SS:BP:  Ptr to IDEPACK
43;   Returns:
44;       AH:     INT 13h Error Code
45;       CX:     Number of successfully transferred sectors
46;       CF:     Cleared if success, Set if error
47;   Corrupts registers:
48;       AL, BX, DX, SI, ES
49;--------------------------------------------------------------------
50ALIGN JUMP_ALIGN
51IdeTransfer_StartWithCommandInAL:
52    ; Are we reading or writing?
53    test    al, 16  ; Bit 4 is cleared on all the read commands but set on 3 of the 4 write commands
54    mov     ah, [bp+IDEPACK.bSectorCount]
55    jnz     SHORT WriteToDrive
56    cmp     al, COMMAND_WRITE_MULTIPLE
57    je      SHORT WriteToDrive
58    ; Fall to ReadFromDrive
59
60;--------------------------------------------------------------------
61; ReadFromDrive
62;   Parameters:
63;       AH:     Number of sectors to transfer (1...128)
64;       ES:SI:  Ptr to buffer to receive data
65;       DS:DI:  Ptr to DPT (in RAMVARS segment)
66;       SS:BP:  Ptr to PIOVARS
67;   Returns:
68;       DS:DI:  Ptr to DPT (in RAMVARS segment)
69;       AH:     BIOS Error code
70;       CX:     Number of successfully transferred sectors
71;       CF:     0 if transfer successful
72;               1 if any error
73;   Corrupts registers:
74;       AL, BX, DX, SI, ES
75;--------------------------------------------------------------------
76ReadFromDrive:
77    ; Prepare to read data to ESSI
78    mov     bx, g_rgfnPioRead
79    call    InitializePiovarsInSSBPwithSectorCountInAH
80
81    ; Wait until drive is ready to transfer
82    call    IdeWait_IRQorDRQ                    ; Wait until ready to transfer
83    jc      SHORT ReturnWithTransferErrorInAH
84    xchg    si, di                              ; ES:DI now points buffer
85
86    mov     cx, [bp+PIOVARS.wSectorsInBlock]    ; Max 128
87
88ALIGN JUMP_ALIGN
89.ReadNextBlockFromDrive:
90    mov     dx, [bp+PIOVARS.wDataPort]
91    cmp     [bp+PIOVARS.bSectorsLeft], cl
92    jbe     SHORT .ReadLastBlockFromDrive
93    call    [bp+PIOVARS.fnXfer]
94
95    ; Wait until ready for next block and check for errors
96    xchg    di, si                              ; DS:DI now points DPT
97    call    IdeWait_IRQorDRQ                    ; Wait until ready to transfer
98    jc      SHORT ReturnWithTransferErrorInAH
99    xchg    si, di                              ; ES:DI now points buffer
100
101    ; Increment number of successfully read sectors
102    mov     cx, [bp+PIOVARS.wSectorsInBlock]
103    sub     [bp+PIOVARS.bSectorsLeft], cl
104    add     [bp+PIOVARS.bSectorsDone], cl
105    jmp     SHORT .ReadNextBlockFromDrive
106
107ALIGN JUMP_ALIGN
108.ReadLastBlockFromDrive:
109    mov     cl, [bp+PIOVARS.bSectorsLeft]       ; CH is already zero
110    push    cx
111    call    [bp+PIOVARS.fnXfer]                 ; Transfer possibly partial block
112
113    ; Check for errors in last block
114    mov     di, si                              ; DS:DI now points DPT
115CheckErrorsAfterTransferringLastBlock:
116    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_BSY)
117    call    IdeWait_PollStatusFlagInBLwithTimeoutInBH
118    pop     cx  ; [bp+PIOVARS.bSectorsLeft]
119    jc      SHORT ReturnWithTransferErrorInAH
120
121    ; All sectors successfully transferred
122    add     cx, [bp+PIOVARS.bSectorsDone]       ; Never sets CF
123    ret
124
125    ; Return number of successfully read sectors
126ReturnWithTransferErrorInAH:
127%ifdef USE_386
128    movzx   cx, [bp+PIOVARS.bSectorsDone]
129%else
130    mov     cl, [bp+PIOVARS.bSectorsDone]
131    mov     ch, 0                               ; Preserve CF
132%endif
133    ret
134
135
136;--------------------------------------------------------------------
137; WriteToDrive
138;   Parameters:
139;       AH:     Number of sectors to transfer (1...128)
140;       DS:DI:  Ptr to DPT (in RAMVARS segment)
141;       ES:SI:  Ptr to buffer containing data
142;       SS:BP:  Ptr to PIOVARS
143;   Returns:
144;       AH:     BIOS Error code
145;       CX:     Number of successfully transferred sectors
146;       CF:     0 if transfer successful
147;               1 if any error
148;   Corrupts registers:
149;       AL, BX, DX, SI, ES
150;--------------------------------------------------------------------
151ALIGN JUMP_ALIGN
152WriteToDrive:
153    ; Prepare to write data from ESSI
154    mov     bx, g_rgfnPioWrite
155    call    InitializePiovarsInSSBPwithSectorCountInAH
156
157    ; Always poll when writing first block (IRQs are generated for following blocks)
158    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
159    call    IdeWait_PollStatusFlagInBLwithTimeoutInBH
160    jc      SHORT ReturnWithTransferErrorInAH
161
162    mov     cx, [bp+PIOVARS.wSectorsInBlock]    ; Max 128
163
164ALIGN JUMP_ALIGN
165.WriteNextBlockToDrive:
166    mov     dx, [bp+PIOVARS.wDataPort]
167    cmp     [bp+PIOVARS.bSectorsLeft], cl
168    jbe     SHORT .WriteLastBlockToDrive
169    call    [bp+PIOVARS.fnXfer]
170
171    ; Wait until ready for next block and check for errors
172    call    IdeWait_IRQorDRQ                    ; Wait until ready to transfer
173    jc      SHORT ReturnWithTransferErrorInAH
174
175    ; Increment number of successfully written sectors
176    mov     cx, [bp+PIOVARS.wSectorsInBlock]
177    sub     [bp+PIOVARS.bSectorsLeft], cl
178    add     [bp+PIOVARS.bSectorsDone], cl
179    jmp     SHORT .WriteNextBlockToDrive
180
181ALIGN JUMP_ALIGN
182.WriteLastBlockToDrive:
183    mov     cl, [bp+PIOVARS.bSectorsLeft]       ; CH is already zero
184    push    cx
185%ifdef USE_186
186    push    CheckErrorsAfterTransferringLastBlock
187    jmp     [bp+PIOVARS.fnXfer]                 ; Transfer possibly partial block
188%else
189    call    [bp+PIOVARS.fnXfer]                 ; Transfer possibly partial block
190    jmp     SHORT CheckErrorsAfterTransferringLastBlock
191%endif
192
193
194;--------------------------------------------------------------------
195; InitializePiovarsInSSBPwithSectorCountInAH
196;   Parameters:
197;       AH:     Number of sectors to transfer (1...128)
198;       BX:     Offset to transfer function lookup table
199;       DS:DI:  Ptr to DPT (in RAMVARS segment)
200;       ES:SI:  Ptr to data buffer
201;       SS:BP:  Ptr to PIOVARS
202;   Returns:
203;       Nothing
204;   Corrupts registers:
205;       AX, BX, DX
206;--------------------------------------------------------------------
207ALIGN JUMP_ALIGN
208InitializePiovarsInSSBPwithSectorCountInAH:
209    ; Store sizes and Data Port
210    mov     [bp+PIOVARS.bSectorsLeft], ah
211    mov     ax, [di+DPT.wBasePort]
212    mov     [bp+PIOVARS.wDataPort], ax
213    eMOVZX  ax, [di+DPT_ATA.bBlockSize]
214    mov     [bp+PIOVARS.wSectorsInBlock], ax
215    mov     [bp+PIOVARS.bSectorsDone], ah       ; Zero
216
217    ; Get transfer function based on bus type
218    xchg    ax, bx                              ; Lookup table offset to AX
219    mov     bl, [di+DPT_ATA.bDevice]
220%ifdef MODULE_8BIT_IDE_ADVANCED
221    mov     dl, bl
222%endif
223    add     bx, ax
224    mov     ax, [cs:bx]                         ; Load offset to transfer function
225    mov     [bp+PIOVARS.fnXfer], ax
226
227    ; Normalize pointer for PIO-transfers and convert to physical address for DMA transfers
228%ifdef MODULE_8BIT_IDE_ADVANCED
229    cmp     dl, DEVICE_8BIT_XTCF_DMA
230    jb      SHORT IdeTransfer_NormalizePointerInESSI
231
232    ; Convert ES:SI to physical address
233%ifdef USE_186          ; Bytes EU Cycles(286)
234    mov     ax, es      ; 2     2
235    rol     ax, 4       ; 3     9
236    mov     dx, ax      ; 2     2
237    and     ax, BYTE 0Fh; 3     3
238    xor     dx, ax      ; 2     2
239    add     si, dx      ; 2     2
240    adc     al, ah      ; 2     2
241    mov     es, ax      ; 2     2
242    ;------------------------------------
243                        ; 18    24
244%else ; 808x
245
246%if 0
247                        ; Bytes EU Cycles(808x)
248    mov     al, 4       ; 2     4
249    mov     dx, es      ; 2     2
250    xchg    cx, ax      ; 1     3
251    rol     dx, cl      ; 2     24
252    mov     cx, dx      ; 2     2
253    xchg    cx, ax      ; 1     3
254    and     ax, BYTE 0Fh; 3     4
255    xor     dx, ax      ; 2     3
256    add     si, dx      ; 2     3
257    adc     al, ah      ; 2     3
258    mov     es, ax      ; 2     2
259    ;------------------------------------
260                        ; 21    53
261;
262; Judging by the Execution Unit cycle count the above block of code is
263; apparently slower. However, the shifts and rotates in the block below
264; execute faster than the Bus Interface Unit on an 8088 can fetch them,
265; thus causing the EU to starve. The difference in true execution speed
266; (if any) might not be worth the extra 5 bytes.
267; In other words, we could use a real world test here.
268;
269%endif ; 0
270                        ; Bytes EU Cycles(808x/286)
271    xor     dx, dx      ; 2     3/2
272    mov     ax, es      ; 2     2/2
273%rep 4
274    shl     ax, 1       ; 8     8/8
275    rcl     dx, 1       ; 8     8/8
276%endrep
277    add     si, ax      ; 2     3/2
278    adc     dl, dh      ; 2     3/2
279    mov     es, dx      ; 2     2/2
280    ;------------------------------------
281%endif                  ; 26    29/26
282    ret
283%endif ; MODULE_8BIT_IDE_ADVANCED
284    ; Fall to IdeTransfer_NormalizePointerInESSI if no MODULE_8BIT_IDE
285
286
287;--------------------------------------------------------------------
288; IdeTransfer_NormalizePointerInESSI
289;   Parameters:
290;       ES:SI:  Ptr to be normalized
291;   Returns:
292;       ES:SI:  Normalized pointer (SI = 0...15)
293;   Corrupts registers:
294;       AX, DX
295;--------------------------------------------------------------------
296IdeTransfer_NormalizePointerInESSI:
297    NORMALIZE_FAR_POINTER   es, si, ax, dx
298    ret
299
300
301; Lookup tables to get transfer function based on bus type
302ALIGN WORD_ALIGN
303g_rgfnPioRead:
304        dw      IdePioBlock_ReadFrom16bitDataPort   ; 0, DEVICE_16BIT_ATA
305        dw      IdePioBlock_ReadFrom32bitDataPort   ; 1, DEVICE_32BIT_ATA
306%ifdef MODULE_8BIT_IDE
307        dw      IdePioBlock_ReadFrom8bitDataPort    ; 2, DEVICE_8BIT_ATA
308        dw      IdePioBlock_ReadFromXtideRev1       ; 3, DEVICE_8BIT_XTIDE_REV1
309        dw      IdePioBlock_ReadFromXtideRev2       ; 4, DEVICE_8BIT_XTIDE_REV2
310%ifdef MODULE_8BIT_IDE_ADVANCED
311        dw      IdePioBlock_ReadFrom8bitDataPort    ; 5, DEVICE_8BIT_XTCF_PIO8
312        dw      IdeDmaBlock_ReadFromXTCF            ; 6, DEVICE_8BIT_XTCF_DMA
313%endif
314%endif
315
316
317g_rgfnPioWrite:
318        dw      IdePioBlock_WriteTo16bitDataPort    ; 0, DEVICE_16BIT_ATA
319        dw      IdePioBlock_WriteTo32bitDataPort    ; 1, DEVICE_32BIT_ATA
320%ifdef MODULE_8BIT_IDE
321        dw      IdePioBlock_WriteTo8bitDataPort     ; 2, DEVICE_8BIT_ATA
322        dw      IdePioBlock_WriteToXtideRev1        ; 3, DEVICE_8BIT_XTIDE_REV1
323        dw      IdePioBlock_WriteToXtideRev2        ; 4, DEVICE_8BIT_XTIDE_REV2
324%ifdef MODULE_8BIT_IDE_ADVANCED     
325        dw      IdePioBlock_WriteTo8bitDataPort     ; 5, DEVICE_8BIT_XTCF_PIO8
326        dw      IdeDmaBlock_WriteToXTCF             ; 6, DEVICE_8BIT_XTCF_DMA
327%endif
328%endif
Note: See TracBrowser for help on using the repository browser.