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

Last change on this file since 547 was 547, checked in by aitotat@…, 11 years ago

Changes to XTIDE Universal BIOS:

  • Hotkeys were incorrectly initialized to use 'C' as first hard drive letter.
  • All CHS translate modes should again work (incorrectly decremented DX instead of DL, it might or might not have caused problems).
File size: 11.2 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_GetLCHStoAXBLBHfromAtaInfoInESSIandTranslateModeInDX
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_GetLCHStoAXBLBHfromAtaInfoInESSIandTranslateModeInDX:
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    ; Generate L-CHS using simple bit shift algorithm (ECHS) if
95    ; 8192 or less cylinders.
96    cmp     ax, 8192
97    jbe     SHORT ConvertPCHfromAXBLtoEnhancedCHinAXBL
98
99    ; We have 8193 or more cylinders so two algorithms are available:
100    ; Revised ECHS or Assisted LBA. The Assisted LBA provides larger
101    ; capacity but requires LBA support from drive (drives this large
102    ; always support LBA but user might have unintentionally set LBA).
103.UseAssistedLBA:
104    test    BYTE [es:si+ATA1.wCaps+1], A1_wCaps_LBA>>8
105    jz      SHORT ConvertPCHfromAXBLtoRevisedEnhancedCHinAXBL
106
107    ; Drive supports LBA
108    call    GetSectorCountToDXAXfromCHSinAXBLBH
109    call    ConvertChsSectorCountFromDXAXtoLbaAssistedLCHSinAXBLBH
110    xor     cx, cx      ; No bits to shift
111    mov     dl, TRANSLATEMODE_ASSISTED_LBA
112    ret
113
114
115;--------------------------------------------------------------------
116; AtaGeometry_GetPCHStoAXBLBHfromAtaInfoInESSI
117;   Parameters:
118;       ES:SI:  Ptr to 512-byte ATA information read from the drive
119;   Returns:
120;       AX:     Number of P-CHS cylinders (1...16383)
121;       BL:     Number of P-CHS heads (1...16)
122;       BH:     Number of P-CHS sectors per track (1...63)
123;   Corrupts registers:
124;       Nothing
125;--------------------------------------------------------------------
126AtaGeometry_GetPCHStoAXBLBHfromAtaInfoInESSI:
127    mov     ax, [es:si+ATA1.wCylCnt]    ; Cylinders (1...16383)
128    mov     bl, [es:si+ATA1.wHeadCnt]   ; Heads (1...16)
129    mov     bh, [es:si+ATA1.wSPT]       ; Sectors per Track (1...63)
130    ret
131
132
133;--------------------------------------------------------------------
134; GetSectorCountToDXAXfromCHSinAXBLBH
135;   Parameters:
136;       ES:SI:  Ptr to 512-byte ATA information read from the drive
137;       AX:     Number of cylinders (1...16383)
138;       BL:     Number of heads (1...255)
139;       BH:     Number of sectors per track (1...63)
140;   Returns:
141;       DX:AX:  Total number of CHS addressable sectors
142;   Corrupts registers:
143;       BX
144;--------------------------------------------------------------------
145GetSectorCountToDXAXfromCHSinAXBLBH:
146    xchg    ax, bx
147    mul     ah          ; AX = Heads * Sectors per track
148    mul     bx
149    ret
150
151
152;--------------------------------------------------------------------
153; Revised Enhanced CHS calculation (Revised ECHS)
154;
155; This algorithm translates P-CHS sector count to L-CHS sector count
156; with bit shift algorithm. Since 256 heads are not allowed
157; (DOS limit), this algorithm makes translations so that maximum of
158; 240 L-CHS heads can be used. This makes the maximum addressable capacity
159; to 7,927,234,560 bytes ~ 7.38 GiB. LBA addressing needs to be used to
160; get more capacity.
161;
162; L-CHS parameters generated here require the drive to use CHS addressing.
163;
164; Here is the algorithm:
165; If cylinders > 8192 and heads = 16
166;  Heads = 15
167;  Cylinders = cylinders * 16 / 15 (losing the fraction component)
168;  Do a standard ECHS translation
169;
170; ConvertPCHfromAXBLtoRevisedEnhancedCHinAXBL:
171;   Parameters:
172;       AX:     Number of P-CHS cylinders (8193...16383)
173;       BL:     Number of P-CHS heads (1...16)
174;   Returns:
175;       AX:     Number of L-CHS cylinders (?...1024)
176;       BL:     Number of L-CHS heads (?...240)
177;       CX:     Number of bits shifted (0...3)
178;       DX:     ADDRESSING_MODE_NORMAL or ADDRESSING_MODE_LARGE
179;   Corrupts registers:
180;       Nothing
181;--------------------------------------------------------------------
182ConvertPCHfromAXBLtoRevisedEnhancedCHinAXBL:
183    ; Generate L-CHS using simple bit shift algorithm (ECHS) if
184    ; 8192 or less cylinders
185    cmp     ax, 8192
186    jbe     SHORT ConvertPCHfromAXBLtoEnhancedCHinAXBL
187    cmp     bl, 16  ; Drives with 8193 or more cylinders can report 15 heads
188    jb      SHORT ConvertPCHfromAXBLtoEnhancedCHinAXBL
189
190    eMOVZX  cx, bl  ; CX = 16
191    dec     bx      ; Heads = 15
192    mul     cx      ; DX:AX = Cylinders * 16
193    dec     cx      ; CX = 15
194    div     cx      ; AX = (Cylinders * 16) / 15
195    ; Fall to ConvertPCHfromAXBXtoEnhancedCHinAXBX
196
197
198;--------------------------------------------------------------------
199; Enhanced CHS calculation (ECHS)
200;
201; This algorithm translates P-CHS sector count to L-CHS sector count
202; with simple bit shift algorithm. Since 256 heads are not allowed
203; (DOS limit), this algorithm require that there are at most 8192
204; P-CHS cylinders. This makes the maximum addressable capacity
205; to 4,227,858,432 bytes ~ 3.94 GiB. Use Revised ECHS or Assisted LBA
206; algorithms if there are more than 8192 P-CHS cylinders.
207;
208; L-CHS parameters generated here require the drive to use CHS addressing.
209;
210; Here is the algorithm:
211;  Multiplier = 1
212;  Cylinder = Cylinder - 1
213;  Is Cylinder < 1024? If not:
214;  Do a right bitwise rotation on the cylinder (i.e., divide by 2)
215;  Do a left bitwise rotation on the multiplier (i.e., multiply by 2)
216;  Use the multiplier on the Cylinder and Head values to obtain the translated values.
217;
218; ConvertPCHfromAXBLtoEnhancedCHinAXBL:
219;   Parameters:
220;       AX:     Number of P-CHS cylinders (1...8192, or up to 17475 if fell from above)
221;       BL:     Number of P-CHS heads (1...16)
222;   Returns:
223;       AX:     Number of L-CHS cylinders (?...1024)
224;       BL:     Number of L-CHS heads (?...128, or up to 240 if fell from above)
225;       CX:     Number of bits shifted (0...3)
226;       DX:     TRANSLATEMODE_NORMAL or TRANSLATEMODE_LARGE
227;   Corrupts registers:
228;       Nothing
229;--------------------------------------------------------------------
230ConvertPCHfromAXBLtoEnhancedCHinAXBL:
231    cwd                 ; Assume TRANSLATEMODE_NORMAL
232    xor     cx, cx      ; No bits to shift initially
233.ShiftIfMoreThan1024Cylinder:
234    cmp     ax, MAX_LCHS_CYLINDERS
235    jbe     SHORT ReturnLCHSinAXBLBH
236    shr     ax, 1       ; Halve cylinders
237    eSHL_IM bl, 1       ; Double heads
238    inc     cx          ; Increment bit shift count
239    mov     dl, TRANSLATEMODE_LARGE
240    jmp     SHORT .ShiftIfMoreThan1024Cylinder
241
242
243;--------------------------------------------------------------------
244; LBA assist calculation (or Assisted LBA)
245;
246; This algorithm translates P-CHS sector count up to largest possible
247; L-CHS sector count (1024, 255, 63). Note that INT 13h interface allows
248; 256 heads but DOS supports up to 255 head. That is why BIOSes never
249; use 256 heads.
250;
251; L-CHS parameters generated here require the drive to use LBA addressing.
252;
253; Here is the algorithm:
254; If cylinders > 8192
255;  Variable CH = Total CHS Sectors / 63
256;  Divide (CH – 1) by 1024 and add 1
257;  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.
258;  Divide CH by the number of heads. This is the value to be used for the number of cylinders.
259;
260; ConvertChsSectorCountFromDXAXtoLbaAssistedLCHSinAXBLBH:
261;   Parameters:
262;       DX:AX:  Total number of P-CHS sectors for CHS addressing
263;               (max = 16383 * 16 * 63 = 16,514,064)
264;   Returns:
265;       AX:     Number of cylinders (?...1027)
266;       BL:     Number of heads (16, 32, 64, 128 or 255)
267;       BH:     Number of sectors per track (always 63)
268;   Corrupts registers:
269;       CX, DX
270;--------------------------------------------------------------------
271ConvertChsSectorCountFromDXAXtoLbaAssistedLCHSinAXBLBH:
272    ; Value CH = Total sector count / 63
273    ; Max = 16,514,064 / 63 = 262128
274    mov     cx, LBA_ASSIST_SPT          ; CX = 63
275    call    Math_DivDXAXbyCX
276    push    dx
277    push    ax                          ; Value CH stored for later use
278
279    ; BX:DX:AX = Value CH - 1
280    ; Max = 262128 - 1 = 262127
281    xor     bx, bx
282    sub     ax, BYTE 1
283    sbb     dx, bx
284
285    ; AX = Number of heads = ((Value CH - 1) / 1024) + 1
286    ; Max = (262127 / 1024) + 1 = 256
287    push    si
288    call    Size_DivideSizeInBXDXAXby1024andIncrementMagnitudeInCX
289    pop     si
290    inc     ax                          ; + 1
291
292    ; Heads must be 16, 32, 64, 128 or 255 (round up to the nearest)
293    ; Max = 255
294    mov     cx, 16                      ; Min number of heads
295.CompareNextValidNumberOfHeads:
296    cmp     ax, cx
297    jbe     SHORT .NumberOfHeadsNowInCX
298    eSHL_IM cl, 1                       ; Double number of heads
299    jnz     SHORT .CompareNextValidNumberOfHeads    ; Reached 256 heads?
300    dec     cl                          ;  If so, limit heads to 255
301.NumberOfHeadsNowInCX:
302    mov     bx, cx                      ; Number of heads are returned in BL
303    mov     bh, LBA_ASSIST_SPT          ; Sectors per Track
304
305    ; DX:AX = Number of cylinders = Value CH (without - 1) / number of heads
306    ; Max = 262128 / 255 = 1027
307    pop     ax
308    pop     dx                          ; Value CH back to DX:AX
309    div     cx
310
311    ; Return L-CHS
312ReturnLCHSinAXBLBH:
313    ret
Note: See TracBrowser for help on using the repository browser.