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

Last change on this file since 601 was 601, checked in by Krister Nordvall, 6 years ago

Changes:

  • Building the BIOS now works again.
  • Added a new IDE device type/transfer mode for use only with XT-IDE rev 2+ (or Chuck(G)-modded rev 1) cards installed in any of the following machines: Olivetti M24, AT&T PC6300, Xerox 6060 and Logabax Persona 1600. This new transfer mode is slightly faster than the regular XT-IDE rev 1 device type and requires that the card is configured for High Speed mode (or, in case of the card being a rev 1 card, has the Chuck(G) mod done). The new device type is called "XTIDE rev 2 (Olivetti M24)" in XTIDECFG.
  • Made some minor improvements to the library code that handles 'Drive Not Ready' errors in XTIDECFG.
  • Optimizations.
File size: 11.8 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-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 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 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: 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%ifdef USE_AT
81 jc SHORT ReturnWithTransferErrorInAH
82%endif
83
84 ; Wait until drive is ready to transfer
85 call IdeWait_IRQorDRQ ; Wait until ready to transfer
86 jc SHORT ReturnWithTransferErrorInAH
87 xchg si, di ; ES:DI now points buffer
88
89 mov cx, [bp+PIOVARS.wSectorsInBlock] ; Max 128
90
91ALIGN JUMP_ALIGN
92.ReadNextBlockFromDrive:
93 mov dx, [bp+PIOVARS.wDataPort]
94 cmp [bp+PIOVARS.bSectorsLeft], cl
95 jbe SHORT .ReadLastBlockFromDrive
96 call [bp+PIOVARS.fnXfer]
97
98 ; Wait until ready for next block and check for errors
99 xchg di, si ; DS:DI now points DPT
100 call IdeWait_IRQorDRQ ; Wait until ready to transfer
101 jc SHORT ReturnWithTransferErrorInAH
102 xchg si, di ; ES:DI now points buffer
103
104 ; Increment number of successfully read sectors
105 mov cx, [bp+PIOVARS.wSectorsInBlock]
106 sub [bp+PIOVARS.bSectorsLeft], cl
107 add [bp+PIOVARS.bSectorsDone], cl
108 jmp SHORT .ReadNextBlockFromDrive
109
110ALIGN JUMP_ALIGN
111.ReadLastBlockFromDrive:
112 mov cl, [bp+PIOVARS.bSectorsLeft] ; CH is already zero
113 push cx
114 call [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
115
116 ; Check for errors in last block
117 mov di, si ; DS:DI now points DPT
118CheckErrorsAfterTransferringLastBlock:
119 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_BSY)
120 call IdeWait_PollStatusFlagInBLwithTimeoutInBH
121 pop cx ; [bp+PIOVARS.bSectorsLeft]
122 jc SHORT ReturnWithTransferErrorInAH
123
124 ; All sectors successfully transferred
125 add cx, [bp+PIOVARS.bSectorsDone] ; Never sets CF
126 ret
127
128 ; Return number of successfully read sectors
129ReturnWithTransferErrorInAH:
130%ifdef USE_386
131 movzx cx, [bp+PIOVARS.bSectorsDone]
132%else
133 mov cl, [bp+PIOVARS.bSectorsDone]
134 mov ch, 0 ; Preserve CF
135%endif
136 ret
137
138
139;--------------------------------------------------------------------
140; WriteToDrive
141; Parameters:
142; AH: Number of sectors to transfer (1...128)
143; DS:DI: Ptr to DPT (in RAMVARS segment)
144; ES:SI: Ptr to buffer containing data
145; SS:BP: Ptr to PIOVARS
146; Returns:
147; AH: BIOS Error code
148; CX: Number of successfully transferred sectors
149; CF: 0 if transfer successful
150; 1 if any error
151; Corrupts registers:
152; AL, BX, DX, SI, ES
153;--------------------------------------------------------------------
154ALIGN JUMP_ALIGN
155WriteToDrive:
156 ; Prepare to write data from ESSI
157 mov bx, g_rgfnPioWrite
158 call InitializePiovarsInSSBPwithSectorCountInAH
159%ifdef USE_AT
160 jc SHORT ReturnWithTransferErrorInAH
161%endif
162
163 ; Always poll when writing first block (IRQs are generated for following blocks)
164 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
165 call IdeWait_PollStatusFlagInBLwithTimeoutInBH
166 jc SHORT ReturnWithTransferErrorInAH
167
168 mov cx, [bp+PIOVARS.wSectorsInBlock] ; Max 128
169
170ALIGN JUMP_ALIGN
171.WriteNextBlockToDrive:
172 mov dx, [bp+PIOVARS.wDataPort]
173 cmp [bp+PIOVARS.bSectorsLeft], cl
174 jbe SHORT .WriteLastBlockToDrive
175 push ds
176 push es
177 pop ds
178 call [bp+PIOVARS.fnXfer]
179 pop ds
180 ; Wait until ready for next block and check for errors
181 call IdeWait_IRQorDRQ ; Wait until ready to transfer
182 jc SHORT ReturnWithTransferErrorInAH
183
184 ; Increment number of successfully written sectors
185 mov cx, [bp+PIOVARS.wSectorsInBlock]
186 sub [bp+PIOVARS.bSectorsLeft], cl
187 add [bp+PIOVARS.bSectorsDone], cl
188 jmp SHORT .WriteNextBlockToDrive
189
190ALIGN JUMP_ALIGN
191.WriteLastBlockToDrive:
192 mov cl, [bp+PIOVARS.bSectorsLeft] ; CH is already zero
193 push cx
194 push ds
195 push es
196 pop ds
197 call [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
198 pop ds
199 jmp SHORT CheckErrorsAfterTransferringLastBlock
200
201
202;--------------------------------------------------------------------
203; InitializePiovarsInSSBPwithSectorCountInAH
204; Parameters:
205; AH: Number of sectors to transfer (1...128)
206; BX: Offset to transfer function lookup table
207; DS:DI: Ptr to DPT (in RAMVARS segment)
208; ES:SI: Ptr to data buffer
209; SS:BP: Ptr to PIOVARS
210; Returns:
211; ES:SI: Normalized pointer
212; AH: INT 13h Error Code (only when CF set)
213; CF: Set if failed to normalize pointer (segment overflow)
214; Cleared if success
215; Corrupts registers:
216; AL, BX, DX
217;--------------------------------------------------------------------
218ALIGN JUMP_ALIGN
219InitializePiovarsInSSBPwithSectorCountInAH:
220 ; Store sizes and Data Port
221 mov [bp+PIOVARS.bSectorsLeft], ah
222%ifdef USE_AT
223 xchg dx, ax
224%endif
225 mov ax, [di+DPT.wBasePort]
226 mov [bp+PIOVARS.wDataPort], ax
227 eMOVZX ax, [di+DPT_ATA.bBlockSize]
228 mov [bp+PIOVARS.wSectorsInBlock], ax
229 mov [bp+PIOVARS.bSectorsDone], ah ; Zero
230
231 ; Get transfer function based on bus type
232 mov al, [di+DPT_ATA.bDevice]
233 add bx, ax
234%ifdef MODULE_8BIT_IDE_ADVANCED
235 cmp al, DEVICE_8BIT_XTCF_DMA
236%endif
237 mov ax, [cs:bx] ; Load offset to transfer function
238 mov [bp+PIOVARS.fnXfer], ax
239
240 ; Normalize pointer for PIO-transfers and convert to physical address for DMA transfers
241%ifdef MODULE_8BIT_IDE_ADVANCED
242 jb SHORT IdeTransfer_NormalizePointerInESSI
243
244 ; Convert ES:SI to physical address
245%ifdef USE_386
246 mov dx, es
247 xor ax, ax
248 shld ax, dx, 4
249 shl dx, 4
250 add si, dx
251 adc al, ah
252 mov es, ax
253
254%elifdef USE_186
255 mov ax, es
256 rol ax, 4
257 mov dx, ax
258 and ax, 0Fh
259 xor dx, ax
260 add si, dx
261 adc al, ah
262 mov es, ax
263
264%else ; 808x
265 mov al, 4
266 mov dx, es
267 xchg cx, ax
268 rol dx, cl
269 mov cx, dx
270 xchg cx, ax
271 and ax, 0Fh
272 xor dx, ax
273 add si, dx
274 adc al, ah
275 mov es, ax
276
277%endif
278
279 ret ; With CF cleared (taken care of by the physical address conversion)
280%endif ; MODULE_8BIT_IDE_ADVANCED
281 ; Fall to IdeTransfer_NormalizePointerInESSI if no MODULE_8BIT_IDE_ADVANCED
282
283
284;--------------------------------------------------------------------
285; IdeTransfer_NormalizePointerInESSI
286; Parameters:
287; DH: Number of sectors to transfer (when USE_AT defined)
288; ES:SI: Ptr to be normalized
289; Returns:
290; ES:SI: Normalized pointer (SI = 0...15)
291; AH: INT 13h Error Code (when USE_AT defined and normalization was attempted)
292; CF: Set if failed to normalize pointer (segment overflow)
293; Cleared if success
294; Corrupts registers:
295; AX, DX
296;--------------------------------------------------------------------
297IdeTransfer_NormalizePointerInESSI:
298; Normalization can cause segment overflow if it is done when not needed
299; (I don't know if any software calls with such seg:off address).
300; This does not apply to XT systems since nothing will write to main BIOS ROM.
301; On AT systems things are quite different, even in protected mode the address
302; is passed in seg:offset form and HMA is accessible in real mode.
303%ifdef USE_AT
304 xor dl, dl
305 eSHL_IM dx, 1
306 dec dx ; Prevents normalization when bytes + offset will be zero
307 add dx, si
308 jc SHORT .NormalizationRequired
309 ret
310.NormalizationRequired:
311%endif ; USE_AT
312
313 NORMALIZE_FAR_POINTER es, si, ax, dx
314%ifdef USE_AT ; CF is always clear for XT builds
315 ; AH = RET_HD_INVALID (01) if CF set, RET_HD_SUCCESS (00) if not. CF unchanged.
316%ifdef USE_386
317 setc ah
318%else
319 sbb ah, ah
320 neg ah
321%endif
322%endif ; USE_AT
323 ret
324
325
326
327; Lookup tables to get transfer function based on bus type
328ALIGN WORD_ALIGN
329g_rgfnPioRead:
330 dw IdePioBlock_ReadFrom16bitDataPort ; 0, DEVICE_16BIT_ATA
331%ifdef MODULE_ADVANCED_ATA
332 dw IdePioBlock_ReadFrom32bitDataPort ; 1, DEVICE_32BIT_ATA
333%elifdef MODULE_8BIT_IDE
334 dw NULL
335%endif ; MODULE_ADVANCED_ATA
336%ifdef MODULE_8BIT_IDE
337 dw IdePioBlock_ReadFrom8bitDataPort ; 2, DEVICE_8BIT_ATA
338 dw IdePioBlock_ReadFromXtideRev1 ; 3, DEVICE_8BIT_XTIDE_REV1
339 dw IdePioBlock_ReadFrom16bitDataPort ; 4, DEVICE_8BIT_XTIDE_REV2
340 dw IdePioBlock_ReadFromXtideRev2_Olivetti ; 5, DEVICE_8BIT_XTIDE_REV2_OLIVETTI
341%ifdef MODULE_8BIT_IDE_ADVANCED
342 dw IdePioBlock_ReadFrom8bitDataPort ; 6, DEVICE_8BIT_XTCF_PIO8
343 dw IdePioBlock_ReadFrom16bitDataPort ; 7, DEVICE_8BIT_XTCF_PIO8_WITH_BIU_OFFLOAD
344 dw IdePioBlock_ReadFrom16bitDataPort ; 8, DEVICE_8BIT_XTCF_PIO16_WITH_BIU_OFFLOAD
345 dw IdeDmaBlock_ReadFromXTCF ; 9, DEVICE_8BIT_XTCF_DMA
346%endif ; MODULE_8BIT_IDE_ADVANCED
347%endif ; MODULE_8BIT_IDE
348
349
350g_rgfnPioWrite:
351 dw IdePioBlock_WriteTo16bitDataPort ; 0, DEVICE_16BIT_ATA
352%ifdef MODULE_ADVANCED_ATA
353 dw IdePioBlock_WriteTo32bitDataPort ; 1, DEVICE_32BIT_ATA
354%elifdef MODULE_8BIT_IDE
355 dw NULL
356%endif ; MODULE_ADVANCED_ATA
357%ifdef MODULE_8BIT_IDE
358 dw IdePioBlock_WriteTo8bitDataPort ; 2, DEVICE_8BIT_ATA
359 dw IdePioBlock_WriteToXtideRev1 ; 3, DEVICE_8BIT_XTIDE_REV1
360 dw IdePioBlock_WriteToXtideRev2 ; 4, DEVICE_8BIT_XTIDE_REV2
361 dw IdePioBlock_WriteToXtideRev2 ; 5, DEVICE_8BIT_XTIDE_REV2_OLIVETTI
362%ifdef MODULE_8BIT_IDE_ADVANCED
363 dw IdePioBlock_WriteTo8bitDataPort ; 6, DEVICE_8BIT_XTCF_PIO8
364 dw IdePioBlock_WriteTo16bitDataPort ; 7, DEVICE_8BIT_XTCF_PIO8_WITH_BIU_OFFLOAD
365 dw IdePioBlock_WriteTo16bitDataPort ; 8, DEVICE_8BIT_XTCF_PIO16_WITH_BIU_OFFLOAD
366 dw IdeDmaBlock_WriteToXTCF ; 9, DEVICE_8BIT_XTCF_DMA
367%endif ; MODULE_8BIT_IDE_ADVANCED
368%endif ; MODULE_8BIT_IDE
Note: See TracBrowser for help on using the repository browser.