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

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

Changes to XTIDE Universal BIOS:

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