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

Last change on this file since 589 was 589, checked in by krille_n_, 8 years ago

Changes:

  • BIOS: Fixed a purely cosmetic bug from r542 where, in builds containing MODULE_EBIOS, the boot menu would display an incorrect drive size (0.4 kB with MODULE_STRINGS_COMPRESSED or 0.5 kB without) for old drives with no support for LBA.
  • Fixed a bug from r392 where Vision_DetectAndReturnIDinAXandPortInDXifControllerPresent would return the ID in AL instead of AH (if DANGEROUS_DETECTION had been defined).
  • Fixed a bug from r587 in AdvAtaInit.asm that would prevent detection of QDI Vision controllers.
  • Also changed how the QDI Vision IDs are defined (removed the need for shifting) to avoid confusion. This fixed a potential bug from r587 in AdvAtaInit.asm where some IDs were not being shifted.
  • Fixed a bug in PDC20x30.asm from r587 where GetPdcIDtoAX would not return with the IDE base port in DX so DisablePdcProgrammingMode would fail.
  • Made some changes to ModuleDependency.inc and other files so that MODULE_ADVANCED_ATA now requires USE_386. Consequently it is no longer included in the regular AT-builds, only in the 386_8k-build.
  • Moved the UNROLL_SECTORS_IN_CX_TO_xWORDS macros from IDE_8bit.inc to IdeIO.inc which means it's now possible to build a BIOS without MODULE_8BIT_IDE.
  • XTIDECFG: Added a minimum DOS version check (since it needs DOS version 2+) to allow the program to quit gracefully in the unlikely scenario where someone tries to run it under DOS version 1.
  • Made some changes to Drive.asm to improve drive enumeration. The old method using GET_DOS_DRIVE_PARAMETER_BLOCK_FOR_SPECIFIC_DRIVE worked well in Windows XP but not in Windows 98 SE (in Windows or in DOS mode). The two problems were; 1) The function call would access the drives which on single floppy drive systems would cause Windows to swap between A: and B: (throwing a blue screen asking the user to insert a disk etc). 2) Only floppy drives and FAT16 drives would be available in the list of drives, no FAT32/optical/network drives.
  • Improved code in IdeControllerMenu.asm so that the default port addresses for all IDE interfaces are now restored when (re-)selecting the (same) type of IDE device.
  • Also made it impossible to select a device type unless the required module is included in the loaded BIOS.
  • The version check done when loading a BIOS now uses the FLASH_SIGNATURE definition from Version.inc. Any changes affecting RomVars now only requires updating that definition. This means that changes to RomVars must be implemented in both the BIOS and XTIDECFG before being committed to the repository.
  • Added a compatibility fix for 3Com 3C503 cards to the ROM checksumming code in Buffers.asm (Buffers_GenerateChecksum).
  • SerDrive: Made some minor changes to file names and paths to improve compatibility with case sensitive environments.
  • BIOSDRVS: Made a minor size optimization which as a side effect also makes it compatible with all DOS versions including DOS version 1.
  • Library: Renamed the WAIT_RETRACE_IF_NECESSARY_THEN macro to CALL_WAIT_FOR_RETRACE_IF_NECESSARY_THEN and made a tail-call-optimized version of it (JMP_WAIT_FOR_RETRACE_IF_NECESSARY_THEN).
  • A speed optimization to the eRCL_IM macro for 386 and higher. This change breaks emulation in the sense that the macro will fail when given a memory operand as the first parameter.
  • Other minor optimizations and fixes.
File size: 11.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-2013 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%ifdef USE_AT
81    jc      SHORT ReturnWithTransferErrorInAH
82%endif
83
84    ; Wait until drive is ready to transfer
85    call    IdeWait_IRQorDRQ                    ; Wait until ready to transfer
86    jc      SHORT ReturnWithTransferErrorInAH
87    xchg    si, di                              ; ES:DI now points buffer
88
89    mov     cx, [bp+PIOVARS.wSectorsInBlock]    ; Max 128
90
91ALIGN JUMP_ALIGN
92.ReadNextBlockFromDrive:
93    mov     dx, [bp+PIOVARS.wDataPort]
94    cmp     [bp+PIOVARS.bSectorsLeft], cl
95    jbe     SHORT .ReadLastBlockFromDrive
96    call    [bp+PIOVARS.fnXfer]
97
98    ; Wait until ready for next block and check for errors
99    xchg    di, si                              ; DS:DI now points DPT
100    call    IdeWait_IRQorDRQ                    ; Wait until ready to transfer
101    jc      SHORT ReturnWithTransferErrorInAH
102    xchg    si, di                              ; ES:DI now points buffer
103
104    ; Increment number of successfully read sectors
105    mov     cx, [bp+PIOVARS.wSectorsInBlock]
106    sub     [bp+PIOVARS.bSectorsLeft], cl
107    add     [bp+PIOVARS.bSectorsDone], cl
108    jmp     SHORT .ReadNextBlockFromDrive
109
110ALIGN JUMP_ALIGN
111.ReadLastBlockFromDrive:
112    mov     cl, [bp+PIOVARS.bSectorsLeft]       ; CH is already zero
113    push    cx
114    call    [bp+PIOVARS.fnXfer]                 ; Transfer possibly partial block
115
116    ; Check for errors in last block
117    mov     di, si                              ; DS:DI now points DPT
118CheckErrorsAfterTransferringLastBlock:
119    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_BSY)
120    call    IdeWait_PollStatusFlagInBLwithTimeoutInBH
121    pop     cx  ; [bp+PIOVARS.bSectorsLeft]
122    jc      SHORT ReturnWithTransferErrorInAH
123
124    ; All sectors successfully transferred
125    add     cx, [bp+PIOVARS.bSectorsDone]       ; Never sets CF
126    ret
127
128    ; Return number of successfully read sectors
129ReturnWithTransferErrorInAH:
130%ifdef USE_386
131    movzx   cx, [bp+PIOVARS.bSectorsDone]
132%else
133    mov     cl, [bp+PIOVARS.bSectorsDone]
134    mov     ch, 0                               ; Preserve CF
135%endif
136    ret
137
138
139;--------------------------------------------------------------------
140; WriteToDrive
141;   Parameters:
142;       AH:     Number of sectors to transfer (1...128)
143;       DS:DI:  Ptr to DPT (in RAMVARS segment)
144;       ES:SI:  Ptr to buffer containing data
145;       SS:BP:  Ptr to PIOVARS
146;   Returns:
147;       AH:     BIOS Error code
148;       CX:     Number of successfully transferred sectors
149;       CF:     0 if transfer successful
150;               1 if any error
151;   Corrupts registers:
152;       AL, BX, DX, SI, ES
153;--------------------------------------------------------------------
154ALIGN JUMP_ALIGN
155WriteToDrive:
156    ; Prepare to write data from ESSI
157    mov     bx, g_rgfnPioWrite
158    call    InitializePiovarsInSSBPwithSectorCountInAH
159%ifdef USE_AT
160    jc      SHORT ReturnWithTransferErrorInAH
161%endif
162
163    ; Always poll when writing first block (IRQs are generated for following blocks)
164    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
165    call    IdeWait_PollStatusFlagInBLwithTimeoutInBH
166    jc      SHORT ReturnWithTransferErrorInAH
167
168    mov     cx, [bp+PIOVARS.wSectorsInBlock]    ; Max 128
169
170ALIGN JUMP_ALIGN
171.WriteNextBlockToDrive:
172    mov     dx, [bp+PIOVARS.wDataPort]
173    cmp     [bp+PIOVARS.bSectorsLeft], cl
174    jbe     SHORT .WriteLastBlockToDrive
175    push    ds
176    push    es
177    pop     ds
178    call    [bp+PIOVARS.fnXfer]
179    pop     ds
180    ; Wait until ready for next block and check for errors
181    call    IdeWait_IRQorDRQ                    ; Wait until ready to transfer
182    jc      SHORT ReturnWithTransferErrorInAH
183
184    ; Increment number of successfully written sectors
185    mov     cx, [bp+PIOVARS.wSectorsInBlock]
186    sub     [bp+PIOVARS.bSectorsLeft], cl
187    add     [bp+PIOVARS.bSectorsDone], cl
188    jmp     SHORT .WriteNextBlockToDrive
189
190ALIGN JUMP_ALIGN
191.WriteLastBlockToDrive:
192    mov     cl, [bp+PIOVARS.bSectorsLeft]       ; CH is already zero
193    push    cx
194    push    ds
195    push    es
196    pop     ds
197    call    [bp+PIOVARS.fnXfer]                 ; Transfer possibly partial block
198    pop     ds
199    jmp     SHORT CheckErrorsAfterTransferringLastBlock
200
201
202;--------------------------------------------------------------------
203; InitializePiovarsInSSBPwithSectorCountInAH
204;   Parameters:
205;       AH:     Number of sectors to transfer (1...128)
206;       BX:     Offset to transfer function lookup table
207;       DS:DI:  Ptr to DPT (in RAMVARS segment)
208;       ES:SI:  Ptr to data buffer
209;       SS:BP:  Ptr to PIOVARS
210;   Returns:
211;       ES:SI:  Normalized pointer
212;       AH:     INT 13h Error Code (only when CF set)
213;       CF:     Set if failed to normalize pointer (segment overflow)
214;               Cleared if success
215;   Corrupts registers:
216;       AL, BX, DX
217;--------------------------------------------------------------------
218ALIGN JUMP_ALIGN
219InitializePiovarsInSSBPwithSectorCountInAH:
220    ; Store sizes and Data Port
221    mov     [bp+PIOVARS.bSectorsLeft], ah
222%ifdef USE_AT
223    xchg    dx, ax
224%endif
225    mov     ax, [di+DPT.wBasePort]
226    mov     [bp+PIOVARS.wDataPort], ax
227    eMOVZX  ax, [di+DPT_ATA.bBlockSize]
228    mov     [bp+PIOVARS.wSectorsInBlock], ax
229    mov     [bp+PIOVARS.bSectorsDone], ah       ; Zero
230
231    ; Get transfer function based on bus type
232    mov     al, [di+DPT_ATA.bDevice]
233    add     bx, ax
234%ifdef MODULE_8BIT_IDE_ADVANCED
235    cmp     al, DEVICE_8BIT_XTCF_DMA
236%endif
237    mov     ax, [cs:bx]                         ; Load offset to transfer function
238    mov     [bp+PIOVARS.fnXfer], ax
239
240    ; Normalize pointer for PIO-transfers and convert to physical address for DMA transfers
241%ifdef MODULE_8BIT_IDE_ADVANCED
242    jb      SHORT IdeTransfer_NormalizePointerInESSI
243
244    ; Convert ES:SI to physical address
245%ifdef USE_386
246    mov     dx, es
247    xor     ax, ax
248    shld    ax, dx, 4
249    shl     dx, 4
250    add     si, dx
251    adc     al, ah
252    mov     es, ax
253
254%elifdef USE_186
255    mov     ax, es
256    rol     ax, 4
257    mov     dx, ax
258    and     ax, 0Fh
259    xor     dx, ax
260    add     si, dx
261    adc     al, ah
262    mov     es, ax
263
264%else ; 808x
265    mov     al, 4
266    mov     dx, es
267    xchg    cx, ax
268    rol     dx, cl
269    mov     cx, dx
270    xchg    cx, ax
271    and     ax, 0Fh
272    xor     dx, ax
273    add     si, dx
274    adc     al, ah
275    mov     es, ax
276
277%endif
278
279    ret     ; With CF cleared (taken care of by the physical address conversion)
280%endif ; MODULE_8BIT_IDE_ADVANCED
281    ; Fall to IdeTransfer_NormalizePointerInESSI if no MODULE_8BIT_IDE_ADVANCED
282
283
284;--------------------------------------------------------------------
285; IdeTransfer_NormalizePointerInESSI
286;   Parameters:
287;       DH:     Number of sectors to transfer (when USE_AT defined)
288;       ES:SI:  Ptr to be normalized
289;   Returns:
290;       ES:SI:  Normalized pointer (SI = 0...15)
291;       AH:     INT 13h Error Code (when USE_AT defined and normalization was attempted)
292;       CF:     Set if failed to normalize pointer (segment overflow)
293;               Cleared if success
294;   Corrupts registers:
295;       AX, DX
296;--------------------------------------------------------------------
297IdeTransfer_NormalizePointerInESSI:
298; Normalization can cause segment overflow if it is done when not needed
299; (I don't know if any software calls with such seg:off address).
300; This does not apply to XT systems since nothing will write to main BIOS ROM.
301; On AT systems things are quite different, even in protected mode the address
302; is passed in seg:offset form and HMA is accessible in real mode.
303%ifdef USE_AT
304    xor     dl, dl
305    eSHL_IM dx, 1
306    dec     dx      ; Prevents normalization when bytes + offset will be zero
307    add     dx, si
308    jc      SHORT .NormalizationRequired
309    ret
310.NormalizationRequired:
311%endif ; USE_AT
312
313    NORMALIZE_FAR_POINTER   es, si, ax, dx
314%ifdef USE_AT       ; CF is always clear for XT builds
315    ; AH = RET_HD_INVALID (01) if CF set, RET_HD_SUCCESS (00) if not. CF unchanged.
316%ifdef USE_386
317    setc    ah
318%else
319    sbb     ah, ah
320    neg     ah
321%endif
322%endif ; USE_AT
323    ret
324
325
326
327; Lookup tables to get transfer function based on bus type
328ALIGN WORD_ALIGN
329g_rgfnPioRead:
330        dw      IdePioBlock_ReadFrom16bitDataPort   ; 0, DEVICE_16BIT_ATA
331%ifdef MODULE_ADVANCED_ATA
332        dw      IdePioBlock_ReadFrom32bitDataPort   ; 1, DEVICE_32BIT_ATA
333%elifdef MODULE_8BIT_IDE
334        dw      NULL
335%endif ; MODULE_ADVANCED_ATA
336%ifdef MODULE_8BIT_IDE
337        dw      IdePioBlock_ReadFrom8bitDataPort    ; 2, DEVICE_8BIT_ATA
338        dw      IdePioBlock_ReadFromXtideRev1       ; 3, DEVICE_8BIT_XTIDE_REV1
339        dw      IdePioBlock_ReadFrom16bitDataPort   ; 4, DEVICE_8BIT_XTIDE_REV2
340%ifdef MODULE_8BIT_IDE_ADVANCED
341        dw      IdePioBlock_ReadFrom8bitDataPort    ; 5, DEVICE_8BIT_XTCF_PIO8
342        dw      IdePioBlock_ReadFrom16bitDataPort   ; 6, DEVICE_8BIT_XTCF_PIO8_WITH_BIU_OFFLOAD
343        dw      IdePioBlock_ReadFrom16bitDataPort   ; 7, DEVICE_8BIT_XTCF_PIO16_WITH_BIU_OFFLOAD
344        dw      IdeDmaBlock_ReadFromXTCF            ; 8, DEVICE_8BIT_XTCF_DMA
345%endif ; MODULE_8BIT_IDE_ADVANCED
346%endif ; MODULE_8BIT_IDE
347
348
349g_rgfnPioWrite:
350        dw      IdePioBlock_WriteTo16bitDataPort    ; 0, DEVICE_16BIT_ATA
351%ifdef MODULE_ADVANCED_ATA
352        dw      IdePioBlock_WriteTo32bitDataPort    ; 1, DEVICE_32BIT_ATA
353%elifdef MODULE_8BIT_IDE
354        dw      NULL
355%endif ; MODULE_ADVANCED_ATA
356%ifdef MODULE_8BIT_IDE
357        dw      IdePioBlock_WriteTo8bitDataPort     ; 2, DEVICE_8BIT_ATA
358        dw      IdePioBlock_WriteToXtideRev1        ; 3, DEVICE_8BIT_XTIDE_REV1
359        dw      IdePioBlock_WriteToXtideRev2        ; 4, DEVICE_8BIT_XTIDE_REV2
360%ifdef MODULE_8BIT_IDE_ADVANCED
361        dw      IdePioBlock_WriteTo8bitDataPort     ; 5, DEVICE_8BIT_XTCF_PIO8
362        dw      IdePioBlock_WriteTo16bitDataPort    ; 6, DEVICE_8BIT_XTCF_PIO8_WITH_BIU_OFFLOAD
363        dw      IdePioBlock_WriteTo16bitDataPort    ; 7, DEVICE_8BIT_XTCF_PIO16_WITH_BIU_OFFLOAD
364        dw      IdeDmaBlock_WriteToXTCF             ; 8, DEVICE_8BIT_XTCF_DMA
365%endif ; MODULE_8BIT_IDE_ADVANCED
366%endif ; MODULE_8BIT_IDE
Note: See TracBrowser for help on using the repository browser.