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

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

Changes to XTIDE Universal BIOS:

  • Moved 8-bit device support to MODULE_8BIT_IDE.
  • JR-IDE/ISA support requires a lot less bytes.
  • AT builds now always use full operating mode.
File size: 12.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
23 .wDataPort resb 2 ; 0, IDE Data Port
24 .fnXfer resb 2 ; 2, Offset to transfer function
25 .wSectorsInBlock resb 2 ; 4, 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 call [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
111
112 ; Check for errors in last block
113 mov di, si ; DS:DI now points DPT
114CheckErrorsAfterTransferringLastBlock:
115 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRDY)
116 call IdeWait_PollStatusFlagInBLwithTimeoutInBH
117
118 ; Return number of successfully read sectors
119ReturnWithTransferErrorInAH:
120%ifdef USE_386
121 movzx cx, [bp+PIOVARS.bSectorsDone]
122%else
123 mov cl, [bp+PIOVARS.bSectorsDone]
124 mov ch, 0 ; Preserve CF
125%endif
126 ret
127
128
129;--------------------------------------------------------------------
130; WriteToDrive
131; Parameters:
132; AH: Number of sectors to transfer (1...128)
133; DS:DI: Ptr to DPT (in RAMVARS segment)
134; ES:SI: Normalized ptr to buffer containing data
135; SS:BP: Ptr to PIOVARS
136; Returns:
137; AH: BIOS Error code
138; CX: Number of successfully transferred sectors
139; CF: 0 if transfer successful
140; 1 if any error
141; Corrupts registers:
142; AL, BX, DX, SI, ES
143;--------------------------------------------------------------------
144ALIGN JUMP_ALIGN
145WriteToDrive:
146 ; Prepare to write data from ESSI
147 mov bx, g_rgfnPioWrite
148 call InitializePiovarsInSSBPwithSectorCountInAH
149
150 ; Always poll when writing first block (IRQs are generated for following blocks)
151 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
152 call IdeWait_PollStatusFlagInBLwithTimeoutInBH
153 jc SHORT ReturnWithTransferErrorInAH
154
155 mov cx, [bp+PIOVARS.wSectorsInBlock] ; Max 128
156
157ALIGN JUMP_ALIGN
158.WriteNextBlockToDrive:
159 mov dx, [bp+PIOVARS.wDataPort]
160 cmp [bp+PIOVARS.bSectorsLeft], cl
161 jbe SHORT .WriteLastBlockToDrive
162 call [bp+PIOVARS.fnXfer]
163
164 ; Wait until ready for next block and check for errors
165 call IdeWait_IRQorDRQ ; Wait until ready to transfer
166 jc SHORT ReturnWithTransferErrorInAH
167
168 ; Increment number of successfully written sectors
169 mov cx, [bp+PIOVARS.wSectorsInBlock]
170 sub [bp+PIOVARS.bSectorsLeft], cl
171 add [bp+PIOVARS.bSectorsDone], cl
172 jmp SHORT .WriteNextBlockToDrive
173
174ALIGN JUMP_ALIGN
175.WriteLastBlockToDrive:
176 mov cl, [bp+PIOVARS.bSectorsLeft] ; CH is already zero
177%ifdef USE_186
178 push CheckErrorsAfterTransferringLastBlock
179 jmp [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
180%else
181 call [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
182 jmp SHORT CheckErrorsAfterTransferringLastBlock
183%endif
184
185
186;--------------------------------------------------------------------
187; InitializePiovarsInSSBPwithSectorCountInAH
188; Parameters:
189; AH: Number of sectors to transfer (1...128)
190; BX: Offset to transfer function lookup table
191; DS:DI: Ptr to DPT (in RAMVARS segment)
192; SS:BP: Ptr to PIOVARS
193; Returns:
194; Nothing
195; Corrupts registers:
196; AX, BX, DX
197;--------------------------------------------------------------------
198ALIGN JUMP_ALIGN
199InitializePiovarsInSSBPwithSectorCountInAH:
200 ; Store sizes
201 mov [bp+PIOVARS.bSectorsLeft], ah
202 eMOVZX ax, [di+DPT_ATA.bBlockSize]
203 mov [bp+PIOVARS.wSectorsInBlock], ax
204 mov [bp+PIOVARS.bSectorsDone], ah ; Zero
205
206 ; Get transfer function based on bus type
207 xchg ax, bx ; Lookup table offset to AX
208 mov bl, [di+DPT.bIdevarsOffset] ; CS:BX now points to IDEVARS
209 mov dx, [cs:bx+IDEVARS.wPort] ; Load IDE Data port address
210 mov bl, [di+DPT_ATA.bDevice]
211 add bx, ax
212
213 mov [bp+PIOVARS.wDataPort], dx
214 mov ax, [cs:bx] ; Load offset to transfer function
215 mov [bp+PIOVARS.fnXfer], ax
216 ret
217
218
219;--------------------------------------------------------------------
220; ReadBlockFromXtideRev1 XTIDE rev 1
221; ReadBlockFromXtideRev2 XTIDE rev 2 or rev 1 with swapped A0 and A3 (chuck-mod)
222; ReadBlockFrom16bitDataPort Normal 16-bit IDE
223; ReadBlockFrom32bitDataPort VLB/PCI 32-bit IDE
224; Parameters:
225; CX: Block size in 512 byte sectors
226; DX: IDE Data port address
227; ES:DI: Normalized ptr to buffer to receive data
228; Returns:
229; Nothing
230; Corrupts registers:
231; AX, BX, CX
232;--------------------------------------------------------------------
233%ifdef MODULE_8BIT_IDE
234
235ALIGN JUMP_ALIGN
236ReadBlockFromXtideRev1:
237 UNROLL_SECTORS_IN_CX_TO_QWORDS
238 mov bl, 8 ; Bit mask for toggling data low/high reg
239ALIGN JUMP_ALIGN
240.InswLoop:
241 XTIDE_INSW
242 XTIDE_INSW
243 XTIDE_INSW
244 XTIDE_INSW
245 loop .InswLoop
246 ret
247
248;--------------------------------------------------------------------
249%ifndef USE_186 ; 8086/8088 compatible WORD read
250ALIGN JUMP_ALIGN
251ReadBlockFromXtideRev2:
252 UNROLL_SECTORS_IN_CX_TO_QWORDS
253ALIGN JUMP_ALIGN
254.ReadNextQword:
255 in ax, dx ; Read 1st WORD
256 stosw ; Store 1st WORD to [ES:DI]
257 in ax, dx
258 stosw ; 2nd
259 in ax, dx
260 stosw ; 3rd
261 in ax, dx
262 stosw ; 4th
263 loop .ReadNextQword
264 ret
265%endif
266
267%endif ; MODULE_8BIT_IDE
268
269;--------------------------------------------------------------------
270ALIGN JUMP_ALIGN
271ReadBlockFrom16bitDataPort:
272 xchg cl, ch ; Sectors to WORDs
273 rep
274 db 6Dh ; INSW (we want this in XT build)
275 ret
276
277;--------------------------------------------------------------------
278ALIGN JUMP_ALIGN
279ReadBlockFrom32bitDataPort:
280 db 0C1h ; SHL
281 db 0E1h ; CX
282 db 7 ; 7 (Sectors to DWORDs)
283 rep
284 db 66h ; Override operand size to 32-bit
285 db 6Dh ; INSW/INSD
286 ret
287
288
289;--------------------------------------------------------------------
290; WriteBlockToXtideRev1 XTIDE rev 1
291; WriteBlockToXtideRev2 XTIDE rev 2 or rev 1 with swapped A0 and A3 (chuck-mod)
292; WriteBlockToFastXtide Fast XTIDE (CPLD v2 project)
293; WriteBlockTo16bitDataPort Normal 16-bit IDE
294; WriteBlockTo32bitDataPort VLB/PCI 32-bit IDE
295; Parameters:
296; CX: Block size in 512-byte sectors
297; DX: IDE Data port address
298; ES:SI: Normalized ptr to buffer containing data
299; Returns:
300; Nothing
301; Corrupts registers:
302; AX, CX
303;--------------------------------------------------------------------
304%ifdef MODULE_8BIT_IDE
305
306ALIGN JUMP_ALIGN
307WriteBlockToXtideRev1:
308 push ds
309 push bx
310 UNROLL_SECTORS_IN_CX_TO_QWORDS
311 mov bl, 8 ; Bit mask for toggling data low/high reg
312 push es ; Copy ES...
313 pop ds ; ...to DS
314ALIGN JUMP_ALIGN
315.OutswLoop:
316 XTIDE_OUTSW
317 XTIDE_OUTSW
318 XTIDE_OUTSW
319 XTIDE_OUTSW
320 loop .OutswLoop
321 pop bx
322 pop ds
323 ret
324
325;--------------------------------------------------------------------
326ALIGN JUMP_ALIGN
327WriteBlockToXtideRev2:
328 UNROLL_SECTORS_IN_CX_TO_QWORDS
329 push ds
330 push es ; Copy ES...
331 pop ds ; ...to DS
332ALIGN JUMP_ALIGN
333.WriteNextQword:
334 XTIDE_MOD_OUTSW
335 XTIDE_MOD_OUTSW
336 XTIDE_MOD_OUTSW
337 XTIDE_MOD_OUTSW
338 loop .WriteNextQword
339 pop ds
340 ret
341
342;--------------------------------------------------------------------
343%ifndef USE_186 ; 8086/8088 compatible WORD write
344ALIGN JUMP_ALIGN
345WriteBlockToFastXtide:
346 UNROLL_SECTORS_IN_CX_TO_QWORDS
347 push ds
348 push es
349 pop ds
350ALIGN JUMP_ALIGN
351.ReadNextQword:
352 lodsw ; Load 1st WORD from [DS:SI]
353 out dx, ax ; Write 1st WORD
354 lodsw
355 out dx, ax ; 2nd
356 lodsw
357 out dx, ax ; 3rd
358 lodsw
359 out dx, ax ; 4th
360 loop .ReadNextQword
361 pop ds
362 ret
363%endif
364
365%endif ; MODULE_8BIT_IDE
366
367;--------------------------------------------------------------------
368ALIGN JUMP_ALIGN
369WriteBlockTo16bitDataPort:
370 xchg cl, ch ; Sectors to WORDs
371 es ; Source is ES segment
372 rep
373 db 6Fh ; OUTSW (we want this in XT build)
374 ret
375
376;--------------------------------------------------------------------
377ALIGN JUMP_ALIGN
378WriteBlockTo32bitDataPort:
379 db 0C1h ; SHL
380 db 0E1h ; CX
381 db 7 ; 7 (Sectors to DWORDs)
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
390; Lookup tables to get transfer function based on bus type
391ALIGN WORD_ALIGN
392g_rgfnPioRead:
393%ifdef MODULE_8BIT_IDE
394 dw ReadBlockFromXtideRev1 ; DEVICE_XTIDE_REV1
395 %ifdef USE_186
396 dw ReadBlockFrom16bitDataPort ; DEVICE_XTIDE_REV2
397 dw ReadBlockFrom16bitDataPort ; DEVICE_FAST_XTIDE
398 %else
399 dw ReadBlockFromXtideRev2 ; DEVICE_XTIDE_REV2
400 dw ReadBlockFromXtideRev2 ; DEVICE_FAST_XTIDE
401 %endif
402
403%else
404 times COUNT_OF_8BIT_IDE_DEVICES dw 0
405%endif
406 dw ReadBlockFrom16bitDataPort ; DEVICE_16BIT_ATA
407 dw ReadBlockFrom32bitDataPort ; DEVICE_32BIT_ATA
408
409
410g_rgfnPioWrite:
411%ifdef MODULE_8BIT_IDE
412 dw WriteBlockToXtideRev1 ; DEVICE_XTIDE_REV1
413 dw WriteBlockToXtideRev2 ; DEVICE_XTIDE_REV2
414 %ifdef USE_186
415 dw WriteBlockTo16bitDataPort ; DEVICE_FAST_XTIDE
416 %else
417 dw WriteBlockToFastXtide ; DEVICE_FAST_XTIDE
418 %endif
419
420%else
421 times COUNT_OF_8BIT_IDE_DEVICES dw 0
422%endif
423 dw WriteBlockTo16bitDataPort ; DEVICE_16BIT_ATA
424 dw WriteBlockTo32bitDataPort ; DEVICE_32BIT_ATA
Note: See TracBrowser for help on using the repository browser.