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

Last change on this file since 575 was 566, checked in by krille_n_@…, 11 years ago

Changes to XTIDE Universal BIOS:

  • Fixed a very old bug (from r150) in IdeError.asm where GetBiosErrorCodeToAHfromStatusAndErrorRegistersInAX would return RET_HD_SEEK_FAIL instead of RET_HD_STATUSERR.
  • Optimizations and other fixes.
File size: 8.9 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 (bits 4...7))
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
49
50 ; Check QD65xx alternative base port
51 or 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 << 4
71 je SHORT VisionControllerDetected
72 cmp al, ID_QD6580 << 4
73 je SHORT VisionControllerDetected
74 cmp al, ID_QD6580_ALTERNATE << 4
75VisionControllerDetected:
76 xchg ah, al
77 ret
78
79
80;--------------------------------------------------------------------
81; Vision_DoesIdePortInBXbelongToControllerWithIDinAX
82; Parameters:
83; AL: QD65xx Config Register contents
84; AH: QDI Vision Controller ID (bits 4...7)
85; BX: IDE Base port to check
86; DX: Vision Controller port
87; Returns:
88; ZF: Set if port belongs to controller
89; Cleared if port belongs to another controller
90; Corrupts registers:
91; Nothing
92;--------------------------------------------------------------------
93Vision_DoesIdePortInBXbelongToControllerWithIDinAX:
94 cmp ah, ID_QD6500 << 4
95 je SHORT .DoesIdePortInDXbelongToQD6500
96
97 ; QD6580 always have Primary IDE at 1F0h
98 ; Secondary IDE at 170h can be enabled or disabled
99 cmp bx, DEVICE_ATA_PRIMARY_PORT
100 je SHORT .ReturnResultInZF
101
102 ; Check if Secondary IDE channel is enabled
103 push ax
104 add dx, BYTE QD6580_CONTROL_REGISTER
105 in al, dx
106 sub dx, BYTE QD6580_CONTROL_REGISTER
107 test al, FLG_QDCONTROL_SECONDARY_DISABLED_in
108 pop ax
109 jz SHORT .CompareBXtoSecondaryIDE
110 ret
111
112 ; QD6500 has only one IDE channel that can be at 1F0h or 170h
113.DoesIdePortInDXbelongToQD6500:
114 test al, FLG_QDCONFIG_PRIMARY_IDE
115 jz SHORT .CompareBXtoSecondaryIDE
116 cmp bx, DEVICE_ATA_PRIMARY_PORT
117 ret
118
119.CompareBXtoSecondaryIDE:
120 cmp bx, DEVICE_ATA_SECONDARY_PORT
121.ReturnResultInZF:
122 ret
123
124
125;--------------------------------------------------------------------
126; Vision_GetMaxPioModeToALandMinCycleTimeToBX
127; Parameters:
128; AL: QD65xx Config Register contents
129; AH: QDI Vision Controller ID (bits 4...7)
130; Returns:
131; AL: Max supported PIO mode
132; AH: FLGH_DPT_IORDY if IORDY supported, zero otherwise
133; BX: Min PIO Cycle Time (only if CF set)
134; CF: Set if PIO limit necessary
135; Cleared if no need to limit timings
136; Corrupts registers:
137; (AX if CF cleared)
138; Corrupts registers:
139; Nothing
140;--------------------------------------------------------------------
141Vision_GetMaxPioModeToALandMinCycleTimeToBX:
142 cmp ah, ID_QD6500 << 4
143 clc
144 jne SHORT .NoNeedToLimitForQD6580
145
146 mov ax, 2 ; Limit to PIO 2 because QD6500 does not support IORDY
147 mov bx, PIO_2_MIN_CYCLE_TIME_NS
148 stc
149.NoNeedToLimitForQD6580:
150 ret
151
152
153;--------------------------------------------------------------------
154; Vision_InitializeWithIDinAHandConfigInAL
155; Parameters:
156; AL: QD65xx Config Register contents
157; AH: QDI Vision Controller ID (bits 4...7)
158; DS:DI: Ptr to DPT for Single or Slave Drive
159; SI: Offset to Master DPT if Slave Drive present
160; Zero if Slave Drive not present
161; Returns:
162; CF: Cleared if success
163; Set if error
164; Corrupts registers:
165; AX, BX, CX, DX, BP
166;--------------------------------------------------------------------
167Vision_InitializeWithIDinAHandConfigInAL:
168 ; QD6580 has a Control Register that needs to be programmed
169 mov dx, [di+DPT_ADVANCED_ATA.wControllerBasePort]
170 cmp ah, ID_QD6500 << 4
171 je SHORT .CalculateTimingForQD6500
172
173 ; Program QD6580 Control Register (not available on QD6500) to
174 ; Enable or Disable Read-Ahead and Post-Write Buffer to match
175 ; jumper setting on the multi I/O card.
176 xor ax, ax
177 add dx, BYTE QD6580_CONTROL_REGISTER
178 in al, dx ; Read to get ATAPI jumper status
179 test al, FLG_QDCONTROL_HDONLY_in
180 eCMOVNZ ah, FLG_QDCONTROL_NONATAPI ; Enable Read-Ahead and Post-Write Buffers
181 mov al, ah
182 or al, MASK_QDCONTROL_FLAGS_TO_SET
183 out dx, al
184 sub dx, BYTE QD6580_CONTROL_REGISTER
185
186 ; Now we need to determine is the drive connected to the Primary or Secondary channel.
187 ; QD6500 has only one channel that can be Primary at 1F0h or Secondary at 170h.
188 ; QD6580 always has Primary channel at 1F0h. Secondary channel at 170h can be Enabled or Disabled.
189 cmp WORD [di+DPT.wBasePort], DEVICE_ATA_PRIMARY_PORT
190 je SHORT .CalculateTimingTicksForQD6580 ; Primary Channel so no need to modify DX
191 times 2 inc dx ; Secondary Channel IDE Timing Register
192
193 ; QD6500 and QD6580 require slightly different calculations.
194.CalculateTimingTicksForQD6580:
195 mov bp, QD6580_MAX_ACTIVE_TIME_CLOCKS | (QD6580_MIN_ACTIVE_TIME_CLOCKS << 8)
196 jmp SHORT .CalculateTimingsForQD65xx
197
198.CalculateTimingForQD6500:
199 mov bp, QD6500_MAX_ACTIVE_TIME_CLOCKS | (QD6500_MIN_ACTIVE_TIME_CLOCKS << 8)
200
201 ; We need the PIO Cycle Time in CX to calculate Active and Recovery Times.
202.CalculateTimingsForQD65xx:
203 call AdvAtaInit_SelectSlowestCommonPioTimingsToBXandCXfromDSSIandDSDI
204
205 ; Calculate Active Time value for QD65xx IDE Timing Register
206 call AtaID_GetActiveTimeToAXfromPioModeInBX
207 call ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue
208 xchg bp, ax
209
210 ; Calculate Recovery Time value for QD65xx IDE Timing Register
211 call AtaID_GetRecoveryTimeToAXfromPioModeInBXandCycleTimeInCX
212 mov bx, bp ; Active Time value now in BL
213 mov bp, QD65xx_MAX_RECOVERY_TIME_CLOCKS | (QD65xx_MIN_RECOVERY_TIME_CLOCKS << 8)
214 call ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue
215
216 ; Merge the values to a single byte to output
217 eSHL_IM al, POSITION_QD65XXIDE_RECOVERY_TIME
218 or al, bl
219 out dx, al
220 ret ; Return with CF cleared
221
222
223;--------------------------------------------------------------------
224; ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue
225; Parameters:
226; AX: Nanosecs to convert
227; BP: Low Byte: Maximum allowed ticks
228; High Byte: Minimum allowed ticks
229; DS:DI: Ptr to DPT for Single or Slave Drive
230; Returns:
231; AL: Timing value for QD65xx register
232; Corrupts registers:
233; Nothing
234;--------------------------------------------------------------------
235ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue:
236 push cx
237
238 ; Get VLB Cycle Time in nanosecs
239 mov cl, VLB_33MHZ_CYCLE_TIME ; Assume 33 MHz or slower VLB bus
240 test BYTE [di+DPT_ADVANCED_ATA.wControllerID], FLG_QDCONFIG_ID3
241 eCMOVZ cl, VLB_40MHZ_CYCLE_TIME
242
243 ; Convert value in AX to VLB ticks
244 div cl ; AL = VLB ticks
245 inc ax ; Round up
246
247 ; Limit value to QD65xx limits
248 mov cx, bp
249 MAX_U al, ch ; Make sure not below minimum
250 MIN_U al, cl ; Make sure not above maximum
251
252 ; Not done yet, we need to invert the ticks since 0 is the slowest
253 ; value on the timing register
254 sub cl, al
255 xchg ax, cx ; Return in AL
256
257 pop cx
258 ret
Note: See TracBrowser for help on using the repository browser.