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

Last change on this file since 469 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
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
[400]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.
[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)
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]
[412]94 cmp [bp+MEMPIOVARS.bSectorsLeft], cl
95 jbe SHORT .ReadLastBlockFromDrive
[400]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]
[412]105 add [bp+MEMPIOVARS.bSectorsDone], cl
[400]106 sub [bp+MEMPIOVARS.bSectorsLeft], cl
[412]107 ja SHORT .ReadNextBlockFromDrive
[400]108
109ALIGN JUMP_ALIGN
110.ReadLastBlockFromDrive:
111 mov cl, [bp+MEMPIOVARS.bSectorsLeft]
[419]112 push cx
[400]113 call ReadSingleBlockFromSectorAccessWindowInDSSItoESDI
114
115 ; Check for errors in last block
116CheckErrorsAfterTransferringLastMemoryMappedBlock:
117 lds di, [bp+MEMPIOVARS.fpDPT] ; DPT now in DS:DI
[417]118 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_BSY)
[400]119 call IdeWait_PollStatusFlagInBLwithTimeoutInBH
[419]120 pop cx ; [bp+MEMPIOVARS.bSectorsLeft]
121 jc SHORT ReturnWithMemoryIOtransferErrorInAH
[400]122
[445]123 ; All sectors successfully transferred
[419]124 add cx, [bp+PIOVARS.bSectorsDone] ; Never sets CF
125 ret
126
[400]127 ; Return number of successfully transferred sectors
128ReturnWithMemoryIOtransferErrorInAH:
129 lds di, [bp+MEMPIOVARS.fpDPT] ; DPT now in DS:DI
130%ifdef USE_386
[412]131 movzx cx, [bp+MEMPIOVARS.bSectorsDone]
[400]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]
[412]166 cmp [bp+MEMPIOVARS.bSectorsLeft], cl
167 jbe SHORT .WriteLastBlockToDrive
[400]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]
[412]177 add [bp+MEMPIOVARS.bSectorsDone], cl
[400]178 sub [bp+MEMPIOVARS.bSectorsLeft], cl
[412]179 ja SHORT .WriteNextBlockToDrive
[400]180
181ALIGN JUMP_ALIGN
182.WriteLastBlockToDrive:
183 mov cl, [bp+MEMPIOVARS.bSectorsLeft]
[419]184 push cx
[400]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
[412]264 %error "JRIDE_SECTOR_ACCESS_WINDOW_SIZE is no longer equal to 512. JrIdeTransfer.asm needs changes."
[400]265%endif
Note: See TracBrowser for help on using the repository browser.