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

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

Changes to XTIDE Universal BIOS:

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