source: xtideuniversalbios/trunk/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/AtaGeometry.asm @ 567

Last change on this file since 567 was 567, checked in by krille_n_@…, 10 years ago

Changes:

  • Renamed MODULE_FEATURE_SETS to MODULE_POWER_MANAGEMENT.
  • Renamed MODULE_VERY_LATE_INITIALIZATION to MODULE_VERY_LATE_INIT and removed it from the official builds.
  • Removed the code that skips detection of slave drives on XT-CF controllers since slave drives can be used with Lo-tech ISA CompactFlash boards.
  • Added autodetection of the SVC ADP50L controller to XTIDECFG.
  • The autodetection of XT-CF controllers now requires MODULE_8BIT_IDE_ADVANCED in the loaded BIOS.
  • Fixed a bug in XTIDECFG from r502 where the "Base (cmd block) address" menu option would be displayed when a serial device was selected as the IDE controller.
  • XTIDECFG would display the "Enable interrupt" menu option for the XTIDE r1 but not for the XTIDE r2. It's now displayed for both controller types.
  • Disabled the "Internal Write Cache" menu option in the Master/Slave Drive menus for serial device type drives.
  • Optimizations and other fixes.
File size: 12.3 KB
Line 
1; Project name  :   XTIDE Universal BIOS
2; Description   :   Functions for generating L-CHS parameters for
3;                   drives with more than 1024 cylinders.
4;
5;                   These algorithms are taken from: http://www.mossywell.com/boot-sequence
6;                   Take a look at it for more detailed information.
7;
8;                   This file is shared with BIOS Drive Information Tool.
9
10;
11; XTIDE Universal BIOS and Associated Tools
12; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2013 by XTIDE Universal BIOS Team.
13;
14; This program is free software; you can redistribute it and/or modify
15; it under the terms of the GNU General Public License as published by
16; the Free Software Foundation; either version 2 of the License, or
17; (at your option) any later version.
18;
19; This program is distributed in the hope that it will be useful,
20; but WITHOUT ANY WARRANTY; without even the implied warranty of
21; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22; GNU General Public License for more details.
23; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
24;
25
26; Section containing code
27SECTION .text
28
29%ifdef MODULE_EBIOS
30;--------------------------------------------------------------------
31; AtaGeometry_GetLbaSectorCountToBXDXAXfromAtaInfoInESSI
32;   Parameters:
33;       ES:SI:  Ptr to 512-byte ATA information read from the drive
34;   Returns:
35;       BX:DX:AX:   48-bit sector count
36;       CL:         FLGL_DPT_LBA48 if LBA48 supported
37;                   Zero if only LBA28 is supported
38;   Corrupts registers:
39;       Nothing
40;--------------------------------------------------------------------
41AtaGeometry_GetLbaSectorCountToBXDXAXfromAtaInfoInESSI:
42    mov     bx, Registers_ExchangeDSSIwithESDI
43    call    bx  ; ATA info now in DS:DI
44    push    bx  ; We will return via Registers_ExchangeDSSIwithESDI
45
46    ; Check if LBA48 supported
47    test    BYTE [di+ATA6.wSetSup83+1], A6_wSetSup83_LBA48>>8
48    jz      SHORT .GetLba28SectorCount
49
50    ; Get LBA48 sector count
51    mov     cl, FLGL_DPT_LBA48
52    mov     ax, [di+ATA6.qwLBACnt]
53    mov     dx, [di+ATA6.qwLBACnt+2]
54    mov     bx, [di+ATA6.qwLBACnt+4]
55    ret
56
57.GetLba28SectorCount:
58    xor     cl, cl
59    xor     bx, bx
60    mov     ax, [di+ATA1.dwLBACnt]
61    mov     dx, [di+ATA1.dwLBACnt+2]
62    ret
63%endif  ; MODULE_EBIOS
64
65
66;--------------------------------------------------------------------
67; AtaGeometry_GetLCHStoAXBLBHfromAtaInfoInESSIwithTranslateModeInDX
68;   Parameters:
69;       DX:     Wanted translate mode or TRANSLATEMODE_AUTO to autodetect
70;       ES:SI:  Ptr to 512-byte ATA information read from the drive
71;   Returns:
72;       AX:     Number of L-CHS cylinders (1...1027, yes 1027)
73;       BL:     Number of L-CHS heads (1...255)
74;       BH:     Number of L-CHS sectors per track (1...63)
75;       CX:     Number of bits shifted (0...3)
76;       DL:     CHS Translate Mode
77;   Corrupts registers:
78;       DH
79;--------------------------------------------------------------------
80AtaGeometry_GetLCHStoAXBLBHfromAtaInfoInESSIwithTranslateModeInDX:
81    call    AtaGeometry_GetPCHStoAXBLBHfromAtaInfoInESSI
82
83    ; Check if user defined translate mode
84    dec     dx                      ; Set ZF if TRANSLATEMODE_LARGE, SF if TRANSLATEMODE_NORMAL
85    jns     SHORT .CheckIfLargeTranslationWanted
86    MIN_U   ax, MAX_LCHS_CYLINDERS  ; TRANSLATEMODE_NORMAL maximum cylinders
87    inc     dx
88.CheckIfLargeTranslationWanted:
89    jz      SHORT ConvertPCHfromAXBLtoRevisedEnhancedCHinAXBL
90    dec     dx                      ; Set ZF if TRANSLATEMODE_ASSISTED_LBA
91    jz      SHORT .UseAssistedLBA
92    ; TRANSLATEMODE_AUTO set
93
94%ifndef MODULE_EBIOS
95    ; Since we do not have EBIOS functions, we might as well use the faster
96    ; LARGE mode for small drives. Assisted LBA provides more capacity for
97    ; larger drives.
98    ; Generate L-CHS using simple bit shift algorithm (ECHS) if
99    ; 8192 or less cylinders.
100    cmp     ax, 8192
101    jbe     SHORT ConvertPCHfromAXBLtoEnhancedCHinAXBL
102%endif
103
104    ; If we have EBIOS functions, we should always use Assisted LBA
105    ; for drives with LBA support. Otherwise the EBIOS functions are
106    ; useless since we never do LBA to P-CHS translation.
107    ; Even if we do not have EBIOS functions, we must do this check
108    ; since user might have forced LBA mode even though the drive does
109    ; not support LBA addressing.
110    test    BYTE [es:si+ATA1.wCaps+1], A1_wCaps_LBA>>8
111    jz      SHORT ConvertPCHfromAXBLtoRevisedEnhancedCHinAXBL
112
113    ; Assisted LBA provides most capacity but translation algorithm is
114    ; slower. The speed difference doesn't matter on AT systems.
115.UseAssistedLBA:
116    call    GetSectorCountToDXAXfromCHSinAXBLBH
117    call    ConvertChsSectorCountFromDXAXtoLbaAssistedLCHSinAXBLBH
118    xor     cx, cx      ; No bits to shift
119    mov     dl, TRANSLATEMODE_ASSISTED_LBA
120    ret
121
122
123;--------------------------------------------------------------------
124; AtaGeometry_GetPCHStoAXBLBHfromAtaInfoInESSI
125;   Parameters:
126;       ES:SI:  Ptr to 512-byte ATA information read from the drive
127;   Returns:
128;       AX:     Number of P-CHS cylinders (1...16383)
129;       BL:     Number of P-CHS heads (1...16)
130;       BH:     Number of P-CHS sectors per track (1...63)
131;   Corrupts registers:
132;       Nothing
133;--------------------------------------------------------------------
134AtaGeometry_GetPCHStoAXBLBHfromAtaInfoInESSI:
135    mov     ax, [es:si+ATA1.wCylCnt]    ; Cylinders (1...16383)
136    mov     bl, [es:si+ATA1.wHeadCnt]   ; Heads (1...16)
137    mov     bh, [es:si+ATA1.wSPT]       ; Sectors per Track (1...63)
138    ret
139
140
141;--------------------------------------------------------------------
142; GetSectorCountToDXAXfromCHSinAXBLBH
143;   Parameters:
144;       ES:SI:  Ptr to 512-byte ATA information read from the drive
145;       AX:     Number of cylinders (1...16383)
146;       BL:     Number of heads (1...255)
147;       BH:     Number of sectors per track (1...63)
148;   Returns:
149;       DX:AX:  Total number of CHS addressable sectors
150;   Corrupts registers:
151;       BX
152;--------------------------------------------------------------------
153GetSectorCountToDXAXfromCHSinAXBLBH:
154    xchg    ax, bx
155    mul     ah          ; AX = Heads * Sectors per track
156    mul     bx
157    ret
158
159
160;--------------------------------------------------------------------
161; Revised Enhanced CHS calculation (Revised ECHS)
162;
163; This algorithm translates P-CHS sector count to L-CHS sector count
164; with bit shift algorithm. Since 256 heads are not allowed
165; (DOS limit), this algorithm makes translations so that maximum of
166; 240 L-CHS heads can be used. This makes the maximum addressable capacity
167; to 7,927,234,560 bytes ~ 7.38 GiB. LBA addressing needs to be used to
168; get more capacity.
169;
170; L-CHS parameters generated here require the drive to use CHS addressing.
171;
172; Here is the algorithm:
173; If cylinders > 8192 and heads = 16
174;  Heads = 15
175;  Cylinders = cylinders * 16 / 15 (losing the fraction component)
176;  Do a standard ECHS translation
177;
178; ConvertPCHfromAXBLtoRevisedEnhancedCHinAXBL:
179;   Parameters:
180;       AX:     Number of P-CHS cylinders (8193...16383)
181;       BL:     Number of P-CHS heads (1...16)
182;   Returns:
183;       AX:     Number of L-CHS cylinders (?...1024)
184;       BL:     Number of L-CHS heads (?...240)
185;       CX:     Number of bits shifted (0...3)
186;       DX:     ADDRESSING_MODE_NORMAL or ADDRESSING_MODE_LARGE
187;   Corrupts registers:
188;       Nothing
189;--------------------------------------------------------------------
190ConvertPCHfromAXBLtoRevisedEnhancedCHinAXBL:
191    ; Generate L-CHS using simple bit shift algorithm (ECHS) if
192    ; 8192 or less cylinders
193    call    AtaGeometry_IsDriveSmallEnoughForECHS
194    jc      SHORT ConvertPCHfromAXBLtoEnhancedCHinAXBL
195
196    eMOVZX  cx, bl  ; CX = 16
197    dec     bx      ; Heads = 15
198    mul     cx      ; DX:AX = Cylinders * 16
199    dec     cx      ; CX = 15
200    div     cx      ; AX = (Cylinders * 16) / 15
201    ; Fall to ConvertPCHfromAXBLtoEnhancedCHinAXBL
202
203
204;--------------------------------------------------------------------
205; Enhanced CHS calculation (ECHS)
206;
207; This algorithm translates P-CHS sector count to L-CHS sector count
208; with simple bit shift algorithm. Since 256 heads are not allowed
209; (DOS limit), this algorithm require that there are at most 8192
210; P-CHS cylinders. This makes the maximum addressable capacity
211; to 4,227,858,432 bytes ~ 3.94 GiB. Use Revised ECHS or Assisted LBA
212; algorithms if there are more than 8192 P-CHS cylinders.
213;
214; L-CHS parameters generated here require the drive to use CHS addressing.
215;
216; Here is the algorithm:
217;  Multiplier = 1
218;  Cylinder = Cylinder - 1
219;  Is Cylinder < 1024? If not:
220;  Do a right bitwise rotation on the cylinder (i.e., divide by 2)
221;  Do a left bitwise rotation on the multiplier (i.e., multiply by 2)
222;  Use the multiplier on the Cylinder and Head values to obtain the translated values.
223;
224; ConvertPCHfromAXBLtoEnhancedCHinAXBL:
225;   Parameters:
226;       AX:     Number of P-CHS cylinders (1...8192, or up to 17475 if fell from above)
227;       BL:     Number of P-CHS heads (1...16)
228;   Returns:
229;       AX:     Number of L-CHS cylinders (?...1024)
230;       BL:     Number of L-CHS heads (?...128, or up to 240 if fell from above)
231;       CX:     Number of bits shifted (0...3)
232;       DX:     TRANSLATEMODE_NORMAL or TRANSLATEMODE_LARGE
233;   Corrupts registers:
234;       Nothing
235;--------------------------------------------------------------------
236ConvertPCHfromAXBLtoEnhancedCHinAXBL:
237    cwd                 ; Assume TRANSLATEMODE_NORMAL
238    xor     cx, cx      ; No bits to shift initially
239.ShiftIfMoreThan1024Cylinder:
240    cmp     ax, MAX_LCHS_CYLINDERS
241    jbe     SHORT ReturnLCHSinAXBLBH
242    shr     ax, 1       ; Halve cylinders
243    eSHL_IM bl, 1       ; Double heads
244    inc     cx          ; Increment bit shift count
245    mov     dl, TRANSLATEMODE_LARGE
246    jmp     SHORT .ShiftIfMoreThan1024Cylinder
247
248
249;--------------------------------------------------------------------
250; Checks should LARGE mode L-CHS be calculated with ECHS or Revised ECHS
251; algorithm. Revised ECHS is needed for drives with 8193 or more cylinders
252; AND 16 heads.
253;
254; AtaGeometry_IsDriveSmallEnoughForECHS:
255;   Parameters:
256;       AX:     Number of P-Cylinders
257;       BL:     Number of P-Heads
258;   Returns:
259;       CF:     Clear if Reviced ECHS is necessary
260;               Set if ECHS is enough
261;   Corrupts registers:
262;       Nothing
263;--------------------------------------------------------------------
264AtaGeometry_IsDriveSmallEnoughForECHS:
265    ; Generate L-CHS using simple bit shift algorithm (ECHS) if
266    ; 8192 or less cylinders. Use Revised ECHS if 8193 or more cylinders
267    ; AND 16 heads.
268    cmp     ax, 8193
269    jb      SHORT .RevisedECHSisNotNeeded
270    cmp     bl, 16  ; Drives with 8193 or more cylinders can report 15 heads
271.RevisedECHSisNotNeeded:
272    ret
273
274
275;--------------------------------------------------------------------
276; LBA assist calculation (or Assisted LBA)
277;
278; This algorithm translates P-CHS sector count up to largest possible
279; L-CHS sector count (1024, 255, 63). Note that INT 13h interface allows
280; 256 heads but DOS supports up to 255 head. That is why BIOSes never
281; use 256 heads.
282;
283; L-CHS parameters generated here require the drive to use LBA addressing.
284;
285; Here is the algorithm:
286; If cylinders > 8192
287;  Variable CH = Total CHS Sectors / 63
288;  Divide (CH – 1) by 1024 and add 1
289;  Round the result up to the nearest of 16, 32, 64, 128 and 255. This is the value to be used for the number of heads.
290;  Divide CH by the number of heads. This is the value to be used for the number of cylinders.
291;
292; ConvertChsSectorCountFromDXAXtoLbaAssistedLCHSinAXBLBH:
293;   Parameters:
294;       DX:AX:  Total number of P-CHS sectors for CHS addressing
295;               (max = 16383 * 16 * 63 = 16,514,064)
296;   Returns:
297;       AX:     Number of cylinders (?...1027)
298;       BL:     Number of heads (16, 32, 64, 128 or 255)
299;       BH:     Number of sectors per track (always 63)
300;   Corrupts registers:
301;       CX, DX
302;--------------------------------------------------------------------
303ConvertChsSectorCountFromDXAXtoLbaAssistedLCHSinAXBLBH:
304    ; Value CH = Total sector count / 63
305    ; Max = 16,514,064 / 63 = 262128
306    mov     cx, LBA_ASSIST_SPT          ; CX = 63
307    call    Math_DivDXAXbyCX
308    push    dx
309    push    ax                          ; Value CH stored for later use
310
311    ; BX:DX:AX = Value CH - 1
312    ; Max = 262128 - 1 = 262127
313    xor     bx, bx
314    sub     ax, BYTE 1
315    sbb     dx, bx
316
317    ; AX = Number of heads = ((Value CH - 1) / 1024) + 1
318    ; Max = (262127 / 1024) + 1 = 256
319    push    si
320    call    Size_DivideSizeInBXDXAXby1024andIncrementMagnitudeInCX
321    pop     si
322    inc     ax                          ; + 1
323
324    ; Heads must be 16, 32, 64, 128 or 255 (round up to the nearest)
325    ; Max = 255
326    mov     cx, 16                      ; Min number of heads
327.CompareNextValidNumberOfHeads:
328    cmp     ax, cx
329    jbe     SHORT .NumberOfHeadsNowInCX
330    eSHL_IM cl, 1                       ; Double number of heads
331    jnz     SHORT .CompareNextValidNumberOfHeads    ; Reached 256 heads?
332    dec     cl                          ;  If so, limit heads to 255
333.NumberOfHeadsNowInCX:
334    mov     bx, cx                      ; Number of heads are returned in BL
335    mov     bh, LBA_ASSIST_SPT          ; Sectors per Track
336
337    ; DX:AX = Number of cylinders = Value CH (without - 1) / number of heads
338    ; Max = 262128 / 255 = 1027
339    pop     ax
340    pop     dx                          ; Value CH back to DX:AX
341    div     cx
342
343    ; Return L-CHS
344ReturnLCHSinAXBLBH:
345    ret
Note: See TracBrowser for help on using the repository browser.