Changeset 364 in xtideuniversalbios for trunk/XTIDE_Universal_BIOS/Src/Initialization/Vision.asm
- Timestamp:
- Mar 27, 2012, 4:21:58 PM (13 years ago)
- google:author:
- aitotat@gmail.com
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/XTIDE_Universal_BIOS/Src/Initialization/Vision.asm
r363 r364 7 7 8 8 ;-------------------------------------------------------------------- 9 ; Vision_DetectAndReturnIDinAXandPortIn CXifControllerPresent9 ; Vision_DetectAndReturnIDinAXandPortInDXifControllerPresent 10 10 ; Parameters: 11 11 ; Nothing … … 14 14 ; (AL = QD65xx Config Register contents) 15 15 ; (AH = QDI Vision Controller ID (bits 4...7)) 16 ; CX: Controller port (not IDE port)16 ; DX: Controller port (not IDE port) 17 17 ; ZF: Set if controller found 18 18 ; Cleared if supported controller not found (AX,DX = undefined) … … 20 20 ; Nothing 21 21 ;-------------------------------------------------------------------- 22 Vision_DetectAndReturnIDinAXandPortIn CXifControllerPresent:22 Vision_DetectAndReturnIDinAXandPortInDXifControllerPresent: 23 23 ; Check QD65xx base port 24 mov cx, QD65XX_BASE_PORT24 mov dx, QD65XX_BASE_PORT 25 25 in al, QD65XX_BASE_PORT + QD65XX_CONFIG_REGISTER_in 26 26 call IsConfigRegisterWithIDinAL … … 28 28 29 29 ; Check QD65xx alternative base port 30 or cl, QD65XX_ALTERNATIVE_BASE_PORT30 or dl, QD65XX_ALTERNATIVE_BASE_PORT 31 31 in al, QD65XX_ALTERNATIVE_BASE_PORT + QD65XX_CONFIG_REGISTER_in 32 32 ; Fall to IsConfigRegisterWithIDinAL … … 56 56 57 57 ;-------------------------------------------------------------------- 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 65 64 ; Returns: 66 65 ; ZF: Set if port belongs to controller 67 66 ; Cleared if port belongs to another controller 68 67 ; Corrupts registers: 69 ; BX70 ;-------------------------------------------------------------------- 71 Vision_DoesIdePortIn DXbelongToControllerWithIDinAX:68 ; Nothing 69 ;-------------------------------------------------------------------- 70 Vision_DoesIdePortInBXbelongToControllerWithIDinAX: 72 71 cmp ah, ID_QD6500 << 4 73 72 je SHORT .DoesIdePortInDXbelongToQD6500 … … 75 74 ; QD6580 always have Primary IDE at 1F0h 76 75 ; Secondary IDE at 170h can be enabled or disabled 77 cmp dx, DEVICE_ATA_DEFAULT_PORT76 cmp bx, DEVICE_ATA_DEFAULT_PORT 78 77 je SHORT .ReturnResultInZF 79 78 80 79 ; Check if Secondary IDE channel is enabled 81 xchg bx, ax ; Backup AX 82 xchg dx, cx ; Swap ports 83 80 push ax 84 81 add dx, BYTE QD6580_CONTROL_REGISTER 85 82 in al, dx 86 83 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 92 87 ret 93 88 … … 95 90 .DoesIdePortInDXbelongToQD6500: 96 91 test al, FLG_QDCONFIG_PRIMARY_IDE 97 jz SHORT .Compare DXtoSecondaryIDE98 cmp dx, DEVICE_ATA_DEFAULT_PORT99 ret 100 101 .Compare DXtoSecondaryIDE:102 cmp dx, DEVICE_ATA_DEFAULT_SECONDARY_PORT92 jz SHORT .CompareBXtoSecondaryIDE 93 cmp bx, DEVICE_ATA_DEFAULT_PORT 94 ret 95 96 .CompareBXtoSecondaryIDE: 97 cmp bx, DEVICE_ATA_DEFAULT_SECONDARY_PORT 103 98 .ReturnResultInZF: 104 99 ret … … 108 103 ; Vision_GetMaxPioModeToAL 109 104 ; 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 114 110 ; CF: Set if PIO limit necessary 115 111 ; Cleared if no need to limit timings 116 112 ; Corrupts registers: 113 ; (AX if CF cleared) 114 ; Corrupts registers: 117 115 ; Nothing 118 116 ;-------------------------------------------------------------------- … … 122 120 jne SHORT .NoNeedToLimitForQD6580 123 121 124 mov a l, 2 ; Limit to PIO 2 because QD6500 supports PIO 3 but without IORDY122 mov ax, 2 ; Limit to PIO 2 because QD6500 does not support IORDY 125 123 stc 126 124 .NoNeedToLimitForQD6580: … … 131 129 ; Vision_InitializeWithIDinAHandConfigInAL 132 130 ; 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 139 136 ; Returns: 140 137 ; CF: Cleared if success 141 138 ; Set if error 142 139 ; Corrupts registers: 143 ; AX, BX, CX, DX, SI, DI140 ; AX, BX, CX, DX, BP 144 141 ;-------------------------------------------------------------------- 145 142 Vision_InitializeWithIDinAHandConfigInAL: 146 143 ; 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 . GetPioTimingsInNanosecs144 mov dx, [di+DPT_ADVANCED_ATA.wControllerBasePort] 145 cmp ah, ID_QD6500 << 4 146 je SHORT .CalculateTimingForQD6500 150 147 151 148 ; Program QD6580 Control Register (not available on QD6500) to 152 149 ; Enable or Disable Read-Ahead and Post-Write Buffer to match 153 150 ; jumper setting on the multi I/O card. 154 .ProgramControlRegisterForQD6580: 155 xchg bx, ax ; Backup AX 151 xor ax, ax 156 152 add dx, BYTE QD6580_CONTROL_REGISTER 157 153 in al, dx ; Read to get ATAPI jumper status 158 154 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 163 158 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 172 160 173 161 ; Now we need to determine is the drive connected to the Primary or Secondary channel. 174 162 ; QD6500 has only one channel that can be Primary at 1F0h or Secondary at 170h. 175 163 ; 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 180 167 times 2 inc dx ; Secondary Channel IDE Timing Register 181 168 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. 185 170 .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 ;-------------------------------------------------------------------- 211 ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue: 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 201 221 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 213 227 214 228 ; Not done yet, we need to invert the ticks since 0 is the slowest 215 229 ; 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.