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

Last change on this file since 595 was 593, checked in by Tomi Tilli, 6 years ago

Flashing now works again.
Hack to get Windows 95 to work properly (MODULE_WIN95_CMOS_HACK included for 386 builds by default).
Edited makefile to produce large 386 build.
Fixed recovery time for QDI Vision VLB-IDE controllers.
No more warnings with Nasm 2.13.xx and later.
File dialog now properly restores default drive when file selection is cancelled.

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 eMOVZX cx, BYTE [cs:bx+.rgbToSubtractFromCycleTimeBasedOnPIOmode]
197 sub ax, cx
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.