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

Last change on this file since 619 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
RevLine 
[392]1; Project name : XTIDE Universal BIOS
2; Description : Functions for initializing QDI Vision
3; QD6500 and QD6580 VLB IDE Controllers.
4
5;
[526]6; XTIDE Universal BIOS and Associated Tools
7; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2013 by XTIDE Universal BIOS Team.
[392]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.
[526]13;
[392]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
[526]17; GNU General Public License for more details.
[392]18; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
[526]19;
[392]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)
[589]31; (AH = QDI Vision Controller ID)
[392]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
[534]42
[392]43 call IsConfigRegisterWithIDinAL
[589]44 je SHORT VisionControllerDetected.Return
[392]45
46 ; Check QD65xx alternative base port
[589]47 mov dl, QD65XX_ALTERNATIVE_BASE_PORT
[392]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;--------------------------------------------------------------------
[542]62IsConfigRegisterWithIDinAL:
[392]63 mov ah, al
64 and al, MASK_QDCONFIG_CONTROLLER_ID
[589]65 cmp al, ID_QD6500
[392]66 je SHORT VisionControllerDetected
[589]67 cmp al, ID_QD6580
[392]68 je SHORT VisionControllerDetected
[589]69 cmp al, ID_QD6580_ALTERNATE
[392]70VisionControllerDetected:
71 xchg ah, al
[589]72.Return:
[392]73 ret
74
75
76;--------------------------------------------------------------------
77; Vision_DoesIdePortInBXbelongToControllerWithIDinAX
78; Parameters:
79; AL: QD65xx Config Register contents
[589]80; AH: QDI Vision Controller ID
[392]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:
[589]90 cmp ah, ID_QD6500
[392]91 je SHORT .DoesIdePortInDXbelongToQD6500
92
93 ; QD6580 always have Primary IDE at 1F0h
94 ; Secondary IDE at 170h can be enabled or disabled
[398]95 cmp bx, DEVICE_ATA_PRIMARY_PORT
[392]96 je SHORT .ReturnResultInZF
97
98 ; Check if Secondary IDE channel is enabled
99 push ax
[582]100 push dx
[392]101 add dx, BYTE QD6580_CONTROL_REGISTER
102 in al, dx
103 test al, FLG_QDCONTROL_SECONDARY_DISABLED_in
[582]104 pop dx
[392]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
[398]113 cmp bx, DEVICE_ATA_PRIMARY_PORT
[392]114 ret
115
116.CompareBXtoSecondaryIDE:
[398]117 cmp bx, DEVICE_ATA_SECONDARY_PORT
[392]118.ReturnResultInZF:
119 ret
120
121
122;--------------------------------------------------------------------
[564]123; Vision_GetMaxPioModeToALandMinCycleTimeToBX
[392]124; Parameters:
125; AL: QD65xx Config Register contents
[589]126; AH: QDI Vision Controller ID
[392]127; Returns:
[592]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)
[582]130; BX: Min PIO Cycle Time (only if ZF set)
131; ZF: Set if PIO limit necessary
[392]132; Cleared if no need to limit timings
133; Corrupts registers:
134; Nothing
135;--------------------------------------------------------------------
[564]136Vision_GetMaxPioModeToALandMinCycleTimeToBX:
[589]137 cmp ah, ID_QD6500
[392]138 jne SHORT .NoNeedToLimitForQD6580
[592]139 mov ax, (~FLGH_DPT_IORDY & 0FFh) << 8 | 2 ; Limit to PIO 2 because QD6500 does not support IORDY
[564]140 mov bx, PIO_2_MIN_CYCLE_TIME_NS
[392]141.NoNeedToLimitForQD6580:
142 ret
143
144
145;--------------------------------------------------------------------
[589]146; Vision_InitializeWithIDinAH
[392]147; Parameters:
[589]148; AH: QDI Vision Controller ID
[392]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;--------------------------------------------------------------------
[589]158Vision_InitializeWithIDinAH:
[392]159 ; QD6580 has a Control Register that needs to be programmed
[589]160 cmp ah, ID_QD6500
[392]161 mov dx, [di+DPT_ADVANCED_ATA.wControllerBasePort]
[582]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
[392]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
[582]170 in al, dx ; Read to get ATAPI jumper status
[392]171 test al, FLG_QDCONTROL_HDONLY_in
[582]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
[392]174 out dx, al
[582]175 dec dx ; Secondary Channel IDE Timing Register
[392]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.
[582]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
[392]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
[593]195 xchg ax, cx
[596]196 mov bl, [cs:bx+.rgbToSubtractFromCycleTimeBasedOnPIOmode]
197 sub ax, bx
[392]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
[566]203 eSHL_IM al, POSITION_QD65XXIDE_RECOVERY_TIME
[392]204 or al, bl
205 out dx, al
206 ret ; Return with CF cleared
207
[593]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
[392]218
[593]219
[392]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
[593]236 mov cl, VLB_33MHZ_CYCLE_TIME ; Assume 33 MHz or slower VLB bus (30 ns)
[392]237 test BYTE [di+DPT_ADVANCED_ATA.wControllerID], FLG_QDCONFIG_ID3
[593]238 eCMOVZ cl, VLB_40MHZ_CYCLE_TIME ; (25 ns)
[392]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.