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_, 14 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.