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

Last change on this file since 628 was 625, checked in by Krister Nordvall, 17 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
RevLine 
[150]1; Project name : XTIDE Universal BIOS
2; Description : IDE Device transfer functions.
3
[376]4;
[445]5; XTIDE Universal BIOS and Associated Tools
[625]6; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2023 by XTIDE Universal BIOS Team.
[376]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.
[445]12;
[376]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
[445]16; GNU General Public License for more details.
[376]17; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
[445]18;
[376]19
[150]20; Structure containing variables for PIO transfer functions.
21; This struct must not be larger than IDEPACK without INTPACK.
[414]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
[363]26 .bSectorsLeft resb 1 ; 6, Sectors left to transfer
[218]27 resb 1 ; 7, IDEPACK.bDeviceControl
[363]28 .bSectorsDone resb 1 ; 8, Number of sectors xferred
[150]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
[171]39; (all PIO read and write commands including Identify Device)
[480]40; ES:SI: Ptr to data buffer
[150]41; DS:DI: Ptr to DPT (in RAMVARS segment)
42; SS:BP: Ptr to IDEPACK
43; Returns:
44; AH: INT 13h Error Code
[218]45; CX: Number of successfully transferred sectors
[150]46; CF: Cleared if success, Set if error
47; Corrupts registers:
[218]48; AL, BX, DX, SI, ES
[150]49;--------------------------------------------------------------------
50ALIGN JUMP_ALIGN
51IdeTransfer_StartWithCommandInAL:
[625]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
[157]60 ; Are we reading or writing?
[171]61 test al, 16 ; Bit 4 is cleared on all the read commands but set on 3 of the 4 write commands
[242]62 mov ah, [bp+IDEPACK.bSectorCount]
63 jnz SHORT WriteToDrive
[171]64 cmp al, COMMAND_WRITE_MULTIPLE
[242]65 je SHORT WriteToDrive
66 ; Fall to ReadFromDrive
[150]67
68;--------------------------------------------------------------------
[242]69; ReadFromDrive
[150]70; Parameters:
[242]71; AH: Number of sectors to transfer (1...128)
[480]72; ES:SI: Ptr to buffer to receive data
[150]73; DS:DI: Ptr to DPT (in RAMVARS segment)
74; SS:BP: Ptr to PIOVARS
75; Returns:
[242]76; DS:DI: Ptr to DPT (in RAMVARS segment)
[150]77; AH: BIOS Error code
[218]78; CX: Number of successfully transferred sectors
[294]79; CF: 0 if transfer successful
[150]80; 1 if any error
81; Corrupts registers:
[218]82; AL, BX, DX, SI, ES
[150]83;--------------------------------------------------------------------
[242]84ReadFromDrive:
85 ; Prepare to read data to ESSI
86 mov bx, g_rgfnPioRead
87 call InitializePiovarsInSSBPwithSectorCountInAH
[538]88%ifdef USE_AT
89 jc SHORT ReturnWithTransferErrorInAH
90%endif
[242]91
92 ; Wait until drive is ready to transfer
93 call IdeWait_IRQorDRQ ; Wait until ready to transfer
[218]94 jc SHORT ReturnWithTransferErrorInAH
[242]95 xchg si, di ; ES:DI now points buffer
[218]96
[363]97 mov cx, [bp+PIOVARS.wSectorsInBlock] ; Max 128
[242]98
[150]99ALIGN JUMP_ALIGN
[242]100.ReadNextBlockFromDrive:
[150]101 mov dx, [bp+PIOVARS.wDataPort]
[363]102 cmp [bp+PIOVARS.bSectorsLeft], cl
[242]103 jbe SHORT .ReadLastBlockFromDrive
[218]104 call [bp+PIOVARS.fnXfer]
[169]105
[218]106 ; Wait until ready for next block and check for errors
[242]107 xchg di, si ; DS:DI now points DPT
[218]108 call IdeWait_IRQorDRQ ; Wait until ready to transfer
109 jc SHORT ReturnWithTransferErrorInAH
[242]110 xchg si, di ; ES:DI now points buffer
[169]111
[363]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
[242]116 jmp SHORT .ReadNextBlockFromDrive
[150]117
118ALIGN JUMP_ALIGN
[242]119.ReadLastBlockFromDrive:
[363]120 mov cl, [bp+PIOVARS.bSectorsLeft] ; CH is already zero
[419]121 push cx
[150]122 call [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
123
[242]124 ; Check for errors in last block
125 mov di, si ; DS:DI now points DPT
126CheckErrorsAfterTransferringLastBlock:
[417]127 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_BSY)
[242]128 call IdeWait_PollStatusFlagInBLwithTimeoutInBH
[419]129 pop cx ; [bp+PIOVARS.bSectorsLeft]
130 jc SHORT ReturnWithTransferErrorInAH
[150]131
[445]132 ; All sectors successfully transferred
[419]133 add cx, [bp+PIOVARS.bSectorsDone] ; Never sets CF
[625]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
[419]140 ret
141
[242]142 ; Return number of successfully read sectors
143ReturnWithTransferErrorInAH:
[370]144%ifdef USE_386
145 movzx cx, [bp+PIOVARS.bSectorsDone]
146%else
[363]147 mov cl, [bp+PIOVARS.bSectorsDone]
148 mov ch, 0 ; Preserve CF
[370]149%endif
[625]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
[242]157 ret
158
159
[150]160;--------------------------------------------------------------------
[242]161; WriteToDrive
[150]162; Parameters:
[242]163; AH: Number of sectors to transfer (1...128)
164; DS:DI: Ptr to DPT (in RAMVARS segment)
[480]165; ES:SI: Ptr to buffer containing data
[150]166; SS:BP: Ptr to PIOVARS
167; Returns:
168; AH: BIOS Error code
[218]169; CX: Number of successfully transferred sectors
[294]170; CF: 0 if transfer successful
[150]171; 1 if any error
172; Corrupts registers:
[218]173; AL, BX, DX, SI, ES
[150]174;--------------------------------------------------------------------
175ALIGN JUMP_ALIGN
[242]176WriteToDrive:
177 ; Prepare to write data from ESSI
178 mov bx, g_rgfnPioWrite
179 call InitializePiovarsInSSBPwithSectorCountInAH
[538]180%ifdef USE_AT
181 jc SHORT ReturnWithTransferErrorInAH
182%endif
[242]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
[218]187 jc SHORT ReturnWithTransferErrorInAH
[150]188
[363]189 mov cx, [bp+PIOVARS.wSectorsInBlock] ; Max 128
[242]190
[218]191ALIGN JUMP_ALIGN
[242]192.WriteNextBlockToDrive:
[150]193 mov dx, [bp+PIOVARS.wDataPort]
[363]194 cmp [bp+PIOVARS.bSectorsLeft], cl
[242]195 jbe SHORT .WriteLastBlockToDrive
[589]196 push ds
197 push es
198 pop ds
[218]199 call [bp+PIOVARS.fnXfer]
[589]200 pop ds
[218]201 ; Wait until ready for next block and check for errors
202 call IdeWait_IRQorDRQ ; Wait until ready to transfer
203 jc SHORT ReturnWithTransferErrorInAH
[150]204
[363]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
[242]209 jmp SHORT .WriteNextBlockToDrive
[169]210
[150]211ALIGN JUMP_ALIGN
[242]212.WriteLastBlockToDrive:
[363]213 mov cl, [bp+PIOVARS.bSectorsLeft] ; CH is already zero
[419]214 push cx
[589]215 push ds
216 push es
217 pop ds
[150]218 call [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
[589]219 pop ds
[242]220 jmp SHORT CheckErrorsAfterTransferringLastBlock
[218]221
[150]222
223;--------------------------------------------------------------------
[218]224; InitializePiovarsInSSBPwithSectorCountInAH
[150]225; Parameters:
[218]226; AH: Number of sectors to transfer (1...128)
[150]227; BX: Offset to transfer function lookup table
228; DS:DI: Ptr to DPT (in RAMVARS segment)
[480]229; ES:SI: Ptr to data buffer
[169]230; SS:BP: Ptr to PIOVARS
[167]231; Returns:
[538]232; ES:SI: Normalized pointer
233; AH: INT 13h Error Code (only when CF set)
[558]234; CF: Set if failed to normalize pointer (segment overflow)
[538]235; Cleared if success
[150]236; Corrupts registers:
[538]237; AL, BX, DX
[150]238;--------------------------------------------------------------------
239ALIGN JUMP_ALIGN
[218]240InitializePiovarsInSSBPwithSectorCountInAH:
[473]241 ; Store sizes and Data Port
[363]242 mov [bp+PIOVARS.bSectorsLeft], ah
[538]243%ifdef USE_AT
244 xchg dx, ax
245%endif
[473]246 mov ax, [di+DPT.wBasePort]
247 mov [bp+PIOVARS.wDataPort], ax
[370]248 eMOVZX ax, [di+DPT_ATA.bBlockSize]
[363]249 mov [bp+PIOVARS.wSectorsInBlock], ax
250 mov [bp+PIOVARS.bSectorsDone], ah ; Zero
[150]251
252 ; Get transfer function based on bus type
[567]253 mov al, [di+DPT_ATA.bDevice]
254 add bx, ax
[493]255%ifdef MODULE_8BIT_IDE_ADVANCED
[567]256 cmp al, DEVICE_8BIT_XTCF_DMA
[480]257%endif
[150]258 mov ax, [cs:bx] ; Load offset to transfer function
259 mov [bp+PIOVARS.fnXfer], ax
[480]260
261 ; Normalize pointer for PIO-transfers and convert to physical address for DMA transfers
[493]262%ifdef MODULE_8BIT_IDE_ADVANCED
[480]263 jb SHORT IdeTransfer_NormalizePointerInESSI
264
265 ; Convert ES:SI to physical address
[568]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
[602]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
[589]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
[602]295%endif
[491]296%else ; 808x
[589]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
[567]309%endif
310
311 ret ; With CF cleared (taken care of by the physical address conversion)
[493]312%endif ; MODULE_8BIT_IDE_ADVANCED
[558]313 ; Fall to IdeTransfer_NormalizePointerInESSI if no MODULE_8BIT_IDE_ADVANCED
[150]314
315
[480]316;--------------------------------------------------------------------
317; IdeTransfer_NormalizePointerInESSI
318; Parameters:
[538]319; DH: Number of sectors to transfer (when USE_AT defined)
[480]320; ES:SI: Ptr to be normalized
321; Returns:
322; ES:SI: Normalized pointer (SI = 0...15)
[558]323; AH: INT 13h Error Code (when USE_AT defined and normalization was attempted)
324; CF: Set if failed to normalize pointer (segment overflow)
[538]325; Cleared if success
[480]326; Corrupts registers:
327; AX, DX
328;--------------------------------------------------------------------
329IdeTransfer_NormalizePointerInESSI:
[538]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
[558]337 eSHL_IM dx, 1
[538]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
[480]345 NORMALIZE_FAR_POINTER es, si, ax, dx
[538]346%ifdef USE_AT ; CF is always clear for XT builds
[558]347 ; AH = RET_HD_INVALID (01) if CF set, RET_HD_SUCCESS (00) if not. CF unchanged.
[589]348%ifdef USE_386
349 setc ah
350%else
[558]351 sbb ah, ah
352 neg ah
[538]353%endif
[589]354%endif ; USE_AT
[480]355 ret
[400]356
[480]357
[538]358
[150]359; Lookup tables to get transfer function based on bus type
360ALIGN WORD_ALIGN
361g_rgfnPioRead:
[601]362 dw IdePioBlock_ReadFrom16bitDataPort ; 0, DEVICE_16BIT_ATA
[589]363%ifdef MODULE_ADVANCED_ATA
[601]364 dw IdePioBlock_ReadFrom32bitDataPort ; 1, DEVICE_32BIT_ATA
[589]365%elifdef MODULE_8BIT_IDE
366 dw NULL
367%endif ; MODULE_ADVANCED_ATA
[400]368%ifdef MODULE_8BIT_IDE
[601]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
[584]373%ifdef MODULE_8BIT_IDE_ADVANCED
[601]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
[545]378%endif ; MODULE_8BIT_IDE_ADVANCED
379%endif ; MODULE_8BIT_IDE
[400]380
[480]381
[473]382g_rgfnPioWrite:
[601]383 dw IdePioBlock_WriteTo16bitDataPort ; 0, DEVICE_16BIT_ATA
[589]384%ifdef MODULE_ADVANCED_ATA
[601]385 dw IdePioBlock_WriteTo32bitDataPort ; 1, DEVICE_32BIT_ATA
[589]386%elifdef MODULE_8BIT_IDE
387 dw NULL
388%endif ; MODULE_ADVANCED_ATA
[400]389%ifdef MODULE_8BIT_IDE
[601]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
[584]394%ifdef MODULE_8BIT_IDE_ADVANCED
[601]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
[545]399%endif ; MODULE_8BIT_IDE_ADVANCED
400%endif ; MODULE_8BIT_IDE
Note: See TracBrowser for help on using the repository browser.