source: xtideuniversalbios/trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeCommand.asm @ 612

Last change on this file since 612 was 612, checked in by krille_n_, 3 years ago

Changes:

  • BIOSDRVS builds again (broken since r609). Also removed the last remnants of RESERVE_DIAGNOSTIC_CYLINDER from BIOSDRVS that I missed in r606.
  • Put in a limit on the P-CHS cylinder count in an attempt to improve compatibility with some CF cards that violates the ATA specification. The limit applies only to the BIOS. BIOSDRVS will continue to show the true cylinder count since we might want to add code later to warn the user when encountering incompatible drives like these.
  • Optimized the bug fix in r611.
  • Updated the copyright notices in XTIDECFG and BIOSDRVS.
File size: 10.2 KB
RevLine 
[150]1; Project name  :   XTIDE Universal BIOS
2; Description   :   IDE Device Command functions.
3
[376]4;
[445]5; XTIDE Universal BIOS and Associated Tools
[526]6; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2013 by XTIDE Universal BIOS Team.
[376]7;
8; This program is free software; you can redistribute it and/or modify
9; it under the terms of the GNU General Public License as published by
10; the Free Software Foundation; either version 2 of the License, or
11; (at your option) any later version.
[445]12;
[376]13; This program is distributed in the hope that it will be useful,
14; but WITHOUT ANY WARRANTY; without even the implied warranty of
15; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16; GNU General Public License for more details.
[445]17; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
18;
[376]19
[150]20; Section containing code
21SECTION .text
22
23;--------------------------------------------------------------------
[507]24; IdeCommand_ResetMasterAndSlaveController
25;   Parameters:
26;       DS:DI:  Ptr to DPT (in RAMVARS segment)
27;   Returns:
28;       AH:     INT 13h Error Code
29;       CF:     Cleared if success, Set if error
30;   Corrupts registers:
31;       AL, BX, CX, DX
32;--------------------------------------------------------------------
[596]33IdeCommand_ResetMasterAndSlaveController:   ; Unused entrypoint OK
[507]34    ; HSR0: Set_SRST
[589]35; Used to be:
36;   call    AccessDPT_GetDeviceControlByteToAL
37;   or      al, FLG_DEVCONTROL_SRST | FLG_DEVCONTROL_nIEN   ; Set Reset bit
38; Is now:
39    mov     al, FLG_DEVCONTROL_SRST | FLG_DEVCONTROL_nIEN
40; ---
[507]41    OUTPUT_AL_TO_IDE_CONTROL_BLOCK_REGISTER     DEVICE_CONTROL_REGISTER_out
42    mov     ax, HSR0_RESET_WAIT_US
43    call    Timer_DelayMicrosecondsFromAX
44
45    ; HSR1: Clear_wait
[589]46; Used to be:
47;   call    AccessDPT_GetDeviceControlByteToAL
48;   or      al, FLG_DEVCONTROL_nIEN
49;   and     al, ~FLG_DEVCONTROL_SRST                        ; Clear reset bit
50; Is now:
51    mov     al, FLG_DEVCONTROL_nIEN
52; ---
[507]53    OUTPUT_AL_TO_IDE_CONTROL_BLOCK_REGISTER     DEVICE_CONTROL_REGISTER_out
54    mov     ax, HSR1_RESET_WAIT_US
55    call    Timer_DelayMicrosecondsFromAX
56
57    ; HSR2: Check_status
58    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_MAXIMUM, FLG_STATUS_BSY)
59    jmp     IdeWait_PollStatusFlagInBLwithTimeoutInBH
60
[589]61; *FIXME* AccessDPT_GetDeviceControlByteToAL currently always returns with
62; AL cleared (0) or with only bit 1 set (FLG_DEVCONTROL_nIEN = 2).
63; The commented away instructions above sets FLG_DEVCONTROL_nIEN anyway
64; making the call to AccessDPT_GetDeviceControlByteToAL redundant.
65; I have left this code as is since I don't know if it's a mistake
66; (from all the way back to r150) or if it's coded this way in anticipation
67; of some future changes to AccessDPT_GetDeviceControlByteToAL.
[507]68
69;--------------------------------------------------------------------
[150]70; IdeCommand_IdentifyDeviceToBufferInESSIwithDriveSelectByteInBH
71;   Parameters:
72;       BH:     Drive Select byte for Drive and Head Select Register
[473]73;       DX:     Autodetected port for XT-CF
[150]74;       DS:     Segment to RAMVARS
75;       ES:SI:  Ptr to buffer to receive 512-byte IDE Information
76;       CS:BP:  Ptr to IDEVARS
77;   Returns:
78;       AH:     INT 13h Error Code
79;       CF:     Cleared if success, Set if error
80;   Corrupts registers:
[443]81;       AL, BX, CX, DX, SI, DI, ES
[150]82;--------------------------------------------------------------------
[596]83IdeCommand_IdentifyDeviceToBufferInESSIwithDriveSelectByteInBH:     ; Unused entrypoint OK
[150]84    ; Create fake DPT to be able to use Device.asm functions
85    call    FindDPT_ForNewDriveToDSDI
[158]86    eMOVZX  ax, bh
[150]87    mov     [di+DPT.wFlags], ax
[473]88    call    CreateDPT_StoreIdevarsOffsetAndBasePortFromCSBPtoDPTinDSDI
89    call    IdeDPT_StoreDeviceTypeToDPTinDSDIfromIdevarsInCSBP
[365]90    mov     BYTE [di+DPT_ATA.bBlockSize], 1 ; Block = 1 sector
[150]91
[443]92    ; Wait until drive motors have reached full speed
[473]93    cmp     bp, BYTE ROMVARS.ideVars0   ; First controller?
[150]94    jne     SHORT .SkipLongWaitSinceDriveIsNotPrimaryMaster
[473]95    test    bh, FLG_DRVNHEAD_DRV        ; Wait already done for Master
[150]96    jnz     SHORT .SkipLongWaitSinceDriveIsNotPrimaryMaster
[545]97    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_MOTOR_STARTUP, FLG_STATUS_BSY)
[507]98    call    IdeWait_PollStatusFlagInBLwithTimeoutInBH
[150]99.SkipLongWaitSinceDriveIsNotPrimaryMaster:
100
101    ; Create IDEPACK without INTPACK
102    push    bp
103    call    Idepack_FakeToSSBP
104
[545]105%ifdef MODULE_8BIT_IDE
[480]106    push    si
[584]107
108    ; Enable 8-bit PIO for DEVICE_8BIT_ATA (no need to verify device type here)
[480]109    call    AH9h_Enable8bitModeForDevice8bitAta
[584]110
111    ; Set XT-CF mode. No need to check here if device is XT-CF or not.
[545]112%ifdef MODULE_8BIT_IDE_ADVANCED
[584]113    call    AH1Eh_GetCurrentXTCFmodeToAX    ; Reads from DPT_ATA.bDevice that we just stored
114    call    AH9h_SetModeFromALtoXTCF        ; Enables/disables 8-bit mode when necessary
[545]115%endif ; MODULE_8BIT_IDE_ADVANCED
[443]116    pop     si
[545]117%endif ; MODULE_8BIT_IDE
[437]118
[150]119    ; Prepare to output Identify Device command
120    mov     dl, 1                       ; Sector count (required by IdeTransfer.asm)
121    mov     al, COMMAND_IDENTIFY_DEVICE
[411]122    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
[150]123    call    Idepack_StoreNonExtParametersAndIssueCommandFromAL
124
125    ; Clean stack and return
[443]126    lea     sp, [bp+SIZE_OF_IDEPACK_WITHOUT_INTPACK]    ; This assumes BP hasn't changed between Idepack_FakeToSSBP and here
[150]127    pop     bp
128    ret
129
130
131;--------------------------------------------------------------------
132; IdeCommand_OutputWithParameters
133;   Parameters:
134;       BH:     System timer ticks for timeout
135;       BL:     IDE Status Register bit to poll after command
136;       ES:SI:  Ptr to buffer (for data transfer commands)
137;       DS:DI:  Ptr to DPT (in RAMVARS segment)
138;       SS:BP:  Ptr to IDEPACK
139;   Returns:
140;       AH:     INT 13h Error Code
[249]141;       CX:     Number of successfully transferred sectors (for transfer commands)
[150]142;       CF:     Cleared if success, Set if error
143;   Corrupts registers:
[249]144;       AL, BX, (CX), DX, (ES:SI for data transfer commands)
[150]145;--------------------------------------------------------------------
146ALIGN JUMP_ALIGN
[596]147IdeCommand_OutputWithParameters:    ; Unused entrypoint OK
[158]148    push    bx                      ; Store status register bits to poll
[150]149
150    ; Select Master or Slave drive and output head number or LBA28 top bits
[400]151    call    IdeCommand_SelectDrive
[150]152    jc      SHORT .DriveNotReady
153
154    ; Output Device Control Byte to enable or disable interrupts
155    mov     al, [bp+IDEPACK.bDeviceControl]
[400]156%ifdef MODULE_IRQ
[158]157    test    al, FLG_DEVCONTROL_nIEN ; Interrupts disabled?
[152]158    jnz     SHORT .DoNotSetInterruptInServiceFlag
[158]159
160    ; Clear Task Flag and set Interrupt In-Service Flag
[152]161    push    ds
[540]162    LOAD_BDA_SEGMENT_TO ds, dx
163    mov     BYTE [BDA.bHDTaskFlg], 1    ; Will be adjusted to zero later
[152]164    pop     ds
165.DoNotSetInterruptInServiceFlag:
[266]166%endif
[267]167    OUTPUT_AL_TO_IDE_CONTROL_BLOCK_REGISTER     DEVICE_CONTROL_REGISTER_out
[150]168
169    ; Output Feature Number
170    mov     al, [bp+IDEPACK.bFeatures]
[267]171    OUTPUT_AL_TO_IDE_REGISTER   FEATURES_REGISTER_out
[150]172
173    ; Output Sector Address High (only used by LBA48)
[285]174%ifdef MODULE_EBIOS
[612]175    mov     ah, [bp+IDEPACK.bLbaLowExt]
176    xor     al, al                          ; Zero sector count
[150]177    mov     cx, [bp+IDEPACK.wLbaMiddleAndHighExt]
[400]178    call    OutputSectorCountAndAddress
[285]179%endif
[150]180
181    ; Output Sector Address Low
182    mov     ax, [bp+IDEPACK.wSectorCountAndLbaLow]
183    mov     cx, [bp+IDEPACK.wLbaMiddleAndHigh]
[400]184    call    OutputSectorCountAndAddress
[150]185
186    ; Output command
187    mov     al, [bp+IDEPACK.bCommand]
[267]188    OUTPUT_AL_TO_IDE_REGISTER   COMMAND_REGISTER_out
[150]189
190    ; Wait until command completed
[400]191    pop     bx                              ; Pop status and timeout for polling
192    cmp     bl, FLG_STATUS_DRQ              ; Data transfer started?
193    jne     SHORT .WaitUntilNonTransferCommandCompletes
[493]194%ifdef MODULE_8BIT_IDE_ADVANCED
[545]195    cmp     BYTE [di+DPT_ATA.bDevice], DEVICE_8BIT_JRIDE_ISA
196    jae     SHORT JrIdeTransfer_StartWithCommandInAL    ; DEVICE_8BIT_JRIDE_ISA or DEVICE_8BIT_ADP50L
[480]197%endif
[474]198    jmp     IdeTransfer_StartWithCommandInAL
[400]199
200.WaitUntilNonTransferCommandCompletes:
201%ifdef MODULE_IRQ
[150]202    test    BYTE [bp+IDEPACK.bDeviceControl], FLG_DEVCONTROL_nIEN
[592]203%ifdef USE_386
204    jnz     IdeWait_IRQorStatusFlagInBLwithTimeoutInBH
205%else
[400]206    jz      SHORT .PollStatusFlagInsteadOfWaitIrq
207    jmp     IdeWait_IRQorStatusFlagInBLwithTimeoutInBH
208.PollStatusFlagInsteadOfWaitIrq:
209%endif
[592]210%endif ; MODULE_IRQ
[400]211    jmp     IdeWait_PollStatusFlagInBLwithTimeoutInBH
[150]212
213.DriveNotReady:
214    pop     bx                          ; Clean stack
215    ret
216
217
218;--------------------------------------------------------------------
219; IdeCommand_SelectDrive
220;   Parameters:
221;       DS:DI:  Ptr to DPT (in RAMVARS segment)
222;       SS:BP:  Ptr to IDEPACK
223;   Returns:
224;       AH:     INT 13h Error Code
225;       CF:     Cleared if success, Set if error
226;   Corrupts registers:
227;       AL, BX, CX, DX
228;--------------------------------------------------------------------
229ALIGN JUMP_ALIGN
[400]230IdeCommand_SelectDrive:
[444]231    ; We use different timeout value when detecting drives.
232    ; This prevents unnecessary long delays when drive is not present.
[473]233    mov     cx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRDY, FLG_STATUS_DRDY)
[444]234    cmp     WORD [RAMVARS.wDrvDetectSignature], RAMVARS_DRV_DETECT_SIGNATURE
[473]235    eCMOVE  ch, TIMEOUT_SELECT_DRIVE_DURING_DRIVE_DETECTION
[408]236
[150]237    ; Select Master or Slave Drive
238    mov     al, [bp+IDEPACK.bDrvAndHead]
[267]239    OUTPUT_AL_TO_IDE_REGISTER   DRIVE_AND_HEAD_SELECT_REGISTER
[473]240    mov     bx, cx
[400]241    call    IdeWait_PollStatusFlagInBLwithTimeoutInBH
[150]242
[610]243    ; Output again to make sure head bits are set. They were lost if the device
244    ; was busy when we first output drive select (although it shouldn't be busy
245    ; since we have waited error result after previous command). Some low power
246    ; drives (CF cards, 1.8" HDDs etc) have some internal sleep modes that
247    ; might cause trouble? Normal HDDs seem to work fine.
[611]248    ;
249    ; Now commented away since this fix was not necessary. Let's keep it here
250    ; if some drive someday has problems crossing 8GB
251    ;mov        al, [bp+IDEPACK.bDrvAndHead]
252    ;OUTPUT_AL_TO_IDE_REGISTER  DRIVE_AND_HEAD_SELECT_REGISTER
[610]253
[281]254    ; Ignore errors from IDE Error Register (set by previous command)
[285]255    cmp     ah, RET_HD_TIMEOUT
256    je      SHORT .FailedToSelectDrive
257    xor     ax, ax                  ; Always success unless timeout
258    ret
259.FailedToSelectDrive:
[281]260    stc
[279]261    ret
[150]262
[279]263
[150]264;--------------------------------------------------------------------
265; OutputSectorCountAndAddress
266;   Parameters:
267;       AH:     LBA low bits (Sector Number)
268;       AL:     Sector Count
269;       CL:     LBA middle bits (Cylinder Number low)
270;       CH:     LBA high bits (Cylinder Number high)
271;       DS:DI:  Ptr to DPT (in RAMVARS segment)
272;   Returns:
273;       Nothing
274;   Corrupts registers:
275;       AL, BX, DX
276;--------------------------------------------------------------------
277ALIGN JUMP_ALIGN
[400]278OutputSectorCountAndAddress:
[267]279    OUTPUT_AL_TO_IDE_REGISTER   SECTOR_COUNT_REGISTER
[150]280
281    mov     al, ah
[267]282    OUTPUT_AL_TO_IDE_REGISTER   LBA_LOW_REGISTER
[150]283
284    mov     al, cl
[267]285    OUTPUT_AL_TO_IDE_REGISTER   LBA_MIDDLE_REGISTER
[150]286
287    mov     al, ch
[473]288    OUTPUT_AL_TO_IDE_REGISTER   LBA_HIGH_REGISTER
289    ret
Note: See TracBrowser for help on using the repository browser.