source: xtideuniversalbios/trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeTransfer.asm@ 320

Last change on this file since 320 was 294, checked in by krille_n_@…, 13 years ago

Commit 2/2 (BIOS):

  • Fixed a bug in AH1h_HStatus.asm.
  • Minor optimizations.
  • Fixed spelling and did some cleaning.
File size: 11.2 KB
Line 
1; Project name : XTIDE Universal BIOS
2; Description : IDE Device transfer functions.
3
4; Structure containing variables for PIO transfer functions.
5; This struct must not be larger than IDEPACK without INTPACK.
6struc PIOVARS
7 .wWordsInBlock resb 2 ; 0, Block size in WORDs
8 .wWordsLeft resb 2 ; 2, WORDs left to transfer
9 .wWordsDone resb 2 ; 4, Number of sectors xferred
10 resb 1 ; 6,
11 resb 1 ; 7, IDEPACK.bDeviceControl
12 .wDataPort resb 2 ; 8, IDE Data Port
13 .fnXfer resb 2 ; 10, Offset to transfer function
14endstruc
15
16
17; Section containing code
18SECTION .text
19
20;--------------------------------------------------------------------
21; IdeTransfer_StartWithCommandInAL
22; Parameters:
23; AL: IDE command that was used to start the transfer
24; (all PIO read and write commands including Identify Device)
25; ES:SI: Ptr to normalized data buffer
26; DS:DI: Ptr to DPT (in RAMVARS segment)
27; SS:BP: Ptr to IDEPACK
28; Returns:
29; AH: INT 13h Error Code
30; CX: Number of successfully transferred sectors
31; CF: Cleared if success, Set if error
32; Corrupts registers:
33; AL, BX, DX, SI, ES
34;--------------------------------------------------------------------
35ALIGN JUMP_ALIGN
36IdeTransfer_StartWithCommandInAL:
37 ; Are we reading or writing?
38 test al, 16 ; Bit 4 is cleared on all the read commands but set on 3 of the 4 write commands
39 mov ah, [bp+IDEPACK.bSectorCount]
40 jnz SHORT WriteToDrive
41 cmp al, COMMAND_WRITE_MULTIPLE
42 je SHORT WriteToDrive
43 ; Fall to ReadFromDrive
44
45;--------------------------------------------------------------------
46; ReadFromDrive
47; Parameters:
48; AH: Number of sectors to transfer (1...128)
49; ES:SI: Normalized ptr to buffer to receive data
50; DS:DI: Ptr to DPT (in RAMVARS segment)
51; SS:BP: Ptr to PIOVARS
52; Returns:
53; DS:DI: Ptr to DPT (in RAMVARS segment)
54; AH: BIOS Error code
55; CX: Number of successfully transferred sectors
56; CF: 0 if transfer successful
57; 1 if any error
58; Corrupts registers:
59; AL, BX, DX, SI, ES
60;--------------------------------------------------------------------
61ReadFromDrive:
62 ; Prepare to read data to ESSI
63 mov bx, g_rgfnPioRead
64 call InitializePiovarsInSSBPwithSectorCountInAH
65
66 ; Wait until drive is ready to transfer
67 call IdeWait_IRQorDRQ ; Wait until ready to transfer
68 jc SHORT ReturnWithTransferErrorInAH
69 xchg si, di ; ES:DI now points buffer
70
71 mov cx, [bp+PIOVARS.wWordsInBlock]
72
73ALIGN JUMP_ALIGN
74.ReadNextBlockFromDrive:
75 mov dx, [bp+PIOVARS.wDataPort]
76 cmp [bp+PIOVARS.wWordsLeft], cx
77 jbe SHORT .ReadLastBlockFromDrive
78 call [bp+PIOVARS.fnXfer]
79
80 ; Wait until ready for next block and check for errors
81 xchg di, si ; DS:DI now points DPT
82 call IdeWait_IRQorDRQ ; Wait until ready to transfer
83 jc SHORT ReturnWithTransferErrorInAH
84 xchg si, di ; ES:DI now points buffer
85
86 ; Increment number of successfully read WORDs
87 mov cx, [bp+PIOVARS.wWordsInBlock]
88 sub [bp+PIOVARS.wWordsLeft], cx
89 add [bp+PIOVARS.wWordsDone], cx
90 jmp SHORT .ReadNextBlockFromDrive
91
92ALIGN JUMP_ALIGN
93.ReadLastBlockFromDrive:
94 mov cx, [bp+PIOVARS.wWordsLeft]
95 call [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
96
97 ; Check for errors in last block
98 mov di, si ; DS:DI now points DPT
99CheckErrorsAfterTransferringLastBlock:
100 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRDY)
101 call IdeWait_PollStatusFlagInBLwithTimeoutInBH
102
103 ; Return number of successfully read sectors
104ReturnWithTransferErrorInAH:
105 mov cx, [bp+PIOVARS.wWordsDone]
106 jc SHORT .ConvertTransferredWordsInCXtoSectors
107 add cx, [bp+PIOVARS.wWordsLeft] ; Never sets CF
108.ConvertTransferredWordsInCXtoSectors:
109 xchg cl, ch
110 ret
111
112
113;--------------------------------------------------------------------
114; WriteToDrive
115; Parameters:
116; AH: Number of sectors to transfer (1...128)
117; DS:DI: Ptr to DPT (in RAMVARS segment)
118; ES:SI: Normalized ptr to buffer containing data
119; SS:BP: Ptr to PIOVARS
120; Returns:
121; AH: BIOS Error code
122; CX: Number of successfully transferred sectors
123; CF: 0 if transfer successful
124; 1 if any error
125; Corrupts registers:
126; AL, BX, DX, SI, ES
127;--------------------------------------------------------------------
128ALIGN JUMP_ALIGN
129WriteToDrive:
130 ; Prepare to write data from ESSI
131 mov bx, g_rgfnPioWrite
132 call InitializePiovarsInSSBPwithSectorCountInAH
133
134 ; Always poll when writing first block (IRQs are generated for following blocks)
135 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
136 call IdeWait_PollStatusFlagInBLwithTimeoutInBH
137 jc SHORT ReturnWithTransferErrorInAH
138
139 mov cx, [bp+PIOVARS.wWordsInBlock]
140
141ALIGN JUMP_ALIGN
142.WriteNextBlockToDrive:
143 mov dx, [bp+PIOVARS.wDataPort]
144 cmp [bp+PIOVARS.wWordsLeft], cx
145 jbe SHORT .WriteLastBlockToDrive
146 call [bp+PIOVARS.fnXfer]
147
148 ; Wait until ready for next block and check for errors
149 call IdeWait_IRQorDRQ ; Wait until ready to transfer
150 jc SHORT ReturnWithTransferErrorInAH
151
152 ; Increment number of successfully written WORDs
153 mov cx, [bp+PIOVARS.wWordsInBlock]
154 sub [bp+PIOVARS.wWordsLeft], cx
155 add [bp+PIOVARS.wWordsDone], cx
156 jmp SHORT .WriteNextBlockToDrive
157
158ALIGN JUMP_ALIGN
159.WriteLastBlockToDrive:
160 mov cx, [bp+PIOVARS.wWordsLeft]
161%ifdef USE_186
162 push CheckErrorsAfterTransferringLastBlock
163 jmp [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
164%else
165 call [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
166 jmp SHORT CheckErrorsAfterTransferringLastBlock
167%endif
168
169
170;--------------------------------------------------------------------
171; InitializePiovarsInSSBPwithSectorCountInAH
172; Parameters:
173; AH: Number of sectors to transfer (1...128)
174; BX: Offset to transfer function lookup table
175; DS:DI: Ptr to DPT (in RAMVARS segment)
176; SS:BP: Ptr to PIOVARS
177; Returns:
178; Nothing
179; Corrupts registers:
180; AX, BX, DX
181;--------------------------------------------------------------------
182ALIGN JUMP_ALIGN
183InitializePiovarsInSSBPwithSectorCountInAH:
184 ; Store sizes
185 xor al, al
186 mov [bp+PIOVARS.wWordsLeft], ax
187 mov ah, [di+DPT_ATA.bSetBlock]
188 mov [bp+PIOVARS.wWordsInBlock], ax
189 cbw
190 mov [bp+PIOVARS.wWordsDone], ax ; Zero
191
192 ; Get transfer function based on bus type
193 xchg ax, bx ; Lookup table offset to AX
194 mov bl, [di+DPT.bIdevarsOffset] ; CS:BX now points to IDEVARS
195 mov dx, [cs:bx+IDEVARS.wPort] ; Load IDE Data port address
196 mov bl, [cs:bx+IDEVARS.bDevice] ; Load device type to BX
197 add bx, ax
198 mov [bp+PIOVARS.wDataPort], dx
199 mov ax, [cs:bx] ; Load offset to transfer function
200 mov [bp+PIOVARS.fnXfer], ax
201 ret
202
203
204;--------------------------------------------------------------------
205; DualByteReadForXtide Dual port 8-bit XTIDE PIO read transfer
206; SingleByteRead Single port 8-bit PIO read transfer
207; WordReadForXTIDEmod 8088/8086 compatible 16-bit IDE PIO read transfer
208; WordReadForXTplusAndAT Normal 16-bit IDE PIO read transfer
209; DWordRead VLB/PCI 32-bit IDE PIO read transfer
210; Parameters:
211; CX: Block size in WORDs
212; DX: IDE Data port address
213; ES:DI: Normalized ptr to buffer to receive data
214; Returns:
215; Nothing
216; Corrupts registers:
217; AX, BX, CX
218;--------------------------------------------------------------------
219ALIGN JUMP_ALIGN
220DualByteReadForXtide:
221 eSHR_IM cx, 2 ; Loop unrolling
222 mov bx, 8 ; Bit mask for toggling data low/high reg
223ALIGN JUMP_ALIGN
224.InswLoop:
225 XTIDE_INSW
226 XTIDE_INSW
227 XTIDE_INSW
228 XTIDE_INSW
229 loop .InswLoop
230 ret
231
232;----
233ALIGN JUMP_ALIGN
234SingleByteRead:
235%ifdef USE_186 ; INS instruction available
236 shl cx, 1 ; WORD count to BYTE count
237 dec cx ; Fix for CX overflowing on a 128 sector transfer
238 insb
239 rep insb
240%else ; If 8088/8086
241 shr cx, 1 ; WORD count to DWORD count
242ALIGN JUMP_ALIGN
243.InsdLoop:
244 in al, dx
245 stosb ; Store to [ES:DI]
246 in al, dx
247 stosb
248 in al, dx
249 stosb
250 in al, dx
251 stosb
252 loop .InsdLoop
253%endif
254 ret
255
256;----
257%ifndef USE_186
258ALIGN JUMP_ALIGN
259WordReadForXTIDEmod:
260 times 2 shr cx, 1 ; WORD count to QWORD count
261ALIGN JUMP_ALIGN
262.ReadNextQword:
263 in ax, dx ; Read 1st WORD
264 stosw ; Store 1st WORD to [ES:DI]
265 in ax, dx
266 stosw ; 2nd
267 in ax, dx
268 stosw ; 3rd
269 in ax, dx
270 stosw ; 4th
271 loop .ReadNextQword
272 ret
273%endif
274
275;----
276ALIGN JUMP_ALIGN
277WordReadForXTplusAndAT:
278 rep
279 db 6Dh ; INSW (we want this in XT build)
280 ret
281
282;----
283ALIGN JUMP_ALIGN
284DWordRead:
285 shr cx, 1 ; WORD count to DWORD count
286 rep
287 db 66h ; Override operand size to 32-bit
288 db 6Dh ; INSW/INSD
289 ret
290
291
292;--------------------------------------------------------------------
293; DualByteWriteForXtide Dual port 8-bit XTIDE PIO write transfer
294; SingleByteWrite Single port 8-bit PIO write transfer
295; WordWriteForXTIDEmod 8088/8086 compatible 16-bit IDE PIO read transfer
296; WordWrite Normal 16-bit IDE PIO write transfer
297; DWordWrite VLB/PCI 32-bit IDE PIO write transfer
298; Parameters:
299; CX: Block size in WORDs
300; DX: IDE Data port address
301; ES:SI: Normalized ptr to buffer containing data
302; Returns:
303; Nothing
304; Corrupts registers:
305; AX, CX
306;--------------------------------------------------------------------
307ALIGN JUMP_ALIGN
308DualByteWriteForXtide:
309 push ds
310 push bx
311 eSHR_IM cx, 2 ; Loop unrolling
312 mov bx, 8 ; Bit mask for toggling data low/high reg
313 push es ; Copy ES...
314 pop ds ; ...to DS
315ALIGN JUMP_ALIGN
316.OutswLoop:
317 XTIDE_OUTSW
318 XTIDE_OUTSW
319 XTIDE_OUTSW
320 XTIDE_OUTSW
321 loop .OutswLoop
322 pop bx
323 pop ds
324 ret
325
326;----
327ALIGN JUMP_ALIGN
328SingleByteWrite:
329%ifdef USE_186 ; OUTS instruction available
330 shl cx, 1 ; WORD count to BYTE count
331 dec cx ; Fix for CX overflowing on a 128 sector transfer
332 es outsb ; Source is ES segment
333 rep es outsb
334%else ; If 8088/8086
335 shr cx, 1 ; WORD count to DWORD count
336 push ds ; Store DS
337 push es ; Copy ES...
338 pop ds ; ...to DS
339ALIGN JUMP_ALIGN
340.OutsdLoop:
341 lodsb ; Load from [DS:SI] to AL
342 out dx, al
343 lodsb
344 out dx, al
345 lodsb
346 out dx, al
347 lodsb
348 out dx, al
349 loop .OutsdLoop
350 pop ds ; Restore DS
351%endif
352 ret
353
354;---
355ALIGN JUMP_ALIGN
356WordWriteForXTIDEmod:
357 push ds
358 eSHR_IM cx, 2 ; Loop unrolling
359 push es ; Copy ES...
360 pop ds ; ...to DS
361ALIGN JUMP_ALIGN
362.WriteNextQword:
363 XTIDE_MOD_OUTSW
364 XTIDE_MOD_OUTSW
365 XTIDE_MOD_OUTSW
366 XTIDE_MOD_OUTSW
367 loop .WriteNextQword
368 pop ds
369 ret
370
371;----
372ALIGN JUMP_ALIGN
373WordWrite:
374 es ; Source is ES segment
375 rep
376 db 6Fh ; OUTSW (we want this in XT build)
377 ret
378
379ALIGN JUMP_ALIGN
380DWordWrite:
381 shr cx, 1 ; WORD count to DWORD count
382 es ; Source is ES segment
383 rep
384 db 66h ; Override operand size to 32-bit
385 db 6Fh ; OUTSW/OUTSD
386 ret
387
388
389; Lookup tables to get transfer function based on bus type
390ALIGN WORD_ALIGN
391g_rgfnPioRead:
392 dw DualByteReadForXtide ; DEVICE_8BIT_DUAL_PORT_XTIDE
393%ifdef USE_186
394 dw WordReadForXTplusAndAT ; DEVICE_XTIDE_WITH_REVERSED_A3_AND_A0
395%else
396 dw WordReadForXTIDEmod
397%endif
398 dw SingleByteRead ; DEVICE_8BIT_SINGLE_PORT
399 dw WordReadForXTplusAndAT ; DEVICE_16BIT_ATA
400 dw DWordRead ; DEVICE_32BIT_ATA
401
402g_rgfnPioWrite:
403 dw DualByteWriteForXtide ; DEVICE_8BIT_DUAL_PORT_XTIDE
404 dw WordWriteForXTIDEmod ; DEVICE_XTIDE_WITH_REVERSED_A3_AND_A0
405 dw SingleByteWrite ; DEVICE_8BIT_SINGLE_PORT
406 dw WordWrite ; DEVICE_16BIT_ATA
407 dw DWordWrite ; DEVICE_32BIT_ATA
Note: See TracBrowser for help on using the repository browser.