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

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

Changes to XTIDE Universal BIOS:

  • ATA ID validation now compares heads to correct maximum number of heads.
  • Added XTCF 8-bit mode transfer functions.
File size: 12.9 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; ReadBlockFrom16bitDataPort Normal 16-bit IDE
231; ReadBlockFrom32bitDataPort VLB/PCI 32-bit IDE
232; Parameters:
233; CX: Block size in 512 byte sectors
234; DX: IDE Data port address
235; ES:DI: Normalized ptr to buffer to receive data
236; Returns:
237; Nothing
238; Corrupts registers:
239; AX, BX, CX
240;--------------------------------------------------------------------
241%ifdef MODULE_8BIT_IDE
242
243ALIGN JUMP_ALIGN
244ReadBlockFromXtideRev1:
245 UNROLL_SECTORS_IN_CX_TO_QWORDS
246 mov bl, 8 ; Bit mask for toggling data low/high reg
247ALIGN JUMP_ALIGN
248.InswLoop:
249 XTIDE_INSW
250 XTIDE_INSW
251 XTIDE_INSW
252 XTIDE_INSW
253 loop .InswLoop
254 ret
255
256;--------------------------------------------------------------------
257%ifndef USE_186 ; 8086/8088 compatible WORD read
258ALIGN JUMP_ALIGN
259ReadBlockFromXtideRev2:
260 UNROLL_SECTORS_IN_CX_TO_QWORDS
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
277ReadBlockFromXTCF:
278 UNROLL_SECTORS_IN_CX_TO_DWORDS
279ALIGN JUMP_ALIGN
280.ReadNextDword:
281 in al, dx ; Read 1st BYTE
282 stosb ; Store 1st BYTE to [ES:DI]
283 in al, dx
284 stosb
285
286 in al, dx
287 stosb
288 in al, dx
289 stosb
290 loop .ReadNextDword
291 ret
292
293%endif ; MODULE_8BIT_IDE
294
295;--------------------------------------------------------------------
296%ifdef USE_186
297ALIGN JUMP_ALIGN
298ReadBlockFrom16bitDataPort:
299 xchg cl, ch ; Sectors to WORDs
300 rep
301 db 6Dh ; INSW (we want this in XT build)
302 ret
303%endif
304
305;--------------------------------------------------------------------
306%ifdef USE_AT
307ALIGN JUMP_ALIGN
308ReadBlockFrom32bitDataPort:
309 db 0C1h ; SHL
310 db 0E1h ; CX
311 db 7 ; 7 (Sectors to DWORDs)
312 rep
313 db 66h ; Override operand size to 32-bit
314 db 6Dh ; INSW/INSD
315 ret
316%endif
317
318
319;--------------------------------------------------------------------
320; WriteBlockToXtideRev1 XTIDE rev 1
321; WriteBlockToXtideRev2 XTIDE rev 2 or rev 1 with swapped A0 and A3 (chuck-mod)
322; WriteBlockToFastXtide Fast XTIDE (CPLD v2 project)
323; WriteBlockTo16bitDataPort Normal 16-bit IDE
324; WriteBlockTo32bitDataPort VLB/PCI 32-bit IDE
325; Parameters:
326; CX: Block size in 512-byte sectors
327; DX: IDE Data port address
328; ES:SI: Normalized ptr to buffer containing data
329; Returns:
330; Nothing
331; Corrupts registers:
332; AX, BX, CX, DX
333;--------------------------------------------------------------------
334%ifdef MODULE_8BIT_IDE
335
336ALIGN JUMP_ALIGN
337WriteBlockToXtideRev1:
338 push ds
339 UNROLL_SECTORS_IN_CX_TO_QWORDS
340 mov bl, 8 ; Bit mask for toggling data low/high reg
341 push es ; Copy ES...
342 pop ds ; ...to DS
343ALIGN JUMP_ALIGN
344.OutswLoop:
345 XTIDE_OUTSW
346 XTIDE_OUTSW
347 XTIDE_OUTSW
348 XTIDE_OUTSW
349 loop .OutswLoop
350 pop ds
351 ret
352
353;--------------------------------------------------------------------
354ALIGN JUMP_ALIGN
355WriteBlockToXtideRev2:
356 UNROLL_SECTORS_IN_CX_TO_QWORDS
357 push ds
358 push es ; Copy ES...
359 pop ds ; ...to DS
360ALIGN JUMP_ALIGN
361.WriteNextQword:
362 XTIDE_MOD_OUTSW
363 XTIDE_MOD_OUTSW
364 XTIDE_MOD_OUTSW
365 XTIDE_MOD_OUTSW
366 loop .WriteNextQword
367 pop ds
368 ret
369
370;--------------------------------------------------------------------
371ALIGN JUMP_ALIGN
372WriteBlockToXTCF:
373 UNROLL_SECTORS_IN_CX_TO_DWORDS
374 push ds
375 push es
376 pop ds
377ALIGN JUMP_ALIGN
378.WriteNextDword:
379 lodsb ; Load 1st BYTE from [DS:SI]
380 out dx, al ; Write 1st BYTE
381 lodsb
382 out dx, al
383
384 lodsb
385 out dx, al
386 lodsb
387 out dx, al
388 loop .WriteNextDword
389 pop ds
390 ret
391%endif ; MODULE_8BIT_IDE
392
393
394;--------------------------------------------------------------------
395%ifdef USE_AT
396ALIGN JUMP_ALIGN
397WriteBlockTo16bitDataPort:
398 xchg cl, ch ; Sectors to WORDs
399 es ; Source is ES segment
400 rep
401 db 6Fh ; OUTSW (we want this in XT build)
402 ret
403
404;--------------------------------------------------------------------
405ALIGN JUMP_ALIGN
406WriteBlockTo32bitDataPort:
407 db 0C1h ; SHL
408 db 0E1h ; CX
409 db 7 ; 7 (Sectors to DWORDs)
410 es ; Source is ES segment
411 rep
412 db 66h ; Override operand size to 32-bit
413 db 6Fh ; OUTSW/OUTSD
414 ret
415%endif ; USE_AT
416
417
418
419; Lookup tables to get transfer function based on bus type
420ALIGN WORD_ALIGN
421g_rgfnPioRead:
422%ifdef MODULE_8BIT_IDE
423 dw 0 ; 0, DEVICE_8BIT_JRIDE_ISA
424 dw ReadBlockFromXTCF ; 1, DEVICE_8BIT_XTCF
425 %ifdef USE_186
426 dw ReadBlockFrom16bitDataPort ; 2, DEVICE_8BIT_XTIDE_REV2
427 %else
428 dw ReadBlockFromXtideRev2 ; 2, DEVICE_8BIT_XTIDE_REV2
429 %endif
430 dw ReadBlockFromXtideRev1 ; 3, DEVICE_XTIDE_REV1
431
432%else
433 times COUNT_OF_8BIT_IDE_DEVICES dw 0
434%endif
435%ifdef USE_AT
436 dw ReadBlockFrom16bitDataPort ; 4, DEVICE_16BIT_ATA
437 dw ReadBlockFrom32bitDataPort ; 5, DEVICE_32BIT_ATA
438%endif
439
440
441g_rgfnPioWrite:
442%ifdef MODULE_8BIT_IDE
443 dw 0 ; 0, DEVICE_8BIT_JRIDE_ISA
444 dw WriteBlockToXTCF ; 1, DEVICE_8BIT_XTCF
445 dw WriteBlockToXtideRev2 ; 2, DEVICE_XTIDE_REV2
446 dw WriteBlockToXtideRev1 ; 3, DEVICE_XTIDE_REV1
447
448%else
449 times COUNT_OF_8BIT_IDE_DEVICES dw 0
450%endif
451%ifdef USE_AT
452 dw WriteBlockTo16bitDataPort ; 4, DEVICE_16BIT_ATA
453 dw WriteBlockTo32bitDataPort ; 5, DEVICE_32BIT_ATA
454%endif
Note: See TracBrowser for help on using the repository browser.