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

Last change on this file since 623 was 596, checked in by Krister Nordvall, 6 years ago

Changes:

  • Made changes to HotkeyBar.asm to give the Boot Menu and Hotkey Bar a more consistent look. It will probably seem a bit strange at first to people used to the classic theme.
  • Added the missing parts of USE_NEC_V that should have been committed with the rest in r593.
  • Removed DEFINES_ALL_FEATURES from the BIOS makefile. It didn't work anymore and never really made sense anyway. Added all the official builds to 'make unused' instead which actually uncovered some unused code in the Tiny build.
  • XTIDECFG will no longer load color themes from unrecognized versions of the BIOS.
  • Other fixes in comments and some minor optimizations.
File size: 9.3 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 call IsConfigRegisterWithIDinAL
44 je SHORT VisionControllerDetected.Return
45
46 ; Check QD65xx alternative base port
47 mov dl, QD65XX_ALTERNATIVE_BASE_PORT
48 in al, QD65XX_ALTERNATIVE_BASE_PORT + QD65XX_CONFIG_REGISTER_in
49 ; Fall to IsConfigRegisterWithIDinAL
50
51;--------------------------------------------------------------------
52; IsConfigRegisterWithIDinAL
53; Parameters:
54; AL: Possible QD65xx Config Register contents
55; Returns:
56; AH QDI Vision Controller ID or undefined
57; ZF: Set if controller found
58; Cleared if supported controller not found (AH = undefined)
59; Corrupts registers:
60; Nothing
61;--------------------------------------------------------------------
62IsConfigRegisterWithIDinAL:
63 mov ah, al
64 and al, MASK_QDCONFIG_CONTROLLER_ID
65 cmp al, ID_QD6500
66 je SHORT VisionControllerDetected
67 cmp al, ID_QD6580
68 je SHORT VisionControllerDetected
69 cmp al, ID_QD6580_ALTERNATE
70VisionControllerDetected:
71 xchg ah, al
72.Return:
73 ret
74
75
76;--------------------------------------------------------------------
77; Vision_DoesIdePortInBXbelongToControllerWithIDinAX
78; Parameters:
79; AL: QD65xx Config Register contents
80; AH: QDI Vision Controller ID
81; BX: IDE Base port to check
82; DX: Vision Controller port
83; Returns:
84; ZF: Set if port belongs to controller
85; Cleared if port belongs to another controller
86; Corrupts registers:
87; Nothing
88;--------------------------------------------------------------------
89Vision_DoesIdePortInBXbelongToControllerWithIDinAX:
90 cmp ah, ID_QD6500
91 je SHORT .DoesIdePortInDXbelongToQD6500
92
93 ; QD6580 always have Primary IDE at 1F0h
94 ; Secondary IDE at 170h can be enabled or disabled
95 cmp bx, DEVICE_ATA_PRIMARY_PORT
96 je SHORT .ReturnResultInZF
97
98 ; Check if Secondary IDE channel is enabled
99 push ax
100 push dx
101 add dx, BYTE QD6580_CONTROL_REGISTER
102 in al, dx
103 test al, FLG_QDCONTROL_SECONDARY_DISABLED_in
104 pop dx
105 pop ax
106 jz SHORT .CompareBXtoSecondaryIDE
107 ret
108
109 ; QD6500 has only one IDE channel that can be at 1F0h or 170h
110.DoesIdePortInDXbelongToQD6500:
111 test al, FLG_QDCONFIG_PRIMARY_IDE
112 jz SHORT .CompareBXtoSecondaryIDE
113 cmp bx, DEVICE_ATA_PRIMARY_PORT
114 ret
115
116.CompareBXtoSecondaryIDE:
117 cmp bx, DEVICE_ATA_SECONDARY_PORT
118.ReturnResultInZF:
119 ret
120
121
122;--------------------------------------------------------------------
123; Vision_GetMaxPioModeToALandMinCycleTimeToBX
124; Parameters:
125; AL: QD65xx Config Register contents
126; AH: QDI Vision Controller ID
127; Returns:
128; AL: Max supported PIO mode (only if ZF set)
129; AH: ~FLGH_DPT_IORDY if IORDY not supported, -1 otherwise (only if ZF set)
130; BX: Min PIO Cycle Time (only if ZF set)
131; ZF: Set if PIO limit necessary
132; Cleared if no need to limit timings
133; Corrupts registers:
134; Nothing
135;--------------------------------------------------------------------
136Vision_GetMaxPioModeToALandMinCycleTimeToBX:
137 cmp ah, ID_QD6500
138 jne SHORT .NoNeedToLimitForQD6580
139 mov ax, (~FLGH_DPT_IORDY & 0FFh) << 8 | 2 ; Limit to PIO 2 because QD6500 does not support IORDY
140 mov bx, PIO_2_MIN_CYCLE_TIME_NS
141.NoNeedToLimitForQD6580:
142 ret
143
144
145;--------------------------------------------------------------------
146; Vision_InitializeWithIDinAH
147; Parameters:
148; AH: QDI Vision Controller ID
149; DS:DI: Ptr to DPT for Single or Slave Drive
150; SI: Offset to Master DPT if Slave Drive present
151; Zero if Slave Drive not present
152; Returns:
153; CF: Cleared if success
154; Set if error
155; Corrupts registers:
156; AX, BX, CX, DX, BP
157;--------------------------------------------------------------------
158Vision_InitializeWithIDinAH:
159 ; QD6580 has a Control Register that needs to be programmed
160 cmp ah, ID_QD6500
161 mov dx, [di+DPT_ADVANCED_ATA.wControllerBasePort]
162 mov bp, QD6500_MAX_ACTIVE_TIME_CLOCKS | (QD6500_MIN_ACTIVE_TIME_CLOCKS << 8) ; Assume QD6500
163 je SHORT .CalculateTimingsForQD65xx
164 mov bp, QD6580_MAX_ACTIVE_TIME_CLOCKS | (QD6580_MIN_ACTIVE_TIME_CLOCKS << 8) ; It's a QD6580
165
166 ; Program QD6580 Control Register (not available on QD6500) to
167 ; Enable or Disable Read-Ahead and Post-Write Buffer to match
168 ; jumper setting on the multi I/O card.
169 add dx, BYTE QD6580_CONTROL_REGISTER
170 in al, dx ; Read to get ATAPI jumper status
171 test al, FLG_QDCONTROL_HDONLY_in
172 mov al, MASK_QDCONTROL_FLAGS_TO_SET
173 eCMOVNZ al, FLG_QDCONTROL_NONATAPI | MASK_QDCONTROL_FLAGS_TO_SET ; Enable Read-Ahead and Post-Write Buffers
174 out dx, al
175 dec dx ; Secondary Channel IDE Timing Register
176
177 ; Now we need to determine is the drive connected to the Primary or Secondary channel.
178 ; QD6500 has only one channel that can be Primary at 1F0h or Secondary at 170h.
179 ; QD6580 always has Primary channel at 1F0h. Secondary channel at 170h can be Enabled or Disabled.
180 cmp BYTE [di+DPT.wBasePort], DEVICE_ATA_SECONDARY_PORT & 0FFh
181 je SHORT .CalculateTimingsForQD65xx ; Secondary Channel so no need to modify DX
182 dec dx
183 dec dx ; Primary Channel IDE Timing Register
184
185 ; We need the PIO Cycle Time in CX to calculate Active and Recovery Times.
186.CalculateTimingsForQD65xx:
187 call AdvAtaInit_SelectSlowestCommonPioTimingsToBXandCXfromDSSIandDSDI
188
189 ; Calculate Active Time value for QD65xx IDE Timing Register
190 call AtaID_GetActiveTimeToAXfromPioModeInBX
191 call ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue
192 xchg bp, ax
193
194 ; Calculate Recovery Time value for QD65xx IDE Timing Register
195 xchg ax, cx
196 mov bl, [cs:bx+.rgbToSubtractFromCycleTimeBasedOnPIOmode]
197 sub ax, bx
198 mov bx, bp ; Active Time value now in BL
199 mov bp, QD65xx_MAX_RECOVERY_TIME_CLOCKS | (QD65xx_MIN_RECOVERY_TIME_CLOCKS << 8)
200 call ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue
201
202 ; Merge the values to a single byte to output
203 eSHL_IM al, POSITION_QD65XXIDE_RECOVERY_TIME
204 or al, bl
205 out dx, al
206 ret ; Return with CF cleared
207
208.rgbToSubtractFromCycleTimeBasedOnPIOmode:
209 ; For PIO 0 to 2 this method (t0 - (t1+t8+t9)) seems to give closest (little less) values to the fixed preset
210 ; values used by QDI6580 DOS driver v3.7
211 db (PIO_0_MIN_ADDRESS_VALID_NS + PIO_0_MAX_ADDR_VALID_TO_IOCS16_RELEASED + PIO_0_DIORW_TO_ADDR_VALID_HOLD)
212 db (PIO_1_MIN_ADDRESS_VALID_NS + PIO_1_MAX_ADDR_VALID_TO_IOCS16_RELEASED + PIO_1_DIORW_TO_ADDR_VALID_HOLD)
213 db (PIO_2_MIN_ADDRESS_VALID_NS + PIO_2_MAX_ADDR_VALID_TO_IOCS16_RELEASED + PIO_2_DIORW_TO_ADDR_VALID_HOLD)
214 db 102 ; QDI6580 DOS driver v3.7 uses fixed values for PIO 3...
215 db 61 ; ...and PIO 4. No idea where these values come from.
216 db (PIO_5_MIN_CYCLE_TIME_NS / 2) ; PIO 5 and 6 were not available when QD6850 was released. Use values...
217 db (PIO_6_MIN_CYCLE_TIME_NS / 2) ; ...that resembles those used for PIO 4
218
219
220;--------------------------------------------------------------------
221; ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue
222; Parameters:
223; AX: Nanosecs to convert
224; BP: Low Byte: Maximum allowed ticks
225; High Byte: Minimum allowed ticks
226; DS:DI: Ptr to DPT for Single or Slave Drive
227; Returns:
228; AL: Timing value for QD65xx register
229; Corrupts registers:
230; Nothing
231;--------------------------------------------------------------------
232ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue:
233 push cx
234
235 ; Get VLB Cycle Time in nanosecs
236 mov cl, VLB_33MHZ_CYCLE_TIME ; Assume 33 MHz or slower VLB bus (30 ns)
237 test BYTE [di+DPT_ADVANCED_ATA.wControllerID], FLG_QDCONFIG_ID3
238 eCMOVZ cl, VLB_40MHZ_CYCLE_TIME ; (25 ns)
239
240 ; Convert value in AX to VLB ticks
241 div cl ; AL = VLB ticks
242 inc ax ; Round up
243
244 ; Limit value to QD65xx limits
245 mov cx, bp
246 MAX_U al, ch ; Make sure not below minimum
247 MIN_U al, cl ; Make sure not above maximum
248
249 ; Not done yet, we need to invert the ticks since 0 is the slowest
250 ; value on the timing register
251 sub cl, al
252 xchg ax, cx ; Return in AL
253
254 pop cx
255 ret
Note: See TracBrowser for help on using the repository browser.