source: xtideuniversalbios/trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeTransfer.asm@ 158

Last change on this file since 158 was 158, checked in by Tomi Tilli, 14 years ago

Changes to XTIDE Universal BIOS:

  • Optimized few bytes.
File size: 11.3 KB
Line 
1; Project name : XTIDE Universal BIOS
2; Description : IDE Device transfer functions.
3
4; Structure containing variables for PIO transfer functions.
5; This struct must not be larger than IDEPACK without INTPACK.
6struc PIOVARS
7 .wBlocksLeft resb 2
8 .wBlockSize resb 2 ; Block size in WORDs (256...32768)
9 .wDataPort resb 2
10 .bSectorsInLastBlock: resb 1
11 resb 1 ; Offset 7 = IDEPACK.bDeviceControl
12 .fnXfer resb 2 ; Offset to transfer function
13endstruc
14
15
16; Section containing code
17SECTION .text
18
19;--------------------------------------------------------------------
20; IdeTransfer_StartWithCommandInAL
21; Parameters:
22; AL: IDE command that was used to start the transfer
23; ES:SI: Ptr to destination buffer or source data
24; DS:DI: Ptr to DPT (in RAMVARS segment)
25; SS:BP: Ptr to IDEPACK
26; Returns:
27; AH: INT 13h Error Code
28; CF: Cleared if success, Set if error
29; Corrupts registers:
30; AL, BX, CX, DX, SI, ES
31;--------------------------------------------------------------------
32ALIGN JUMP_ALIGN
33IdeTransfer_StartWithCommandInAL:
34 mov ah, [bp+IDEPACK.bSectorCountHighExt]
35
36 ; Are we reading or writing?
37 test al, 16 ; Bit 4 is cleared on all the read commands but set on 3 of the 4 write commands
38 jnz SHORT .PrepareToWriteDataFromESSI
39 cmp al, COMMAND_WRITE_MULTIPLE
40 je SHORT .PrepareToWriteDataFromESSI
41
42 ; Prepare to read data to ESSI
43 mov bx, g_rgfnPioRead
44 mov al, [bp+IDEPACK.bSectorCount]
45 call InitializePiovarsInSSBPwithSectorCountInAX
46 xchg si, di
47 call Registers_NormalizeESDI
48 jmp SHORT ReadFromDrive
49
50ALIGN JUMP_ALIGN
51.PrepareToWriteDataFromESSI:
52 mov bx, g_rgfnPioWrite
53 mov al, [bp+IDEPACK.bSectorCount]
54 call InitializePiovarsInSSBPwithSectorCountInAX
55 call Registers_NormalizeESSI
56 ; Fall to WriteToDrive
57
58
59;--------------------------------------------------------------------
60; WriteToDrive
61; Parameters:
62; DS:DI: Ptr to DPT (in RAMVARS segment)
63; ES:SI: Normalized ptr to buffer containing data
64; SS:BP: Ptr to PIOVARS
65; Returns:
66; AH: BIOS Error code
67; CF: 0 if transfer succesfull
68; 1 if any error
69; Corrupts registers:
70; AL, BX, CX, DX, SI, ES
71;--------------------------------------------------------------------
72WriteToDrive:
73 ; Always poll when writing first block (IRQs are generated for following blocks)
74 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
75 call IdeWait_PollStatusFlagInBLwithTimeoutInBH
76 jc SHORT .ReturnWithTransferErrorInAH
77ALIGN JUMP_ALIGN
78.WriteNextBlock:
79 mov dx, [bp+PIOVARS.wDataPort]
80 dec WORD [bp+PIOVARS.wBlocksLeft] ; Transferring last (possibly partial) block?
81 jz SHORT .XferLastBlock ; If so, jump to transfer
82 mov cx, [bp+PIOVARS.wBlockSize] ; Load block size in WORDs
83 call [bp+PIOVARS.fnXfer] ; Transfer full block
84
85 ; Normalize pointer when necessary
86 mov ax, si
87 shr ax, 1 ; WORD offset
88 add ax, [bp+PIOVARS.wBlockSize]
89 jns SHORT .WaitUntilReadyToTransferNextBlock
90 call Registers_NormalizeESSI
91
92ALIGN JUMP_ALIGN
93.WaitUntilReadyToTransferNextBlock:
94%ifdef USE_186
95 push .WriteNextBlock
96 jmp IdeWait_IRQorDRQ
97%else
98 call IdeWait_IRQorDRQ
99 jnc SHORT .WriteNextBlock
100%endif
101.ReturnWithTransferErrorInAH:
102 ret
103
104ALIGN JUMP_ALIGN
105.XferLastBlock:
106 xor cx, cx
107 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRDY)
108 mov ch, [bp+PIOVARS.bSectorsInLastBlock]; CX = Partial block size in WORDs
109%ifdef USE_186
110 push IdeWait_IRQorStatusFlagInBLwithTimeoutInBH
111 jmp [bp+PIOVARS.fnXfer]
112%else
113 call [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
114 jmp IdeWait_IRQorStatusFlagInBLwithTimeoutInBH ; Check for errors
115%endif
116
117
118;--------------------------------------------------------------------
119; ReadFromDrive
120; Parameters:
121; ES:DI: Normalized ptr to buffer to recieve data
122; DS:SI: Ptr to DPT (in RAMVARS segment)
123; SS:BP: Ptr to PIOVARS
124; Returns:
125; DS:DI: Ptr to DPT (in RAMVARS segment)
126; AH: BIOS Error code
127; CF: 0 if transfer succesfull
128; 1 if any error
129; Corrupts registers:
130; AL, BX, CX, DX, SI, ES
131;--------------------------------------------------------------------
132ALIGN JUMP_ALIGN
133ReadFromDrive:
134 ; Wait until drive is ready to transfer
135 xchg di, si ; DS:DI now points DPT
136 call IdeWait_IRQorDRQ ; Wait until ready to transfer
137 jc SHORT WriteToDrive.ReturnWithTransferErrorInAH
138 xchg si, di ; ES:DI now points buffer
139
140 ; Transfer full or last (possible partial) block
141 mov dx, [bp+PIOVARS.wDataPort]
142 dec WORD [bp+PIOVARS.wBlocksLeft]
143 jz SHORT .XferLastBlock
144 mov cx, [bp+PIOVARS.wBlockSize] ; Load block size in WORDs
145 call [bp+PIOVARS.fnXfer] ; Transfer full block
146
147 ; Normalize pointer when necessary
148 mov ax, di
149 shr ax, 1 ; WORD offset
150 add ax, [bp+PIOVARS.wBlockSize]
151 jns SHORT ReadFromDrive
152 call Registers_NormalizeESDI
153 jmp SHORT ReadFromDrive ; Loop while blocks left
154
155ALIGN JUMP_ALIGN
156.XferLastBlock:
157 xor cx, cx
158 mov ch, [bp+PIOVARS.bSectorsInLastBlock]; CX = Partial block size in WORDs
159 call [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
160 mov di, si ; DS:DI now points DPT
161 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRDY)
162 jmp IdeWait_PollStatusFlagInBLwithTimeoutInBH
163
164
165;--------------------------------------------------------------------
166; InitializePiovarsInSSBPwithSectorCountInAX
167; Parameters:
168; AX: Number of sectors to transfer (1...65535)
169; BX: Offset to transfer function lookup table
170; DS:DI: Ptr to DPT (in RAMVARS segment)
171; SS:BP: Ptr to PIOVARS
172; Returns:
173; Nothing
174; Corrupts registers:
175; AX, BX, CX, DX
176;--------------------------------------------------------------------
177ALIGN JUMP_ALIGN
178InitializePiovarsInSSBPwithSectorCountInAX:
179 ; Store number of blocks to transfer
180 eMOVZX cx, BYTE [di+DPT_ATA.bSetBlock] ; Block size in sectors
181 xor dx, dx ; DX:AX = Sectors to transfer (1...65535)
182 div cx ; AX = Full blocks to transfer
183 test dx, dx
184 mov dh, cl ; DH = Full block size if no partial blocks to transfer
185 jz SHORT .NoPartialBlocksToTransfer
186 inc ax ; Partial block
187 mov dh, dl ; DH = Size of partial block in sectors
188.NoPartialBlocksToTransfer:
189 mov [bp+PIOVARS.wBlocksLeft], ax
190 mov [bp+PIOVARS.bSectorsInLastBlock], dh
191
192 ; Store block size in WORDs
193 xchg ch, cl ; CX = Block size in WORDs
194 mov [bp+PIOVARS.wBlockSize], cx
195
196 ; Get transfer function based on bus type
197 xchg ax, bx ; Lookup table offset to AX
198 eMOVZX bx, BYTE [di+DPT.bIdevarsOffset] ; CS:BX now points to IDEVARS
199 mov dx, [cs:bx+IDEVARS.wPort] ; Load IDE Data port address
200 mov bl, [cs:bx+IDEVARS.bDevice] ; Load device type to BX
201 add bx, ax
202 mov ax, [cs:bx] ; Load offset to transfer function
203 mov [bp+PIOVARS.wDataPort], dx
204 mov [bp+PIOVARS.fnXfer], ax
205 ret
206
207
208;--------------------------------------------------------------------
209; DualByteReadForXtide Dual port 8-bit XTIDE PIO read transfer
210; SingleByteRead Single port 8-bit PIO read transfer
211; WordReadForXTIDEmod 8088/8086 compatible 16-bit IDE PIO read transfer
212; WordReadForXTplusAndAT Normal 16-bit IDE PIO read transfer
213; DWordRead VLB/PCI 32-bit IDE PIO read transfer
214; Parameters:
215; CX: Block size in WORDs
216; DX: IDE Data port address
217; ES:DI: Normalized ptr to buffer to recieve data
218; Returns:
219; Nothing
220; Corrupts registers:
221; AX, BX, CX
222;--------------------------------------------------------------------
223ALIGN JUMP_ALIGN
224DualByteReadForXtide:
225 times 2 shr cx, 1 ; Loop unrolling
226 mov bx, 8 ; Bit mask for toggling data low/high reg
227ALIGN JUMP_ALIGN
228.InswLoop:
229 XTIDE_INSW
230 XTIDE_INSW
231 XTIDE_INSW
232 XTIDE_INSW
233 loop .InswLoop
234 ret
235
236;----
237ALIGN JUMP_ALIGN
238SingleByteRead:
239%ifdef USE_186 ; INS instruction available
240 shl cx, 1 ; WORD count to BYTE count
241 rep insb
242%else ; If 8088/8086
243 shr cx, 1 ; WORD count to DWORD count
244ALIGN JUMP_ALIGN
245.InsdLoop:
246 in al, dx
247 stosb ; Store to [ES:DI]
248 in al, dx
249 stosb
250 in al, dx
251 stosb
252 in al, dx
253 stosb
254 loop .InsdLoop
255%endif
256 ret
257
258;----
259%ifndef USE_186
260ALIGN JUMP_ALIGN
261WordReadForXTIDEmod:
262 times 2 shr cx, 1 ; WORD count to QWORD count
263ALIGN JUMP_ALIGN
264.ReadNextQword:
265 in ax, dx ; Read 1st WORD
266 stosw ; Store 1st WORD to [ES:DI]
267 in ax, dx
268 stosw ; 2nd
269 in ax, dx
270 stosw ; 3rd
271 in ax, dx
272 stosw ; 4th
273 loop .ReadNextQword
274 ret
275%endif
276
277;----
278ALIGN JUMP_ALIGN
279WordReadForXTplusAndAT:
280 rep
281 db 6Dh ; INSW (we want this in XT build)
282 ret
283
284;----
285ALIGN JUMP_ALIGN
286DWordRead:
287 shr cx, 1 ; WORD count to DWORD count
288 rep
289 db 66h ; Override operand size to 32-bit
290 db 6Dh ; INSW/INSD
291 ret
292
293
294;--------------------------------------------------------------------
295; DualByteWriteForXtide Dual port 8-bit XTIDE PIO write transfer
296; SingleByteWrite Single port 8-bit PIO write transfer
297; WordWriteForXTIDEmod 8088/8086 compatible 16-bit IDE PIO read transfer
298; WordWrite Normal 16-bit IDE PIO write transfer
299; DWordWrite VLB/PCI 32-bit IDE PIO write transfer
300; Parameters:
301; CX: Block size in WORDs
302; DX: IDE Data port address
303; ES:SI: Normalized ptr to buffer containing data
304; Returns:
305; Nothing
306; Corrupts registers:
307; AX, CX
308;--------------------------------------------------------------------
309ALIGN JUMP_ALIGN
310DualByteWriteForXtide:
311 push ds
312 push bx
313 times 2 shr cx, 1 ; Loop unrolling
314 mov bx, 8 ; Bit mask for toggling data low/high reg
315 push es ; Copy ES...
316 pop ds ; ...to DS
317ALIGN JUMP_ALIGN
318.OutswLoop:
319 XTIDE_OUTSW
320 XTIDE_OUTSW
321 XTIDE_OUTSW
322 XTIDE_OUTSW
323 loop .OutswLoop
324 pop bx
325 pop ds
326 ret
327
328;----
329ALIGN JUMP_ALIGN
330SingleByteWrite:
331%ifdef USE_186 ; OUTS instruction available
332 shl cx, 1 ; WORD count to BYTE count
333 eSEG es ; Source is ES segment
334 rep outsb
335%else ; If 8088/8086
336 shr cx, 1 ; WORD count to DWORD count
337 push ds ; Store DS
338 push es ; Copy ES...
339 pop ds ; ...to DS
340ALIGN JUMP_ALIGN
341.OutsdLoop:
342 lodsb ; Load from [DS:SI] to AL
343 out dx, al
344 lodsb
345 out dx, al
346 lodsb
347 out dx, al
348 lodsb
349 out dx, al
350 loop .OutsdLoop
351 pop ds ; Restore DS
352%endif
353 ret
354
355;---
356ALIGN JUMP_ALIGN
357WordWriteForXTIDEmod:
358 push ds
359 times 2 shr cx, 1 ; Loop unrolling
360 push es ; Copy ES...
361 pop ds ; ...to DS
362ALIGN JUMP_ALIGN
363.WriteNextQword:
364 XTIDE_MOD_OUTSW
365 XTIDE_MOD_OUTSW
366 XTIDE_MOD_OUTSW
367 XTIDE_MOD_OUTSW
368 loop .WriteNextQword
369 pop ds
370 ret
371
372;----
373ALIGN JUMP_ALIGN
374WordWrite:
375 eSEG es ; Source is ES segment
376 rep
377 db 6Fh ; OUTSW (we want this in XT build)
378 ret
379
380ALIGN JUMP_ALIGN
381DWordWrite:
382 shr cx, 1 ; WORD count to DWORD count
383 eSEG es ; Source is ES segment
384 rep
385 db 66h ; Override operand size to 32-bit
386 db 6Fh ; OUTSW/OUTSD
387 ret
388
389
390
391; Lookup tables to get transfer function based on bus type
392ALIGN WORD_ALIGN
393g_rgfnPioRead:
394 dw DualByteReadForXtide ; DEVICE_8BIT_DUAL_PORT_XTIDE
395%ifdef USE_186
396 dw WordReadForXTplusAndAT ; DEVICE_XTIDE_WITH_REVERSED_A3_AND_A0
397%else
398 dw WordReadForXTIDEmod
399%endif
400 dw SingleByteRead ; DEVICE_8BIT_SINGLE_PORT
401 dw WordReadForXTplusAndAT ; DEVICE_16BIT_ATA
402 dw DWordRead ; DEVICE_32BIT_ATA
403
404g_rgfnPioWrite:
405 dw DualByteWriteForXtide ; DEVICE_8BIT_DUAL_PORT_XTIDE
406 dw WordWriteForXTIDEmod ; DEVICE_XTIDE_WITH_REVERSED_A3_AND_A0
407 dw SingleByteWrite ; DEVICE_8BIT_SINGLE_PORT
408 dw WordWrite ; DEVICE_16BIT_ATA
409 dw DWordWrite ; DEVICE_32BIT_ATA
Note: See TracBrowser for help on using the repository browser.