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

Last change on this file since 510 was 488, checked in by gregli@…, 12 years ago

Removed unused '4' entry from Strings.asm and recompressed. Added 8x multiplier value for serial drives. Wrapped some preprocessor symbol references so that 'make xt_unused' analysis continues to work.

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