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

Last change on this file since 601 was 601, checked in by krille_n_, 5 years ago

Changes:

  • Building the BIOS now works again.
  • Added a new IDE device type/transfer mode for use only with XT-IDE rev 2+ (or Chuck(G)-modded rev 1) cards installed in any of the following machines: Olivetti M24, AT&T PC6300, Xerox 6060 and Logabax Persona 1600. This new transfer mode is slightly faster than the regular XT-IDE rev 1 device type and requires that the card is configured for High Speed mode (or, in case of the card being a rev 1 card, has the Chuck(G) mod done). The new device type is called "XTIDE rev 2 (Olivetti M24)" in XTIDECFG.
  • Made some minor improvements to the library code that handles 'Drive Not Ready' errors in XTIDECFG.
  • Optimizations.
File size: 9.0 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     dx, [bp+MEMPIOVARS.wSectorsInBlock] ; Clears DH
103    cmp     [bp+MEMPIOVARS.bSectorsLeft], dl
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     dx, [bp+MEMPIOVARS.wSectorsInBlock]
122    sub     [bp+MEMPIOVARS.bSectorsLeft], dl
123    add     [bp+MEMPIOVARS.bSectorsDone], dl
124    cmp     [bp+MEMPIOVARS.bSectorsLeft], dl
125    ja      SHORT .ReadNextBlockFromDrive
126
127ALIGN JUMP_ALIGN
128.ReadLastBlockFromDrive:
129    mov     dl, [bp+MEMPIOVARS.bSectorsLeft]
130    push    dx
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, [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     dx, [bp+MEMPIOVARS.wSectorsInBlock]
184    cmp     [bp+MEMPIOVARS.bSectorsLeft], dl
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     dx, [bp+MEMPIOVARS.wSectorsInBlock]
195    sub     [bp+MEMPIOVARS.bSectorsLeft], dl
196    add     [bp+MEMPIOVARS.bSectorsDone], dl
197    cmp     [bp+MEMPIOVARS.bSectorsLeft], dl
198    ja      SHORT .WriteNextBlockToDrive
199
200ALIGN JUMP_ALIGN
201.WriteLastBlockToDrive:
202    mov     dl, [bp+MEMPIOVARS.bSectorsLeft]
203    push    dx
204    ePUSH_T bx, CheckErrorsAfterTransferringLastMemoryMappedBlock
205    ; Fall to WriteSingleBlockFromDSSIToSectorAccessWindowInESDI
206
207;--------------------------------------------------------------------
208; WriteSingleBlockFromDSSIToSectorAccessWindowInESDI
209;   Parameters:
210;       DX:     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    xor     cx, cx
223ALIGN JUMP_ALIGN
224.WriteNextSector:
225    inc     ch
226    rep movsw
227    mov     di, bx  ; Reset for next sector
228    dec     dx
229    jnz     SHORT .WriteNextSector
230    ret
231
232
233;--------------------------------------------------------------------
234; ReadSingleBlockFromSectorAccessWindowInDSSItoESDI
235;   Parameters:
236;       DX:     Number of sectors in block
237;       ES:DI:  Normalized ptr to destination buffer
238;       DS:SI:  Ptr to Sector Access Window
239;   Returns:
240;       CX, DX: Zero
241;       DI:     Updated
242;   Corrupts registers:
243;       BX
244;--------------------------------------------------------------------
245ALIGN JUMP_ALIGN
246ReadSingleBlockFromSectorAccessWindowInDSSItoESDI:
247    mov     bx, si
248    xor     cx, cx
249ALIGN JUMP_ALIGN
250.ReadNextSector:
251    inc     ch
252    rep movsw
253    mov     si, bx  ; Reset for next sector
254    dec     dx
255    jnz     SHORT .ReadNextSector
256    ret
257
258
259;--------------------------------------------------------------------
260; WaitUntilReadyToTransferNextBlock
261;   Parameters:
262;       SS:BP:  Ptr to MEMPIOVARS
263;   Returns:
264;       AH:     INT 13h Error Code
265;       CF:     Cleared if success, Set if error
266;   Corrupts registers:
267;       AL, BX, CX, DX
268;--------------------------------------------------------------------
269ALIGN JUMP_ALIGN
270WaitUntilReadyToTransferNextBlock:
271    push    ds
272    push    di
273    lds     di, [bp+MEMPIOVARS.fpDPT]   ; DPT now in DS:DI
274    call    IdeWait_IRQorDRQ            ; Always polls
275    pop     di
276    pop     ds
277    ret
278
Note: See TracBrowser for help on using the repository browser.