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

Last change on this file since 526 was 526, checked in by krille_n_@…, 9 years ago

Changes:

  • Update of the copyright notices to include the year 2013.
File size: 8.6 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    call    IsConfigRegisterWithIDinAL
43    je      SHORT VisionControllerDetected
44
45    ; Check QD65xx alternative base port
46    or      dl, QD65XX_ALTERNATIVE_BASE_PORT
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
63    and     al, MASK_QDCONFIG_CONTROLLER_ID
64    cmp     al, ID_QD6500 << 4
65    je      SHORT VisionControllerDetected
66    cmp     al, ID_QD6580 << 4
67    je      SHORT VisionControllerDetected
68    cmp     al, ID_QD6580_ALTERNATE << 4
69VisionControllerDetected:
70    xchg    ah, al
71    ret
72
73
74;--------------------------------------------------------------------
75; Vision_DoesIdePortInBXbelongToControllerWithIDinAX
76;   Parameters:
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
81;   Returns:
82;       ZF:     Set if port belongs to controller
83;               Cleared if port belongs to another controller
84;   Corrupts registers:
85;       Nothing
86;--------------------------------------------------------------------
87Vision_DoesIdePortInBXbelongToControllerWithIDinAX:
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
93    cmp     bx, DEVICE_ATA_PRIMARY_PORT
94    je      SHORT .ReturnResultInZF
95
96    ; Check if Secondary IDE channel is enabled
97    push    ax
98    add     dx, BYTE QD6580_CONTROL_REGISTER
99    in      al, dx
100    sub     dx, BYTE QD6580_CONTROL_REGISTER
101    test    al, FLG_QDCONTROL_SECONDARY_DISABLED_in
102    pop     ax
103    jz      SHORT .CompareBXtoSecondaryIDE
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
109    jz      SHORT .CompareBXtoSecondaryIDE
110    cmp     bx, DEVICE_ATA_PRIMARY_PORT
111    ret
112
113.CompareBXtoSecondaryIDE:
114    cmp     bx, DEVICE_ATA_SECONDARY_PORT
115.ReturnResultInZF:
116    ret
117
118
119;--------------------------------------------------------------------
120; Vision_GetMaxPioModeToAL
121;   Parameters:
122;       AL:     QD65xx Config Register contents
123;       AH:     QDI Vision Controller ID (bits 4...7)
124;   Returns:
125;       AL:     Max supported PIO mode
126;       AH:     FLGH_DPT_IORDY if IORDY supported, zero otherwise
127;       CF:     Set if PIO limit necessary
128;               Cleared if no need to limit timings
129;   Corrupts registers:
130;       (AX if CF cleared)
131;   Corrupts registers:
132;       Nothing
133;--------------------------------------------------------------------
134Vision_GetMaxPioModeToAL:
135    cmp     ah, ID_QD6500 << 4
136    clc
137    jne     SHORT .NoNeedToLimitForQD6580
138
139    mov     ax, 2   ; Limit to PIO 2 because QD6500 does not support IORDY
140    stc
141.NoNeedToLimitForQD6580:
142    ret
143
144
145;--------------------------------------------------------------------
146; Vision_InitializeWithIDinAHandConfigInAL
147;   Parameters:
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
153;   Returns:
154;       CF:     Cleared if success
155;               Set if error
156;   Corrupts registers:
157;       AX, BX, CX, DX, BP
158;--------------------------------------------------------------------
159Vision_InitializeWithIDinAHandConfigInAL:
160    ; QD6580 has a Control Register that needs to be programmed
161    mov     dx, [di+DPT_ADVANCED_ATA.wControllerBasePort]
162    cmp     ah, ID_QD6500 << 4
163    je      SHORT .CalculateTimingForQD6500
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.
168    xor     ax, ax
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    eCMOVNZ ah, FLG_QDCONTROL_NONATAPI              ; Enable Read-Ahead and Post-Write Buffers
173    or      ah, MASK_QDCONTROL_FLAGS_TO_SET
174    mov     al, ah
175    out     dx, al
176    sub     dx, BYTE QD6580_CONTROL_REGISTER
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.
181    mov     bx, [di+DPT.wBasePort]
182    cmp     bx, DEVICE_ATA_PRIMARY_PORT
183    je      SHORT .CalculateTimingTicksForQD6580    ; Primary Channel so no need to modify DX
184    times 2 inc dx                                  ; Secondary Channel IDE Timing Register
185
186    ; QD6500 and QD6580 require slightly different calculations.
187.CalculateTimingTicksForQD6580:
188    mov     bp, QD6580_MAX_ACTIVE_TIME_CLOCKS | (QD6580_MIN_ACTIVE_TIME_CLOCKS << 8)
189    jmp     SHORT .CalculateTimingsForQD65xx
190
191.CalculateTimingForQD6500:
192    mov     bp, QD6500_MAX_ACTIVE_TIME_CLOCKS | (QD6500_MIN_ACTIVE_TIME_CLOCKS << 8)
193
194    ; We need the PIO Cycle Time in CX to calculate Active and Recovery Times.
195.CalculateTimingsForQD65xx:
196    call    AdvAtaInit_SelectSlowestCommonPioTimingsToBXandCXfromDSSIandDSDI
197
198    ; Calculate Active Time value for QD65xx IDE Timing Register
199    call    AtaID_GetActiveTimeToAXfromPioModeInBX
200    call    ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue
201    xchg    bp, ax
202
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
238    inc     ax                          ; Round up
239
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
245    ; Not done yet, we need to invert the ticks since 0 is the slowest
246    ; value on the timing register
247    sub     cl, al
248    xchg    ax, cx                      ; Return in AL
249
250    pop     cx
251    ret
Note: See TracBrowser for help on using the repository browser.