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

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

Changes to XTIDE Universal BIOS:

  • Segment overflow is now checked when transfer buffer pointer is normalized (AT builds only).
File size: 9.5 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-2013 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 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 ; Initialize MEMPIOVARS
52 xchg cx, ax ; IDE command to CL
53 xor ax, ax
54 mov [bp+MEMPIOVARS.bSectorsDone], al
55 mov dh, [bp+IDEPACK.bSectorCount]
56 mov [bp+MEMPIOVARS.bSectorsLeft], dh
57 mov al, [di+DPT_ATA.bBlockSize]
58 mov [bp+MEMPIOVARS.wSectorsInBlock], ax
59 mov [bp+MEMPIOVARS.fpDPT], di
60 mov [bp+MEMPIOVARS.fpDPT+2], ds
61
62 ; Normalize pointer
63 call IdeTransfer_NormalizePointerInESSI
64%ifdef USE_AT
65 jc SHORT ReturnWithMemoryIOtransferErrorInAH
66%endif
67
68 ; Get far pointer to Sector Access Window
69 mov dx, [di+DPT.wBasePort]
70 cmp BYTE [di+DPT_ATA.bDevice], DEVICE_8BIT_JRIDE_ISA
71 jb SHORT .GetSectorAccessWindowForXTCF
72
73 ; Get Sector Access Window for JR-IDE/ISA and ADP50L
74 mov ds, dx ; Segment for JR-IDE/ISA and ADP50L
75 mov di, JRIDE_SECTOR_ACCESS_WINDOW_OFFSET
76 je SHORT .SectorAccessWindowLoadedToDSDI
77 mov di, ADP50L_SECTOR_ACCESS_WINDOW_OFFSET
78 jmp SHORT .SectorAccessWindowLoadedToDSDI
79
80.GetSectorAccessWindowForXTCF:
81 xor di, di
82 add dl, XTCF_CONTROL_REGISTER
83 in al, dx ; Read high byte for Sector Access Window segment
84 xchg ah, al
85 mov ds, ax
86
87 ; Are we reading or writing?
88.SectorAccessWindowLoadedToDSDI:
89 test cl, 16 ; Bit 4 is cleared on all the read commands but set on 3 of the 4 write commands
90 jnz SHORT WriteToSectorAccessWindow
91 cmp cl, COMMAND_WRITE_MULTIPLE
92 je SHORT WriteToSectorAccessWindow
93 ; Fall to ReadFromSectorAccessWindow
94
95;--------------------------------------------------------------------
96; ReadFromSectorAccessWindow
97; Parameters:
98; DS:DI: Ptr to Sector Access Window
99; ES:SI: Normalized ptr to buffer to receive data
100; SS:BP: Ptr to MEMPIOVARS
101; Returns:
102; DS:DI: Ptr to DPT (in RAMVARS segment)
103; AH: BIOS Error code
104; CX: Number of successfully transferred sectors
105; CF: 0 if transfer successful
106; 1 if any error
107; Corrupts registers:
108; AL, BX, DX, SI
109;--------------------------------------------------------------------
110ReadFromSectorAccessWindow:
111 xchg si, di ; DS:SI = source, ES:DI = Destination
112 call WaitUntilReadyToTransferNextBlock
113 jc SHORT ReturnWithMemoryIOtransferErrorInAH
114
115 mov cx, [bp+MEMPIOVARS.wSectorsInBlock] ; Clears CH
116 cmp [bp+MEMPIOVARS.bSectorsLeft], cl
117 jbe SHORT .ReadLastBlockFromDrive
118
119ALIGN JUMP_ALIGN
120.ReadNextBlockFromDrive:
121 call ReadSingleBlockFromSectorAccessWindowInDSSItoESDI
122 call WaitUntilReadyToTransferNextBlock
123 jc SHORT ReturnWithMemoryIOtransferErrorInAH
124
125 ; Update number of successfully read sectors and sectors left to transfer.
126 ; We cannot use SUB instruction as a comparison since it will not
127 ; work in this situation:
128 ; Before SUB we have 2 full blocks left to transfer. SUB command
129 ; then compares 2 full blocks against one full block and updates
130 ; sectors left to one full block and jumps to .ReadNextBlockFromDrive,
131 ; since we have one full block left to transfer. After it has been
132 ; transferred, there will be a wait for next block but DRQ is never
133 ; set since all is transferred! Then we get timeout error.
134 mov cx, [bp+MEMPIOVARS.wSectorsInBlock]
135 sub [bp+MEMPIOVARS.bSectorsLeft], cl
136 add [bp+MEMPIOVARS.bSectorsDone], cl
137 cmp [bp+MEMPIOVARS.bSectorsLeft], cl
138 ja SHORT .ReadNextBlockFromDrive
139
140ALIGN JUMP_ALIGN
141.ReadLastBlockFromDrive:
142 mov cl, [bp+MEMPIOVARS.bSectorsLeft]
143 push cx
144 call ReadSingleBlockFromSectorAccessWindowInDSSItoESDI
145
146 ; Check for errors in last block
147CheckErrorsAfterTransferringLastMemoryMappedBlock:
148 lds di, [bp+MEMPIOVARS.fpDPT] ; DPT now in DS:DI
149 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_BSY)
150 call IdeWait_PollStatusFlagInBLwithTimeoutInBH
151 pop cx ; [bp+MEMPIOVARS.bSectorsLeft]
152 jc SHORT ReturnWithMemoryIOtransferErrorInAH
153
154 ; All sectors successfully transferred
155 add cl, [bp+MEMPIOVARS.bSectorsDone] ; Never sets CF
156 ret
157
158 ; Return number of successfully transferred sectors
159ReturnWithMemoryIOtransferErrorInAH:
160 lds di, [bp+MEMPIOVARS.fpDPT] ; DPT now in DS:DI
161%ifdef USE_386
162 movzx cx, BYTE [bp+MEMPIOVARS.bSectorsDone]
163%else
164 mov ch, 0 ; Preserve CF
165 mov cl, [bp+MEMPIOVARS.bSectorsDone]
166%endif
167 ret
168
169
170;--------------------------------------------------------------------
171; WriteToSectorAccessWindow
172; Parameters:
173; DS:DI: Ptr to Sector Access Window
174; ES:SI: Normalized ptr to buffer containing data
175; SS:BP: Ptr to MEMPIOVARS
176; Returns:
177; DS:DI: Ptr to DPT (in RAMVARS segment)
178; AH: BIOS Error code
179; CX: Number of successfully transferred sectors
180; CF: 0 if transfer successful
181; 1 if any error
182; Corrupts registers:
183; AL, BX, DX, SI, ES
184;--------------------------------------------------------------------
185ALIGN JUMP_ALIGN
186WriteToSectorAccessWindow:
187 push es
188 push ds
189 pop es ; ES:DI = Sector Access Window (destination)
190 pop ds ; DS:SI = Ptr to source buffer
191
192 ; Always poll when writing first block (IRQs are generated for following blocks)
193 call WaitUntilReadyToTransferNextBlock
194 jc SHORT ReturnWithMemoryIOtransferErrorInAH
195
196 mov cx, [bp+MEMPIOVARS.wSectorsInBlock]
197 cmp [bp+MEMPIOVARS.bSectorsLeft], cl
198 jbe SHORT .WriteLastBlockToDrive
199
200ALIGN JUMP_ALIGN
201.WriteNextBlockToDrive:
202 call WriteSingleBlockFromDSSIToSectorAccessWindowInESDI
203 call WaitUntilReadyToTransferNextBlock
204 jc SHORT ReturnWithMemoryIOtransferErrorInAH
205
206 ; Increment number of successfully written WORDs
207 mov cx, [bp+MEMPIOVARS.wSectorsInBlock]
208 sub [bp+MEMPIOVARS.bSectorsLeft], cl
209 add [bp+MEMPIOVARS.bSectorsDone], cl
210 cmp [bp+MEMPIOVARS.bSectorsLeft], cl
211 ja SHORT .WriteNextBlockToDrive
212
213ALIGN JUMP_ALIGN
214.WriteLastBlockToDrive:
215 mov cl, [bp+MEMPIOVARS.bSectorsLeft]
216 push cx
217 ePUSH_T bx, CheckErrorsAfterTransferringLastMemoryMappedBlock
218 ; Fall to WriteSingleBlockFromDSSIToSectorAccessWindowInESDI
219
220;--------------------------------------------------------------------
221; WriteSingleBlockFromDSSIToSectorAccessWindowInESDI
222; Parameters:
223; CX: Number of sectors in block
224; DS:SI: Normalized ptr to source buffer
225; ES:DI: Ptr to Sector Access Window
226; Returns:
227; CX, DX: Zero
228; SI: Updated
229; Corrupts registers:
230; BX
231;--------------------------------------------------------------------
232ALIGN JUMP_ALIGN
233WriteSingleBlockFromDSSIToSectorAccessWindowInESDI:
234 mov bx, di
235 mov dx, cx
236 xor cx, cx
237ALIGN JUMP_ALIGN
238.WriteNextSector:
239 inc ch
240 rep movsw
241 mov di, bx ; Reset for next sector
242 dec dx
243 jnz SHORT .WriteNextSector
244 ret
245
246
247;--------------------------------------------------------------------
248; ReadSingleBlockFromSectorAccessWindowInDSSItoESDI
249; Parameters:
250; CX Number of sectors in full block or sectors in last partial block
251; ES:DI: Normalized ptr to buffer to receive data (destination)
252; DS:SI: Ptr to Sector Access Window (source)
253; Returns:
254; CX, DX: Zero
255; DI: Updated
256; Corrupts registers:
257; BX
258;--------------------------------------------------------------------
259ALIGN JUMP_ALIGN
260ReadSingleBlockFromSectorAccessWindowInDSSItoESDI:
261 mov bx, si
262 mov dx, cx
263 xor cx, cx
264ALIGN JUMP_ALIGN
265.ReadNextSector:
266 inc ch
267 rep movsw
268 mov si, bx ; Reset for next sector
269 dec dx
270 jnz SHORT .ReadNextSector
271 ret
272
273
274;--------------------------------------------------------------------
275; WaitUntilReadyToTransferNextBlock
276; Parameters:
277; SS:BP: Ptr to MEMPIOVARS
278; Returns:
279; AH: INT 13h Error Code
280; CF: Cleared if success, Set if error
281; Corrupts registers:
282; AL, BX, CX, DX
283;--------------------------------------------------------------------
284ALIGN JUMP_ALIGN
285WaitUntilReadyToTransferNextBlock:
286 push ds
287 push di
288 lds di, [bp+MEMPIOVARS.fpDPT] ; DPT now in DS:DI
289 call IdeWait_IRQorDRQ ; Always polls
290 pop di
291 pop ds
292 ret
293
Note: See TracBrowser for help on using the repository browser.