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

Last change on this file since 606 was 606, checked in by krille_n_, 3 years ago

Changes:

  • RESERVE_DIAGNOSTIC_CYLINDER has been completely removed as it wasted hard drive space, caused a compatibility problem with 32-bit disk access drivers under Windows 3.x and most importantly, it was in fact not needed since the same thing can be accomplished using the "User specified CHS" feature in XTIDECFG which is better because that applies only to that specific drive instead of all drives under XUB control.
  • In BIOS builds containing MODULE_EBIOS (i.e. all official builds except the Tiny build), drives with a cylinder count less than or equal to 1024 had CHS translation applied to them unnecessarily if CHS translation method was set to Auto (which is the default). This bug has been present for a long time and, as a side effect, made RESERVE_DIAGNOSTIC_CYLINDER useless since the idea behind that was to provide compatibility with other old BIOSes using NORMAL addressing mode. WARNING! With this bug now being fixed, upgrading to this revision of the BIOS will require repartitioning and reformatting any drives affected by this (BIOSDRVS.COM can be helpful in determining which drives are affected).
File size: 13.0 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;       DX:     CHS Translate Mode
77;   Corrupts registers:
78;       Nothing
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%else
103    ; Check if the drive is within the limits of NORMAL addressing.
104    ; If it is, then no CHS translation is necessary.
105    cmp     ax, MAX_LCHS_CYLINDERS
106    jbe     SHORT ConvertPCHfromAXBLtoEnhancedCHinAXBL
107%endif
108
109    ; If we have EBIOS functions, we should always use Assisted LBA
110    ; for drives with LBA support. Otherwise the EBIOS functions are
111    ; useless since we never do LBA to P-CHS translation.
112    ; Even if we do not have EBIOS functions, we must do this check
113    ; since user might have forced LBA mode even though the drive does
114    ; not support LBA addressing.
115    test    BYTE [es:si+ATA1.wCaps+1], A1_wCaps_LBA>>8
116    jz      SHORT ConvertPCHfromAXBLtoRevisedEnhancedCHinAXBL
117
118    ; Assisted LBA provides most capacity but translation algorithm is
119    ; slower. The speed difference doesn't matter on AT systems.
120.UseAssistedLBA:
121    ; Fall to GetSectorCountToDXAXfromCHSinAXBLBH
122
123
124;--------------------------------------------------------------------
125; GetSectorCountToDXAXfromCHSinAXBLBH
126;   Parameters:
127;       AX:     Number of cylinders (1...16383)
128;       BL:     Number of heads (1...255)
129;       BH:     Number of sectors per track (1...63)
130;   Returns:
131;       DX:AX:  Total number of CHS addressable sectors
132;   Corrupts registers:
133;       BX
134;--------------------------------------------------------------------
135GetSectorCountToDXAXfromCHSinAXBLBH:
136    xchg    ax, bx
137    mul     ah          ; AX = Heads * Sectors per track
138    mul     bx
139    ; Fall to ConvertChsSectorCountFromDXAXtoLbaAssistedLCHSinAXBLBH
140
141
142;--------------------------------------------------------------------
143; LBA assist calculation (or Assisted LBA)
144;
145; This algorithm translates P-CHS sector count up to largest possible
146; L-CHS sector count (1024, 255, 63). Note that INT 13h interface allows
147; 256 heads but DOS supports up to 255 head. That is why BIOSes never
148; use 256 heads.
149;
150; L-CHS parameters generated here require the drive to use LBA addressing.
151;
152; Here is the algorithm:
153; If cylinders > 8192
154;  Variable CH = Total CHS Sectors / 63
155;  Divide (CH - 1) by 1024 and add 1
156;  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.
157;  Divide CH by the number of heads. This is the value to be used for the number of cylinders.
158;
159; ConvertChsSectorCountFromDXAXtoLbaAssistedLCHSinAXBLBH:
160;   Parameters:
161;       DX:AX:  Total number of P-CHS sectors for CHS addressing
162;               (max = 16383 * 16 * 63 = 16,514,064)
163;   Returns:
164;       AX:     Number of cylinders (?...1027)
165;       BL:     Number of heads (16, 32, 64, 128 or 255)
166;       BH:     Number of sectors per track (always 63)
167;       CX:     Number of bits shifted (0)
168;       DX:     TRANSLATEMODE_ASSISTED_LBA
169;   Corrupts registers:
170;       Nothing
171;--------------------------------------------------------------------
172ConvertChsSectorCountFromDXAXtoLbaAssistedLCHSinAXBLBH:
173    ; Value CH = Total sector count / 63
174    ; Max = 16,514,064 / 63 = 262128
175    mov     cx, LBA_ASSIST_SPT          ; CX = 63
176
177    ; --- Math_DivDXAXbyCX inlined (and slightly modified) since it's only used here
178    xor     bx, bx
179    xchg    bx, ax
180    xchg    dx, ax
181    div     cx
182    xchg    ax, bx
183    div     cx
184    mov     dx, bx
185    ; ---
186
187    push    ax
188    push    dx                          ; Value CH stored for later use
189
190    ; BX:DX:AX = Value CH - 1
191    ; Max = 262128 - 1 = 262127
192    xor     bx, bx
193    sub     ax, BYTE 1
194    sbb     dx, bx
195
196    ; AX = Number of heads = ((Value CH - 1) / 1024) + 1
197    ; Max = (262127 / 1024) + 1 = 256
198    call    Size_DivideSizeInBXDXAXby1024   ; Preserves CX and returns with BH cleared
199    pop     dx
200    inc     ax                          ; + 1
201
202    ; Heads must be 16, 32, 64, 128 or 255 (round up to the nearest)
203    ; Max = 255
204    mov     bl, 16                      ; Min number of heads
205.CompareNextValidNumberOfHeads:
206    cmp     ax, bx
207    jbe     SHORT .NumberOfHeadsNowInBX
208    eSHL_IM bx, 1                       ; Double number of heads
209    jpo     SHORT .CompareNextValidNumberOfHeads    ; Reached 256 heads?
210    dec     bx                          ;  If so, limit heads to 255
211.NumberOfHeadsNowInBX:
212
213    ; DX:AX = Number of cylinders = Value CH (without - 1) / number of heads
214    ; Max = 262128 / 255 = 1027
215    pop     ax                          ; Value CH back to DX:AX
216    div     bx
217
218    xchg    bh, cl                      ; Sectors per Track to BH, zero to CL (CX)
219    mov     dl, TRANSLATEMODE_ASSISTED_LBA
220    ; All combinations of value CH from 1 to 262128 divided by number of heads
221    ; (16/32/64/128/255) has been verified to return with DH cleared.
222ReturnLCHSinAXBLBH:
223    ret
224
225
226;--------------------------------------------------------------------
227; AtaGeometry_GetPCHStoAXBLBHfromAtaInfoInESSI
228;   Parameters:
229;       ES:SI:  Ptr to 512-byte ATA information read from the drive
230;   Returns:
231;       AX:     Number of P-CHS cylinders (1...16383)
232;       BL:     Number of P-CHS heads (1...16)
233;       BH:     Number of P-CHS sectors per track (1...63)
234;   Corrupts registers:
235;       Nothing
236;--------------------------------------------------------------------
237AtaGeometry_GetPCHStoAXBLBHfromAtaInfoInESSI:
238    mov     ax, [es:si+ATA1.wCylCnt]    ; Cylinders (1...16383)
239    mov     bl, [es:si+ATA1.wHeadCnt]   ; Heads (1...16)
240    mov     bh, [es:si+ATA1.wSPT]       ; Sectors per Track (1...63)
241    ret
242
243
244;--------------------------------------------------------------------
245; Revised Enhanced CHS calculation (Revised ECHS)
246;
247; This algorithm translates P-CHS sector count to L-CHS sector count
248; with bit shift algorithm. Since 256 heads are not allowed
249; (DOS limit), this algorithm makes translations so that maximum of
250; 240 L-CHS heads can be used. This makes the maximum addressable capacity
251; to 7,927,234,560 bytes ~ 7.38 GiB. LBA addressing needs to be used to
252; get more capacity.
253;
254; L-CHS parameters generated here require the drive to use CHS addressing.
255;
256; Here is the algorithm:
257; If cylinders > 8192 and heads = 16
258;  Heads = 15
259;  Cylinders = cylinders * 16 / 15 (losing the fraction component)
260;  Do a standard ECHS translation
261;
262; *FIXME* The above algorithm seems to be conflicting with info found here
263; https://web.archive.org/web/20000817071418/http://www.firmware.com:80/support/bios/over4gb.htm
264; which says that Revised ECHS is used when the cylinder count is > 8191.
265;
266; ConvertPCHfromAXBLtoRevisedEnhancedCHinAXBL:
267;   Parameters:
268;       AX:     Number of P-CHS cylinders (8193...16383)
269;       BL:     Number of P-CHS heads (1...16)
270;   Returns:
271;       AX:     Number of L-CHS cylinders (?...1024)
272;       BL:     Number of L-CHS heads (?...240)
273;       CX:     Number of bits shifted (0...3)
274;       DX:     TRANSLATEMODE_NORMAL or TRANSLATEMODE_LARGE
275;   Corrupts registers:
276;       Nothing
277;--------------------------------------------------------------------
278ConvertPCHfromAXBLtoRevisedEnhancedCHinAXBL:
279    ; Generate L-CHS using simple bit shift algorithm (ECHS) if
280    ; 8192 or less cylinders
281    call    AtaGeometry_IsDriveSmallEnoughForECHS
282    jc      SHORT ConvertPCHfromAXBLtoEnhancedCHinAXBL
283
284    eMOVZX  cx, bl  ; CX = 16
285    dec     bx      ; Heads = 15
286    mul     cx      ; DX:AX = Cylinders * 16
287    dec     cx      ; CX = 15
288    div     cx      ; AX = (Cylinders * 16) / 15
289    ; Fall to ConvertPCHfromAXBLtoEnhancedCHinAXBL
290
291
292;--------------------------------------------------------------------
293; Enhanced CHS calculation (ECHS)
294;
295; This algorithm translates P-CHS sector count to L-CHS sector count
296; with simple bit shift algorithm. Since 256 heads are not allowed
297; (DOS limit), this algorithm require that there are at most 8192
298; P-CHS cylinders. This makes the maximum addressable capacity
299; to 4,227,858,432 bytes ~ 3.94 GiB. Use Revised ECHS or Assisted LBA
300; algorithms if there are more than 8192 P-CHS cylinders.
301;
302; L-CHS parameters generated here require the drive to use CHS addressing.
303;
304; Here is the algorithm:
305;  Multiplier = 1
306;  Cylinder = Cylinder - 1
307;  Is Cylinder < 1024? If not:
308;  Do a right bitwise rotation on the cylinder (i.e., divide by 2)
309;  Do a left bitwise rotation on the multiplier (i.e., multiply by 2)
310;  Use the multiplier on the Cylinder and Head values to obtain the translated values.
311;
312; ConvertPCHfromAXBLtoEnhancedCHinAXBL:
313;   Parameters:
314;       AX:     Number of P-CHS cylinders (1...8192, or up to 17475 if fell from above)
315;       BL:     Number of P-CHS heads (1...16)
316;   Returns:
317;       AX:     Number of L-CHS cylinders (?...1024)
318;       BL:     Number of L-CHS heads (?...128, or up to 240 if fell from above)
319;       CX:     Number of bits shifted (0...3)
320;       DX:     TRANSLATEMODE_NORMAL or TRANSLATEMODE_LARGE
321;   Corrupts registers:
322;       Nothing
323;--------------------------------------------------------------------
324ConvertPCHfromAXBLtoEnhancedCHinAXBL:
325    cwd                 ; Assume TRANSLATEMODE_NORMAL
326    xor     cx, cx      ; No bits to shift initially
327.ShiftIfMoreThan1024Cylinder:
328    cmp     ax, MAX_LCHS_CYLINDERS
329    jbe     SHORT ReturnLCHSinAXBLBH
330    shr     ax, 1       ; Halve cylinders
331    eSHL_IM bl, 1       ; Double heads
332    inc     cx          ; Increment bit shift count
333    mov     dl, TRANSLATEMODE_LARGE
334    jmp     SHORT .ShiftIfMoreThan1024Cylinder
335
336
337;--------------------------------------------------------------------
338; Checks should LARGE mode L-CHS be calculated with ECHS or Revised ECHS
339; algorithm. Revised ECHS is needed for drives with 8193 or more cylinders
340; AND 16 heads.
341;
342; AtaGeometry_IsDriveSmallEnoughForECHS:
343;   Parameters:
344;       AX:     Number of P-Cylinders
345;       BL:     Number of P-Heads
346;   Returns:
347;       CF:     Clear if Reviced ECHS is necessary
348;               Set if ECHS is enough
349;   Corrupts registers:
350;       Nothing
351;--------------------------------------------------------------------
352AtaGeometry_IsDriveSmallEnoughForECHS:
353    ; Generate L-CHS using simple bit shift algorithm (ECHS) if
354    ; 8192 or less cylinders. Use Revised ECHS if 8193 or more cylinders
355    ; AND 16 heads.
356    cmp     ax, 8193
357    jb      SHORT .RevisedECHSisNotNeeded
358    cmp     bl, 16  ; Drives with 8193 or more cylinders can report 15 heads
359.RevisedECHSisNotNeeded:
360    ret
361
Note: See TracBrowser for help on using the repository browser.