Ignore:
Timestamp:
May 9, 2012, 7:12:53 PM (12 years ago)
Author:
aitotat@…
google:author:
aitotat@gmail.com
Message:

Changes to XTIDE Universal BIOS:

  • Addressing modes are now NORMAL, LARGE and LBA.
  • L-CHS parameters are now generated differently for drives with 8192 or less cylinders.
File:
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/AtaGeometry.asm

    r419 r421  
    11; Project name  :   XTIDE Universal BIOS
    22; 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.       
    47;
    58;                   This file is shared with BIOS Drive Information Tool.
     
    2427SECTION .text
    2528
    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;--------------------------------------------------------------------
     40AtaGeometry_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;--------------------------------------------------------------------
     78AtaGeometry_GetLCHStoAXBLBHfromAtaInfoInESSI:
     79    call    AtaGeometry_GetPCHStoAXBLBHfromAtaInfoInESSI
     80    ; Fall to AtaGeometry_GetLCHStoAXBLBHfromPCHSinAXBLBH
     81
     82AtaGeometry_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;--------------------------------------------------------------------
     115AtaGeometry_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;--------------------------------------------------------------------
     134AtaGeometry_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;--------------------------------------------------------------------
     171ConvertPCHfromAXBXtoRevisedEnhancedCHinAXBX:
     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;--------------------------------------------------------------------
     215ConvertPCHfromAXBXtoEnhancedCHinAXBX:
     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:
    31239; If cylinders > 8192
    32 ;  Variable CH = Total Sectors / 63
    33 ;  Divide (CH – 1) by 1024 (as an assembler bitwise right shift) and add 1
     240;  Variable CH = Total CHS Sectors / 63
     241;  Divide (CH – 1) by 1024 and add 1
    34242;  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.
    35243;  Divide CH by the number of heads. This is the value to be used for the number of cylinders.
    36244;
    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)
    46252;       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;--------------------------------------------------------------------
     256ConvertChsSectorCountFromDXAXtoLbaAssistedLCHSinAXBLBH:
     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
    53272    push    si
    54 
    55     ; Value CH = Total sector count / 63
    56     xor     cx, cx
    57     push    cx                          ; Push zero for bits 48...63
    58     push    bx
    59     push    dx
    60     push    ax                          ; 64-bit sector count now in stack
    61     mov     cl, LBA_ASSIST_SPT
    62     mov     bp, sp                      ; SS:BP now points sector count
    63     call    Math_DivQWatSSBPbyCX        ; Temporary value A now in stack
    64 
    65     ; BX:DX:AX = Value CH - 1
    66     mov     ax, [bp]
    67     mov     dx, [bp+2]
    68     mov     bx, [bp+4]
    69     sub     ax, BYTE 1                  ; Subtract 1
    70     sbb     dx, BYTE 0
    71     sbb     bx, BYTE 0
    72 
    73     ; DX:AX = Number of heads = ((Value CH - 1) / 1024) + 1
    74273    call    Size_DivideSizeInBXDXAXby1024andIncrementMagnitudeInCX
    75     add     ax, BYTE 1                  ; Add 1
    76     adc     dx, bx                      ; BX = 0
     274    pop     si
     275    inc     ax                          ; + 1
    77276
    78277    ; 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
    81279    mov     cx, 16                      ; Min number of heads
    82280.CompareNextValidNumberOfHeads:
     
    85283    shl     cx, 1                       ; Double number of heads
    86284    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
    90287.NumberOfHeadsNowInCX:
    91288    mov     bx, cx                      ; Number of heads are returned in BL
     
    93290
    94291    ; 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
     298ReturnLCHSinAXBLBH:
     299    ret
Note: See TracChangeset for help on using the changeset viewer.