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

Last change on this file since 477 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.