source: xtideuniversalbios/trunk/XTIDE_Universal_BIOS/Src/Device/IDE/JrIdeTransfer.asm @ 592

Last change on this file since 592 was 592, checked in by krille_n_, 6 years ago

Changes:

  • The problem with NASM in the previous revision (r591) has been fixed.
  • The colors used by the boot menu and hotkey bar can now be customized by selecting one of a number of pre-defined color themes. Suggestions for additional themes are more than welcome!
  • Large builds are now 10 KB. Small builds are still 8 KB with the exception of the Tiny build which is now 4 KB. In other words, builds are now as small as possible to make it easier to combine them with other BIOSes.
  • Added code to the library to improve drive error handling. XTIDECFG can now handle "Drive Not Ready" errors.
  • Fixed a couple of potential bugs in AtaID.asm (AtaID_GetMaxPioModeToAXandMinCycleTimeToCX); 1) ATA1.bPioMode was treated as a WORD variable. 2) ATA2.bPIOSupp was assumed to be non-zero which would result in PIO mode 3 being returned if the assumption was wrong.
  • Made the same changes in the equivalent function used by BIOSDRVS (DisplayPioModeInformationUsingAtaInfoFromDSBX in AtaInfo.asm).
  • Fixed a bug from r587 in PDC20x30.asm in PDC20x30_GetMaxPioModeToALandMinPioCycleTimeToBX.
  • Fixed a bug from r523 in XTIDECFG where Auto Configure would only set the IRQ on one IDE interface on AT-builds.
  • XTIDECFG will now restore the default settings for the "Serial port virtual device" when reselecting it in the list of device types. This makes it behave consistently for all device types.
  • The eAAM macro is now used regardless if USE_UNDOC_INTEL is defined or not because it is apparently supported on all processors including the NEC V20/V30 CPUs.
  • Renamed the EXCLUDE_FROM_XTIDE_UNIVERSAL_BIOS define to EXCLUDE_FROM_XUB.
  • Added a define to exclude unused library code from BIOSDRVS (EXCLUDE_FROM_BIOSDRVS). This makes it a lot smaller than in previous revisions.
  • All unnecessary CLD-instructions are now under a new define 'CLD_NEEDED' which is only enabled for the BIOS. It is disabled for XTIDECFG and BIOSDRVS but can be enabled if needed by adding this define to the respective makefile. This change was made because these unnecessary instructions are wasteful and should never be needed. In fact, they only serve to hide bugs (in other peoples code) which I strongly believe should be avoided. I recommend people making their own BIOSes from source to not use this define as it's extremely unlikely to be needed.
  • Updated the copyright info in SerDrive and changed an URL to point to the new site.
  • Updated the copyright info and version number in BIOSDRVS.
  • Updated the copyright info in XTIDECFG.
  • Optimizations in general.
File size: 9.1 KB
RevLine 
[400]1; Project name  :   XTIDE Universal BIOS
2; Description   :   Memory mapped IDE Device transfer functions.
3
4;
[412]5; XTIDE Universal BIOS and Associated Tools
[526]6; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2013 by XTIDE Universal BIOS Team.
[400]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.
[412]12;
[400]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
[412]16; GNU General Public License for more details.
[400]17; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
[412]18;
[400]19
20; Structure containing variables for PIO transfer functions.
21; This struct must not be larger than IDEPACK without INTPACK.
[414]22struc MEMPIOVARS    ; Must not be larger than 9 bytes! See IDEPACK in RamVars.inc.
23    .wSectorsInBlock        resb    2   ; 0-1, Block size in sectors
24    .fpDPT                  resb    4   ; 2-5, Far pointer to DPT
25    .bSectorsLeft           resb    1   ; 6, Sectors left to transfer
[400]26                            resb    1   ; 7, IDEPACK.bDeviceControl
[414]27    .bSectorsDone           resb    1   ; 8, Number of sectors xferred
[400]28endstruc
29
30
31; Section containing code
32SECTION .text
33
34;--------------------------------------------------------------------
35; JrIdeTransfer_StartWithCommandInAL
36;   Parameters:
37;       AL:     IDE command that was used to start the transfer
38;               (all PIO read and write commands including Identify Device)
[480]39;       ES:SI:  Ptr to data buffer
[400]40;       DS:DI:  Ptr to DPT (in RAMVARS segment)
41;       SS:BP:  Ptr to IDEPACK
42;   Returns:
43;       AH:     INT 13h Error Code
44;       CX:     Number of successfully transferred sectors
45;       CF:     Cleared if success, Set if error
46;   Corrupts registers:
47;       AL, BX, DX, SI, ES
48;--------------------------------------------------------------------
49ALIGN JUMP_ALIGN
50JrIdeTransfer_StartWithCommandInAL:
[473]51    ; Initialize MEMPIOVARS
52    xchg    cx, ax          ; IDE command to CL
53    xor     ax, ax
54    mov     [bp+MEMPIOVARS.bSectorsDone], al
[538]55    mov     dh, [bp+IDEPACK.bSectorCount]
56    mov     [bp+MEMPIOVARS.bSectorsLeft], dh
[473]57    mov     al, [di+DPT_ATA.bBlockSize]
58    mov     [bp+MEMPIOVARS.wSectorsInBlock], ax
[400]59    mov     [bp+MEMPIOVARS.fpDPT], di
60    mov     [bp+MEMPIOVARS.fpDPT+2], ds
61
[480]62    ; Normalize pointer
63    call    IdeTransfer_NormalizePointerInESSI
[538]64%ifdef USE_AT
65    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
66%endif
[480]67
[473]68    ; Get far pointer to Sector Access Window
69    cmp     BYTE [di+DPT_ATA.bDevice], DEVICE_8BIT_JRIDE_ISA
[545]70    mov     ds, [di+DPT.wBasePort]  ; Segment for JR-IDE/ISA and ADP50L
[536]71    mov     di, ADP50L_SECTOR_ACCESS_WINDOW_OFFSET
[545]72    eCMOVE  di, JRIDE_SECTOR_ACCESS_WINDOW_OFFSET
[473]73
[400]74    ; Are we reading or writing?
[473]75.SectorAccessWindowLoadedToDSDI:
76    test    cl, 16  ; Bit 4 is cleared on all the read commands but set on 3 of the 4 write commands
[400]77    jnz     SHORT WriteToSectorAccessWindow
[473]78    cmp     cl, COMMAND_WRITE_MULTIPLE
[400]79    je      SHORT WriteToSectorAccessWindow
80    ; Fall to ReadFromSectorAccessWindow
81
82;--------------------------------------------------------------------
83; ReadFromSectorAccessWindow
84;   Parameters:
[473]85;       DS:DI:  Ptr to Sector Access Window
[400]86;       ES:SI:  Normalized ptr to buffer to receive data
87;       SS:BP:  Ptr to MEMPIOVARS
88;   Returns:
89;       DS:DI:  Ptr to DPT (in RAMVARS segment)
90;       AH:     BIOS Error code
91;       CX:     Number of successfully transferred sectors
92;       CF:     0 if transfer successful
93;               1 if any error
94;   Corrupts registers:
[475]95;       AL, BX, DX, SI
[400]96;--------------------------------------------------------------------
97ReadFromSectorAccessWindow:
[473]98    xchg    si, di  ; DS:SI = source, ES:DI = Destination
[400]99    call    WaitUntilReadyToTransferNextBlock
100    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
101
[475]102    mov     cx, [bp+MEMPIOVARS.wSectorsInBlock] ; Clears CH
[412]103    cmp     [bp+MEMPIOVARS.bSectorsLeft], cl
104    jbe     SHORT .ReadLastBlockFromDrive
[400]105
106ALIGN JUMP_ALIGN
107.ReadNextBlockFromDrive:
108    call    ReadSingleBlockFromSectorAccessWindowInDSSItoESDI
109    call    WaitUntilReadyToTransferNextBlock
110    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
111
[476]112    ; Update number of successfully read sectors and sectors left to transfer.
113    ; We cannot use SUB instruction as a comparison since it will not
114    ; work in this situation:
115    ; Before SUB we have 2 full blocks left to transfer. SUB command
116    ; then compares 2 full blocks against one full block and updates
117    ; sectors left to one full block and jumps to .ReadNextBlockFromDrive,
118    ; since we have one full block left to transfer. After it has been
119    ; transferred, there will be a wait for next block but DRQ is never
120    ; set since all is transferred! Then we get timeout error.
[400]121    mov     cx, [bp+MEMPIOVARS.wSectorsInBlock]
[476]122    sub     [bp+MEMPIOVARS.bSectorsLeft], cl
[412]123    add     [bp+MEMPIOVARS.bSectorsDone], cl
[476]124    cmp     [bp+MEMPIOVARS.bSectorsLeft], cl
[412]125    ja      SHORT .ReadNextBlockFromDrive
[400]126
127ALIGN JUMP_ALIGN
128.ReadLastBlockFromDrive:
129    mov     cl, [bp+MEMPIOVARS.bSectorsLeft]
[419]130    push    cx
[400]131    call    ReadSingleBlockFromSectorAccessWindowInDSSItoESDI
132
133    ; Check for errors in last block
134CheckErrorsAfterTransferringLastMemoryMappedBlock:
135    lds     di, [bp+MEMPIOVARS.fpDPT]           ; DPT now in DS:DI
[417]136    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_BSY)
[400]137    call    IdeWait_PollStatusFlagInBLwithTimeoutInBH
[419]138    pop     cx  ; [bp+MEMPIOVARS.bSectorsLeft]
139    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
[400]140
[445]141    ; All sectors successfully transferred
[475]142    add     cl, [bp+MEMPIOVARS.bSectorsDone]    ; Never sets CF
[419]143    ret
144
[400]145    ; Return number of successfully transferred sectors
146ReturnWithMemoryIOtransferErrorInAH:
147    lds     di, [bp+MEMPIOVARS.fpDPT]           ; DPT now in DS:DI
148%ifdef USE_386
[592]149    movzx   cx, [bp+MEMPIOVARS.bSectorsDone]
[400]150%else
[475]151    mov     ch, 0                               ; Preserve CF
[400]152    mov     cl, [bp+MEMPIOVARS.bSectorsDone]
153%endif
154    ret
155
156
157;--------------------------------------------------------------------
158; WriteToSectorAccessWindow
159;   Parameters:
[473]160;       DS:DI:  Ptr to Sector Access Window
[400]161;       ES:SI:  Normalized ptr to buffer containing data
162;       SS:BP:  Ptr to MEMPIOVARS
163;   Returns:
164;       DS:DI:  Ptr to DPT (in RAMVARS segment)
165;       AH:     BIOS Error code
166;       CX:     Number of successfully transferred sectors
167;       CF:     0 if transfer successful
168;               1 if any error
169;   Corrupts registers:
170;       AL, BX, DX, SI, ES
171;--------------------------------------------------------------------
172ALIGN JUMP_ALIGN
173WriteToSectorAccessWindow:
174    push    es
[473]175    push    ds
176    pop     es      ; ES:DI = Sector Access Window (destination)
177    pop     ds      ; DS:SI = Ptr to source buffer
[400]178
179    ; Always poll when writing first block (IRQs are generated for following blocks)
180    call    WaitUntilReadyToTransferNextBlock
181    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
182
183    mov     cx, [bp+MEMPIOVARS.wSectorsInBlock]
[412]184    cmp     [bp+MEMPIOVARS.bSectorsLeft], cl
185    jbe     SHORT .WriteLastBlockToDrive
[400]186
187ALIGN JUMP_ALIGN
188.WriteNextBlockToDrive:
189    call    WriteSingleBlockFromDSSIToSectorAccessWindowInESDI
190    call    WaitUntilReadyToTransferNextBlock
191    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
192
193    ; Increment number of successfully written WORDs
194    mov     cx, [bp+MEMPIOVARS.wSectorsInBlock]
[476]195    sub     [bp+MEMPIOVARS.bSectorsLeft], cl
[412]196    add     [bp+MEMPIOVARS.bSectorsDone], cl
[476]197    cmp     [bp+MEMPIOVARS.bSectorsLeft], cl
[412]198    ja      SHORT .WriteNextBlockToDrive
[400]199
200ALIGN JUMP_ALIGN
201.WriteLastBlockToDrive:
202    mov     cl, [bp+MEMPIOVARS.bSectorsLeft]
[419]203    push    cx
[400]204    ePUSH_T bx, CheckErrorsAfterTransferringLastMemoryMappedBlock
205    ; Fall to WriteSingleBlockFromDSSIToSectorAccessWindowInESDI
206
207;--------------------------------------------------------------------
208; WriteSingleBlockFromDSSIToSectorAccessWindowInESDI
209;   Parameters:
210;       CX:     Number of sectors in block
211;       DS:SI:  Normalized ptr to source buffer
212;       ES:DI:  Ptr to Sector Access Window
213;   Returns:
214;       CX, DX: Zero
215;       SI:     Updated
216;   Corrupts registers:
217;       BX
218;--------------------------------------------------------------------
219ALIGN JUMP_ALIGN
220WriteSingleBlockFromDSSIToSectorAccessWindowInESDI:
221    mov     bx, di
222    mov     dx, cx
[536]223    xor     cx, cx
[400]224ALIGN JUMP_ALIGN
[475]225.WriteNextSector:
[536]226    inc     ch
[400]227    rep movsw
228    mov     di, bx  ; Reset for next sector
229    dec     dx
[475]230    jnz     SHORT .WriteNextSector
[400]231    ret
232
233
234;--------------------------------------------------------------------
235; ReadSingleBlockFromSectorAccessWindowInDSSItoESDI
236;   Parameters:
[475]237;       CX      Number of sectors in full block or sectors in last partial block
[400]238;       ES:DI:  Normalized ptr to buffer to receive data (destination)
239;       DS:SI:  Ptr to Sector Access Window (source)
240;   Returns:
241;       CX, DX: Zero
242;       DI:     Updated
243;   Corrupts registers:
244;       BX
245;--------------------------------------------------------------------
246ALIGN JUMP_ALIGN
247ReadSingleBlockFromSectorAccessWindowInDSSItoESDI:
248    mov     bx, si
249    mov     dx, cx
[536]250    xor     cx, cx
[400]251ALIGN JUMP_ALIGN
[475]252.ReadNextSector:
[536]253    inc     ch
[400]254    rep movsw
255    mov     si, bx  ; Reset for next sector
256    dec     dx
[475]257    jnz     SHORT .ReadNextSector
[400]258    ret
259
260
261;--------------------------------------------------------------------
262; WaitUntilReadyToTransferNextBlock
263;   Parameters:
264;       SS:BP:  Ptr to MEMPIOVARS
265;   Returns:
266;       AH:     INT 13h Error Code
267;       CF:     Cleared if success, Set if error
268;   Corrupts registers:
269;       AL, BX, CX, DX
270;--------------------------------------------------------------------
271ALIGN JUMP_ALIGN
272WaitUntilReadyToTransferNextBlock:
273    push    ds
274    push    di
275    lds     di, [bp+MEMPIOVARS.fpDPT]   ; DPT now in DS:DI
276    call    IdeWait_IRQorDRQ            ; Always polls
277    pop     di
278    pop     ds
279    ret
280
Note: See TracBrowser for help on using the repository browser.