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

Last change on this file since 625 was 625, checked in by Krister Nordvall, 22 months ago

Changes:

  • Added a configuration option to let the BIOS store RamVars to an UMB when Full operating mode is enabled. This is primarily for XT class machines with RAM in the UMA (which apparently is a common thing these days).
  • Added two new builds specifically for IBM PS/2 machines. This is for support of the new McIDE adapter from the guys at zzxio.com. Note that the additional hardware specific code (under the USE_PS2 define) is for the PS/2 machines themselves and not for the McIDE adapters, so any controller in an IBM PS/2 machine can be used with the USE_PS2 define.
  • Moved pColorTheme out of the range of ROMVARS being copied over when doing "Load old settings from EEPROM" in XTIDECFG. This fixed a serious bug from r592 where loading a BIOS from file and then loading the old settings from ROM would corrupt 7 bytes of code somewhere in the loaded BIOS.
  • Optimizations (speed and size) to the library. Browsing the menus in XTIDECFG should now feel a little less sluggish.
  • Hopefully fixed a problem with the PostCommitHook script where it sometimes wouldn't find the CommitInProgress file. I say hopefully because testing this is a nightmare.
File size: 12.6 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-2023 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%ifdef USE_PS2
53 ; Turn on the software controlled HDD LED on IBM PS/2 machines
54 xchg bx, ax ; Save AX
55 in al, 92h ; Read System Control Port A
56 or al, 80h ; Set bit 7 to turn on LED (bit 6 would also work)
57 out 92h, al ; Write it back
58 xchg bx, ax ; Restore AX
59%endif
60 ; Are we reading or writing?
61 test al, 16 ; Bit 4 is cleared on all the read commands but set on 3 of the 4 write commands
62 mov ah, [bp+IDEPACK.bSectorCount]
63 jnz SHORT WriteToDrive
64 cmp al, COMMAND_WRITE_MULTIPLE
65 je SHORT WriteToDrive
66 ; Fall to ReadFromDrive
67
68;--------------------------------------------------------------------
69; ReadFromDrive
70; Parameters:
71; AH: Number of sectors to transfer (1...128)
72; ES:SI: Ptr to buffer to receive data
73; DS:DI: Ptr to DPT (in RAMVARS segment)
74; SS:BP: Ptr to PIOVARS
75; Returns:
76; DS:DI: Ptr to DPT (in RAMVARS segment)
77; AH: BIOS Error code
78; CX: Number of successfully transferred sectors
79; CF: 0 if transfer successful
80; 1 if any error
81; Corrupts registers:
82; AL, BX, DX, SI, ES
83;--------------------------------------------------------------------
84ReadFromDrive:
85 ; Prepare to read data to ESSI
86 mov bx, g_rgfnPioRead
87 call InitializePiovarsInSSBPwithSectorCountInAH
88%ifdef USE_AT
89 jc SHORT ReturnWithTransferErrorInAH
90%endif
91
92 ; Wait until drive is ready to transfer
93 call IdeWait_IRQorDRQ ; Wait until ready to transfer
94 jc SHORT ReturnWithTransferErrorInAH
95 xchg si, di ; ES:DI now points buffer
96
97 mov cx, [bp+PIOVARS.wSectorsInBlock] ; Max 128
98
99ALIGN JUMP_ALIGN
100.ReadNextBlockFromDrive:
101 mov dx, [bp+PIOVARS.wDataPort]
102 cmp [bp+PIOVARS.bSectorsLeft], cl
103 jbe SHORT .ReadLastBlockFromDrive
104 call [bp+PIOVARS.fnXfer]
105
106 ; Wait until ready for next block and check for errors
107 xchg di, si ; DS:DI now points DPT
108 call IdeWait_IRQorDRQ ; Wait until ready to transfer
109 jc SHORT ReturnWithTransferErrorInAH
110 xchg si, di ; ES:DI now points buffer
111
112 ; Increment number of successfully read sectors
113 mov cx, [bp+PIOVARS.wSectorsInBlock]
114 sub [bp+PIOVARS.bSectorsLeft], cl
115 add [bp+PIOVARS.bSectorsDone], cl
116 jmp SHORT .ReadNextBlockFromDrive
117
118ALIGN JUMP_ALIGN
119.ReadLastBlockFromDrive:
120 mov cl, [bp+PIOVARS.bSectorsLeft] ; CH is already zero
121 push cx
122 call [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
123
124 ; Check for errors in last block
125 mov di, si ; DS:DI now points DPT
126CheckErrorsAfterTransferringLastBlock:
127 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_BSY)
128 call IdeWait_PollStatusFlagInBLwithTimeoutInBH
129 pop cx ; [bp+PIOVARS.bSectorsLeft]
130 jc SHORT ReturnWithTransferErrorInAH
131
132 ; All sectors successfully transferred
133 add cx, [bp+PIOVARS.bSectorsDone] ; Never sets CF
134%ifdef USE_PS2
135 ; Turn off the software controlled HDD LED on IBM PS/2 machines
136 in al, 92h ; Read System Control Port A
137 and al, 3Fh ; Clear bits 7 and 6 to turn off LED
138 out 92h, al ; Write it back
139%endif
140 ret
141
142 ; Return number of successfully read sectors
143ReturnWithTransferErrorInAH:
144%ifdef USE_386
145 movzx cx, [bp+PIOVARS.bSectorsDone]
146%else
147 mov cl, [bp+PIOVARS.bSectorsDone]
148 mov ch, 0 ; Preserve CF
149%endif
150%ifdef USE_PS2
151 ; Turn off the software controlled HDD LED on IBM PS/2 machines
152 in al, 92h ; Read System Control Port A
153 and al, 3Fh ; Clear bits 7 and 6 to turn off LED (Clears CF)
154 out 92h, al ; Write it back
155 stc ; Restore the CF
156%endif
157 ret
158
159
160;--------------------------------------------------------------------
161; WriteToDrive
162; Parameters:
163; AH: Number of sectors to transfer (1...128)
164; DS:DI: Ptr to DPT (in RAMVARS segment)
165; ES:SI: Ptr to buffer containing data
166; SS:BP: Ptr to PIOVARS
167; Returns:
168; AH: BIOS Error code
169; CX: Number of successfully transferred sectors
170; CF: 0 if transfer successful
171; 1 if any error
172; Corrupts registers:
173; AL, BX, DX, SI, ES
174;--------------------------------------------------------------------
175ALIGN JUMP_ALIGN
176WriteToDrive:
177 ; Prepare to write data from ESSI
178 mov bx, g_rgfnPioWrite
179 call InitializePiovarsInSSBPwithSectorCountInAH
180%ifdef USE_AT
181 jc SHORT ReturnWithTransferErrorInAH
182%endif
183
184 ; Always poll when writing first block (IRQs are generated for following blocks)
185 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
186 call IdeWait_PollStatusFlagInBLwithTimeoutInBH
187 jc SHORT ReturnWithTransferErrorInAH
188
189 mov cx, [bp+PIOVARS.wSectorsInBlock] ; Max 128
190
191ALIGN JUMP_ALIGN
192.WriteNextBlockToDrive:
193 mov dx, [bp+PIOVARS.wDataPort]
194 cmp [bp+PIOVARS.bSectorsLeft], cl
195 jbe SHORT .WriteLastBlockToDrive
196 push ds
197 push es
198 pop ds
199 call [bp+PIOVARS.fnXfer]
200 pop ds
201 ; Wait until ready for next block and check for errors
202 call IdeWait_IRQorDRQ ; Wait until ready to transfer
203 jc SHORT ReturnWithTransferErrorInAH
204
205 ; Increment number of successfully written sectors
206 mov cx, [bp+PIOVARS.wSectorsInBlock]
207 sub [bp+PIOVARS.bSectorsLeft], cl
208 add [bp+PIOVARS.bSectorsDone], cl
209 jmp SHORT .WriteNextBlockToDrive
210
211ALIGN JUMP_ALIGN
212.WriteLastBlockToDrive:
213 mov cl, [bp+PIOVARS.bSectorsLeft] ; CH is already zero
214 push cx
215 push ds
216 push es
217 pop ds
218 call [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
219 pop ds
220 jmp SHORT CheckErrorsAfterTransferringLastBlock
221
222
223;--------------------------------------------------------------------
224; InitializePiovarsInSSBPwithSectorCountInAH
225; Parameters:
226; AH: Number of sectors to transfer (1...128)
227; BX: Offset to transfer function lookup table
228; DS:DI: Ptr to DPT (in RAMVARS segment)
229; ES:SI: Ptr to data buffer
230; SS:BP: Ptr to PIOVARS
231; Returns:
232; ES:SI: Normalized pointer
233; AH: INT 13h Error Code (only when CF set)
234; CF: Set if failed to normalize pointer (segment overflow)
235; Cleared if success
236; Corrupts registers:
237; AL, BX, DX
238;--------------------------------------------------------------------
239ALIGN JUMP_ALIGN
240InitializePiovarsInSSBPwithSectorCountInAH:
241 ; Store sizes and Data Port
242 mov [bp+PIOVARS.bSectorsLeft], ah
243%ifdef USE_AT
244 xchg dx, ax
245%endif
246 mov ax, [di+DPT.wBasePort]
247 mov [bp+PIOVARS.wDataPort], ax
248 eMOVZX ax, [di+DPT_ATA.bBlockSize]
249 mov [bp+PIOVARS.wSectorsInBlock], ax
250 mov [bp+PIOVARS.bSectorsDone], ah ; Zero
251
252 ; Get transfer function based on bus type
253 mov al, [di+DPT_ATA.bDevice]
254 add bx, ax
255%ifdef MODULE_8BIT_IDE_ADVANCED
256 cmp al, DEVICE_8BIT_XTCF_DMA
257%endif
258 mov ax, [cs:bx] ; Load offset to transfer function
259 mov [bp+PIOVARS.fnXfer], ax
260
261 ; Normalize pointer for PIO-transfers and convert to physical address for DMA transfers
262%ifdef MODULE_8BIT_IDE_ADVANCED
263 jb SHORT IdeTransfer_NormalizePointerInESSI
264
265 ; Convert ES:SI to physical address
266%ifdef USE_386
267 mov dx, es
268 xor ax, ax
269 shld ax, dx, 4
270 shl dx, 4
271 add si, dx
272 adc al, ah
273 mov es, ax
274
275%elifdef USE_186
276%ifdef USE_NEC_V
277 mov dx, es
278 xor ax, ax
279 eROL4 dl
280 eROL4 dh
281 add si, dx
282 adc al, ah
283 mov es, ax
284
285%else
286 mov ax, es
287 rol ax, 4
288 mov dx, ax
289 and ax, 0Fh
290 xor dx, ax
291 add si, dx
292 adc al, ah
293 mov es, ax
294
295%endif
296%else ; 808x
297 mov al, 4
298 mov dx, es
299 xchg cx, ax
300 rol dx, cl
301 mov cx, dx
302 xchg cx, ax
303 and ax, 0Fh
304 xor dx, ax
305 add si, dx
306 adc al, ah
307 mov es, ax
308
309%endif
310
311 ret ; With CF cleared (taken care of by the physical address conversion)
312%endif ; MODULE_8BIT_IDE_ADVANCED
313 ; Fall to IdeTransfer_NormalizePointerInESSI if no MODULE_8BIT_IDE_ADVANCED
314
315
316;--------------------------------------------------------------------
317; IdeTransfer_NormalizePointerInESSI
318; Parameters:
319; DH: Number of sectors to transfer (when USE_AT defined)
320; ES:SI: Ptr to be normalized
321; Returns:
322; ES:SI: Normalized pointer (SI = 0...15)
323; AH: INT 13h Error Code (when USE_AT defined and normalization was attempted)
324; CF: Set if failed to normalize pointer (segment overflow)
325; Cleared if success
326; Corrupts registers:
327; AX, DX
328;--------------------------------------------------------------------
329IdeTransfer_NormalizePointerInESSI:
330; Normalization can cause segment overflow if it is done when not needed
331; (I don't know if any software calls with such seg:off address).
332; This does not apply to XT systems since nothing will write to main BIOS ROM.
333; On AT systems things are quite different, even in protected mode the address
334; is passed in seg:offset form and HMA is accessible in real mode.
335%ifdef USE_AT
336 xor dl, dl
337 eSHL_IM dx, 1
338 dec dx ; Prevents normalization when bytes + offset will be zero
339 add dx, si
340 jc SHORT .NormalizationRequired
341 ret
342.NormalizationRequired:
343%endif ; USE_AT
344
345 NORMALIZE_FAR_POINTER es, si, ax, dx
346%ifdef USE_AT ; CF is always clear for XT builds
347 ; AH = RET_HD_INVALID (01) if CF set, RET_HD_SUCCESS (00) if not. CF unchanged.
348%ifdef USE_386
349 setc ah
350%else
351 sbb ah, ah
352 neg ah
353%endif
354%endif ; USE_AT
355 ret
356
357
358
359; Lookup tables to get transfer function based on bus type
360ALIGN WORD_ALIGN
361g_rgfnPioRead:
362 dw IdePioBlock_ReadFrom16bitDataPort ; 0, DEVICE_16BIT_ATA
363%ifdef MODULE_ADVANCED_ATA
364 dw IdePioBlock_ReadFrom32bitDataPort ; 1, DEVICE_32BIT_ATA
365%elifdef MODULE_8BIT_IDE
366 dw NULL
367%endif ; MODULE_ADVANCED_ATA
368%ifdef MODULE_8BIT_IDE
369 dw IdePioBlock_ReadFrom8bitDataPort ; 2, DEVICE_8BIT_ATA
370 dw IdePioBlock_ReadFromXtideRev1 ; 3, DEVICE_8BIT_XTIDE_REV1
371 dw IdePioBlock_ReadFrom16bitDataPort ; 4, DEVICE_8BIT_XTIDE_REV2
372 dw IdePioBlock_ReadFromXtideRev2_Olivetti ; 5, DEVICE_8BIT_XTIDE_REV2_OLIVETTI
373%ifdef MODULE_8BIT_IDE_ADVANCED
374 dw IdePioBlock_ReadFrom8bitDataPort ; 6, DEVICE_8BIT_XTCF_PIO8
375 dw IdePioBlock_ReadFrom16bitDataPort ; 7, DEVICE_8BIT_XTCF_PIO8_WITH_BIU_OFFLOAD
376 dw IdePioBlock_ReadFrom16bitDataPort ; 8, DEVICE_8BIT_XTCF_PIO16_WITH_BIU_OFFLOAD
377 dw IdeDmaBlock_ReadFromXTCF ; 9, DEVICE_8BIT_XTCF_DMA
378%endif ; MODULE_8BIT_IDE_ADVANCED
379%endif ; MODULE_8BIT_IDE
380
381
382g_rgfnPioWrite:
383 dw IdePioBlock_WriteTo16bitDataPort ; 0, DEVICE_16BIT_ATA
384%ifdef MODULE_ADVANCED_ATA
385 dw IdePioBlock_WriteTo32bitDataPort ; 1, DEVICE_32BIT_ATA
386%elifdef MODULE_8BIT_IDE
387 dw NULL
388%endif ; MODULE_ADVANCED_ATA
389%ifdef MODULE_8BIT_IDE
390 dw IdePioBlock_WriteTo8bitDataPort ; 2, DEVICE_8BIT_ATA
391 dw IdePioBlock_WriteToXtideRev1 ; 3, DEVICE_8BIT_XTIDE_REV1
392 dw IdePioBlock_WriteToXtideRev2 ; 4, DEVICE_8BIT_XTIDE_REV2
393 dw IdePioBlock_WriteToXtideRev2 ; 5, DEVICE_8BIT_XTIDE_REV2_OLIVETTI
394%ifdef MODULE_8BIT_IDE_ADVANCED
395 dw IdePioBlock_WriteTo8bitDataPort ; 6, DEVICE_8BIT_XTCF_PIO8
396 dw IdePioBlock_WriteTo16bitDataPort ; 7, DEVICE_8BIT_XTCF_PIO8_WITH_BIU_OFFLOAD
397 dw IdePioBlock_WriteTo16bitDataPort ; 8, DEVICE_8BIT_XTCF_PIO16_WITH_BIU_OFFLOAD
398 dw IdeDmaBlock_WriteToXTCF ; 9, DEVICE_8BIT_XTCF_DMA
399%endif ; MODULE_8BIT_IDE_ADVANCED
400%endif ; MODULE_8BIT_IDE
Note: See TracBrowser for help on using the repository browser.