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

Last change on this file since 178 was 171, checked in by aitotat@…, 13 years ago

Changes to XTIDE Universal BIOS:

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