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

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

Changes to XTIDE Universal BIOS:

  • Old Int 13h functions can now transfer 256 sectors per call.
  • eINT 13h functions can now transfer 65535 sectors per call.
File size: 11.6 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%ifdef USE_186
153 push ReadFromDrive
154 jmp Registers_NormalizeESDI
155%else
156 call Registers_NormalizeESDI
157 jmp SHORT ReadFromDrive ; Loop while blocks left
158%endif
159
160
161ALIGN JUMP_ALIGN
162.XferLastBlock:
163 xor cx, cx
164 mov ch, [bp+PIOVARS.bSectorsInLastBlock]; CX = Partial block size in WORDs
165 call [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
166 mov di, si ; DS:DI now points DPT
167 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRDY)
168 jmp IdeWait_PollStatusFlagInBLwithTimeoutInBH
169
170
171;--------------------------------------------------------------------
172; InitializePiovarsInSSBPwithSectorCountInAX
173; Parameters:
174; AX: Number of sectors to transfer (1...65535)
175; BX: Offset to transfer function lookup table
176; DS:DI: Ptr to DPT (in RAMVARS segment)
177; SS:BP: Ptr to PIOVARS
178; Returns:
179; Nothing
180; Corrupts registers:
181; AX, BX, CX, DX
182;--------------------------------------------------------------------
183ALIGN JUMP_ALIGN
184InitializePiovarsInSSBPwithSectorCountInAX:
185 ; Store number of blocks to transfer
186 eMOVZX cx, BYTE [di+DPT_ATA.bSetBlock] ; Block size in sectors
187 xor dx, dx ; DX:AX = Sectors to transfer (1...65535)
188 div cx ; AX = Full blocks to transfer
189 test dx, dx
190 mov dh, cl ; DH = Full block size if no partial blocks to transfer
191 jz SHORT .NoPartialBlocksToTransfer
192 inc ax ; Partial block
193 mov dh, dl ; DH = Size of partial block in sectors
194.NoPartialBlocksToTransfer:
195 mov [bp+PIOVARS.wBlocksLeft], ax
196 mov [bp+PIOVARS.bSectorsInLastBlock], dh
197
198 ; Store block size in WORDs
199 xchg ch, cl ; CX = Block size in WORDs
200 mov [bp+PIOVARS.wBlockSize], cx
201
202 ; Get transfer function based on bus type
203 xchg ax, bx ; Lookup table offset to AX
204 eMOVZX bx, BYTE [di+DPT.bIdevarsOffset] ; CS:BX now points to IDEVARS
205 mov dx, [cs:bx+IDEVARS.wPort] ; Load IDE Data port address
206 mov bl, [cs:bx+IDEVARS.bDevice] ; Load device type to BX
207 add bx, ax
208 mov ax, [cs:bx] ; Load offset to transfer function
209 mov [bp+PIOVARS.wDataPort], dx
210 mov [bp+PIOVARS.fnXfer], ax
211 ret
212
213
214;--------------------------------------------------------------------
215; DualByteReadForXtide Dual port 8-bit XTIDE PIO read transfer
216; SingleByteRead Single port 8-bit PIO read transfer
217; WordReadForXTIDEmod 8088/8086 compatible 16-bit IDE PIO read transfer
218; WordReadForXTplusAndAT Normal 16-bit IDE PIO read transfer
219; DWordRead VLB/PCI 32-bit IDE PIO read transfer
220; Parameters:
221; CX: Block size in WORDs
222; DX: IDE Data port address
223; ES:DI: Normalized ptr to buffer to recieve data
224; Returns:
225; Nothing
226; Corrupts registers:
227; AX, BX, CX
228;--------------------------------------------------------------------
229ALIGN JUMP_ALIGN
230DualByteReadForXtide:
231%ifdef USE_186
232 shr cx, 2 ; Smaller but slower on 186/286
233%else
234 times 2 shr cx, 1 ; Loop unrolling
235%endif
236 mov bx, 8 ; Bit mask for toggling data low/high reg
237ALIGN JUMP_ALIGN
238.InswLoop:
239 XTIDE_INSW
240 XTIDE_INSW
241 XTIDE_INSW
242 XTIDE_INSW
243 loop .InswLoop
244 ret
245
246;----
247ALIGN JUMP_ALIGN
248SingleByteRead:
249%ifdef USE_186 ; INS instruction available
250 shl cx, 1 ; WORD count to BYTE count
251 rep insb
252%else ; If 8088/8086
253 shr cx, 1 ; WORD count to DWORD count
254ALIGN JUMP_ALIGN
255.InsdLoop:
256 in al, dx
257 stosb ; Store to [ES:DI]
258 in al, dx
259 stosb
260 in al, dx
261 stosb
262 in al, dx
263 stosb
264 loop .InsdLoop
265%endif
266 ret
267
268;----
269%ifndef USE_186
270ALIGN JUMP_ALIGN
271WordReadForXTIDEmod:
272 times 2 shr cx, 1 ; WORD count to QWORD count
273ALIGN JUMP_ALIGN
274.ReadNextQword:
275 in ax, dx ; Read 1st WORD
276 stosw ; Store 1st WORD to [ES:DI]
277 in ax, dx
278 stosw ; 2nd
279 in ax, dx
280 stosw ; 3rd
281 in ax, dx
282 stosw ; 4th
283 loop .ReadNextQword
284 ret
285%endif
286
287;----
288ALIGN JUMP_ALIGN
289WordReadForXTplusAndAT:
290 rep
291 db 6Dh ; INSW (we want this in XT build)
292 ret
293
294;----
295ALIGN JUMP_ALIGN
296DWordRead:
297 shr cx, 1 ; WORD count to DWORD count
298 rep
299 db 66h ; Override operand size to 32-bit
300 db 6Dh ; INSW/INSD
301 ret
302
303
304;--------------------------------------------------------------------
305; DualByteWriteForXtide Dual port 8-bit XTIDE PIO write transfer
306; SingleByteWrite Single port 8-bit PIO write transfer
307; WordWriteForXTIDEmod 8088/8086 compatible 16-bit IDE PIO read transfer
308; WordWrite Normal 16-bit IDE PIO write transfer
309; DWordWrite VLB/PCI 32-bit IDE PIO write transfer
310; Parameters:
311; CX: Block size in WORDs
312; DX: IDE Data port address
313; ES:SI: Normalized ptr to buffer containing data
314; Returns:
315; Nothing
316; Corrupts registers:
317; AX, CX
318;--------------------------------------------------------------------
319ALIGN JUMP_ALIGN
320DualByteWriteForXtide:
321 push ds
322 push bx
323%ifdef USE_186
324 shr cx, 2 ; Smaller but slower on 186/286
325%else
326 times 2 shr cx, 1 ; Loop unrolling
327%endif
328 mov bx, 8 ; Bit mask for toggling data low/high reg
329 push es ; Copy ES...
330 pop ds ; ...to DS
331ALIGN JUMP_ALIGN
332.OutswLoop:
333 XTIDE_OUTSW
334 XTIDE_OUTSW
335 XTIDE_OUTSW
336 XTIDE_OUTSW
337 loop .OutswLoop
338 pop bx
339 pop ds
340 ret
341
342;----
343ALIGN JUMP_ALIGN
344SingleByteWrite:
345%ifdef USE_186 ; OUTS instruction available
346 shl cx, 1 ; WORD count to BYTE count
347 eSEG es ; Source is ES segment
348 rep outsb
349%else ; If 8088/8086
350 shr cx, 1 ; WORD count to DWORD count
351 push ds ; Store DS
352 push es ; Copy ES...
353 pop ds ; ...to DS
354ALIGN JUMP_ALIGN
355.OutsdLoop:
356 lodsb ; Load from [DS:SI] to AL
357 out dx, al
358 lodsb
359 out dx, al
360 lodsb
361 out dx, al
362 lodsb
363 out dx, al
364 loop .OutsdLoop
365 pop ds ; Restore DS
366%endif
367 ret
368
369;---
370ALIGN JUMP_ALIGN
371WordWriteForXTIDEmod:
372 push ds
373%ifdef USE_186
374 shr cx, 2 ; Smaller but slower on 186/286
375%else
376 times 2 shr cx, 1 ; Loop unrolling
377%endif
378 push es ; Copy ES...
379 pop ds ; ...to DS
380ALIGN JUMP_ALIGN
381.WriteNextQword:
382 XTIDE_MOD_OUTSW
383 XTIDE_MOD_OUTSW
384 XTIDE_MOD_OUTSW
385 XTIDE_MOD_OUTSW
386 loop .WriteNextQword
387 pop ds
388 ret
389
390;----
391ALIGN JUMP_ALIGN
392WordWrite:
393 eSEG es ; Source is ES segment
394 rep
395 db 6Fh ; OUTSW (we want this in XT build)
396 ret
397
398ALIGN JUMP_ALIGN
399DWordWrite:
400 shr cx, 1 ; WORD count to DWORD count
401 eSEG es ; Source is ES segment
402 rep
403 db 66h ; Override operand size to 32-bit
404 db 6Fh ; OUTSW/OUTSD
405 ret
406
407
408
409; Lookup tables to get transfer function based on bus type
410ALIGN WORD_ALIGN
411g_rgfnPioRead:
412 dw DualByteReadForXtide ; DEVICE_8BIT_DUAL_PORT_XTIDE
413%ifdef USE_186
414 dw WordReadForXTplusAndAT ; DEVICE_XTIDE_WITH_REVERSED_A3_AND_A0
415%else
416 dw WordReadForXTIDEmod
417%endif
418 dw SingleByteRead ; DEVICE_8BIT_SINGLE_PORT
419 dw WordReadForXTplusAndAT ; DEVICE_16BIT_ATA
420 dw DWordRead ; DEVICE_32BIT_ATA
421
422g_rgfnPioWrite:
423 dw DualByteWriteForXtide ; DEVICE_8BIT_DUAL_PORT_XTIDE
424 dw WordWriteForXTIDEmod ; DEVICE_XTIDE_WITH_REVERSED_A3_AND_A0
425 dw SingleByteWrite ; DEVICE_8BIT_SINGLE_PORT
426 dw WordWrite ; DEVICE_16BIT_ATA
427 dw DWordWrite ; DEVICE_32BIT_ATA
Note: See TracBrowser for help on using the repository browser.