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

Last change on this file since 378 was 376, checked in by gregli@…, 13 years ago

WIDE checkin... Added copyright and license information to sorce files, as per the GPL instructions for usage.

File size: 8.6 KB
RevLine 
[363]1; Project name : XTIDE Universal BIOS
2; Description : Functions for initializing QDI Vision
3; QD6500 and QD6580 VLB IDE Controllers.
4
[376]5;
6; XTIDE Universal BIOS and Associated Tools
7; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 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
[363]21; Section containing code
22SECTION .text
23
24;--------------------------------------------------------------------
[364]25; Vision_DetectAndReturnIDinAXandPortInDXifControllerPresent
[363]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))
[364]32; DX: Controller port (not IDE port)
[363]33; ZF: Set if controller found
34; Cleared if supported controller not found (AX,DX = undefined)
35; Corrupts registers:
36; Nothing
37;--------------------------------------------------------------------
[364]38Vision_DetectAndReturnIDinAXandPortInDXifControllerPresent:
[363]39 ; Check QD65xx base port
[364]40 mov dx, QD65XX_BASE_PORT
[363]41 in al, QD65XX_BASE_PORT + QD65XX_CONFIG_REGISTER_in
42 call IsConfigRegisterWithIDinAL
43 je SHORT VisionControllerDetected
44
45 ; Check QD65xx alternative base port
[364]46 or dl, QD65XX_ALTERNATIVE_BASE_PORT
[363]47 in al, QD65XX_ALTERNATIVE_BASE_PORT + QD65XX_CONFIG_REGISTER_in
48 ; Fall to IsConfigRegisterWithIDinAL
49
50;--------------------------------------------------------------------
51; IsConfigRegisterWithIDinAL
52; Parameters:
53; AL: Possible QD65xx Config Register contents
54; Returns:
55; AH QDI Vision Controller ID or undefined
56; ZF: Set if controller found
57; Cleared if supported controller not found (AH = undefined)
58; Corrupts registers:
59; Nothing
60;--------------------------------------------------------------------
61IsConfigRegisterWithIDinAL:
62 mov ah, al
[370]63 and al, MASK_QDCONFIG_CONTROLLER_ID
64 cmp al, ID_QD6500 << 4
[363]65 je SHORT VisionControllerDetected
[370]66 cmp al, ID_QD6580 << 4
[363]67 je SHORT VisionControllerDetected
[370]68 cmp al, ID_QD6580_ALTERNATE << 4
[363]69VisionControllerDetected:
[370]70 xchg ah, al
[363]71 ret
72
73
74;--------------------------------------------------------------------
[364]75; Vision_DoesIdePortInBXbelongToControllerWithIDinAX
[363]76; Parameters:
[364]77; AL: QD65xx Config Register contents
78; AH: QDI Vision Controller ID (bits 4...7)
79; BX: IDE Base port to check
80; DX: Vision Controller port
[363]81; Returns:
82; ZF: Set if port belongs to controller
83; Cleared if port belongs to another controller
84; Corrupts registers:
[364]85; Nothing
[363]86;--------------------------------------------------------------------
[364]87Vision_DoesIdePortInBXbelongToControllerWithIDinAX:
[363]88 cmp ah, ID_QD6500 << 4
89 je SHORT .DoesIdePortInDXbelongToQD6500
90
91 ; QD6580 always have Primary IDE at 1F0h
92 ; Secondary IDE at 170h can be enabled or disabled
[364]93 cmp bx, DEVICE_ATA_DEFAULT_PORT
[363]94 je SHORT .ReturnResultInZF
95
96 ; Check if Secondary IDE channel is enabled
[364]97 push ax
[363]98 add dx, BYTE QD6580_CONTROL_REGISTER
99 in al, dx
100 sub dx, BYTE QD6580_CONTROL_REGISTER
[364]101 test al, FLG_QDCONTROL_SECONDARY_DISABLED_in
102 pop ax
103 jz SHORT .CompareBXtoSecondaryIDE
[363]104 ret
105
106 ; QD6500 has only one IDE channel that can be at 1F0h or 170h
107.DoesIdePortInDXbelongToQD6500:
108 test al, FLG_QDCONFIG_PRIMARY_IDE
[364]109 jz SHORT .CompareBXtoSecondaryIDE
110 cmp bx, DEVICE_ATA_DEFAULT_PORT
[363]111 ret
112
[364]113.CompareBXtoSecondaryIDE:
114 cmp bx, DEVICE_ATA_DEFAULT_SECONDARY_PORT
[363]115.ReturnResultInZF:
116 ret
117
118
119;--------------------------------------------------------------------
120; Vision_GetMaxPioModeToAL
121; Parameters:
[364]122; AL: QD65xx Config Register contents
123; AH: QDI Vision Controller ID (bits 4...7)
[363]124; Returns:
[364]125; AL: Max supported PIO mode
126; AH: FLGH_DPT_IORDY if IORDY supported, zero otherwise
[363]127; CF: Set if PIO limit necessary
128; Cleared if no need to limit timings
129; Corrupts registers:
[364]130; (AX if CF cleared)
131; Corrupts registers:
[363]132; Nothing
133;--------------------------------------------------------------------
134Vision_GetMaxPioModeToAL:
135 cmp ah, ID_QD6500 << 4
136 clc
137 jne SHORT .NoNeedToLimitForQD6580
138
[364]139 mov ax, 2 ; Limit to PIO 2 because QD6500 does not support IORDY
[363]140 stc
141.NoNeedToLimitForQD6580:
142 ret
143
144
145;--------------------------------------------------------------------
146; Vision_InitializeWithIDinAHandConfigInAL
147; Parameters:
[364]148; AL: QD65xx Config Register contents
149; AH: QDI Vision Controller ID (bits 4...7)
150; DS:DI: Ptr to DPT for Single or Slave Drive
151; SI: Offset to Master DPT if Slave Drive present
152; Zero if Slave Drive not present
[363]153; Returns:
154; CF: Cleared if success
155; Set if error
156; Corrupts registers:
[364]157; AX, BX, CX, DX, BP
[363]158;--------------------------------------------------------------------
159Vision_InitializeWithIDinAHandConfigInAL:
160 ; QD6580 has a Control Register that needs to be programmed
[364]161 mov dx, [di+DPT_ADVANCED_ATA.wControllerBasePort]
[363]162 cmp ah, ID_QD6500 << 4
[364]163 je SHORT .CalculateTimingForQD6500
[363]164
165 ; Program QD6580 Control Register (not available on QD6500) to
166 ; Enable or Disable Read-Ahead and Post-Write Buffer to match
167 ; jumper setting on the multi I/O card.
[364]168 xor ax, ax
[363]169 add dx, BYTE QD6580_CONTROL_REGISTER
170 in al, dx ; Read to get ATAPI jumper status
171 test al, FLG_QDCONTROL_HDONLY_in
[364]172 eCMOVNZ ah, FLG_QDCONTROL_NONATAPI ; Enable Read-Ahead and Post-Write Buffers
173 or ah, MASK_QDCONTROL_FLAGS_TO_SET
174 mov al, ah
[363]175 out dx, al
[364]176 sub dx, BYTE QD6580_CONTROL_REGISTER
[363]177
178 ; Now we need to determine is the drive connected to the Primary or Secondary channel.
179 ; QD6500 has only one channel that can be Primary at 1F0h or Secondary at 170h.
180 ; QD6580 always has Primary channel at 1F0h. Secondary channel at 170h can be Enabled or Disabled.
[364]181 call AccessDPT_GetIdeBasePortToBX
182 cmp bx, DEVICE_ATA_DEFAULT_PORT
183 je SHORT .CalculateTimingTicksForQD6580 ; Primary Channel so no need to modify DX
[363]184 times 2 inc dx ; Secondary Channel IDE Timing Register
185
[364]186 ; QD6500 and QD6580 require slightly different calculations.
[363]187.CalculateTimingTicksForQD6580:
[364]188 mov bp, QD6580_MAX_ACTIVE_TIME_CLOCKS | (QD6580_MIN_ACTIVE_TIME_CLOCKS << 8)
189 jmp SHORT .CalculateTimingsForQD65xx
[363]190
[364]191.CalculateTimingForQD6500:
192 mov bp, QD6500_MAX_ACTIVE_TIME_CLOCKS | (QD6500_MIN_ACTIVE_TIME_CLOCKS << 8)
[363]193
[370]194 ; We need the PIO Cycle Time in CX to calculate Active and Recovery Times.
[364]195.CalculateTimingsForQD65xx:
196 call AdvAtaInit_SelectSlowestCommonPioTimingsToBXandCXfromDSSIandDSDI
[363]197
[364]198 ; Calculate Active Time value for QD65xx IDE Timing Register
199 call AtaID_GetActiveTimeToAXfromPioModeInBX
200 call ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue
201 xchg bp, ax
[363]202
[364]203 ; Calculate Recovery Time value for QD65xx IDE Timing Register
204 call AtaID_GetRecoveryTimeToAXfromPioModeInBXandCycleTimeInCX
205 mov bx, bp ; Active Time value now in BL
206 mov bp, QD65xx_MAX_RECOVERY_TIME_CLOCKS | (QD65xx_MIN_RECOVERY_TIME_CLOCKS << 8)
207 call ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue
208
209 ; Merge the values to a single byte to output
210 eSHIFT_IM al, POSITON_QD65XXIDE_RECOVERY_TIME, shl
211 or al, bl
212 out dx, al
213 ret ; Return with CF cleared
214
215
216;--------------------------------------------------------------------
217; ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue
218; Parameters:
219; AX: Nanosecs to convert
220; BP: Low Byte: Maximum allowed ticks
221; High Byte: Minimum allowed ticks
222; DS:DI: Ptr to DPT for Single or Slave Drive
223; Returns:
224; AL: Timing value for QD65xx register
225; Corrupts registers:
226; Nothing
227;--------------------------------------------------------------------
228ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue:
229 push cx
230
231 ; Get VLB Cycle Time in nanosecs
232 mov cl, VLB_33MHZ_CYCLE_TIME ; Assume 33 MHz or slower VLB bus
233 test BYTE [di+DPT_ADVANCED_ATA.wControllerID], FLG_QDCONFIG_ID3
234 eCMOVZ cl, VLB_40MHZ_CYCLE_TIME
235
236 ; Convert value in AX to VLB ticks
237 div cl ; AL = VLB ticks
[363]238 inc ax ; Round up
239
[364]240 ; Limit value to QD65xx limits
241 mov cx, bp
242 MAX_U al, ch ; Make sure not below minimum
243 MIN_U al, cl ; Make sure not above maximum
244
[363]245 ; Not done yet, we need to invert the ticks since 0 is the slowest
246 ; value on the timing register
[364]247 sub cl, al
248 xchg ax, cx ; Return in AL
[363]249
[364]250 pop cx
251 ret
Note: See TracBrowser for help on using the repository browser.