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

Last change on this file since 619 was 601, checked in by Krister Nordvall, 6 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.