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

Last change on this file since 363 was 363, checked in by aitotat@…, 13 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.