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

Last change on this file since 363 was 363, checked in by aitotat@…, 12 years ago

Changes to XTIDE Universal BIOS:

  • Added Advanced ATA Module (MODULE_ADVANCED_ATA) with native support for QDI Vision QD6500 and QD6580 VLB IDE Controllers.
  • Hopefully optimized IDE transfer functions for 8088 (replaced some memory accesses from WORD to BYTE).
  • XT build does not fit in 8k at the moment!!!
File size: 7.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; Section containing code
6SECTION .text
7
8;--------------------------------------------------------------------
9; Vision_DetectAndReturnIDinAXandPortInCXifControllerPresent
10;   Parameters:
11;       Nothing
12;   Returns:
13;       AX:     ID WORD specific for QDI Vision Controllers
14;               (AL = QD65xx Config Register contents)
15;               (AH = QDI Vision Controller ID (bits 4...7))
16;       CX:     Controller port (not IDE port)
17;       ZF:     Set if controller found
18;               Cleared if supported controller not found (AX,DX = undefined)
19;   Corrupts registers:
20;       Nothing
21;--------------------------------------------------------------------
22Vision_DetectAndReturnIDinAXandPortInCXifControllerPresent:
23    ; Check QD65xx base port
24    mov     cx, QD65XX_BASE_PORT
25    in      al, QD65XX_BASE_PORT + QD65XX_CONFIG_REGISTER_in
26    call    IsConfigRegisterWithIDinAL
27    je      SHORT VisionControllerDetected
28
29    ; Check QD65xx alternative base port
30    or      cl, QD65XX_ALTERNATIVE_BASE_PORT
31    in      al, QD65XX_ALTERNATIVE_BASE_PORT + QD65XX_CONFIG_REGISTER_in
32    ; Fall to IsConfigRegisterWithIDinAL
33
34;--------------------------------------------------------------------
35; IsConfigRegisterWithIDinAL
36;   Parameters:
37;       AL:     Possible QD65xx Config Register contents
38;   Returns:
39;       AH      QDI Vision Controller ID or undefined
40;       ZF:     Set if controller found
41;               Cleared if supported controller not found (AH = undefined)
42;   Corrupts registers:
43;       Nothing
44;--------------------------------------------------------------------
45IsConfigRegisterWithIDinAL:
46    mov     ah, al
47    and     ah, MASK_QDCONFIG_CONTROLLER_ID
48    cmp     ah, ID_QD6500 << 4
49    je      SHORT VisionControllerDetected
50    cmp     ah, ID_QD6580 << 4
51    je      SHORT VisionControllerDetected
52    cmp     ah, ID_QD6580_ALTERNATE << 4
53VisionControllerDetected:
54    ret
55
56
57;--------------------------------------------------------------------
58; Vision_DoesIdePortInDXbelongToControllerWithIDinAX
59;   Parameters:
60;       AX:     ID WORD specific for QDI Vision Controllers
61;               (AL = QD65xx Config Register contents)
62;               (AH = QDI Vision Controller ID (bits 4...7))
63;       CX:     Vision Controller port
64;       DX:     IDE base port to check
65;   Returns:
66;       ZF:     Set if port belongs to controller
67;               Cleared if port belongs to another controller
68;   Corrupts registers:
69;       BX
70;--------------------------------------------------------------------
71Vision_DoesIdePortInDXbelongToControllerWithIDinAX:
72    cmp     ah, ID_QD6500 << 4
73    je      SHORT .DoesIdePortInDXbelongToQD6500
74
75    ; QD6580 always have Primary IDE at 1F0h
76    ; Secondary IDE at 170h can be enabled or disabled
77    cmp     dx, DEVICE_ATA_DEFAULT_PORT
78    je      SHORT .ReturnResultInZF
79
80    ; Check if Secondary IDE channel is enabled
81    xchg    bx, ax      ; Backup AX
82    xchg    dx, cx      ; Swap ports
83
84    add     dx, BYTE QD6580_CONTROL_REGISTER
85    in      al, dx
86    sub     dx, BYTE QD6580_CONTROL_REGISTER
87
88    xchg    cx, dx
89    xchg    ax, bx      ; Restore AX, Control Register to BL
90    test    bl, FLG_QDCONTROL_SECONDARY_DISABLED_in
91    jz      SHORT .CompareDXtoSecondaryIDE
92    ret
93
94    ; QD6500 has only one IDE channel that can be at 1F0h or 170h
95.DoesIdePortInDXbelongToQD6500:
96    test    al, FLG_QDCONFIG_PRIMARY_IDE
97    jz      SHORT .CompareDXtoSecondaryIDE
98    cmp     dx, DEVICE_ATA_DEFAULT_PORT
99    ret
100
101.CompareDXtoSecondaryIDE:
102    cmp     dx, DEVICE_ATA_DEFAULT_SECONDARY_PORT
103.ReturnResultInZF:
104    ret
105
106
107;--------------------------------------------------------------------
108; Vision_GetMaxPioModeToAL
109;   Parameters:
110;       AX:     ID WORD specific for QDI Vision Controllers
111;               (AH = QDI Vision Controller ID (bits 4...7))
112;   Returns:
113;       AL:     Max supported PIO mode (if CF set)
114;       CF:     Set if PIO limit necessary
115;               Cleared if no need to limit timings
116;   Corrupts registers:
117;       Nothing
118;--------------------------------------------------------------------
119Vision_GetMaxPioModeToAL:
120    cmp     ah, ID_QD6500 << 4
121    clc
122    jne     SHORT .NoNeedToLimitForQD6580
123
124    mov     al, 2   ; Limit to PIO 2 because QD6500 supports PIO 3 but without IORDY
125    stc
126.NoNeedToLimitForQD6580:
127    ret
128
129
130;--------------------------------------------------------------------
131; Vision_InitializeWithIDinAHandConfigInAL
132;   Parameters:
133;       AX:     ID WORD specific for QDI Vision Controllers
134;               (AL = QD65xx Config Register contents)
135;               (AH = QDI Vision Controller ID (bits 4...7))
136;       DS:SI:  Ptr to BOOTMENUINFO for Single or Master Drive
137;       DS:DI:  Ptr to BOOTMENUINFO for Slave Drive
138;               Zero if Slave not present
139;   Returns:
140;       CF:     Cleared if success
141;               Set if error
142;   Corrupts registers:
143;       AX, BX, CX, DX, SI, DI
144;--------------------------------------------------------------------
145Vision_InitializeWithIDinAHandConfigInAL:
146    ; QD6580 has a Control Register that needs to be programmed
147    mov     dx, [si+BOOTMENUINFO.wControllerBasePort]
148    cmp     ah, ID_QD6500 << 4
149    je      SHORT .GetPioTimingsInNanosecs
150
151    ; Program QD6580 Control Register (not available on QD6500) to
152    ; Enable or Disable Read-Ahead and Post-Write Buffer to match
153    ; jumper setting on the multi I/O card.
154.ProgramControlRegisterForQD6580:
155    xchg    bx, ax                                  ; Backup AX
156    add     dx, BYTE QD6580_CONTROL_REGISTER
157    in      al, dx                                  ; Read to get ATAPI jumper status
158    test    al, FLG_QDCONTROL_HDONLY_in
159    mov     al, MASK_QDCONTROL_FLAGS_TO_SET
160    jz      SHORT .SkipHdonlyBitSinceAtapiPossible
161    or      al, FLG_QDCONTROL_NONATAPI
162.SkipHdonlyBitSinceAtapiPossible:
163    out     dx, al
164    sub     dx, BYTE QD6580_CONTROL_REGISTER        ; Back to base port
165    xchg    ax, bx                                  ; Restore AX
166
167    ; If we have Master and Slave drive in the system, we must select
168    ; timings from the slower drive (this is why it is a bad idea to use
169    ; fast and slow drive on the same IDE channel)
170.GetPioTimingsInNanosecs:
171    call    AdvAtaInit_SelectSlowestTimingsToBXandCX
172
173    ; Now we need to determine is the drive connected to the Primary or Secondary channel.
174    ; QD6500 has only one channel that can be Primary at 1F0h or Secondary at 170h.
175    ; QD6580 always has Primary channel at 1F0h. Secondary channel at 170h can be Enabled or Disabled.
176    cmp     ah, ID_QD6500 << 4
177    je      SHORT .CalculateTimingTicksForQD6500
178    cmp     WORD [si+BOOTMENUINFO.wIdeBasePort], DEVICE_ATA_DEFAULT_PORT
179    je      SHORT .CalculateTimingTicksForQD6580
180    times 2 inc dx                                  ; Secondary Channel IDE Timing Register
181
182    ; Now we must translate the PIO timing nanosecs in CX and DX to VLB ticks
183    ; suitable for QD65xx IDE Timing Register.
184    ; Both of the controllers require slightly different calculations.
185.CalculateTimingTicksForQD6580:
186    mov     si, QD6580_MIN_ACTIVE_TIME_CLOCKS
187    mov     di, QD6580_MAX_ACTIVE_TIME_CLOCKS
188    jmp     SHORT .CalculateTimingForQD65xx
189
190.CalculateTimingTicksForQD6500:
191    mov     si, QD6500_MIN_ACTIVE_TIME_CLOCKS
192    mov     di, QD6500_MAX_ACTIVE_TIME_CLOCKS
193
194.CalculateTimingForQD65xx:
195    test    al, FLG_QDCONFIG_ID3        ; Set ZF if 40 MHz VLB bus
196    mov     al, VLB_33MHZ_CYCLE_TIME    ; Assume 33 MHz or slower VLB bus
197    xchg    ax, bx                      ; Active Time to AX
198    eCMOVZ  bl, VLB_40MHZ_CYCLE_TIME
199
200    div     bl
201    inc     ax                          ; Round up
202    xor     ah, ah
203    xchg    cx, ax                      ; CX = Active Time in VLB ticks
204    MAX_U   cx, si                      ; Limit ticks to valid values...
205    MIN_U   cx, di                      ; ...for QD65xx
206
207    div     bl
208    inc     ax                          ; Round up
209    xchg    bx, ax                      ; BL = Recovery Time in VLB ticks
210    mov     al, QD65xx_MAX_RECOVERY_TIME_CLOCKS
211    MAX_U   bl, QD65xx_MIN_RECOVERY_TIME_CLOCKS
212    MIN_U   bl, al
213
214    ; Not done yet, we need to invert the ticks since 0 is the slowest
215    ; value on the timing register
216    sub     di, cx                      ; DI = Active Time value to program
217    sub     al, bl                      ; AL = Recovery Time value to program
218
219    ; Finally we can shift the values in places and program the Timing Register
220    eSHIFT_IM   al, POSITON_QD65XXIDE_RECOVERY_TIME, shl
221    or      ax, di
222    out     dx, al
223    ret                                 ; Return with CF cleared
Note: See TracBrowser for help on using the repository browser.