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

Last change on this file since 622 was 622, checked in by aitotat, 2 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.