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

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

Changes:

  • SerDrive: Using named pipe mode (serdrive -p) now works under Windows XP/2000/Server 2003.
  • checksum.pl: Added a compatibility fix for 3Com 3C503 cards.
  • XTIDECFG will now scan every possible segment address to find and load the BIOS and/or its settings from EEPROM. This should simplify things for people using combined option ROMs.
  • Fixed a bug from r521 in BootSector.asm where the BIOS would not display a timeout error if it failed to load the boot sector from harddrive.
  • Fixed a bug from r541 in CompatibleDPT.asm where CompatibleDPT_CreateDeviceParameterTableExtensionToESBXfromDPTinDSSI would generate an invalid checksum in the DPTE.
  • 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;       AX:     Number of cylinders (1...16383)
145;       BL:     Number of heads (1...255)
146;       BH:     Number of sectors per track (1...63)
147;   Returns:
148;       DX:AX:  Total number of CHS addressable sectors
149;   Corrupts registers:
150;       BX
151;--------------------------------------------------------------------
152GetSectorCountToDXAXfromCHSinAXBLBH:
153    xchg    ax, bx
154    mul     ah          ; AX = Heads * Sectors per track
155    mul     bx
156    ret
157
158
159;--------------------------------------------------------------------
160; Revised Enhanced CHS calculation (Revised ECHS)
161;
162; This algorithm translates P-CHS sector count to L-CHS sector count
163; with bit shift algorithm. Since 256 heads are not allowed
164; (DOS limit), this algorithm makes translations so that maximum of
165; 240 L-CHS heads can be used. This makes the maximum addressable capacity
166; to 7,927,234,560 bytes ~ 7.38 GiB. LBA addressing needs to be used to
167; get more capacity.
168;
169; L-CHS parameters generated here require the drive to use CHS addressing.
170;
171; Here is the algorithm:
172; If cylinders > 8192 and heads = 16
173;  Heads = 15
174;  Cylinders = cylinders * 16 / 15 (losing the fraction component)
175;  Do a standard ECHS translation
176;
177; ConvertPCHfromAXBLtoRevisedEnhancedCHinAXBL:
178;   Parameters:
179;       AX:     Number of P-CHS cylinders (8193...16383)
180;       BL:     Number of P-CHS heads (1...16)
181;   Returns:
182;       AX:     Number of L-CHS cylinders (?...1024)
183;       BL:     Number of L-CHS heads (?...240)
184;       CX:     Number of bits shifted (0...3)
185;       DX:     ADDRESSING_MODE_NORMAL or ADDRESSING_MODE_LARGE
186;   Corrupts registers:
187;       Nothing
188;--------------------------------------------------------------------
189ConvertPCHfromAXBLtoRevisedEnhancedCHinAXBL:
190    ; Generate L-CHS using simple bit shift algorithm (ECHS) if
191    ; 8192 or less cylinders
192    call    AtaGeometry_IsDriveSmallEnoughForECHS
193    jc      SHORT ConvertPCHfromAXBLtoEnhancedCHinAXBL
194
195    eMOVZX  cx, bl  ; CX = 16
196    dec     bx      ; Heads = 15
197    mul     cx      ; DX:AX = Cylinders * 16
198    dec     cx      ; CX = 15
199    div     cx      ; AX = (Cylinders * 16) / 15
200    ; Fall to ConvertPCHfromAXBLtoEnhancedCHinAXBL
201
202
203;--------------------------------------------------------------------
204; Enhanced CHS calculation (ECHS)
205;
206; This algorithm translates P-CHS sector count to L-CHS sector count
207; with simple bit shift algorithm. Since 256 heads are not allowed
208; (DOS limit), this algorithm require that there are at most 8192
209; P-CHS cylinders. This makes the maximum addressable capacity
210; to 4,227,858,432 bytes ~ 3.94 GiB. Use Revised ECHS or Assisted LBA
211; algorithms if there are more than 8192 P-CHS cylinders.
212;
213; L-CHS parameters generated here require the drive to use CHS addressing.
214;
215; Here is the algorithm:
216;  Multiplier = 1
217;  Cylinder = Cylinder - 1
218;  Is Cylinder < 1024? If not:
219;  Do a right bitwise rotation on the cylinder (i.e., divide by 2)
220;  Do a left bitwise rotation on the multiplier (i.e., multiply by 2)
221;  Use the multiplier on the Cylinder and Head values to obtain the translated values.
222;
223; ConvertPCHfromAXBLtoEnhancedCHinAXBL:
224;   Parameters:
225;       AX:     Number of P-CHS cylinders (1...8192, or up to 17475 if fell from above)
226;       BL:     Number of P-CHS heads (1...16)
227;   Returns:
228;       AX:     Number of L-CHS cylinders (?...1024)
229;       BL:     Number of L-CHS heads (?...128, or up to 240 if fell from above)
230;       CX:     Number of bits shifted (0...3)
231;       DX:     TRANSLATEMODE_NORMAL or TRANSLATEMODE_LARGE
232;   Corrupts registers:
233;       Nothing
234;--------------------------------------------------------------------
235ConvertPCHfromAXBLtoEnhancedCHinAXBL:
236    cwd                 ; Assume TRANSLATEMODE_NORMAL
237    xor     cx, cx      ; No bits to shift initially
238.ShiftIfMoreThan1024Cylinder:
239    cmp     ax, MAX_LCHS_CYLINDERS
240    jbe     SHORT ReturnLCHSinAXBLBH
241    shr     ax, 1       ; Halve cylinders
242    eSHL_IM bl, 1       ; Double heads
243    inc     cx          ; Increment bit shift count
244    mov     dl, TRANSLATEMODE_LARGE
245    jmp     SHORT .ShiftIfMoreThan1024Cylinder
246
247
248;--------------------------------------------------------------------
249; Checks should LARGE mode L-CHS be calculated with ECHS or Revised ECHS
250; algorithm. Revised ECHS is needed for drives with 8193 or more cylinders
251; AND 16 heads.
252;
253; AtaGeometry_IsDriveSmallEnoughForECHS:
254;   Parameters:
255;       AX:     Number of P-Cylinders
256;       BL:     Number of P-Heads
257;   Returns:
258;       CF:     Clear if Reviced ECHS is necessary
259;               Set if ECHS is enough
260;   Corrupts registers:
261;       Nothing
262;--------------------------------------------------------------------
263AtaGeometry_IsDriveSmallEnoughForECHS:
264    ; Generate L-CHS using simple bit shift algorithm (ECHS) if
265    ; 8192 or less cylinders. Use Revised ECHS if 8193 or more cylinders
266    ; AND 16 heads.
267    cmp     ax, 8193
268    jb      SHORT .RevisedECHSisNotNeeded
269    cmp     bl, 16  ; Drives with 8193 or more cylinders can report 15 heads
270.RevisedECHSisNotNeeded:
271    ret
272
273
274;--------------------------------------------------------------------
275; LBA assist calculation (or Assisted LBA)
276;
277; This algorithm translates P-CHS sector count up to largest possible
278; L-CHS sector count (1024, 255, 63). Note that INT 13h interface allows
279; 256 heads but DOS supports up to 255 head. That is why BIOSes never
280; use 256 heads.
281;
282; L-CHS parameters generated here require the drive to use LBA addressing.
283;
284; Here is the algorithm:
285; If cylinders > 8192
286;  Variable CH = Total CHS Sectors / 63
287;  Divide (CH – 1) by 1024 and add 1
288;  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.
289;  Divide CH by the number of heads. This is the value to be used for the number of cylinders.
290;
291; ConvertChsSectorCountFromDXAXtoLbaAssistedLCHSinAXBLBH:
292;   Parameters:
293;       DX:AX:  Total number of P-CHS sectors for CHS addressing
294;               (max = 16383 * 16 * 63 = 16,514,064)
295;   Returns:
296;       AX:     Number of cylinders (?...1027)
297;       BL:     Number of heads (16, 32, 64, 128 or 255)
298;       BH:     Number of sectors per track (always 63)
299;   Corrupts registers:
300;       CX, DX
301;--------------------------------------------------------------------
302ConvertChsSectorCountFromDXAXtoLbaAssistedLCHSinAXBLBH:
303    ; Value CH = Total sector count / 63
304    ; Max = 16,514,064 / 63 = 262128
305    mov     cx, LBA_ASSIST_SPT          ; CX = 63
306    call    Math_DivDXAXbyCX
307    push    dx
308    push    ax                          ; Value CH stored for later use
309
310    ; BX:DX:AX = Value CH - 1
311    ; Max = 262128 - 1 = 262127
312    xor     bx, bx
313    sub     ax, BYTE 1
314    sbb     dx, bx
315
316    ; AX = Number of heads = ((Value CH - 1) / 1024) + 1
317    ; Max = (262127 / 1024) + 1 = 256
318    push    si
319    call    Size_DivideSizeInBXDXAXby1024andIncrementMagnitudeInCX
320    pop     si
321    inc     ax                          ; + 1
322
323    ; Heads must be 16, 32, 64, 128 or 255 (round up to the nearest)
324    ; Max = 255
325    mov     cx, 16                      ; Min number of heads
326.CompareNextValidNumberOfHeads:
327    cmp     ax, cx
328    jbe     SHORT .NumberOfHeadsNowInCX
329    eSHL_IM cx, 1                       ; Double number of heads
330    jpo     SHORT .CompareNextValidNumberOfHeads    ; Reached 256 heads?
331    dec     cx                          ;  If so, limit heads to 255
332.NumberOfHeadsNowInCX:
333    mov     bx, cx                      ; Number of heads are returned in BL
334    mov     bh, LBA_ASSIST_SPT          ; Sectors per Track
335
336    ; DX:AX = Number of cylinders = Value CH (without - 1) / number of heads
337    ; Max = 262128 / 255 = 1027
338    pop     ax
339    pop     dx                          ; Value CH back to DX:AX
340    div     cx
341
342    ; Return L-CHS
343ReturnLCHSinAXBLBH:
344    ret
Note: See TracBrowser for help on using the repository browser.