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

Last change on this file since 625 was 625, checked in by krille_n_, 13 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.