Ignore:
Timestamp:
Mar 27, 2012, 4:21:58 PM (12 years ago)
Author:
aitotat@…
google:author:
aitotat@gmail.com
Message:

Changes to XTIDE Universal BIOS:

  • Advanced ATA Module variables are now kept in DPTs.
  • Forced full mode when using Advanced ATA Module.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/XTIDE_Universal_BIOS/Src/Initialization/Vision.asm

    r363 r364  
    77
    88;--------------------------------------------------------------------
    9 ; Vision_DetectAndReturnIDinAXandPortInCXifControllerPresent
     9; Vision_DetectAndReturnIDinAXandPortInDXifControllerPresent
    1010;   Parameters:
    1111;       Nothing
     
    1414;               (AL = QD65xx Config Register contents)
    1515;               (AH = QDI Vision Controller ID (bits 4...7))
    16 ;       CX:     Controller port (not IDE port)
     16;       DX:     Controller port (not IDE port)
    1717;       ZF:     Set if controller found
    1818;               Cleared if supported controller not found (AX,DX = undefined)
     
    2020;       Nothing
    2121;--------------------------------------------------------------------
    22 Vision_DetectAndReturnIDinAXandPortInCXifControllerPresent:
     22Vision_DetectAndReturnIDinAXandPortInDXifControllerPresent:
    2323    ; Check QD65xx base port
    24     mov     cx, QD65XX_BASE_PORT
     24    mov     dx, QD65XX_BASE_PORT
    2525    in      al, QD65XX_BASE_PORT + QD65XX_CONFIG_REGISTER_in
    2626    call    IsConfigRegisterWithIDinAL
     
    2828
    2929    ; Check QD65xx alternative base port
    30     or      cl, QD65XX_ALTERNATIVE_BASE_PORT
     30    or      dl, QD65XX_ALTERNATIVE_BASE_PORT
    3131    in      al, QD65XX_ALTERNATIVE_BASE_PORT + QD65XX_CONFIG_REGISTER_in
    3232    ; Fall to IsConfigRegisterWithIDinAL
     
    5656
    5757;--------------------------------------------------------------------
    58 ; Vision_DoesIdePortInDXbelongToControllerWithIDinAX
    59 ;   Parameters:
    60 ;       AX:     ID WORD specific for QDI Vision Controllers
    61 ;               (AL = QD65xx Config Register contents)
    62 ;               (AH = QDI Vision Controller ID (bits 4...7))
    63 ;       CX:     Vision Controller port
    64 ;       DX:     IDE base port to check
     58; Vision_DoesIdePortInBXbelongToControllerWithIDinAX
     59;   Parameters:
     60;       AL:     QD65xx Config Register contents
     61;       AH:     QDI Vision Controller ID (bits 4...7)
     62;       BX:     IDE Base port to check
     63;       DX:     Vision Controller port
    6564;   Returns:
    6665;       ZF:     Set if port belongs to controller
    6766;               Cleared if port belongs to another controller
    6867;   Corrupts registers:
    69 ;       BX
    70 ;--------------------------------------------------------------------
    71 Vision_DoesIdePortInDXbelongToControllerWithIDinAX:
     68;       Nothing
     69;--------------------------------------------------------------------
     70Vision_DoesIdePortInBXbelongToControllerWithIDinAX:
    7271    cmp     ah, ID_QD6500 << 4
    7372    je      SHORT .DoesIdePortInDXbelongToQD6500
     
    7574    ; QD6580 always have Primary IDE at 1F0h
    7675    ; Secondary IDE at 170h can be enabled or disabled
    77     cmp     dx, DEVICE_ATA_DEFAULT_PORT
     76    cmp     bx, DEVICE_ATA_DEFAULT_PORT
    7877    je      SHORT .ReturnResultInZF
    7978
    8079    ; Check if Secondary IDE channel is enabled
    81     xchg    bx, ax      ; Backup AX
    82     xchg    dx, cx      ; Swap ports
    83 
     80    push    ax
    8481    add     dx, BYTE QD6580_CONTROL_REGISTER
    8582    in      al, dx
    8683    sub     dx, BYTE QD6580_CONTROL_REGISTER
    87 
    88     xchg    cx, dx
    89     xchg    ax, bx      ; Restore AX, Control Register to BL
    90     test    bl, FLG_QDCONTROL_SECONDARY_DISABLED_in
    91     jz      SHORT .CompareDXtoSecondaryIDE
     84    test    al, FLG_QDCONTROL_SECONDARY_DISABLED_in
     85    pop     ax
     86    jz      SHORT .CompareBXtoSecondaryIDE
    9287    ret
    9388
     
    9590.DoesIdePortInDXbelongToQD6500:
    9691    test    al, FLG_QDCONFIG_PRIMARY_IDE
    97     jz      SHORT .CompareDXtoSecondaryIDE
    98     cmp     dx, DEVICE_ATA_DEFAULT_PORT
    99     ret
    100 
    101 .CompareDXtoSecondaryIDE:
    102     cmp     dx, DEVICE_ATA_DEFAULT_SECONDARY_PORT
     92    jz      SHORT .CompareBXtoSecondaryIDE
     93    cmp     bx, DEVICE_ATA_DEFAULT_PORT
     94    ret
     95
     96.CompareBXtoSecondaryIDE:
     97    cmp     bx, DEVICE_ATA_DEFAULT_SECONDARY_PORT
    10398.ReturnResultInZF:
    10499    ret
     
    108103; Vision_GetMaxPioModeToAL
    109104;   Parameters:
    110 ;       AX:     ID WORD specific for QDI Vision Controllers
    111 ;               (AH = QDI Vision Controller ID (bits 4...7))
    112 ;   Returns:
    113 ;       AL:     Max supported PIO mode (if CF set)
     105;       AL:     QD65xx Config Register contents
     106;       AH:     QDI Vision Controller ID (bits 4...7)
     107;   Returns:
     108;       AL:     Max supported PIO mode
     109;       AH:     FLGH_DPT_IORDY if IORDY supported, zero otherwise
    114110;       CF:     Set if PIO limit necessary
    115111;               Cleared if no need to limit timings
    116112;   Corrupts registers:
     113;       (AX if CF cleared)
     114;   Corrupts registers:
    117115;       Nothing
    118116;--------------------------------------------------------------------
     
    122120    jne     SHORT .NoNeedToLimitForQD6580
    123121
    124     mov     al, 2   ; Limit to PIO 2 because QD6500 supports PIO 3 but without IORDY
     122    mov     ax, 2   ; Limit to PIO 2 because QD6500 does not support IORDY
    125123    stc
    126124.NoNeedToLimitForQD6580:
     
    131129; Vision_InitializeWithIDinAHandConfigInAL
    132130;   Parameters:
    133 ;       AX:     ID WORD specific for QDI Vision Controllers
    134 ;               (AL = QD65xx Config Register contents)
    135 ;               (AH = QDI Vision Controller ID (bits 4...7))
    136 ;       DS:SI:  Ptr to BOOTMENUINFO for Single or Master Drive
    137 ;       DS:DI:  Ptr to BOOTMENUINFO for Slave Drive
    138 ;               Zero if Slave not present
     131;       AL:     QD65xx Config Register contents
     132;       AH:     QDI Vision Controller ID (bits 4...7)
     133;       DS:DI:  Ptr to DPT for Single or Slave Drive
     134;       SI:     Offset to Master DPT if Slave Drive present
     135;               Zero if Slave Drive not present
    139136;   Returns:
    140137;       CF:     Cleared if success
    141138;               Set if error
    142139;   Corrupts registers:
    143 ;       AX, BX, CX, DX, SI, DI
     140;       AX, BX, CX, DX, BP
    144141;--------------------------------------------------------------------
    145142Vision_InitializeWithIDinAHandConfigInAL:
    146143    ; QD6580 has a Control Register that needs to be programmed
    147     mov     dx, [si+BOOTMENUINFO.wControllerBasePort]
    148     cmp     ah, ID_QD6500 << 4
    149     je      SHORT .GetPioTimingsInNanosecs
     144    mov     dx, [di+DPT_ADVANCED_ATA.wControllerBasePort]
     145    cmp     ah, ID_QD6500 << 4
     146    je      SHORT .CalculateTimingForQD6500
    150147
    151148    ; Program QD6580 Control Register (not available on QD6500) to
    152149    ; Enable or Disable Read-Ahead and Post-Write Buffer to match
    153150    ; jumper setting on the multi I/O card.
    154 .ProgramControlRegisterForQD6580:
    155     xchg    bx, ax                                  ; Backup AX
     151    xor     ax, ax
    156152    add     dx, BYTE QD6580_CONTROL_REGISTER
    157153    in      al, dx                                  ; Read to get ATAPI jumper status
    158154    test    al, FLG_QDCONTROL_HDONLY_in
    159     mov     al, MASK_QDCONTROL_FLAGS_TO_SET
    160     jz      SHORT .SkipHdonlyBitSinceAtapiPossible
    161     or      al, FLG_QDCONTROL_NONATAPI
    162 .SkipHdonlyBitSinceAtapiPossible:
     155    eCMOVNZ ah, FLG_QDCONTROL_NONATAPI              ; Enable Read-Ahead and Post-Write Buffers
     156    or      ah, MASK_QDCONTROL_FLAGS_TO_SET
     157    mov     al, ah
    163158    out     dx, al
    164     sub     dx, BYTE QD6580_CONTROL_REGISTER        ; Back to base port
    165     xchg    ax, bx                                  ; Restore AX
    166 
    167     ; If we have Master and Slave drive in the system, we must select
    168     ; timings from the slower drive (this is why it is a bad idea to use
    169     ; fast and slow drive on the same IDE channel)
    170 .GetPioTimingsInNanosecs:
    171     call    AdvAtaInit_SelectSlowestTimingsToBXandCX
     159    sub     dx, BYTE QD6580_CONTROL_REGISTER
    172160
    173161    ; Now we need to determine is the drive connected to the Primary or Secondary channel.
    174162    ; QD6500 has only one channel that can be Primary at 1F0h or Secondary at 170h.
    175163    ; QD6580 always has Primary channel at 1F0h. Secondary channel at 170h can be Enabled or Disabled.
    176     cmp     ah, ID_QD6500 << 4
    177     je      SHORT .CalculateTimingTicksForQD6500
    178     cmp     WORD [si+BOOTMENUINFO.wIdeBasePort], DEVICE_ATA_DEFAULT_PORT
    179     je      SHORT .CalculateTimingTicksForQD6580
     164    call    AccessDPT_GetIdeBasePortToBX
     165    cmp     bx, DEVICE_ATA_DEFAULT_PORT
     166    je      SHORT .CalculateTimingTicksForQD6580    ; Primary Channel so no need to modify DX
    180167    times 2 inc dx                                  ; Secondary Channel IDE Timing Register
    181168
    182     ; Now we must translate the PIO timing nanosecs in CX and DX to VLB ticks
    183     ; suitable for QD65xx IDE Timing Register.
    184     ; Both of the controllers require slightly different calculations.
     169    ; QD6500 and QD6580 require slightly different calculations.
    185170.CalculateTimingTicksForQD6580:
    186     mov     si, QD6580_MIN_ACTIVE_TIME_CLOCKS
    187     mov     di, QD6580_MAX_ACTIVE_TIME_CLOCKS
    188     jmp     SHORT .CalculateTimingForQD65xx
    189 
    190 .CalculateTimingTicksForQD6500:
    191     mov     si, QD6500_MIN_ACTIVE_TIME_CLOCKS
    192     mov     di, QD6500_MAX_ACTIVE_TIME_CLOCKS
    193 
    194 .CalculateTimingForQD65xx:
    195     test    al, FLG_QDCONFIG_ID3        ; Set ZF if 40 MHz VLB bus
    196     mov     al, VLB_33MHZ_CYCLE_TIME    ; Assume 33 MHz or slower VLB bus
    197     xchg    ax, bx                      ; Active Time to AX
    198     eCMOVZ  bl, VLB_40MHZ_CYCLE_TIME
    199 
    200     div     bl
     171    mov     bp, QD6580_MAX_ACTIVE_TIME_CLOCKS | (QD6580_MIN_ACTIVE_TIME_CLOCKS << 8)
     172    jmp     SHORT .CalculateTimingsForQD65xx
     173
     174.CalculateTimingForQD6500:
     175    mov     bp, QD6500_MAX_ACTIVE_TIME_CLOCKS | (QD6500_MIN_ACTIVE_TIME_CLOCKS << 8)
     176
     177    ; We need the PIO Cycle Time in CX to calculate Active and Recovery Times.
     178.CalculateTimingsForQD65xx:
     179    call    AdvAtaInit_SelectSlowestCommonPioTimingsToBXandCXfromDSSIandDSDI
     180
     181    ; Calculate Active Time value for QD65xx IDE Timing Register
     182    call    AtaID_GetActiveTimeToAXfromPioModeInBX
     183    call    ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue
     184    xchg    bp, ax
     185
     186    ; Calculate Recovery Time value for QD65xx IDE Timing Register
     187    call    AtaID_GetRecoveryTimeToAXfromPioModeInBXandCycleTimeInCX
     188    mov     bx, bp                      ; Active Time value now in BL
     189    mov     bp, QD65xx_MAX_RECOVERY_TIME_CLOCKS | (QD65xx_MIN_RECOVERY_TIME_CLOCKS << 8)
     190    call    ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue
     191
     192    ; Merge the values to a single byte to output
     193    eSHIFT_IM   al, POSITON_QD65XXIDE_RECOVERY_TIME, shl
     194    or      al, bl
     195    out     dx, al
     196    ret                                 ; Return with CF cleared
     197
     198
     199;--------------------------------------------------------------------
     200; ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue
     201;   Parameters:
     202;       AX:     Nanosecs to convert
     203;       BP:     Low Byte:   Maximum allowed ticks
     204;               High Byte:  Minimum allowed ticks
     205;       DS:DI:  Ptr to DPT for Single or Slave Drive
     206;   Returns:
     207;       AL:     Timing value for QD65xx register
     208;   Corrupts registers:
     209;       Nothing
     210;--------------------------------------------------------------------
     211ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue:
     212    push    cx
     213
     214    ; Get VLB Cycle Time in nanosecs
     215    mov     cl, VLB_33MHZ_CYCLE_TIME    ; Assume 33 MHz or slower VLB bus
     216    test    BYTE [di+DPT_ADVANCED_ATA.wControllerID], FLG_QDCONFIG_ID3
     217    eCMOVZ  cl, VLB_40MHZ_CYCLE_TIME
     218
     219    ; Convert value in AX to VLB ticks
     220    div     cl                          ; AL = VLB ticks
    201221    inc     ax                          ; Round up
    202     xor     ah, ah
    203     xchg    cx, ax                      ; CX = Active Time in VLB ticks
    204     MAX_U   cx, si                      ; Limit ticks to valid values...
    205     MIN_U   cx, di                      ; ...for QD65xx
    206 
    207     div     bl
    208     inc     ax                          ; Round up
    209     xchg    bx, ax                      ; BL = Recovery Time in VLB ticks
    210     mov     al, QD65xx_MAX_RECOVERY_TIME_CLOCKS
    211     MAX_U   bl, QD65xx_MIN_RECOVERY_TIME_CLOCKS
    212     MIN_U   bl, al
     222
     223    ; Limit value to QD65xx limits
     224    mov     cx, bp
     225    MAX_U   al, ch                      ; Make sure not below minimum
     226    MIN_U   al, cl                      ; Make sure not above maximum
    213227
    214228    ; Not done yet, we need to invert the ticks since 0 is the slowest
    215229    ; value on the timing register
    216     sub     di, cx                      ; DI = Active Time value to program
    217     sub     al, bl                      ; AL = Recovery Time value to program
    218 
    219     ; Finally we can shift the values in places and program the Timing Register
    220     eSHIFT_IM   al, POSITON_QD65XXIDE_RECOVERY_TIME, shl
    221     or      ax, di
    222     out     dx, al
    223     ret                                 ; Return with CF cleared
     230    sub     cl, al
     231    xchg    ax, cx                      ; Return in AL
     232
     233    pop     cx
     234    ret
Note: See TracChangeset for help on using the changeset viewer.