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

Last change on this file was 596, checked in by krille_n_, 3 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.