source: xtideuniversalbios/trunk/XTIDE_Universal_BIOS/Src/Initialization/AdvancedAta/Vision.asm @ 592

Last change on this file since 592 was 592, checked in by krille_n_, 6 years ago

Changes:

  • The problem with NASM in the previous revision (r591) has been fixed.
  • The colors used by the boot menu and hotkey bar can now be customized by selecting one of a number of pre-defined color themes. Suggestions for additional themes are more than welcome!
  • Large builds are now 10 KB. Small builds are still 8 KB with the exception of the Tiny build which is now 4 KB. In other words, builds are now as small as possible to make it easier to combine them with other BIOSes.
  • Added code to the library to improve drive error handling. XTIDECFG can now handle "Drive Not Ready" errors.
  • Fixed a couple of potential bugs in AtaID.asm (AtaID_GetMaxPioModeToAXandMinCycleTimeToCX); 1) ATA1.bPioMode was treated as a WORD variable. 2) ATA2.bPIOSupp was assumed to be non-zero which would result in PIO mode 3 being returned if the assumption was wrong.
  • Made the same changes in the equivalent function used by BIOSDRVS (DisplayPioModeInformationUsingAtaInfoFromDSBX in AtaInfo.asm).
  • Fixed a bug from r587 in PDC20x30.asm in PDC20x30_GetMaxPioModeToALandMinPioCycleTimeToBX.
  • Fixed a bug from r523 in XTIDECFG where Auto Configure would only set the IRQ on one IDE interface on AT-builds.
  • XTIDECFG will now restore the default settings for the "Serial port virtual device" when reselecting it in the list of device types. This makes it behave consistently for all device types.
  • The eAAM macro is now used regardless if USE_UNDOC_INTEL is defined or not because it is apparently supported on all processors including the NEC V20/V30 CPUs.
  • Renamed the EXCLUDE_FROM_XTIDE_UNIVERSAL_BIOS define to EXCLUDE_FROM_XUB.
  • Added a define to exclude unused library code from BIOSDRVS (EXCLUDE_FROM_BIOSDRVS). This makes it a lot smaller than in previous revisions.
  • All unnecessary CLD-instructions are now under a new define 'CLD_NEEDED' which is only enabled for the BIOS. It is disabled for XTIDECFG and BIOSDRVS but can be enabled if needed by adding this define to the respective makefile. This change was made because these unnecessary instructions are wasteful and should never be needed. In fact, they only serve to hide bugs (in other peoples code) which I strongly believe should be avoided. I recommend people making their own BIOSes from source to not use this define as it's extremely unlikely to be needed.
  • Updated the copyright info in SerDrive and changed an URL to point to the new site.
  • Updated the copyright info and version number in BIOSDRVS.
  • Updated the copyright info in XTIDECFG.
  • Optimizations in general.
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 (only if ZF set)
134;       AH:     ~FLGH_DPT_IORDY if IORDY not supported, -1 otherwise (only if ZF set)
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    mov     ax, (~FLGH_DPT_IORDY & 0FFh) << 8 | 2   ; Limit to PIO 2 because QD6500 does not support IORDY
145    mov     bx, PIO_2_MIN_CYCLE_TIME_NS
146.NoNeedToLimitForQD6580:
147    ret
148
149
150;--------------------------------------------------------------------
151; Vision_InitializeWithIDinAH
152;   Parameters:
153;       AH:     QDI Vision Controller ID
154;       DS:DI:  Ptr to DPT for Single or Slave Drive
155;       SI:     Offset to Master DPT if Slave Drive present
156;               Zero if Slave Drive not present
157;   Returns:
158;       CF:     Cleared if success
159;               Set if error
160;   Corrupts registers:
161;       AX, BX, CX, DX, BP
162;--------------------------------------------------------------------
163Vision_InitializeWithIDinAH:
164    ; QD6580 has a Control Register that needs to be programmed
165    cmp     ah, ID_QD6500
166    mov     dx, [di+DPT_ADVANCED_ATA.wControllerBasePort]
167    mov     bp, QD6500_MAX_ACTIVE_TIME_CLOCKS | (QD6500_MIN_ACTIVE_TIME_CLOCKS << 8)    ; Assume QD6500
168    je      SHORT .CalculateTimingsForQD65xx
169    mov     bp, QD6580_MAX_ACTIVE_TIME_CLOCKS | (QD6580_MIN_ACTIVE_TIME_CLOCKS << 8)    ; It's a QD6580
170
171    ; Program QD6580 Control Register (not available on QD6500) to
172    ; Enable or Disable Read-Ahead and Post-Write Buffer to match
173    ; jumper setting on the multi I/O card.
174    add     dx, BYTE QD6580_CONTROL_REGISTER
175    in      al, dx                      ; Read to get ATAPI jumper status
176    test    al, FLG_QDCONTROL_HDONLY_in
177    mov     al, MASK_QDCONTROL_FLAGS_TO_SET
178    eCMOVNZ al, FLG_QDCONTROL_NONATAPI | MASK_QDCONTROL_FLAGS_TO_SET    ; Enable Read-Ahead and Post-Write Buffers
179    out     dx, al
180    dec     dx                          ; Secondary Channel IDE Timing Register
181
182    ; Now we need to determine is the drive connected to the Primary or Secondary channel.
183    ; QD6500 has only one channel that can be Primary at 1F0h or Secondary at 170h.
184    ; QD6580 always has Primary channel at 1F0h. Secondary channel at 170h can be Enabled or Disabled.
185    cmp     BYTE [di+DPT.wBasePort], DEVICE_ATA_SECONDARY_PORT & 0FFh
186    je      SHORT .CalculateTimingsForQD65xx        ; Secondary Channel so no need to modify DX
187    dec     dx
188    dec     dx                          ; Primary Channel IDE Timing Register
189
190    ; We need the PIO Cycle Time in CX to calculate Active and Recovery Times.
191.CalculateTimingsForQD65xx:
192    call    AdvAtaInit_SelectSlowestCommonPioTimingsToBXandCXfromDSSIandDSDI
193
194    ; Calculate Active Time value for QD65xx IDE Timing Register
195    call    AtaID_GetActiveTimeToAXfromPioModeInBX
196    call    ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue
197    xchg    bp, ax
198
199    ; Calculate Recovery Time value for QD65xx IDE Timing Register
200    call    AtaID_GetRecoveryTimeToAXfromPioModeInBXandCycleTimeInCX
201    mov     bx, bp                      ; Active Time value now in BL
202    mov     bp, QD65xx_MAX_RECOVERY_TIME_CLOCKS | (QD65xx_MIN_RECOVERY_TIME_CLOCKS << 8)
203    call    ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue
204
205    ; Merge the values to a single byte to output
206    eSHL_IM al, POSITION_QD65XXIDE_RECOVERY_TIME
207    or      al, bl
208    out     dx, al
209    ret                                 ; Return with CF cleared
210
211
212;--------------------------------------------------------------------
213; ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue
214;   Parameters:
215;       AX:     Nanosecs to convert
216;       BP:     Low Byte:   Maximum allowed ticks
217;               High Byte:  Minimum allowed ticks
218;       DS:DI:  Ptr to DPT for Single or Slave Drive
219;   Returns:
220;       AL:     Timing value for QD65xx register
221;   Corrupts registers:
222;       Nothing
223;--------------------------------------------------------------------
224ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue:
225    push    cx
226
227    ; Get VLB Cycle Time in nanosecs
228    mov     cl, VLB_33MHZ_CYCLE_TIME    ; Assume 33 MHz or slower VLB bus
229    test    BYTE [di+DPT_ADVANCED_ATA.wControllerID], FLG_QDCONFIG_ID3
230    eCMOVZ  cl, VLB_40MHZ_CYCLE_TIME
231
232    ; Convert value in AX to VLB ticks
233    div     cl                          ; AL = VLB ticks
234    inc     ax                          ; Round up
235
236    ; Limit value to QD65xx limits
237    mov     cx, bp
238    MAX_U   al, ch                      ; Make sure not below minimum
239    MIN_U   al, cl                      ; Make sure not above maximum
240
241    ; Not done yet, we need to invert the ticks since 0 is the slowest
242    ; value on the timing register
243    sub     cl, al
244    xchg    ax, cx                      ; Return in AL
245
246    pop     cx
247    ret
Note: See TracBrowser for help on using the repository browser.