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

Last change on this file since 445 was 445, checked in by krille_n_@…, 12 years ago

Changes:

  • A speed optimization to the eSHL_IM macro for 386 and higher. This change breaks emulation in the sense that the macro will fail when given a memory operand as the first parameter.
  • Memory_SumCXbytesFromESSItoAL now returns with the zero flag set/cleared according to the result.
  • Unrolled all the 8 bit READ transfer loops to do 16 bytes per iteration. Added a new macro (UNROLL_SECTORS_IN_CX_TO_OWORDS) as part of it. Size wise this is expensive but I think it should be worth the ROM space. The WRITE transfer loops were left as is since writes are rare anyway (<10% of all disk I/O IIRC).
  • Minor optimizations and fixes here and there.
File size: 8.4 KB
Line 
1; Project name  :   XTIDE Universal BIOS
2; Description   :   Memory mapped IDE Device transfer functions.
3
4;
5; XTIDE Universal BIOS and Associated Tools
6; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
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.
12;
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.
17; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
18;
19
20; Structure containing variables for PIO transfer functions.
21; This struct must not be larger than IDEPACK without INTPACK.
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
26                            resb    1   ; 7, IDEPACK.bDeviceControl
27    .bSectorsDone           resb    1   ; 8, Number of sectors xferred
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)
39;       ES:SI:  Ptr to normalized data buffer
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:
51    push    cs  ; We push CS here (segment of SAW) and later pop it to DS (reads) or ES (writes)
52
53    ; Initialize PIOVARS
54    xor     cx, cx
55    mov     [bp+MEMPIOVARS.bSectorsDone], cl
56    mov     cl, [bp+IDEPACK.bSectorCount]
57    mov     [bp+MEMPIOVARS.bSectorsLeft], cl
58    mov     cl, [di+DPT_ATA.bBlockSize]
59    mov     [bp+MEMPIOVARS.wSectorsInBlock], cx
60    mov     [bp+MEMPIOVARS.fpDPT], di
61    mov     [bp+MEMPIOVARS.fpDPT+2], ds
62
63    ; Are we reading or writing?
64    test    al, 16  ; Bit 4 is cleared on all the read commands but set on 3 of the 4 write commands
65    jnz     SHORT WriteToSectorAccessWindow
66    cmp     al, COMMAND_WRITE_MULTIPLE
67    je      SHORT WriteToSectorAccessWindow
68    ; Fall to ReadFromSectorAccessWindow
69
70;--------------------------------------------------------------------
71; ReadFromSectorAccessWindow
72;   Parameters:
73;       Stack:  Segment part of ptr to Sector Access Window
74;       ES:SI:  Normalized ptr to buffer to receive data
75;       SS:BP:  Ptr to MEMPIOVARS
76;   Returns:
77;       DS:DI:  Ptr to DPT (in RAMVARS segment)
78;       AH:     BIOS Error code
79;       CX:     Number of successfully transferred sectors
80;       CF:     0 if transfer successful
81;               1 if any error
82;   Corrupts registers:
83;       AL, BX, DX, SI, ES
84;--------------------------------------------------------------------
85ReadFromSectorAccessWindow:
86    pop     ds      ; CS -> DS
87    mov     di, si  ; ES:DI = destination
88    mov     si, JRIDE_SECTOR_ACCESS_WINDOW_OFFSET   ; DS:SI = source
89
90    call    WaitUntilReadyToTransferNextBlock
91    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
92
93    mov     cx, [bp+MEMPIOVARS.wSectorsInBlock]
94    cmp     [bp+MEMPIOVARS.bSectorsLeft], cl
95    jbe     SHORT .ReadLastBlockFromDrive
96
97ALIGN JUMP_ALIGN
98.ReadNextBlockFromDrive:
99    call    ReadSingleBlockFromSectorAccessWindowInDSSItoESDI
100    call    WaitUntilReadyToTransferNextBlock
101    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
102
103    ; Increment number of successfully read sectors
104    mov     cx, [bp+MEMPIOVARS.wSectorsInBlock]
105    add     [bp+MEMPIOVARS.bSectorsDone], cl
106    sub     [bp+MEMPIOVARS.bSectorsLeft], cl
107    ja      SHORT .ReadNextBlockFromDrive
108
109ALIGN JUMP_ALIGN
110.ReadLastBlockFromDrive:
111    mov     cl, [bp+MEMPIOVARS.bSectorsLeft]
112    push    cx
113    call    ReadSingleBlockFromSectorAccessWindowInDSSItoESDI
114
115    ; Check for errors in last block
116CheckErrorsAfterTransferringLastMemoryMappedBlock:
117    lds     di, [bp+MEMPIOVARS.fpDPT]           ; DPT now in DS:DI
118    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_BSY)
119    call    IdeWait_PollStatusFlagInBLwithTimeoutInBH
120    pop     cx  ; [bp+MEMPIOVARS.bSectorsLeft]
121    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
122
123    ; All sectors successfully transferred
124    add     cx, [bp+PIOVARS.bSectorsDone]       ; Never sets CF
125    ret
126
127    ; Return number of successfully transferred sectors
128ReturnWithMemoryIOtransferErrorInAH:
129    lds     di, [bp+MEMPIOVARS.fpDPT]           ; DPT now in DS:DI
130%ifdef USE_386
131    movzx   cx, [bp+MEMPIOVARS.bSectorsDone]
132%else
133    mov     ch, 0
134    mov     cl, [bp+MEMPIOVARS.bSectorsDone]
135%endif
136    ret
137
138
139;--------------------------------------------------------------------
140; WriteToSectorAccessWindow
141;   Parameters:
142;       Stack:  Segment part of ptr to Sector Access Window
143;       ES:SI:  Normalized ptr to buffer containing data
144;       SS:BP:  Ptr to MEMPIOVARS
145;   Returns:
146;       DS:DI:  Ptr to DPT (in RAMVARS segment)
147;       AH:     BIOS Error code
148;       CX:     Number of successfully transferred sectors
149;       CF:     0 if transfer successful
150;               1 if any error
151;   Corrupts registers:
152;       AL, BX, DX, SI, ES
153;--------------------------------------------------------------------
154ALIGN JUMP_ALIGN
155WriteToSectorAccessWindow:
156    push    es
157    pop     ds
158    pop     es  ; CS -> ES
159    mov     di, JRIDE_SECTOR_ACCESS_WINDOW_OFFSET
160
161    ; Always poll when writing first block (IRQs are generated for following blocks)
162    call    WaitUntilReadyToTransferNextBlock
163    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
164
165    mov     cx, [bp+MEMPIOVARS.wSectorsInBlock]
166    cmp     [bp+MEMPIOVARS.bSectorsLeft], cl
167    jbe     SHORT .WriteLastBlockToDrive
168
169ALIGN JUMP_ALIGN
170.WriteNextBlockToDrive:
171    call    WriteSingleBlockFromDSSIToSectorAccessWindowInESDI
172    call    WaitUntilReadyToTransferNextBlock
173    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
174
175    ; Increment number of successfully written WORDs
176    mov     cx, [bp+MEMPIOVARS.wSectorsInBlock]
177    add     [bp+MEMPIOVARS.bSectorsDone], cl
178    sub     [bp+MEMPIOVARS.bSectorsLeft], cl
179    ja      SHORT .WriteNextBlockToDrive
180
181ALIGN JUMP_ALIGN
182.WriteLastBlockToDrive:
183    mov     cl, [bp+MEMPIOVARS.bSectorsLeft]
184    push    cx
185    ePUSH_T bx, CheckErrorsAfterTransferringLastMemoryMappedBlock
186    ; Fall to WriteSingleBlockFromDSSIToSectorAccessWindowInESDI
187
188;--------------------------------------------------------------------
189; WriteSingleBlockFromDSSIToSectorAccessWindowInESDI
190;   Parameters:
191;       CX:     Number of sectors in block
192;       DS:SI:  Normalized ptr to source buffer
193;       ES:DI:  Ptr to Sector Access Window
194;   Returns:
195;       CX, DX: Zero
196;       SI:     Updated
197;   Corrupts registers:
198;       BX
199;--------------------------------------------------------------------
200ALIGN JUMP_ALIGN
201WriteSingleBlockFromDSSIToSectorAccessWindowInESDI:
202    mov     bx, di
203    mov     dx, cx
204    xor     cl, cl
205ALIGN JUMP_ALIGN
206.WriteBlock:
207    mov     ch, JRIDE_SECTOR_ACCESS_WINDOW_SIZE >> 9
208    rep movsw
209    mov     di, bx  ; Reset for next sector
210    dec     dx
211    jnz     SHORT .WriteBlock
212    ret
213
214
215;--------------------------------------------------------------------
216; ReadSingleBlockFromSectorAccessWindowInDSSItoESDI
217;   Parameters:
218;       CX      Number of sectors in block
219;       ES:DI:  Normalized ptr to buffer to receive data (destination)
220;       DS:SI:  Ptr to Sector Access Window (source)
221;   Returns:
222;       CX, DX: Zero
223;       DI:     Updated
224;   Corrupts registers:
225;       BX
226;--------------------------------------------------------------------
227ALIGN JUMP_ALIGN
228ReadSingleBlockFromSectorAccessWindowInDSSItoESDI:
229    mov     bx, si
230    mov     dx, cx
231    xor     cl, cl
232ALIGN JUMP_ALIGN
233.ReadBlock:
234    mov     ch, JRIDE_SECTOR_ACCESS_WINDOW_SIZE >> 9
235    rep movsw
236    mov     si, bx  ; Reset for next sector
237    dec     dx
238    jnz     SHORT .ReadBlock
239    ret
240
241
242;--------------------------------------------------------------------
243; WaitUntilReadyToTransferNextBlock
244;   Parameters:
245;       SS:BP:  Ptr to MEMPIOVARS
246;   Returns:
247;       AH:     INT 13h Error Code
248;       CF:     Cleared if success, Set if error
249;   Corrupts registers:
250;       AL, BX, CX, DX
251;--------------------------------------------------------------------
252ALIGN JUMP_ALIGN
253WaitUntilReadyToTransferNextBlock:
254    push    ds
255    push    di
256    lds     di, [bp+MEMPIOVARS.fpDPT]   ; DPT now in DS:DI
257    call    IdeWait_IRQorDRQ            ; Always polls
258    pop     di
259    pop     ds
260    ret
261
262
263%if JRIDE_SECTOR_ACCESS_WINDOW_SIZE <> 512
264    %error "JRIDE_SECTOR_ACCESS_WINDOW_SIZE is no longer equal to 512. JrIdeTransfer.asm needs changes."
265%endif
Note: See TracBrowser for help on using the repository browser.