source: xtideuniversalbios/trunk/XTIDE_Universal_BIOS/Src/Initialization/AdvancedAta/Vision.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: 8.6 KB
Line 
1; Project name  :   XTIDE Universal BIOS
2; Description   :   Functions for initializing QDI Vision
3;                   QD6500 and QD6580 VLB IDE Controllers.
4
5;
6; XTIDE Universal BIOS and Associated Tools
7; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2013 by XTIDE Universal BIOS Team.
8;
9; This program is free software; you can redistribute it and/or modify
10; it under the terms of the GNU General Public License as published by
11; the Free Software Foundation; either version 2 of the License, or
12; (at your option) any later version.
13;
14; This program is distributed in the hope that it will be useful,
15; but WITHOUT ANY WARRANTY; without even the implied warranty of
16; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17; GNU General Public License for more details.
18; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19;
20
21; Section containing code
22SECTION .text
23
24;--------------------------------------------------------------------
25; Vision_DetectAndReturnIDinAXandPortInDXifControllerPresent
26;   Parameters:
27;       Nothing
28;   Returns:
29;       AX:     ID WORD specific for QDI Vision Controllers
30;               (AL = QD65xx Config Register contents)
31;               (AH = QDI Vision Controller ID)
32;       DX:     Controller port (not IDE port)
33;       ZF:     Set if controller found
34;               Cleared if supported controller not found (AX,DX = undefined)
35;   Corrupts registers:
36;       Nothing
37;--------------------------------------------------------------------
38Vision_DetectAndReturnIDinAXandPortInDXifControllerPresent:
39    ; Check QD65xx base port
40    mov     dx, QD65XX_BASE_PORT
41    in      al, QD65XX_BASE_PORT + QD65XX_CONFIG_REGISTER_in
42
43%ifdef DANGEROUS_DETECTION
44    ; Checking alternative base port is currently commented away
45    ; since Intel PIIX4 south bridge mirrors Interrupt Controller registers
46    ; from Axh to Bxh.
47    call    IsConfigRegisterWithIDinAL
48    je      SHORT VisionControllerDetected.Return
49
50    ; Check QD65xx alternative base port
51    mov     dl, QD65XX_ALTERNATIVE_BASE_PORT
52    in      al, QD65XX_ALTERNATIVE_BASE_PORT + QD65XX_CONFIG_REGISTER_in
53%endif ; DANGEROUS_DETECTION
54    ; Fall to IsConfigRegisterWithIDinAL
55
56;--------------------------------------------------------------------
57; IsConfigRegisterWithIDinAL
58;   Parameters:
59;       AL:     Possible QD65xx Config Register contents
60;   Returns:
61;       AH      QDI Vision Controller ID or undefined
62;       ZF:     Set if controller found
63;               Cleared if supported controller not found (AH = undefined)
64;   Corrupts registers:
65;       Nothing
66;--------------------------------------------------------------------
67IsConfigRegisterWithIDinAL:
68    mov     ah, al
69    and     al, MASK_QDCONFIG_CONTROLLER_ID
70    cmp     al, ID_QD6500
71    je      SHORT VisionControllerDetected
72    cmp     al, ID_QD6580
73    je      SHORT VisionControllerDetected
74    cmp     al, ID_QD6580_ALTERNATE
75VisionControllerDetected:
76    xchg    ah, al
77.Return:
78    ret
79
80
81;--------------------------------------------------------------------
82; Vision_DoesIdePortInBXbelongToControllerWithIDinAX
83;   Parameters:
84;       AL:     QD65xx Config Register contents
85;       AH:     QDI Vision Controller ID
86;       BX:     IDE Base port to check
87;       DX:     Vision Controller port
88;   Returns:
89;       ZF:     Set if port belongs to controller
90;               Cleared if port belongs to another controller
91;   Corrupts registers:
92;       Nothing
93;--------------------------------------------------------------------
94Vision_DoesIdePortInBXbelongToControllerWithIDinAX:
95    cmp     ah, ID_QD6500
96    je      SHORT .DoesIdePortInDXbelongToQD6500
97
98    ; QD6580 always have Primary IDE at 1F0h
99    ; Secondary IDE at 170h can be enabled or disabled
100    cmp     bx, DEVICE_ATA_PRIMARY_PORT
101    je      SHORT .ReturnResultInZF
102
103    ; Check if Secondary IDE channel is enabled
104    push    ax
105    push    dx
106    add     dx, BYTE QD6580_CONTROL_REGISTER
107    in      al, dx
108    test    al, FLG_QDCONTROL_SECONDARY_DISABLED_in
109    pop     dx
110    pop     ax
111    jz      SHORT .CompareBXtoSecondaryIDE
112    ret
113
114    ; QD6500 has only one IDE channel that can be at 1F0h or 170h
115.DoesIdePortInDXbelongToQD6500:
116    test    al, FLG_QDCONFIG_PRIMARY_IDE
117    jz      SHORT .CompareBXtoSecondaryIDE
118    cmp     bx, DEVICE_ATA_PRIMARY_PORT
119    ret
120
121.CompareBXtoSecondaryIDE:
122    cmp     bx, DEVICE_ATA_SECONDARY_PORT
123.ReturnResultInZF:
124    ret
125
126
127;--------------------------------------------------------------------
128; Vision_GetMaxPioModeToALandMinCycleTimeToBX
129;   Parameters:
130;       AL:     QD65xx Config Register contents
131;       AH:     QDI Vision Controller ID
132;   Returns:
133;       AL:     Max supported PIO mode
134;       AH:     FLGH_DPT_IORDY if IORDY supported, zero otherwise
135;       BX:     Min PIO Cycle Time (only if ZF set)
136;       ZF:     Set if PIO limit necessary
137;               Cleared if no need to limit timings
138;   Corrupts registers:
139;       Nothing
140;--------------------------------------------------------------------
141Vision_GetMaxPioModeToALandMinCycleTimeToBX:
142    cmp     ah, ID_QD6500
143    jne     SHORT .NoNeedToLimitForQD6580
144
145    mov     ax, 2   ; Limit to PIO 2 because QD6500 does not support IORDY
146    mov     bx, PIO_2_MIN_CYCLE_TIME_NS
147.NoNeedToLimitForQD6580:
148    ret
149
150
151;--------------------------------------------------------------------
152; Vision_InitializeWithIDinAH
153;   Parameters:
154;       AH:     QDI Vision Controller ID
155;       DS:DI:  Ptr to DPT for Single or Slave Drive
156;       SI:     Offset to Master DPT if Slave Drive present
157;               Zero if Slave Drive not present
158;   Returns:
159;       CF:     Cleared if success
160;               Set if error
161;   Corrupts registers:
162;       AX, BX, CX, DX, BP
163;--------------------------------------------------------------------
164Vision_InitializeWithIDinAH:
165    ; QD6580 has a Control Register that needs to be programmed
166    cmp     ah, ID_QD6500
167    mov     dx, [di+DPT_ADVANCED_ATA.wControllerBasePort]
168    mov     bp, QD6500_MAX_ACTIVE_TIME_CLOCKS | (QD6500_MIN_ACTIVE_TIME_CLOCKS << 8)    ; Assume QD6500
169    je      SHORT .CalculateTimingsForQD65xx
170    mov     bp, QD6580_MAX_ACTIVE_TIME_CLOCKS | (QD6580_MIN_ACTIVE_TIME_CLOCKS << 8)    ; It's a QD6580
171
172    ; Program QD6580 Control Register (not available on QD6500) to
173    ; Enable or Disable Read-Ahead and Post-Write Buffer to match
174    ; jumper setting on the multi I/O card.
175    add     dx, BYTE QD6580_CONTROL_REGISTER
176    in      al, dx                      ; Read to get ATAPI jumper status
177    test    al, FLG_QDCONTROL_HDONLY_in
178    mov     al, MASK_QDCONTROL_FLAGS_TO_SET
179    eCMOVNZ al, FLG_QDCONTROL_NONATAPI | MASK_QDCONTROL_FLAGS_TO_SET    ; Enable Read-Ahead and Post-Write Buffers
180    out     dx, al
181    dec     dx                          ; Secondary Channel IDE Timing Register
182
183    ; Now we need to determine is the drive connected to the Primary or Secondary channel.
184    ; QD6500 has only one channel that can be Primary at 1F0h or Secondary at 170h.
185    ; QD6580 always has Primary channel at 1F0h. Secondary channel at 170h can be Enabled or Disabled.
186    cmp     BYTE [di+DPT.wBasePort], DEVICE_ATA_SECONDARY_PORT & 0FFh
187    je      SHORT .CalculateTimingsForQD65xx        ; Secondary Channel so no need to modify DX
188    dec     dx
189    dec     dx                          ; Primary Channel IDE Timing Register
190
191    ; We need the PIO Cycle Time in CX to calculate Active and Recovery Times.
192.CalculateTimingsForQD65xx:
193    call    AdvAtaInit_SelectSlowestCommonPioTimingsToBXandCXfromDSSIandDSDI
194
195    ; Calculate Active Time value for QD65xx IDE Timing Register
196    call    AtaID_GetActiveTimeToAXfromPioModeInBX
197    call    ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue
198    xchg    bp, ax
199
200    ; Calculate Recovery Time value for QD65xx IDE Timing Register
201    call    AtaID_GetRecoveryTimeToAXfromPioModeInBXandCycleTimeInCX
202    mov     bx, bp                      ; Active Time value now in BL
203    mov     bp, QD65xx_MAX_RECOVERY_TIME_CLOCKS | (QD65xx_MIN_RECOVERY_TIME_CLOCKS << 8)
204    call    ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue
205
206    ; Merge the values to a single byte to output
207    eSHL_IM al, POSITION_QD65XXIDE_RECOVERY_TIME
208    or      al, bl
209    out     dx, al
210    ret                                 ; Return with CF cleared
211
212
213;--------------------------------------------------------------------
214; ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue
215;   Parameters:
216;       AX:     Nanosecs to convert
217;       BP:     Low Byte:   Maximum allowed ticks
218;               High Byte:  Minimum allowed ticks
219;       DS:DI:  Ptr to DPT for Single or Slave Drive
220;   Returns:
221;       AL:     Timing value for QD65xx register
222;   Corrupts registers:
223;       Nothing
224;--------------------------------------------------------------------
225ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue:
226    push    cx
227
228    ; Get VLB Cycle Time in nanosecs
229    mov     cl, VLB_33MHZ_CYCLE_TIME    ; Assume 33 MHz or slower VLB bus
230    test    BYTE [di+DPT_ADVANCED_ATA.wControllerID], FLG_QDCONFIG_ID3
231    eCMOVZ  cl, VLB_40MHZ_CYCLE_TIME
232
233    ; Convert value in AX to VLB ticks
234    div     cl                          ; AL = VLB ticks
235    inc     ax                          ; Round up
236
237    ; Limit value to QD65xx limits
238    mov     cx, bp
239    MAX_U   al, ch                      ; Make sure not below minimum
240    MIN_U   al, cl                      ; Make sure not above maximum
241
242    ; Not done yet, we need to invert the ticks since 0 is the slowest
243    ; value on the timing register
244    sub     cl, al
245    xchg    ax, cx                      ; Return in AL
246
247    pop     cx
248    ret
Note: See TracBrowser for help on using the repository browser.