source: xtideuniversalbios/trunk/XTIDE_Universal_BIOS/Src/Device/IDE/JrIdeTransfer.asm @ 476

Last change on this file since 476 was 476, checked in by aitotat@…, 12 years ago

Changes to XTIDE Universal BIOS:

  • Memory Mapped Transfers now work again.
File size: 9.5 KB
RevLine 
[400]1; Project name  :   XTIDE Universal BIOS
2; Description   :   Memory mapped IDE Device transfer functions.
3
4;
[412]5; XTIDE Universal BIOS and Associated Tools
[400]6; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 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.
[412]12;
[400]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
[412]16; GNU General Public License for more details.
[400]17; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
[412]18;
[400]19
20; Structure containing variables for PIO transfer functions.
21; This struct must not be larger than IDEPACK without INTPACK.
[414]22struc MEMPIOVARS    ; Must not be larger than 9 bytes! See IDEPACK in RamVars.inc.
23    .wSectorsInBlock        resb    2   ; 0-1, Block size in sectors
24    .fpDPT                  resb    4   ; 2-5, Far pointer to DPT
25    .bSectorsLeft           resb    1   ; 6, Sectors left to transfer
[400]26                            resb    1   ; 7, IDEPACK.bDeviceControl
[414]27    .bSectorsDone           resb    1   ; 8, Number of sectors xferred
[400]28endstruc
29
[473]30SECTOR_ACCESS_WINDOW_SIZE   EQU     512 ; 512 bytes
[400]31
[473]32
[400]33; Section containing code
34SECTION .text
35
36;--------------------------------------------------------------------
37; JrIdeTransfer_StartWithCommandInAL
38;   Parameters:
39;       AL:     IDE command that was used to start the transfer
40;               (all PIO read and write commands including Identify Device)
[474]41;       ES:SI:  Ptr to normalized data buffer
[400]42;       DS:DI:  Ptr to DPT (in RAMVARS segment)
43;       SS:BP:  Ptr to IDEPACK
44;   Returns:
45;       AH:     INT 13h Error Code
46;       CX:     Number of successfully transferred sectors
47;       CF:     Cleared if success, Set if error
48;   Corrupts registers:
49;       AL, BX, DX, SI, ES
50;--------------------------------------------------------------------
51ALIGN JUMP_ALIGN
52JrIdeTransfer_StartWithCommandInAL:
[473]53    ; Initialize MEMPIOVARS
54    xchg    cx, ax          ; IDE command to CL
55    xor     ax, ax
56    mov     [bp+MEMPIOVARS.bSectorsDone], al
57    mov     al, [bp+IDEPACK.bSectorCount]
58    mov     [bp+MEMPIOVARS.bSectorsLeft], al
59    mov     al, [di+DPT_ATA.bBlockSize]
60    mov     [bp+MEMPIOVARS.wSectorsInBlock], ax
[400]61    mov     [bp+MEMPIOVARS.fpDPT], di
62    mov     [bp+MEMPIOVARS.fpDPT+2], ds
63
[473]64    ; Get far pointer to Sector Access Window
65    mov     dx, [di+DPT.wBasePort]
66    cmp     BYTE [di+DPT_ATA.bDevice], DEVICE_8BIT_JRIDE_ISA
67    jne     SHORT .GetSectorAccessWindowForXTCF
68
69    ; Get Sector Access Window for JR-IDE/ISA
70    mov     di, JRIDE_SECTOR_ACCESS_WINDOW_OFFSET
71    mov     ds, dx      ; Segment for JR-IDE/ISA
72    jmp     SHORT .SectorAccessWindowLoadedToDSDI
73
74.GetSectorAccessWindowForXTCF:
75    xor     di, di
76    add     dl, XTCF_CONTROL_REGISTER
77    in      al, dx                  ; Read high byte for Sector Access Window segment
78    xchg    ah, al
79    mov     ds, ax
80
[400]81    ; Are we reading or writing?
[473]82.SectorAccessWindowLoadedToDSDI:
83    test    cl, 16  ; Bit 4 is cleared on all the read commands but set on 3 of the 4 write commands
[400]84    jnz     SHORT WriteToSectorAccessWindow
[473]85    cmp     cl, COMMAND_WRITE_MULTIPLE
[400]86    je      SHORT WriteToSectorAccessWindow
87    ; Fall to ReadFromSectorAccessWindow
88
89;--------------------------------------------------------------------
90; ReadFromSectorAccessWindow
91;   Parameters:
[473]92;       DS:DI:  Ptr to Sector Access Window
[400]93;       ES:SI:  Normalized ptr to buffer to receive data
94;       SS:BP:  Ptr to MEMPIOVARS
95;   Returns:
96;       DS:DI:  Ptr to DPT (in RAMVARS segment)
97;       AH:     BIOS Error code
98;       CX:     Number of successfully transferred sectors
99;       CF:     0 if transfer successful
100;               1 if any error
101;   Corrupts registers:
[475]102;       AL, BX, DX, SI
[400]103;--------------------------------------------------------------------
104ReadFromSectorAccessWindow:
[473]105    xchg    si, di  ; DS:SI = source, ES:DI = Destination
[400]106    call    WaitUntilReadyToTransferNextBlock
107    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
108
[475]109    mov     cx, [bp+MEMPIOVARS.wSectorsInBlock] ; Clears CH
[412]110    cmp     [bp+MEMPIOVARS.bSectorsLeft], cl
111    jbe     SHORT .ReadLastBlockFromDrive
[400]112
113ALIGN JUMP_ALIGN
114.ReadNextBlockFromDrive:
115    call    ReadSingleBlockFromSectorAccessWindowInDSSItoESDI
116    call    WaitUntilReadyToTransferNextBlock
117    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
118
[476]119    ; Update number of successfully read sectors and sectors left to transfer.
120    ; We cannot use SUB instruction as a comparison since it will not
121    ; work in this situation:
122    ; Before SUB we have 2 full blocks left to transfer. SUB command
123    ; then compares 2 full blocks against one full block and updates
124    ; sectors left to one full block and jumps to .ReadNextBlockFromDrive,
125    ; since we have one full block left to transfer. After it has been
126    ; transferred, there will be a wait for next block but DRQ is never
127    ; set since all is transferred! Then we get timeout error.
[400]128    mov     cx, [bp+MEMPIOVARS.wSectorsInBlock]
[476]129    sub     [bp+MEMPIOVARS.bSectorsLeft], cl
[412]130    add     [bp+MEMPIOVARS.bSectorsDone], cl
[476]131    cmp     [bp+MEMPIOVARS.bSectorsLeft], cl
[412]132    ja      SHORT .ReadNextBlockFromDrive
[400]133
134ALIGN JUMP_ALIGN
135.ReadLastBlockFromDrive:
136    mov     cl, [bp+MEMPIOVARS.bSectorsLeft]
[419]137    push    cx
[400]138    call    ReadSingleBlockFromSectorAccessWindowInDSSItoESDI
139
140    ; Check for errors in last block
141CheckErrorsAfterTransferringLastMemoryMappedBlock:
142    lds     di, [bp+MEMPIOVARS.fpDPT]           ; DPT now in DS:DI
[417]143    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_BSY)
[400]144    call    IdeWait_PollStatusFlagInBLwithTimeoutInBH
[419]145    pop     cx  ; [bp+MEMPIOVARS.bSectorsLeft]
146    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
[400]147
[445]148    ; All sectors successfully transferred
[475]149    add     cl, [bp+MEMPIOVARS.bSectorsDone]    ; Never sets CF
[419]150    ret
151
[400]152    ; Return number of successfully transferred sectors
153ReturnWithMemoryIOtransferErrorInAH:
154    lds     di, [bp+MEMPIOVARS.fpDPT]           ; DPT now in DS:DI
155%ifdef USE_386
[475]156    movzx   cx, BYTE [bp+MEMPIOVARS.bSectorsDone]
[400]157%else
[475]158    mov     ch, 0                               ; Preserve CF
[400]159    mov     cl, [bp+MEMPIOVARS.bSectorsDone]
160%endif
161    ret
162
163
164;--------------------------------------------------------------------
165; WriteToSectorAccessWindow
166;   Parameters:
[473]167;       DS:DI:  Ptr to Sector Access Window
[400]168;       ES:SI:  Normalized ptr to buffer containing data
169;       SS:BP:  Ptr to MEMPIOVARS
170;   Returns:
171;       DS:DI:  Ptr to DPT (in RAMVARS segment)
172;       AH:     BIOS Error code
173;       CX:     Number of successfully transferred sectors
174;       CF:     0 if transfer successful
175;               1 if any error
176;   Corrupts registers:
177;       AL, BX, DX, SI, ES
178;--------------------------------------------------------------------
179ALIGN JUMP_ALIGN
180WriteToSectorAccessWindow:
181    push    es
[473]182    push    ds
183    pop     es      ; ES:DI = Sector Access Window (destination)
184    pop     ds      ; DS:SI = Ptr to source buffer
[400]185
186    ; Always poll when writing first block (IRQs are generated for following blocks)
187    call    WaitUntilReadyToTransferNextBlock
188    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
189
190    mov     cx, [bp+MEMPIOVARS.wSectorsInBlock]
[412]191    cmp     [bp+MEMPIOVARS.bSectorsLeft], cl
192    jbe     SHORT .WriteLastBlockToDrive
[400]193
194ALIGN JUMP_ALIGN
195.WriteNextBlockToDrive:
196    call    WriteSingleBlockFromDSSIToSectorAccessWindowInESDI
197    call    WaitUntilReadyToTransferNextBlock
198    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
199
200    ; Increment number of successfully written WORDs
201    mov     cx, [bp+MEMPIOVARS.wSectorsInBlock]
[476]202    sub     [bp+MEMPIOVARS.bSectorsLeft], cl
[412]203    add     [bp+MEMPIOVARS.bSectorsDone], cl
[476]204    cmp     [bp+MEMPIOVARS.bSectorsLeft], cl
[412]205    ja      SHORT .WriteNextBlockToDrive
[400]206
207ALIGN JUMP_ALIGN
208.WriteLastBlockToDrive:
209    mov     cl, [bp+MEMPIOVARS.bSectorsLeft]
[419]210    push    cx
[400]211    ePUSH_T bx, CheckErrorsAfterTransferringLastMemoryMappedBlock
212    ; Fall to WriteSingleBlockFromDSSIToSectorAccessWindowInESDI
213
214;--------------------------------------------------------------------
215; WriteSingleBlockFromDSSIToSectorAccessWindowInESDI
216;   Parameters:
217;       CX:     Number of sectors in block
218;       DS:SI:  Normalized ptr to source buffer
219;       ES:DI:  Ptr to Sector Access Window
220;   Returns:
221;       CX, DX: Zero
222;       SI:     Updated
223;   Corrupts registers:
224;       BX
225;--------------------------------------------------------------------
226ALIGN JUMP_ALIGN
227WriteSingleBlockFromDSSIToSectorAccessWindowInESDI:
228    mov     bx, di
229    mov     dx, cx
230    xor     cl, cl
231ALIGN JUMP_ALIGN
[475]232.WriteNextSector:
[473]233    mov     ch, SECTOR_ACCESS_WINDOW_SIZE >> 9
[400]234    rep movsw
235    mov     di, bx  ; Reset for next sector
236    dec     dx
[475]237    jnz     SHORT .WriteNextSector
[400]238    ret
239
240
241;--------------------------------------------------------------------
242; ReadSingleBlockFromSectorAccessWindowInDSSItoESDI
243;   Parameters:
[475]244;       CX      Number of sectors in full block or sectors in last partial block
[400]245;       ES:DI:  Normalized ptr to buffer to receive data (destination)
246;       DS:SI:  Ptr to Sector Access Window (source)
247;   Returns:
248;       CX, DX: Zero
249;       DI:     Updated
250;   Corrupts registers:
251;       BX
252;--------------------------------------------------------------------
253ALIGN JUMP_ALIGN
254ReadSingleBlockFromSectorAccessWindowInDSSItoESDI:
255    mov     bx, si
256    mov     dx, cx
257    xor     cl, cl
258ALIGN JUMP_ALIGN
[475]259.ReadNextSector:
[473]260    mov     ch, SECTOR_ACCESS_WINDOW_SIZE >> 9
[400]261    rep movsw
262    mov     si, bx  ; Reset for next sector
263    dec     dx
[475]264    jnz     SHORT .ReadNextSector
[400]265    ret
266
267
268;--------------------------------------------------------------------
269; WaitUntilReadyToTransferNextBlock
270;   Parameters:
271;       SS:BP:  Ptr to MEMPIOVARS
272;   Returns:
273;       AH:     INT 13h Error Code
274;       CF:     Cleared if success, Set if error
275;   Corrupts registers:
276;       AL, BX, CX, DX
277;--------------------------------------------------------------------
278ALIGN JUMP_ALIGN
279WaitUntilReadyToTransferNextBlock:
280    push    ds
281    push    di
282    lds     di, [bp+MEMPIOVARS.fpDPT]   ; DPT now in DS:DI
283    call    IdeWait_IRQorDRQ            ; Always polls
284    pop     di
285    pop     ds
286    ret
287
288
[473]289%if SECTOR_ACCESS_WINDOW_SIZE <> 512
290    %error "SECTOR_ACCESS_WINDOW_SIZE is no longer equal to 512. JrIdeTransfer.asm needs changes."
[400]291%endif
Note: See TracBrowser for help on using the repository browser.