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

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

Changes to XTIDE Universal BIOS:

  • Added XT-CF transfer functions for 80188/80186 and later.
  • XT-CF drive detection timeouts are now the same as for other controllers.
File size: 13.3 KB
Line 
1; Project name : XTIDE Universal BIOS
2; Description : 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 PIOVARS ; Must not be larger than 9 bytes! See IDEPACK in RamVars.inc.
23 .wDataPort resb 2 ; 0-1, IDE Data Port
24 .fnXfer resb 2 ; 2-3, Offset to transfer function
25 .wSectorsInBlock resb 2 ; 4-5, Block size in sectors
26 .bSectorsLeft resb 1 ; 6, Sectors left to transfer
27 resb 1 ; 7, IDEPACK.bDeviceControl
28 .bSectorsDone resb 1 ; 8, Number of sectors xferred
29endstruc
30
31
32; Section containing code
33SECTION .text
34
35;--------------------------------------------------------------------
36; IdeTransfer_StartWithCommandInAL
37; Parameters:
38; AL: IDE command that was used to start the transfer
39; (all PIO read and write commands including Identify Device)
40; ES:SI: Ptr to normalized data buffer
41; DS:DI: Ptr to DPT (in RAMVARS segment)
42; SS:BP: Ptr to IDEPACK
43; Returns:
44; AH: INT 13h Error Code
45; CX: Number of successfully transferred sectors
46; CF: Cleared if success, Set if error
47; Corrupts registers:
48; AL, BX, DX, SI, ES
49;--------------------------------------------------------------------
50ALIGN JUMP_ALIGN
51IdeTransfer_StartWithCommandInAL:
52 ; Are we reading or writing?
53 test al, 16 ; Bit 4 is cleared on all the read commands but set on 3 of the 4 write commands
54 mov ah, [bp+IDEPACK.bSectorCount]
55 jnz SHORT WriteToDrive
56 cmp al, COMMAND_WRITE_MULTIPLE
57 je SHORT WriteToDrive
58 ; Fall to ReadFromDrive
59
60;--------------------------------------------------------------------
61; ReadFromDrive
62; Parameters:
63; AH: Number of sectors to transfer (1...128)
64; ES:SI: Normalized ptr to buffer to receive data
65; DS:DI: Ptr to DPT (in RAMVARS segment)
66; SS:BP: Ptr to PIOVARS
67; Returns:
68; DS:DI: Ptr to DPT (in RAMVARS segment)
69; AH: BIOS Error code
70; CX: Number of successfully transferred sectors
71; CF: 0 if transfer successful
72; 1 if any error
73; Corrupts registers:
74; AL, BX, DX, SI, ES
75;--------------------------------------------------------------------
76ReadFromDrive:
77 ; Prepare to read data to ESSI
78 mov bx, g_rgfnPioRead
79 call InitializePiovarsInSSBPwithSectorCountInAH
80
81 ; Wait until drive is ready to transfer
82 call IdeWait_IRQorDRQ ; Wait until ready to transfer
83 jc SHORT ReturnWithTransferErrorInAH
84 xchg si, di ; ES:DI now points buffer
85
86 mov cx, [bp+PIOVARS.wSectorsInBlock] ; Max 128
87
88ALIGN JUMP_ALIGN
89.ReadNextBlockFromDrive:
90 mov dx, [bp+PIOVARS.wDataPort]
91 cmp [bp+PIOVARS.bSectorsLeft], cl
92 jbe SHORT .ReadLastBlockFromDrive
93 call [bp+PIOVARS.fnXfer]
94
95 ; Wait until ready for next block and check for errors
96 xchg di, si ; DS:DI now points DPT
97 call IdeWait_IRQorDRQ ; Wait until ready to transfer
98 jc SHORT ReturnWithTransferErrorInAH
99 xchg si, di ; ES:DI now points buffer
100
101 ; Increment number of successfully read sectors
102 mov cx, [bp+PIOVARS.wSectorsInBlock]
103 sub [bp+PIOVARS.bSectorsLeft], cl
104 add [bp+PIOVARS.bSectorsDone], cl
105 jmp SHORT .ReadNextBlockFromDrive
106
107ALIGN JUMP_ALIGN
108.ReadLastBlockFromDrive:
109 mov cl, [bp+PIOVARS.bSectorsLeft] ; CH is already zero
110 push cx
111 call [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
112
113 ; Check for errors in last block
114 mov di, si ; DS:DI now points DPT
115CheckErrorsAfterTransferringLastBlock:
116 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_BSY)
117 call IdeWait_PollStatusFlagInBLwithTimeoutInBH
118 pop cx ; [bp+PIOVARS.bSectorsLeft]
119 jc SHORT ReturnWithTransferErrorInAH
120
121 ; All sectors succesfully transferred
122 add cx, [bp+PIOVARS.bSectorsDone] ; Never sets CF
123 ret
124
125 ; Return number of successfully read sectors
126ReturnWithTransferErrorInAH:
127%ifdef USE_386
128 movzx cx, [bp+PIOVARS.bSectorsDone]
129%else
130 mov cl, [bp+PIOVARS.bSectorsDone]
131 mov ch, 0 ; Preserve CF
132%endif
133 ret
134
135
136;--------------------------------------------------------------------
137; WriteToDrive
138; Parameters:
139; AH: Number of sectors to transfer (1...128)
140; DS:DI: Ptr to DPT (in RAMVARS segment)
141; ES:SI: Normalized ptr to buffer containing data
142; SS:BP: Ptr to PIOVARS
143; Returns:
144; AH: BIOS Error code
145; CX: Number of successfully transferred sectors
146; CF: 0 if transfer successful
147; 1 if any error
148; Corrupts registers:
149; AL, BX, DX, SI, ES
150;--------------------------------------------------------------------
151ALIGN JUMP_ALIGN
152WriteToDrive:
153 ; Prepare to write data from ESSI
154 mov bx, g_rgfnPioWrite
155 call InitializePiovarsInSSBPwithSectorCountInAH
156
157 ; Always poll when writing first block (IRQs are generated for following blocks)
158 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
159 call IdeWait_PollStatusFlagInBLwithTimeoutInBH
160 jc SHORT ReturnWithTransferErrorInAH
161
162 mov cx, [bp+PIOVARS.wSectorsInBlock] ; Max 128
163
164ALIGN JUMP_ALIGN
165.WriteNextBlockToDrive:
166 mov dx, [bp+PIOVARS.wDataPort]
167 cmp [bp+PIOVARS.bSectorsLeft], cl
168 jbe SHORT .WriteLastBlockToDrive
169 call [bp+PIOVARS.fnXfer]
170
171 ; Wait until ready for next block and check for errors
172 call IdeWait_IRQorDRQ ; Wait until ready to transfer
173 jc SHORT ReturnWithTransferErrorInAH
174
175 ; Increment number of successfully written sectors
176 mov cx, [bp+PIOVARS.wSectorsInBlock]
177 sub [bp+PIOVARS.bSectorsLeft], cl
178 add [bp+PIOVARS.bSectorsDone], cl
179 jmp SHORT .WriteNextBlockToDrive
180
181ALIGN JUMP_ALIGN
182.WriteLastBlockToDrive:
183 mov cl, [bp+PIOVARS.bSectorsLeft] ; CH is already zero
184 push cx
185%ifdef USE_186
186 push CheckErrorsAfterTransferringLastBlock
187 jmp [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
188%else
189 call [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
190 jmp SHORT CheckErrorsAfterTransferringLastBlock
191%endif
192
193
194;--------------------------------------------------------------------
195; InitializePiovarsInSSBPwithSectorCountInAH
196; Parameters:
197; AH: Number of sectors to transfer (1...128)
198; BX: Offset to transfer function lookup table
199; DS:DI: Ptr to DPT (in RAMVARS segment)
200; SS:BP: Ptr to PIOVARS
201; Returns:
202; Nothing
203; Corrupts registers:
204; AX, BX, DX
205;--------------------------------------------------------------------
206ALIGN JUMP_ALIGN
207InitializePiovarsInSSBPwithSectorCountInAH:
208 ; Store sizes
209 mov [bp+PIOVARS.bSectorsLeft], ah
210 eMOVZX ax, [di+DPT_ATA.bBlockSize]
211 mov [bp+PIOVARS.wSectorsInBlock], ax
212 mov [bp+PIOVARS.bSectorsDone], ah ; Zero
213
214 ; Get transfer function based on bus type
215 xchg ax, bx ; Lookup table offset to AX
216 mov bl, [di+DPT.bIdevarsOffset] ; CS:BX now points to IDEVARS
217 mov dx, [cs:bx+IDEVARS.wPort] ; Load IDE Data port address
218 mov bl, [di+DPT_ATA.bDevice]
219 add bx, ax
220
221 mov [bp+PIOVARS.wDataPort], dx
222 mov ax, [cs:bx] ; Load offset to transfer function
223 mov [bp+PIOVARS.fnXfer], ax
224 ret
225
226
227;--------------------------------------------------------------------
228; ReadBlockFromXtideRev1 XTIDE rev 1
229; ReadBlockFromXtideRev2 XTIDE rev 2 or rev 1 with swapped A0 and A3 (chuck-mod)
230; ReadBlockFrom8bitDataPort CF-XT when using 8-bit PIO
231; ReadBlockFrom16bitDataPort Normal 16-bit IDE
232; ReadBlockFrom32bitDataPort VLB/PCI 32-bit IDE
233; Parameters:
234; CX: Block size in 512 byte sectors
235; DX: IDE Data port address
236; ES:DI: Normalized ptr to buffer to receive data
237; Returns:
238; Nothing
239; Corrupts registers:
240; AX, BX, CX
241;--------------------------------------------------------------------
242%ifdef MODULE_8BIT_IDE
243
244 ALIGN JUMP_ALIGN
245 ReadBlockFromXtideRev1:
246 UNROLL_SECTORS_IN_CX_TO_QWORDS
247 mov bl, 8 ; Bit mask for toggling data low/high reg
248 ALIGN JUMP_ALIGN
249 .InswLoop:
250 XTIDE_INSW
251 XTIDE_INSW
252 XTIDE_INSW
253 XTIDE_INSW
254 loop .InswLoop
255 ret
256
257 ;--------------------------------------------------------------------
258 %ifndef USE_186 ; 8086/8088 compatible WORD read
259 ALIGN JUMP_ALIGN
260 ReadBlockFromXtideRev2:
261 UNROLL_SECTORS_IN_CX_TO_QWORDS
262 ALIGN JUMP_ALIGN
263 .ReadNextQword:
264 in ax, dx ; Read 1st WORD
265 stosw ; Store 1st WORD to [ES:DI]
266 in ax, dx
267 stosw ; 2nd
268 in ax, dx
269 stosw ; 3rd
270 in ax, dx
271 stosw ; 4th
272 loop .ReadNextQword
273 ret
274 %endif
275
276 ;--------------------------------------------------------------------
277 %ifdef USE_186
278 ALIGN JUMP_ALIGN
279 ReadBlockFrom8bitDataPort:
280 shl cx, 9 ; Sectors to BYTEs
281 rep insb
282 ret
283
284 %else ; If 8088/8086
285 ALIGN JUMP_ALIGN
286 ReadBlockFrom8bitDataPort:
287 UNROLL_SECTORS_IN_CX_TO_DWORDS
288 ALIGN JUMP_ALIGN
289 .ReadNextDword:
290 in al, dx ; Read 1st BYTE
291 stosb ; Store 1st BYTE to [ES:DI]
292 in al, dx
293 stosb
294
295 in al, dx
296 stosb
297 in al, dx
298 stosb
299 loop .ReadNextDword
300 ret
301 %endif
302%endif ; MODULE_8BIT_IDE
303
304;--------------------------------------------------------------------
305%ifdef USE_186
306 ALIGN JUMP_ALIGN
307 ReadBlockFrom16bitDataPort:
308 xchg cl, ch ; Sectors to WORDs
309 rep insw
310 ret
311%endif
312
313;--------------------------------------------------------------------
314%ifdef USE_AT
315 ALIGN JUMP_ALIGN
316 ReadBlockFrom32bitDataPort:
317 shl cx, 7 ; Sectors to DWORDs
318 rep
319 db 66h ; Override operand size to 32-bit
320 db 6Dh ; INSW/INSD
321 ret
322%endif
323
324
325;--------------------------------------------------------------------
326; WriteBlockToXtideRev1 XTIDE rev 1
327; WriteBlockToXtideRev2 XTIDE rev 2 or rev 1 with swapped A0 and A3 (chuck-mod)
328; WriteBlockTo8bitDataPort XT-CF when using 8-bit PIO
329; WriteBlockTo16bitDataPort Normal 16-bit IDE
330; WriteBlockTo32bitDataPort VLB/PCI 32-bit IDE
331; Parameters:
332; CX: Block size in 512-byte sectors
333; DX: IDE Data port address
334; ES:SI: Normalized ptr to buffer containing data
335; Returns:
336; Nothing
337; Corrupts registers:
338; AX, BX, CX, DX
339;--------------------------------------------------------------------
340%ifdef MODULE_8BIT_IDE
341
342 ALIGN JUMP_ALIGN
343 WriteBlockToXtideRev1:
344 push ds
345 UNROLL_SECTORS_IN_CX_TO_QWORDS
346 mov bl, 8 ; Bit mask for toggling data low/high reg
347 push es ; Copy ES...
348 pop ds ; ...to DS
349 ALIGN JUMP_ALIGN
350 .OutswLoop:
351 XTIDE_OUTSW
352 XTIDE_OUTSW
353 XTIDE_OUTSW
354 XTIDE_OUTSW
355 loop .OutswLoop
356 pop ds
357 ret
358
359 ;--------------------------------------------------------------------
360 ALIGN JUMP_ALIGN
361 WriteBlockToXtideRev2:
362 UNROLL_SECTORS_IN_CX_TO_QWORDS
363 push ds
364 push es ; Copy ES...
365 pop ds ; ...to DS
366 ALIGN JUMP_ALIGN
367 .WriteNextQword:
368 XTIDE_MOD_OUTSW
369 XTIDE_MOD_OUTSW
370 XTIDE_MOD_OUTSW
371 XTIDE_MOD_OUTSW
372 loop .WriteNextQword
373 pop ds
374 ret
375
376 ;--------------------------------------------------------------------
377 %ifdef USE_186
378 ALIGN JUMP_ALIGN
379 WriteBlockTo8bitDataPort:
380 shl cx, 9 ; Sectors to BYTEs
381 es ; Source is ES segment
382 rep outsb
383 ret
384
385 %else ; If 8088/8086
386 ALIGN JUMP_ALIGN
387 WriteBlockTo8bitDataPort:
388 UNROLL_SECTORS_IN_CX_TO_DWORDS
389 push ds
390 push es
391 pop ds
392 ALIGN JUMP_ALIGN
393 .WriteNextDword:
394 lodsb ; Load 1st BYTE from [DS:SI]
395 out dx, al ; Write 1st BYTE
396 lodsb
397 out dx, al
398
399 lodsb
400 out dx, al
401 lodsb
402 out dx, al
403 loop .WriteNextDword
404 pop ds
405 ret
406 %endif
407%endif ; MODULE_8BIT_IDE
408
409;--------------------------------------------------------------------
410%ifdef USE_AT
411ALIGN JUMP_ALIGN
412WriteBlockTo16bitDataPort:
413 xchg cl, ch ; Sectors to WORDs
414 es ; Source is ES segment
415 rep outsw
416 ret
417
418;--------------------------------------------------------------------
419ALIGN JUMP_ALIGN
420WriteBlockTo32bitDataPort:
421 shl cx, 7 ; Sectors to DWORDs
422 es ; Source is ES segment
423 rep
424 db 66h ; Override operand size to 32-bit
425 db 6Fh ; OUTSW/OUTSD
426 ret
427%endif ; USE_AT
428
429
430
431; Lookup tables to get transfer function based on bus type
432ALIGN WORD_ALIGN
433g_rgfnPioRead:
434%ifdef MODULE_8BIT_IDE
435 dw 0 ; 0, DEVICE_8BIT_JRIDE_ISA
436 dw ReadBlockFrom8bitDataPort ; 1, DEVICE_8BIT_XTCF
437 %ifdef USE_186
438 dw ReadBlockFrom16bitDataPort ; 2, DEVICE_8BIT_XTIDE_REV2
439 %else
440 dw ReadBlockFromXtideRev2 ; 2, DEVICE_8BIT_XTIDE_REV2
441 %endif
442 dw ReadBlockFromXtideRev1 ; 3, DEVICE_XTIDE_REV1
443
444%else
445 times COUNT_OF_8BIT_IDE_DEVICES dw 0
446%endif
447%ifdef USE_AT
448 dw ReadBlockFrom16bitDataPort ; 4, DEVICE_16BIT_ATA
449 dw ReadBlockFrom32bitDataPort ; 5, DEVICE_32BIT_ATA
450%endif
451
452
453g_rgfnPioWrite:
454%ifdef MODULE_8BIT_IDE
455 dw 0 ; 0, DEVICE_8BIT_JRIDE_ISA
456 dw WriteBlockTo8bitDataPort ; 1, DEVICE_8BIT_XTCF
457 dw WriteBlockToXtideRev2 ; 2, DEVICE_XTIDE_REV2
458 dw WriteBlockToXtideRev1 ; 3, DEVICE_XTIDE_REV1
459
460%else
461 times COUNT_OF_8BIT_IDE_DEVICES dw 0
462%endif
463%ifdef USE_AT
464 dw WriteBlockTo16bitDataPort ; 4, DEVICE_16BIT_ATA
465 dw WriteBlockTo32bitDataPort ; 5, DEVICE_32BIT_ATA
466%endif
Note: See TracBrowser for help on using the repository browser.