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

Last change on this file since 592 was 592, checked in by krille_n_, 6 years ago

Changes:

  • The problem with NASM in the previous revision (r591) has been fixed.
  • The colors used by the boot menu and hotkey bar can now be customized by selecting one of a number of pre-defined color themes. Suggestions for additional themes are more than welcome!
  • Large builds are now 10 KB. Small builds are still 8 KB with the exception of the Tiny build which is now 4 KB. In other words, builds are now as small as possible to make it easier to combine them with other BIOSes.
  • Added code to the library to improve drive error handling. XTIDECFG can now handle "Drive Not Ready" errors.
  • Fixed a couple of potential bugs in AtaID.asm (AtaID_GetMaxPioModeToAXandMinCycleTimeToCX); 1) ATA1.bPioMode was treated as a WORD variable. 2) ATA2.bPIOSupp was assumed to be non-zero which would result in PIO mode 3 being returned if the assumption was wrong.
  • Made the same changes in the equivalent function used by BIOSDRVS (DisplayPioModeInformationUsingAtaInfoFromDSBX in AtaInfo.asm).
  • Fixed a bug from r587 in PDC20x30.asm in PDC20x30_GetMaxPioModeToALandMinPioCycleTimeToBX.
  • Fixed a bug from r523 in XTIDECFG where Auto Configure would only set the IRQ on one IDE interface on AT-builds.
  • XTIDECFG will now restore the default settings for the "Serial port virtual device" when reselecting it in the list of device types. This makes it behave consistently for all device types.
  • The eAAM macro is now used regardless if USE_UNDOC_INTEL is defined or not because it is apparently supported on all processors including the NEC V20/V30 CPUs.
  • Renamed the EXCLUDE_FROM_XTIDE_UNIVERSAL_BIOS define to EXCLUDE_FROM_XUB.
  • Added a define to exclude unused library code from BIOSDRVS (EXCLUDE_FROM_BIOSDRVS). This makes it a lot smaller than in previous revisions.
  • All unnecessary CLD-instructions are now under a new define 'CLD_NEEDED' which is only enabled for the BIOS. It is disabled for XTIDECFG and BIOSDRVS but can be enabled if needed by adding this define to the respective makefile. This change was made because these unnecessary instructions are wasteful and should never be needed. In fact, they only serve to hide bugs (in other peoples code) which I strongly believe should be avoided. I recommend people making their own BIOSes from source to not use this define as it's extremely unlikely to be needed.
  • Updated the copyright info in SerDrive and changed an URL to point to the new site.
  • Updated the copyright info and version number in BIOSDRVS.
  • Updated the copyright info in XTIDECFG.
  • Optimizations in general.
File size: 12.6 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    ; Fall to GetSectorCountToDXAXfromCHSinAXBLBH
117
118
119;--------------------------------------------------------------------
120; GetSectorCountToDXAXfromCHSinAXBLBH
121;   Parameters:
122;       AX:     Number of cylinders (1...16383)
123;       BL:     Number of heads (1...255)
124;       BH:     Number of sectors per track (1...63)
125;   Returns:
126;       DX:AX:  Total number of CHS addressable sectors
127;   Corrupts registers:
128;       BX
129;--------------------------------------------------------------------
130GetSectorCountToDXAXfromCHSinAXBLBH:
131    xchg    ax, bx
132    mul     ah          ; AX = Heads * Sectors per track
133    mul     bx
134    ; Fall to ConvertChsSectorCountFromDXAXtoLbaAssistedLCHSinAXBLBH
135
136
137;--------------------------------------------------------------------
138; LBA assist calculation (or Assisted LBA)
139;
140; This algorithm translates P-CHS sector count up to largest possible
141; L-CHS sector count (1024, 255, 63). Note that INT 13h interface allows
142; 256 heads but DOS supports up to 255 head. That is why BIOSes never
143; use 256 heads.
144;
145; L-CHS parameters generated here require the drive to use LBA addressing.
146;
147; Here is the algorithm:
148; If cylinders > 8192
149;  Variable CH = Total CHS Sectors / 63
150;  Divide (CH - 1) by 1024 and add 1
151;  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.
152;  Divide CH by the number of heads. This is the value to be used for the number of cylinders.
153;
154; ConvertChsSectorCountFromDXAXtoLbaAssistedLCHSinAXBLBH:
155;   Parameters:
156;       DX:AX:  Total number of P-CHS sectors for CHS addressing
157;               (max = 16383 * 16 * 63 = 16,514,064)
158;   Returns:
159;       AX:     Number of cylinders (?...1027)
160;       BL:     Number of heads (16, 32, 64, 128 or 255)
161;       BH:     Number of sectors per track (always 63)
162;       CX:     Number of bits shifted (0)
163;       DL:     TRANSLATEMODE_ASSISTED_LBA
164;   Corrupts registers:
165;       DH
166;--------------------------------------------------------------------
167ConvertChsSectorCountFromDXAXtoLbaAssistedLCHSinAXBLBH:
168    ; Value CH = Total sector count / 63
169    ; Max = 16,514,064 / 63 = 262128
170    mov     cx, LBA_ASSIST_SPT          ; CX = 63
171
172    ; --- Math_DivDXAXbyCX inlined (and slightly modified) since it's only used here
173    xor     bx, bx
174    xchg    bx, ax
175    xchg    dx, ax
176    div     cx
177    xchg    ax, bx
178    div     cx
179    mov     dx, bx
180    ; ---
181
182    push    ax
183    push    dx                          ; Value CH stored for later use
184
185    ; BX:DX:AX = Value CH - 1
186    ; Max = 262128 - 1 = 262127
187    xor     bx, bx
188    sub     ax, BYTE 1
189    sbb     dx, bx
190
191    ; AX = Number of heads = ((Value CH - 1) / 1024) + 1
192    ; Max = (262127 / 1024) + 1 = 256
193    call    Size_DivideSizeInBXDXAXby1024   ; Preserves CX and returns with BH cleared
194    pop     dx
195    inc     ax                          ; + 1
196
197    ; Heads must be 16, 32, 64, 128 or 255 (round up to the nearest)
198    ; Max = 255
199    mov     bl, 16                      ; Min number of heads
200.CompareNextValidNumberOfHeads:
201    cmp     ax, bx
202    jbe     SHORT .NumberOfHeadsNowInBX
203    eSHL_IM bx, 1                       ; Double number of heads
204    jpo     SHORT .CompareNextValidNumberOfHeads    ; Reached 256 heads?
205    dec     bx                          ;  If so, limit heads to 255
206.NumberOfHeadsNowInBX:
207
208    ; DX:AX = Number of cylinders = Value CH (without - 1) / number of heads
209    ; Max = 262128 / 255 = 1027
210    pop     ax                          ; Value CH back to DX:AX
211    div     bx
212
213    xchg    bh, cl                      ; Sectors per Track to BH, zero to CL (CX)
214    mov     dl, TRANSLATEMODE_ASSISTED_LBA
215ReturnLCHSinAXBLBH:
216    ret
217
218
219;--------------------------------------------------------------------
220; AtaGeometry_GetPCHStoAXBLBHfromAtaInfoInESSI
221;   Parameters:
222;       ES:SI:  Ptr to 512-byte ATA information read from the drive
223;   Returns:
224;       AX:     Number of P-CHS cylinders (1...16383)
225;       BL:     Number of P-CHS heads (1...16)
226;       BH:     Number of P-CHS sectors per track (1...63)
227;   Corrupts registers:
228;       Nothing
229;--------------------------------------------------------------------
230AtaGeometry_GetPCHStoAXBLBHfromAtaInfoInESSI:
231    mov     ax, [es:si+ATA1.wCylCnt]    ; Cylinders (1...16383)
232    mov     bl, [es:si+ATA1.wHeadCnt]   ; Heads (1...16)
233    mov     bh, [es:si+ATA1.wSPT]       ; Sectors per Track (1...63)
234    ret
235
236
237;--------------------------------------------------------------------
238; Revised Enhanced CHS calculation (Revised ECHS)
239;
240; This algorithm translates P-CHS sector count to L-CHS sector count
241; with bit shift algorithm. Since 256 heads are not allowed
242; (DOS limit), this algorithm makes translations so that maximum of
243; 240 L-CHS heads can be used. This makes the maximum addressable capacity
244; to 7,927,234,560 bytes ~ 7.38 GiB. LBA addressing needs to be used to
245; get more capacity.
246;
247; L-CHS parameters generated here require the drive to use CHS addressing.
248;
249; Here is the algorithm:
250; If cylinders > 8192 and heads = 16
251;  Heads = 15
252;  Cylinders = cylinders * 16 / 15 (losing the fraction component)
253;  Do a standard ECHS translation
254;
255; *FIXME* The above algorithm seems to be conflicting with info found here
256; https://web.archive.org/web/20000817071418/http://www.firmware.com:80/support/bios/over4gb.htm
257; which says that Revised ECHS is used when the cylinder count is > 8191.
258;
259; ConvertPCHfromAXBLtoRevisedEnhancedCHinAXBL:
260;   Parameters:
261;       AX:     Number of P-CHS cylinders (8193...16383)
262;       BL:     Number of P-CHS heads (1...16)
263;   Returns:
264;       AX:     Number of L-CHS cylinders (?...1024)
265;       BL:     Number of L-CHS heads (?...240)
266;       CX:     Number of bits shifted (0...3)
267;       DX:     TRANSLATEMODE_NORMAL or TRANSLATEMODE_LARGE
268;   Corrupts registers:
269;       Nothing
270;--------------------------------------------------------------------
271ConvertPCHfromAXBLtoRevisedEnhancedCHinAXBL:
272    ; Generate L-CHS using simple bit shift algorithm (ECHS) if
273    ; 8192 or less cylinders
274    call    AtaGeometry_IsDriveSmallEnoughForECHS
275    jc      SHORT ConvertPCHfromAXBLtoEnhancedCHinAXBL
276
277    eMOVZX  cx, bl  ; CX = 16
278    dec     bx      ; Heads = 15
279    mul     cx      ; DX:AX = Cylinders * 16
280    dec     cx      ; CX = 15
281    div     cx      ; AX = (Cylinders * 16) / 15
282    ; Fall to ConvertPCHfromAXBLtoEnhancedCHinAXBL
283
284
285;--------------------------------------------------------------------
286; Enhanced CHS calculation (ECHS)
287;
288; This algorithm translates P-CHS sector count to L-CHS sector count
289; with simple bit shift algorithm. Since 256 heads are not allowed
290; (DOS limit), this algorithm require that there are at most 8192
291; P-CHS cylinders. This makes the maximum addressable capacity
292; to 4,227,858,432 bytes ~ 3.94 GiB. Use Revised ECHS or Assisted LBA
293; algorithms if there are more than 8192 P-CHS cylinders.
294;
295; L-CHS parameters generated here require the drive to use CHS addressing.
296;
297; Here is the algorithm:
298;  Multiplier = 1
299;  Cylinder = Cylinder - 1
300;  Is Cylinder < 1024? If not:
301;  Do a right bitwise rotation on the cylinder (i.e., divide by 2)
302;  Do a left bitwise rotation on the multiplier (i.e., multiply by 2)
303;  Use the multiplier on the Cylinder and Head values to obtain the translated values.
304;
305; ConvertPCHfromAXBLtoEnhancedCHinAXBL:
306;   Parameters:
307;       AX:     Number of P-CHS cylinders (1...8192, or up to 17475 if fell from above)
308;       BL:     Number of P-CHS heads (1...16)
309;   Returns:
310;       AX:     Number of L-CHS cylinders (?...1024)
311;       BL:     Number of L-CHS heads (?...128, or up to 240 if fell from above)
312;       CX:     Number of bits shifted (0...3)
313;       DX:     TRANSLATEMODE_NORMAL or TRANSLATEMODE_LARGE
314;   Corrupts registers:
315;       Nothing
316;--------------------------------------------------------------------
317ConvertPCHfromAXBLtoEnhancedCHinAXBL:
318    cwd                 ; Assume TRANSLATEMODE_NORMAL
319    xor     cx, cx      ; No bits to shift initially
320.ShiftIfMoreThan1024Cylinder:
321    cmp     ax, MAX_LCHS_CYLINDERS
322    jbe     SHORT ReturnLCHSinAXBLBH
323    shr     ax, 1       ; Halve cylinders
324    eSHL_IM bl, 1       ; Double heads
325    inc     cx          ; Increment bit shift count
326    mov     dl, TRANSLATEMODE_LARGE
327    jmp     SHORT .ShiftIfMoreThan1024Cylinder
328
329
330;--------------------------------------------------------------------
331; Checks should LARGE mode L-CHS be calculated with ECHS or Revised ECHS
332; algorithm. Revised ECHS is needed for drives with 8193 or more cylinders
333; AND 16 heads.
334;
335; AtaGeometry_IsDriveSmallEnoughForECHS:
336;   Parameters:
337;       AX:     Number of P-Cylinders
338;       BL:     Number of P-Heads
339;   Returns:
340;       CF:     Clear if Reviced ECHS is necessary
341;               Set if ECHS is enough
342;   Corrupts registers:
343;       Nothing
344;--------------------------------------------------------------------
345AtaGeometry_IsDriveSmallEnoughForECHS:
346    ; Generate L-CHS using simple bit shift algorithm (ECHS) if
347    ; 8192 or less cylinders. Use Revised ECHS if 8193 or more cylinders
348    ; AND 16 heads.
349    cmp     ax, 8193
350    jb      SHORT .RevisedECHSisNotNeeded
351    cmp     bl, 16  ; Drives with 8193 or more cylinders can report 15 heads
352.RevisedECHSisNotNeeded:
353    ret
354
Note: See TracBrowser for help on using the repository browser.