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

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

Changes to XTIDE Universal BIOS:

  • Integrated XT-CFv3 support by James Pearce.
  • XT-CFv2 memory mapped I/O and DMA modes are no longer supported (but PIO mode is).
File size: 9.1 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    cmp     BYTE [di+DPT_ATA.bDevice], DEVICE_8BIT_JRIDE_ISA
70    mov     ds, [di+DPT.wBasePort]  ; Segment for JR-IDE/ISA and ADP50L
71    mov     di, ADP50L_SECTOR_ACCESS_WINDOW_OFFSET
72    eCMOVE  di, JRIDE_SECTOR_ACCESS_WINDOW_OFFSET
73
74    ; Are we reading or writing?
75.SectorAccessWindowLoadedToDSDI:
76    test    cl, 16  ; Bit 4 is cleared on all the read commands but set on 3 of the 4 write commands
77    jnz     SHORT WriteToSectorAccessWindow
78    cmp     cl, COMMAND_WRITE_MULTIPLE
79    je      SHORT WriteToSectorAccessWindow
80    ; Fall to ReadFromSectorAccessWindow
81
82;--------------------------------------------------------------------
83; ReadFromSectorAccessWindow
84;   Parameters:
85;       DS:DI:  Ptr to Sector Access Window
86;       ES:SI:  Normalized ptr to buffer to receive data
87;       SS:BP:  Ptr to MEMPIOVARS
88;   Returns:
89;       DS:DI:  Ptr to DPT (in RAMVARS segment)
90;       AH:     BIOS Error code
91;       CX:     Number of successfully transferred sectors
92;       CF:     0 if transfer successful
93;               1 if any error
94;   Corrupts registers:
95;       AL, BX, DX, SI
96;--------------------------------------------------------------------
97ReadFromSectorAccessWindow:
98    xchg    si, di  ; DS:SI = source, ES:DI = Destination
99    call    WaitUntilReadyToTransferNextBlock
100    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
101
102    mov     cx, [bp+MEMPIOVARS.wSectorsInBlock] ; Clears CH
103    cmp     [bp+MEMPIOVARS.bSectorsLeft], cl
104    jbe     SHORT .ReadLastBlockFromDrive
105
106ALIGN JUMP_ALIGN
107.ReadNextBlockFromDrive:
108    call    ReadSingleBlockFromSectorAccessWindowInDSSItoESDI
109    call    WaitUntilReadyToTransferNextBlock
110    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
111
112    ; Update number of successfully read sectors and sectors left to transfer.
113    ; We cannot use SUB instruction as a comparison since it will not
114    ; work in this situation:
115    ; Before SUB we have 2 full blocks left to transfer. SUB command
116    ; then compares 2 full blocks against one full block and updates
117    ; sectors left to one full block and jumps to .ReadNextBlockFromDrive,
118    ; since we have one full block left to transfer. After it has been
119    ; transferred, there will be a wait for next block but DRQ is never
120    ; set since all is transferred! Then we get timeout error.
121    mov     cx, [bp+MEMPIOVARS.wSectorsInBlock]
122    sub     [bp+MEMPIOVARS.bSectorsLeft], cl
123    add     [bp+MEMPIOVARS.bSectorsDone], cl
124    cmp     [bp+MEMPIOVARS.bSectorsLeft], cl
125    ja      SHORT .ReadNextBlockFromDrive
126
127ALIGN JUMP_ALIGN
128.ReadLastBlockFromDrive:
129    mov     cl, [bp+MEMPIOVARS.bSectorsLeft]
130    push    cx
131    call    ReadSingleBlockFromSectorAccessWindowInDSSItoESDI
132
133    ; Check for errors in last block
134CheckErrorsAfterTransferringLastMemoryMappedBlock:
135    lds     di, [bp+MEMPIOVARS.fpDPT]           ; DPT now in DS:DI
136    mov     bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_BSY)
137    call    IdeWait_PollStatusFlagInBLwithTimeoutInBH
138    pop     cx  ; [bp+MEMPIOVARS.bSectorsLeft]
139    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
140
141    ; All sectors successfully transferred
142    add     cl, [bp+MEMPIOVARS.bSectorsDone]    ; Never sets CF
143    ret
144
145    ; Return number of successfully transferred sectors
146ReturnWithMemoryIOtransferErrorInAH:
147    lds     di, [bp+MEMPIOVARS.fpDPT]           ; DPT now in DS:DI
148%ifdef USE_386
149    movzx   cx, BYTE [bp+MEMPIOVARS.bSectorsDone]
150%else
151    mov     ch, 0                               ; Preserve CF
152    mov     cl, [bp+MEMPIOVARS.bSectorsDone]
153%endif
154    ret
155
156
157;--------------------------------------------------------------------
158; WriteToSectorAccessWindow
159;   Parameters:
160;       DS:DI:  Ptr to Sector Access Window
161;       ES:SI:  Normalized ptr to buffer containing data
162;       SS:BP:  Ptr to MEMPIOVARS
163;   Returns:
164;       DS:DI:  Ptr to DPT (in RAMVARS segment)
165;       AH:     BIOS Error code
166;       CX:     Number of successfully transferred sectors
167;       CF:     0 if transfer successful
168;               1 if any error
169;   Corrupts registers:
170;       AL, BX, DX, SI, ES
171;--------------------------------------------------------------------
172ALIGN JUMP_ALIGN
173WriteToSectorAccessWindow:
174    push    es
175    push    ds
176    pop     es      ; ES:DI = Sector Access Window (destination)
177    pop     ds      ; DS:SI = Ptr to source buffer
178
179    ; Always poll when writing first block (IRQs are generated for following blocks)
180    call    WaitUntilReadyToTransferNextBlock
181    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
182
183    mov     cx, [bp+MEMPIOVARS.wSectorsInBlock]
184    cmp     [bp+MEMPIOVARS.bSectorsLeft], cl
185    jbe     SHORT .WriteLastBlockToDrive
186
187ALIGN JUMP_ALIGN
188.WriteNextBlockToDrive:
189    call    WriteSingleBlockFromDSSIToSectorAccessWindowInESDI
190    call    WaitUntilReadyToTransferNextBlock
191    jc      SHORT ReturnWithMemoryIOtransferErrorInAH
192
193    ; Increment number of successfully written WORDs
194    mov     cx, [bp+MEMPIOVARS.wSectorsInBlock]
195    sub     [bp+MEMPIOVARS.bSectorsLeft], cl
196    add     [bp+MEMPIOVARS.bSectorsDone], cl
197    cmp     [bp+MEMPIOVARS.bSectorsLeft], cl
198    ja      SHORT .WriteNextBlockToDrive
199
200ALIGN JUMP_ALIGN
201.WriteLastBlockToDrive:
202    mov     cl, [bp+MEMPIOVARS.bSectorsLeft]
203    push    cx
204    ePUSH_T bx, CheckErrorsAfterTransferringLastMemoryMappedBlock
205    ; Fall to WriteSingleBlockFromDSSIToSectorAccessWindowInESDI
206
207;--------------------------------------------------------------------
208; WriteSingleBlockFromDSSIToSectorAccessWindowInESDI
209;   Parameters:
210;       CX:     Number of sectors in block
211;       DS:SI:  Normalized ptr to source buffer
212;       ES:DI:  Ptr to Sector Access Window
213;   Returns:
214;       CX, DX: Zero
215;       SI:     Updated
216;   Corrupts registers:
217;       BX
218;--------------------------------------------------------------------
219ALIGN JUMP_ALIGN
220WriteSingleBlockFromDSSIToSectorAccessWindowInESDI:
221    mov     bx, di
222    mov     dx, cx
223    xor     cx, cx
224ALIGN JUMP_ALIGN
225.WriteNextSector:
226    inc     ch
227    rep movsw
228    mov     di, bx  ; Reset for next sector
229    dec     dx
230    jnz     SHORT .WriteNextSector
231    ret
232
233
234;--------------------------------------------------------------------
235; ReadSingleBlockFromSectorAccessWindowInDSSItoESDI
236;   Parameters:
237;       CX      Number of sectors in full block or sectors in last partial block
238;       ES:DI:  Normalized ptr to buffer to receive data (destination)
239;       DS:SI:  Ptr to Sector Access Window (source)
240;   Returns:
241;       CX, DX: Zero
242;       DI:     Updated
243;   Corrupts registers:
244;       BX
245;--------------------------------------------------------------------
246ALIGN JUMP_ALIGN
247ReadSingleBlockFromSectorAccessWindowInDSSItoESDI:
248    mov     bx, si
249    mov     dx, cx
250    xor     cx, cx
251ALIGN JUMP_ALIGN
252.ReadNextSector:
253    inc     ch
254    rep movsw
255    mov     si, bx  ; Reset for next sector
256    dec     dx
257    jnz     SHORT .ReadNextSector
258    ret
259
260
261;--------------------------------------------------------------------
262; WaitUntilReadyToTransferNextBlock
263;   Parameters:
264;       SS:BP:  Ptr to MEMPIOVARS
265;   Returns:
266;       AH:     INT 13h Error Code
267;       CF:     Cleared if success, Set if error
268;   Corrupts registers:
269;       AL, BX, CX, DX
270;--------------------------------------------------------------------
271ALIGN JUMP_ALIGN
272WaitUntilReadyToTransferNextBlock:
273    push    ds
274    push    di
275    lds     di, [bp+MEMPIOVARS.fpDPT]   ; DPT now in DS:DI
276    call    IdeWait_IRQorDRQ            ; Always polls
277    pop     di
278    pop     ds
279    ret
280
Note: See TracBrowser for help on using the repository browser.