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

Last change on this file since 575 was 568, checked in by krille_n_@…, 10 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.