source: xtideuniversalbios/trunk/XTIDE_Universal_BIOS/Src/Initialization/AdvancedAta/PDC20x30.asm@ 624

Last change on this file since 624 was 622, checked in by Tomi Tilli, 3 years ago
  • Supported VLB controllers are now forced to 32-bit mode on 386 builds only. AT builds use 16-bit transfers unless configured to 32-bit from xtidecfg
  • Partially fixed support for PDC 20230C VLB IDE controller. PIO-1 drives stay at PIO-0 but PIO-2, 3 and 4 drives are set to maximum speed that PDC2030C supports
  • Large 386 build is now 12k instead of 10k (did not fit to 10k because of the fixes)
File size: 10.2 KB
RevLine 
[587]1; Project name : XTIDE Universal BIOS
2; Description : Functions for initializing Promise
3; PDC 20230 and 20630 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; PDC20x30_DetectControllerForIdeBaseInBX
26; Parameters:
27; BX: IDE Base Port
28; Returns:
29; AX: ID WORD for detected controller
30; DX: Controller base port
31; CF: Set if PDC detected
32; Corrupts registers:
33; BX (only when PDC detected)
34;--------------------------------------------------------------------
35PDC20x30_DetectControllerForIdeBaseInBX:
36 mov dx, bx
37 call EnablePdcProgrammingMode
[589]38 jnz SHORT DisablePdcProgrammingMode.Return ; PDC controller not detected
39; ePUSH_T ax, DisablePdcProgrammingMode ; Uncomment this if GetPdcIDtoAX needs to be a real function
40 ; Fall to GetPdcIDtoAX
41
42;--------------------------------------------------------------------
43; Programming mode must be enabled for this function.
44; This function also enables PDC 20630 extra registers.
45;
46; GetPdcIDtoAX
47; Parameters:
48; DX: IDE Base port
49; Returns:
50; AH: PDC ID
51; Corrupts registers:
52; AL, BX
53;--------------------------------------------------------------------
54GetPdcIDtoAX:
[622]55;Force ID_PDC20230 instead of PDC20630 detection
56;mov ax, ID_PDC20230<<8
57;jmp SHORT DisablePdcProgrammingMode
58
[589]59 push dx
60
61 ; Try to enable PDC 20630 extra registers
62 add dx, BYTE LOW_CYLINDER_REGISTER
63 in al, dx
64 or al, FLG_PDCLCR_ENABLE_EXTRA_REGISTERS
65 out dx, al
66
67 ; Try to access PDC 20630 registers to see if they are available
68 ; Hopefully this does not cause problems for systems with PDC 20230
69 add dx, BYTE PDC20630_INDEX_REGISTER - LOW_CYLINDER_REGISTER
70 mov al, PDCREG7_STATUS ; Try to access PDC 20630 status register
71 out dx, al
72 xchg bx, ax
73 in al, dx ; Does index register contain status register index?
74 cmp al, bl
75 mov ah, ID_PDC20630
76 eCMOVNE ah, ID_PDC20230
77
78 pop dx
79; ret ; Uncomment this to make GetPdcIDtoAX a real function
[587]80 ; Fall to DisablePdcProgrammingMode
81
82
83;--------------------------------------------------------------------
84; DisablePdcProgrammingMode
85; Parameters:
86; DX: Base port
87; Returns:
[589]88; CF: Set
[587]89; Corrupts registers:
90; AL
91;--------------------------------------------------------------------
92DisablePdcProgrammingMode:
[622]93 add dx, BYTE HIGH_CYLINDER_REGISTER ; 1F5h
[587]94 in al, dx
[589]95 add dx, -HIGH_CYLINDER_REGISTER ; Sets CF for PDC20x30_DetectControllerForIdeBaseInBX
[622]96%if 0
97 ; Disassembly of VG4.BIN shows that bit 7 (programming mode activated)
98 ; is cleared manually after reading from HIGH_CYLINDER_REGISTER
99 ; That does not seem to be necessary.
100 inc dx
101 inc dx
102 call AdvAtaInit_InputWithDelay
103 and al, 7Fh
104 out dx, al
105 dec dx
106 dec dx
107 stc
108%endif
[589]109.Return:
[587]110 ret
111
112
113;--------------------------------------------------------------------
114; EnablePdcProgrammingMode
115; Parameters:
116; DX: Base port
117; Returns:
[589]118; CF: Cleared
[587]119; ZF: Set if programming mode enabled
120; Corrupts registers:
121; AL
122;--------------------------------------------------------------------
123EnablePdcProgrammingMode:
124 ; Set bit 7 to sector count register
[589]125 inc dx
126 inc dx
[622]127 call AdvAtaInit_InputWithDelay ; 1F2h (SECTOR_COUNT_REGISTER)
[587]128 or al, 80h
129 out dx, al
130
[622]131 ; PDC detection sequence
132 add dx, BYTE HIGH_CYLINDER_REGISTER - SECTOR_COUNT_REGISTER ; 5 - 2
[587]133 cli
[622]134 call AdvAtaInit_InputWithDelay ; 1F5
135
[587]136 sub dx, BYTE HIGH_CYLINDER_REGISTER - SECTOR_COUNT_REGISTER
[622]137 call AdvAtaInit_InputWithDelay ; 1F2h
138
139 add dx, STANDARD_CONTROL_BLOCK_OFFSET + (ALTERNATE_STATUS_REGISTER_in - SECTOR_COUNT_REGISTER) ; 200h+(6-2)
140 call AdvAtaInit_InputWithDelay ; 3F6h
141
142 call AdvAtaInit_InputWithDelay ; 3F6h
143
[587]144 sub dx, STANDARD_CONTROL_BLOCK_OFFSET + (ALTERNATE_STATUS_REGISTER_in - SECTOR_COUNT_REGISTER)
[622]145 call AdvAtaInit_InputWithDelay ; 1F2h
146
147 call AdvAtaInit_InputWithDelay ; 1F2h
[587]148 sti
149
150 ; PDC20230C and PDC20630 clears the bit we set at the beginning
[622]151 call AdvAtaInit_InputWithDelay ; 1F2h
[589]152 dec dx
153 dec dx ; Base port
154 test al, 80h ; Clears CF
[587]155 ret
156
157
158;--------------------------------------------------------------------
159; PDC20x30_GetMaxPioModeToALandMinPioCycleTimeToBX
160; Parameters:
161; AX: ID WORD specific for detected controller
162; Returns:
[592]163; AL: Max supported PIO mode (only if ZF set)
164; AH: ~FLGH_DPT_IORDY if IORDY not supported, -1 otherwise (only if ZF set)
[587]165; BX: Min PIO cycle time (only if ZF set)
166; ZF: Set if PIO limit necessary
167; Cleared if no need to limit timings
168; Corrupts registers:
169; Nothing
170;--------------------------------------------------------------------
171PDC20x30_GetMaxPioModeToALandMinPioCycleTimeToBX:
[592]172 cmp ah, ID_PDC20230
173 jne SHORT .Return ; No need to limit anything for ID_PDC20630
174 mov ax, (~FLGH_DPT_IORDY & 0FFh) << 8 | 2 ; Limit PIO to 2 for ID_PDC20230
[587]175 mov bx, PIO_2_MIN_CYCLE_TIME_NS
[589]176.Return:
[587]177 ret
178
179
180;--------------------------------------------------------------------
181; PDC20x30_InitializeForDPTinDSDI
182; Parameters:
183; DS:DI: Ptr to DPT for Single or Slave Drive
184; Returns:
185; AH: Int 13h return status
186; CF: Cleared if success or no controller to initialize
187; Set if error
188; Corrupts registers:
189; AL, BX, CX, DX
190;--------------------------------------------------------------------
191PDC20x30_InitializeForDPTinDSDI:
[589]192%ifdef USE_386
193 xor ch, ch
194 test BYTE [di+DPT.bFlagsLow], FLGL_DPT_SLAVE
195 setnz cl
196%else
[587]197 xor cx, cx
198 test BYTE [di+DPT.bFlagsLow], FLGL_DPT_SLAVE
[589]199 jz SHORT .NotSlave
200 inc cx
201.NotSlave:
202%endif
[587]203
204 mov dx, [di+DPT.wBasePort]
205 call EnablePdcProgrammingMode
206 call SetSpeedForDriveInCX
207 cmp BYTE [di+DPT_ADVANCED_ATA.wControllerID+1], ID_PDC20630
[589]208 jne SHORT .InitializationCompleted
[587]209 call SetPdc20630SpeedForDriveInCX
[622]210
211 ; TODO: Should we first call SetPdc20630SpeedForDriveInCX and then
212 ; force SetSpeedForDriveInCX to PIO 0 (maximum speed setting 8)?
213 ; Need to test with PCD20630.
214
[589]215.InitializationCompleted:
[587]216 mov dx, [di+DPT.wBasePort]
217 call DisablePdcProgrammingMode
218 xor ah, ah
219 ret
220
221
222;--------------------------------------------------------------------
223; SetSpeedForDriveInCX
224; Parameters:
225; CX: 0 for master, 1 for slave drive
226; DX: IDE Base port
227; DS:DI: Ptr to DPT
228; Returns:
[622]229; DX: Sector Number Register (1F3h)
[587]230; Corrupts registers:
231; AX, BX
232;--------------------------------------------------------------------
233SetSpeedForDriveInCX:
[592]234 mov bx, .rgbPioModeToPDCspeedValue
235 mov al, [di+DPT_ADVANCED_ATA.bPioMode]
236 MIN_U al, 2 ; Limit to PIO2
237 cs xlat
238 xchg bx, ax
[587]239
[622]240 add dx, BYTE SECTOR_NUMBER_REGISTER ; 1F3h
241 mov bh, ~MASK_PDCSNR_DEV1SPEED ; Assume slave
[588]242 inc cx
[622]243 mov ah, 7 ; Max speed value. Set unknown bit 7 if either of drives are set to this
[589]244 loop .SetSpeed
[622]245 mov ah, 7 << POS_PDCSNR_DEV0SPEED
246 eSHL_IM bl, POS_PDCSNR_DEV0SPEED
247 mov bh, ~MASK_PDCSNR_DEV0SPEED
[589]248.SetSpeed:
[587]249 in al, dx
250 and al, bh
251 or al, bl
[622]252 cmp bl, ah
[589]253 jb SHORT .OutputNewValue
[622]254 or al, FLG_PDCSNR_UNKNOWN_BIT7 ; Flag for PIO 2 and above?
[589]255.OutputNewValue:
256 out dx, al
[622]257
258 ; The above speed set does not work with Octek VL-COMBO rev 3.2 with PDC20230C
259 ; Only thing to make it work is to set FLG_PDCSCR_BOTHMAX to 1F2h. Are all PDC20230C controllers
260 ; like that? If so, why the above speed is not set? Or does the VL-COMBO or other PDC20230C
261 ; controllers have a jumper to prevent speed setup by software? (PDC20230B can only be set
262 ; by hardware, for example), like pin-compatible operation with older PDC20230B, perhaps?
263 ; Datasheets would be very useful...
264 ; For now, we just set the FLG_PDCSCR_BOTHMAX bit if either of the drives are set to speed 7
265 ;
266 ; Code below is not perfect. It does not properly test if both drives support PIO 2 but
267 ; likely if slave does, so does master (and if slave does not, we clear the
268 ; FLG_PDCSCR_BOTHMAX set by master)
269 mov bl, 1 ; Set bit 0, see VG4.BIN comments below
270 test al, al
271 jns SHORT .DoNotSetMaxSpeedBit
272 or bl, FLG_PDCSCR_BOTHMAX
273.DoNotSetMaxSpeedBit:
274 dec dx ; SECTOR_COUNT_REGISTER, 1F2h
275 call AdvAtaInit_InputWithDelay
276 and al, ~FLG_PDCSCR_BOTHMAX
277 or al, bl
278 out dx, al
279
280 ; VG4.BIN ("External BIOS") does the following after programming speed (1F3h)
281 ; (It never seems to set the speed bit we just set above).
282 ; The below code does not seem to have any effect, at least not for PDC20230C.
283 ; Why is bit 0 set to 1F2h?
284 ; Is it just to keep programming mode active if it has timeout, for example?
285 ; But after all that it just reads 1F5h to disable programming mode.
286%if 0
287 ; Test code start
288 push cx
289 mov cx, 100
290 DELAY_WITH_LOOP_INSTRUCTION_NA
291
292 ; Does below tell the controller that new speed is set?
293 in al, dx
294 or al, 1
295 out dx, al
296
297 mov cx, 100
298 DELAY_WITH_LOOP_INSTRUCTION_NA
299 pop cx
300 ; Test code end
301%endif
302
303 inc dx ; SECTOR_NUMBER_REGISTER, 1F3h
[589]304 ret
[587]305
306.rgbPioModeToPDCspeedValue:
307 db 0 ; PIO 0
308 db 4 ; PIO 1
309 db 7 ; PIO 2
310
311
312;--------------------------------------------------------------------
313; SetPdc20630SpeedForDriveInCX
314; Parameters:
315; CX: 0 for master, 1 for slave drive
316; DS:DI: Ptr to DPT
[622]317; DX: Sector Number Register, 1F3h
[587]318; Returns:
319; DX: Low Cylinder Register
320; Corrupts registers:
[589]321; AX
[587]322;--------------------------------------------------------------------
323SetPdc20630SpeedForDriveInCX:
324 inc dx ; LOW_CYLINDER_REGISTER
[589]325 mov ah, ~(FLG_PDCLCR_DEV0SPEED_BIT4 | FLG_PDCLCR_DEV0IORDY)
326 ror ah, cl
[587]327 in al, dx
328 and al, ah ; Clear drive specific bits
329 cmp BYTE [di+DPT_ADVANCED_ATA.bPioMode], 2
[589]330 jbe .ClearBitsOnly
[587]331 not ah
332 or al, ah
[589]333.ClearBitsOnly:
[587]334 out dx, al
335 ret
336
Note: See TracBrowser for help on using the repository browser.