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

Last change on this file since 593 was 593, checked in by aitotat, 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
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
196    eMOVZX  cx, BYTE [cs:bx+.rgbToSubtractFromCycleTimeBasedOnPIOmode]
197    sub     ax, cx
[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.