Changeset 421 in xtideuniversalbios for trunk/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/AtaGeometry.asm
- Timestamp:
- May 9, 2012, 7:12:53 PM (12 years ago)
- google:author:
- aitotat@gmail.com
- File:
-
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/AtaGeometry.asm
r419 r421 1 1 ; Project name : XTIDE Universal BIOS 2 2 ; Description : Functions for generating L-CHS parameters for 3 ; LBA drives. 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. 4 7 ; 5 8 ; This file is shared with BIOS Drive Information Tool. … … 24 27 SECTION .text 25 28 26 ;-------------------------------------------------------------------- 27 ; LBA assist calculation: 28 ; this is how to fit a big drive into INT13's skimpy size requirements, 29 ; with a maximum of 8.4G available. 30 ; 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, zero otherwise 37 ; Corrupts registers: 38 ; Nothing 39 ;-------------------------------------------------------------------- 40 AtaGeometry_GetLbaSectorCountToBXDXAXfromAtaInfoInESSI: 41 mov bx, Registers_ExchangeDSSIwithESDI 42 call bx ; ATA info now in DS:DI 43 push bx ; We will return via Registers_ExchangeDSSIwithESDI 44 45 ; Check if LBA48 supported 46 test BYTE [di+ATA6.wSetSup83+1], A6_wSetSup83_LBA48>>8 47 jz SHORT .GetLba28SectorCount 48 49 ; Get LBA48 sector count 50 mov cl, FLGL_DPT_LBA48 51 mov ax, [di+ATA6.qwLBACnt] 52 mov dx, [di+ATA6.qwLBACnt+2] 53 mov bx, [di+ATA6.qwLBACnt+4] 54 ret 55 56 .GetLba28SectorCount: 57 xor cl, cl 58 xor bx, bx 59 mov ax, [di+ATA1.dwLBACnt] 60 mov dx, [di+ATA1.dwLBACnt+2] 61 ret 62 %endif ; MODULE_EBIOS 63 64 65 ;-------------------------------------------------------------------- 66 ; AtaGeometry_GetLCHStoAXBLBHfromAtaInfoInESSI: 67 ; Parameters: 68 ; ES:SI: Ptr to 512-byte ATA information read from the drive 69 ; Returns: 70 ; AX: Number of L-CHS cylinders (1...1027, yes 1027) 71 ; BL: Number of L-CHS heads (1...255) 72 ; BH: Number of L-CHS sectors per track (1...63) 73 ; CX: Number of bits shifted (0...3) 74 ; DL: Addressing mode 75 ; Corrupts registers: 76 ; DH 77 ;-------------------------------------------------------------------- 78 AtaGeometry_GetLCHStoAXBLBHfromAtaInfoInESSI: 79 call AtaGeometry_GetPCHStoAXBLBHfromAtaInfoInESSI 80 ; Fall to AtaGeometry_GetLCHStoAXBLBHfromPCHSinAXBLBH 81 82 AtaGeometry_GetLCHStoAXBLBHfromPCHSinAXBLBH: 83 ; Generate L-CHS using simple bit shift algorithm (ECHS) if 84 ; 8192 or less cylinders. 85 cmp ax, 8192 86 jbe SHORT ConvertPCHfromAXBXtoEnhancedCHinAXBX 87 88 ; We have 8193 or more cylinders so two algorithms are available: 89 ; Revised ECHS or Assisted LBA. The Assisted LBA provides larger 90 ; capacity but requires LBA support from drive (drives this large 91 ; always support LBA but we may have intentionally cleared the LBA 92 ; bit to force CHS addressing). 93 test BYTE [es:si+ATA1.wCaps+1], A1_wCaps_LBA>>8 94 jz SHORT ConvertPCHfromAXBXtoRevisedEnhancedCHinAXBX 95 96 ; Drive supports LBA 97 call AtaGeometry_GetSectorCountToDXAXfromCHSinAXBLBH 98 call ConvertChsSectorCountFromDXAXtoLbaAssistedLCHSinAXBLBH 99 xor cx, cx ; No bits to shift 100 mov dl, ADDRESSING_MODE_ASSISTED_LBA 101 ret 102 103 104 ;-------------------------------------------------------------------- 105 ; AtaGeometry_GetPCHStoAXBLBHfromAtaInfoInESSI 106 ; Parameters: 107 ; ES:SI: Ptr to 512-byte ATA information read from the drive 108 ; Returns: 109 ; AX: Number of P-CHS cylinders (1...16383) 110 ; BL: Number of P-CHS heads (1...16) 111 ; BH: Number of P-CHS sectors per track (1...63) 112 ; Corrupts registers: 113 ; Nothing 114 ;-------------------------------------------------------------------- 115 AtaGeometry_GetPCHStoAXBLBHfromAtaInfoInESSI: 116 mov ax, [es:si+ATA1.wCylCnt] ; Cylinders (1...16383) 117 mov bl, [es:si+ATA1.wHeadCnt] ; Heads (1...16) 118 mov bh, [es:si+ATA1.wSPT] ; Sectors per Track (1...63) 119 ret 120 121 122 ;-------------------------------------------------------------------- 123 ; AtaGeometry_GetSectorCountToDXAXfromCHSinAXBLBH 124 ; Parameters: 125 ; ES:SI: Ptr to 512-byte ATA information read from the drive 126 ; AX: Number of cylinders (1...16383) 127 ; BL: Number of heads (1...255) 128 ; BH: Number of sectors per track (1...63) 129 ; Returns: 130 ; DX:AX: Total number of CHS addressable sectors 131 ; Corrupts registers: 132 ; BX 133 ;-------------------------------------------------------------------- 134 AtaGeometry_GetSectorCountToDXAXfromCHSinAXBLBH: 135 xchg ax, bx 136 mul ah ; AX = Heads * Sectors per track 137 mul bx 138 ret 139 140 141 ;-------------------------------------------------------------------- 142 ; Revised Enhanced CHS calculation (Revised ECHS) 143 ; 144 ; This algorithm translates P-CHS sector count to L-CHS sector count 145 ; with bit shift algorithm. Since 256 heads are not allowed 146 ; (DOS limit), this algorithm makes translations so that maximum of 147 ; 240 L-CHS heads can be used. This makes the maximum addressable capacity 148 ; to 7,927,234,560 bytes ~ 7.38 GiB. LBA addressing needs to be used to 149 ; get more capacity. 150 ; 151 ; L-CHS parameters generated here require the drive to use CHS addressing. 152 ; 153 ; Here is the algorithm: 154 ; If cylinders > 8192 and heads = 16 155 ; Heads = 15 156 ; Cylinders = cylinders * 16 / 15 (losing the fraction component) 157 ; Do a standard ECHS translation 158 ; 159 ; ConvertPCHfromAXBXtoRevisedEnhancedCHinAXBX: 160 ; Parameters: 161 ; AX: Number of P-CHS cylinders (8193...16383) 162 ; BL: Number of P-CHS heads (1...16) 163 ; Returns: 164 ; AX: Number of L-CHS cylinders (?...1024) 165 ; BL: Number of L-CHS heads (?...240) 166 ; CX: Number of bits shifted (0...3) 167 ; DL: ADDRESSING_MODE_NORMAL or ADDRESSING_MODE_LARGE 168 ; Corrupts registers: 169 ; Nothing 170 ;-------------------------------------------------------------------- 171 ConvertPCHfromAXBXtoRevisedEnhancedCHinAXBX: 172 cmp bl, 16 ; Drives with 8193 or more cylinders can report 15 heads 173 jb SHORT ConvertPCHfromAXBXtoEnhancedCHinAXBX 174 175 eMOVZX cx, bl ; CX = 16 176 dec bx ; Heads = 15 177 mul cx ; DX:AX = Cylinders * 16 178 dec cx ; CX = 15 179 div cx ; AX = (Cylinders * 16) / 15 180 ; Fall to ConvertPCHfromAXBXtoEnhancedCHinAXBX 181 182 183 ;-------------------------------------------------------------------- 184 ; Enhanced CHS calculation (ECHS) 185 ; 186 ; This algorithm translates P-CHS sector count to L-CHS sector count 187 ; with simple bit shift algorithm. Since 256 heads are not allowed 188 ; (DOS limit), this algorithm require that there are at most 8192 189 ; P-CHS cylinders. This makes the maximum addressable capacity 190 ; to 4,227,858,432 bytes ~ 3.94 GiB. Use Revised ECHS or Assisted LBA 191 ; algorithms if there are more than 8192 P-CHS cylinders. 192 ; 193 ; L-CHS parameters generated here require the drive to use CHS addressing. 194 ; 195 ; Here is the algorithm: 196 ; Multiplier = 1 197 ; Cylinder = Cylinder - 1 198 ; Is Cylinder < 1024? If not: 199 ; Do a right bitwise rotation on the cylinder (i.e., divide by 2) 200 ; Do a left bitwise rotation on the multiplier (i.e., multiply by 2) 201 ; Use the multiplier on the Cylinder and Head values to obtain the translated values. 202 ; 203 ; ConvertPCHfromAXBXtoEnhancedCHinAXBX: 204 ; Parameters: 205 ; AX: Number of P-CHS cylinders (1...8192) 206 ; BL: Number of P-CHS heads (1...16) 207 ; Returns: 208 ; AX: Number of L-CHS cylinders (?...1024) 209 ; BL: Number of L-CHS heads (?...128) 210 ; CX: Number of bits shifted (0...3) 211 ; DL: ADDRESSING_MODE_NORMAL or ADDRESSING_MODE_LARGE 212 ; Corrupts registers: 213 ; Nothing 214 ;-------------------------------------------------------------------- 215 ConvertPCHfromAXBXtoEnhancedCHinAXBX: 216 xor cx, cx ; No bits to shift initially 217 xor dl, dl ; Assume ADDRESSING_MODE_NORMAL 218 .ShiftIfMoreThan1024Cylinder: 219 cmp ax, MAX_LCHS_CYLINDERS 220 jbe SHORT ReturnLCHSinAXBLBH 221 shr ax, 1 222 shl bl, 1 223 inc cx ; Increment bit shift count 224 mov dl, ADDRESSING_MODE_LARGE 225 jmp SHORT .ShiftIfMoreThan1024Cylinder 226 227 228 ;-------------------------------------------------------------------- 229 ; LBA assist calculation (or Assisted LBA) 230 ; 231 ; This algorithm translates P-CHS sector count up to largest possible 232 ; L-CHS sector count (1024, 255, 63). Note that INT 13h interface allows 233 ; 256 heads but DOS supports up to 255 head. That is why BIOSes never 234 ; use 256 heads. 235 ; 236 ; L-CHS parameters generated here require the drive to use LBA addressing. 237 ; 238 ; Here is the algorithm: 31 239 ; If cylinders > 8192 32 ; Variable CH = Total Sectors / 6333 ; Divide (CH 1) by 1024 (as an assembler bitwise right shift)and add 1240 ; Variable CH = Total CHS Sectors / 63 241 ; Divide (CH 1) by 1024 and add 1 34 242 ; 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. 35 243 ; Divide CH by the number of heads. This is the value to be used for the number of cylinders. 36 244 ; 37 ; There's a wealth of information at: http://www.mossywell.com/boot-sequence 38 ; they show a slightly different approach to LBA assist calulations, but 39 ; the method here provides compatibility with phoenix BIOS. 40 ; 41 ; LbaAssist_ConvertSectorCountFromBXDXAXtoLbaAssistedCHSinDXAXBLBH: 42 ; Parameters: 43 ; BX:DX:AX: Total number of sectors 44 ; Returns: 45 ; DX:AX: Number of cylinders 245 ; ConvertChsSectorCountFromDXAXtoLbaAssistedLCHSinAXBLBH: 246 ; Parameters: 247 ; DX:AX: Total number of P-CHS sectors for CHS addressing 248 ; (max = 16383 * 16 * 63 = 16,514,064) 249 ; Returns: 250 ; AX: Number of cylinders (?...1027) 251 ; BL: Number of heads (16, 32, 64, 128 or 255) 46 252 ; BH: Number of sectors per track (always 63) 47 ; BL: Number of heads (16, 32, 64, 128 or 255) 48 ; Corrupts registers: 49 ; CX 50 ;-------------------------------------------------------------------- 51 LbaAssist_ConvertSectorCountFromBXDXAXtoLbaAssistedCHSinDXAXBLBH: 52 push bp 253 ; Corrupts registers: 254 ; CX, DX 255 ;-------------------------------------------------------------------- 256 ConvertChsSectorCountFromDXAXtoLbaAssistedLCHSinAXBLBH: 257 ; Value CH = Total sector count / 63 258 ; Max = 16,514,064 / 63 = 262128 259 mov cx, LBA_ASSIST_SPT ; CX = 63 260 call Math_DivDXAXbyCX 261 push dx 262 push ax ; Value CH stored for later use 263 264 ; BX:DX:AX = Value CH - 1 265 ; Max = 262128 - 1 = 262127 266 xor bx, bx 267 sub ax, BYTE 1 268 sbb dx, bx 269 270 ; AX = Number of heads = ((Value CH - 1) / 1024) + 1 271 ; Max = (262127 / 1024) + 1 = 256 53 272 push si 54 55 ; Value CH = Total sector count / 6356 xor cx, cx57 push cx ; Push zero for bits 48...6358 push bx59 push dx60 push ax ; 64-bit sector count now in stack61 mov cl, LBA_ASSIST_SPT62 mov bp, sp ; SS:BP now points sector count63 call Math_DivQWatSSBPbyCX ; Temporary value A now in stack64 65 ; BX:DX:AX = Value CH - 166 mov ax, [bp]67 mov dx, [bp+2]68 mov bx, [bp+4]69 sub ax, BYTE 1 ; Subtract 170 sbb dx, BYTE 071 sbb bx, BYTE 072 73 ; DX:AX = Number of heads = ((Value CH - 1) / 1024) + 174 273 call Size_DivideSizeInBXDXAXby1024andIncrementMagnitudeInCX 75 add ax, BYTE 1 ; Add 176 adc dx, bx ; BX = 0274 pop si 275 inc ax ; + 1 77 276 78 277 ; Heads must be 16, 32, 64, 128 or 255 (round up to the nearest) 79 test dx, dx ; 65536 or more heads? 80 jnz SHORT .LimitHeadsTo255 278 ; Max = 255 81 279 mov cx, 16 ; Min number of heads 82 280 .CompareNextValidNumberOfHeads: … … 85 283 shl cx, 1 ; Double number of heads 86 284 test ch, ch ; Reached 256 heads? 87 jnz SHORT .CompareNextValidNumberOfHeads 88 .LimitHeadsTo255: 89 mov cx, 255 285 jz SHORT .CompareNextValidNumberOfHeads 286 dec cx ; If so, limit heads to 255 90 287 .NumberOfHeadsNowInCX: 91 288 mov bx, cx ; Number of heads are returned in BL … … 93 290 94 291 ; DX:AX = Number of cylinders = Value CH (without - 1) / number of heads 95 call Math_DivQWatSSBPbyCX 96 mov ax, [bp] 97 mov dx, [bp+2] ; Cylinders now in DX:AX 98 99 ; Return LBA assisted CHS 100 add sp, BYTE 8 ; Clean stack 101 pop si 102 pop bp 103 ret 292 ; Max = 262128 / 255 = 1027 293 pop ax 294 pop dx ; Value CH back to DX:AX 295 div cx 296 297 ; Return L-CHS 298 ReturnLCHSinAXBLBH: 299 ret
Note: See TracChangeset
for help on using the changeset viewer.