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

Last change on this file since 166 was 161, checked in by krille_n_@…, 14 years ago

Changes to XTIDE Universal BIOS:

  • Minor size optimizations.
  • Tried to minimize the time spent with interrupts disabled in IdeIrq.asm and Int13h.asm
File size: 11.5 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%ifdef USE_186
226 shr cx, 2 ; Smaller but slower on 186/286
227%else
228 times 2 shr cx, 1 ; Loop unrolling
229%endif
230 mov bx, 8 ; Bit mask for toggling data low/high reg
231ALIGN JUMP_ALIGN
232.InswLoop:
233 XTIDE_INSW
234 XTIDE_INSW
235 XTIDE_INSW
236 XTIDE_INSW
237 loop .InswLoop
238 ret
239
240;----
241ALIGN JUMP_ALIGN
242SingleByteRead:
243%ifdef USE_186 ; INS instruction available
244 shl cx, 1 ; WORD count to BYTE count
245 rep insb
246%else ; If 8088/8086
247 shr cx, 1 ; WORD count to DWORD count
248ALIGN JUMP_ALIGN
249.InsdLoop:
250 in al, dx
251 stosb ; Store to [ES:DI]
252 in al, dx
253 stosb
254 in al, dx
255 stosb
256 in al, dx
257 stosb
258 loop .InsdLoop
259%endif
260 ret
261
262;----
263%ifndef USE_186
264ALIGN JUMP_ALIGN
265WordReadForXTIDEmod:
266 times 2 shr cx, 1 ; WORD count to QWORD count
267ALIGN JUMP_ALIGN
268.ReadNextQword:
269 in ax, dx ; Read 1st WORD
270 stosw ; Store 1st WORD to [ES:DI]
271 in ax, dx
272 stosw ; 2nd
273 in ax, dx
274 stosw ; 3rd
275 in ax, dx
276 stosw ; 4th
277 loop .ReadNextQword
278 ret
279%endif
280
281;----
282ALIGN JUMP_ALIGN
283WordReadForXTplusAndAT:
284 rep
285 db 6Dh ; INSW (we want this in XT build)
286 ret
287
288;----
289ALIGN JUMP_ALIGN
290DWordRead:
291 shr cx, 1 ; WORD count to DWORD count
292 rep
293 db 66h ; Override operand size to 32-bit
294 db 6Dh ; INSW/INSD
295 ret
296
297
298;--------------------------------------------------------------------
299; DualByteWriteForXtide Dual port 8-bit XTIDE PIO write transfer
300; SingleByteWrite Single port 8-bit PIO write transfer
301; WordWriteForXTIDEmod 8088/8086 compatible 16-bit IDE PIO read transfer
302; WordWrite Normal 16-bit IDE PIO write transfer
303; DWordWrite VLB/PCI 32-bit IDE PIO write transfer
304; Parameters:
305; CX: Block size in WORDs
306; DX: IDE Data port address
307; ES:SI: Normalized ptr to buffer containing data
308; Returns:
309; Nothing
310; Corrupts registers:
311; AX, CX
312;--------------------------------------------------------------------
313ALIGN JUMP_ALIGN
314DualByteWriteForXtide:
315 push ds
316 push bx
317%ifdef USE_186
318 shr cx, 2 ; Smaller but slower on 186/286
319%else
320 times 2 shr cx, 1 ; Loop unrolling
321%endif
322 mov bx, 8 ; Bit mask for toggling data low/high reg
323 push es ; Copy ES...
324 pop ds ; ...to DS
325ALIGN JUMP_ALIGN
326.OutswLoop:
327 XTIDE_OUTSW
328 XTIDE_OUTSW
329 XTIDE_OUTSW
330 XTIDE_OUTSW
331 loop .OutswLoop
332 pop bx
333 pop ds
334 ret
335
336;----
337ALIGN JUMP_ALIGN
338SingleByteWrite:
339%ifdef USE_186 ; OUTS instruction available
340 shl cx, 1 ; WORD count to BYTE count
341 eSEG es ; Source is ES segment
342 rep outsb
343%else ; If 8088/8086
344 shr cx, 1 ; WORD count to DWORD count
345 push ds ; Store DS
346 push es ; Copy ES...
347 pop ds ; ...to DS
348ALIGN JUMP_ALIGN
349.OutsdLoop:
350 lodsb ; Load from [DS:SI] to AL
351 out dx, al
352 lodsb
353 out dx, al
354 lodsb
355 out dx, al
356 lodsb
357 out dx, al
358 loop .OutsdLoop
359 pop ds ; Restore DS
360%endif
361 ret
362
363;---
364ALIGN JUMP_ALIGN
365WordWriteForXTIDEmod:
366 push ds
367%ifdef USE_186
368 shr cx, 2 ; Smaller but slower on 186/286
369%else
370 times 2 shr cx, 1 ; Loop unrolling
371%endif
372 push es ; Copy ES...
373 pop ds ; ...to DS
374ALIGN JUMP_ALIGN
375.WriteNextQword:
376 XTIDE_MOD_OUTSW
377 XTIDE_MOD_OUTSW
378 XTIDE_MOD_OUTSW
379 XTIDE_MOD_OUTSW
380 loop .WriteNextQword
381 pop ds
382 ret
383
384;----
385ALIGN JUMP_ALIGN
386WordWrite:
387 eSEG es ; Source is ES segment
388 rep
389 db 6Fh ; OUTSW (we want this in XT build)
390 ret
391
392ALIGN JUMP_ALIGN
393DWordWrite:
394 shr cx, 1 ; WORD count to DWORD count
395 eSEG es ; Source is ES segment
396 rep
397 db 66h ; Override operand size to 32-bit
398 db 6Fh ; OUTSW/OUTSD
399 ret
400
401
402
403; Lookup tables to get transfer function based on bus type
404ALIGN WORD_ALIGN
405g_rgfnPioRead:
406 dw DualByteReadForXtide ; DEVICE_8BIT_DUAL_PORT_XTIDE
407%ifdef USE_186
408 dw WordReadForXTplusAndAT ; DEVICE_XTIDE_WITH_REVERSED_A3_AND_A0
409%else
410 dw WordReadForXTIDEmod
411%endif
412 dw SingleByteRead ; DEVICE_8BIT_SINGLE_PORT
413 dw WordReadForXTplusAndAT ; DEVICE_16BIT_ATA
414 dw DWordRead ; DEVICE_32BIT_ATA
415
416g_rgfnPioWrite:
417 dw DualByteWriteForXtide ; DEVICE_8BIT_DUAL_PORT_XTIDE
418 dw WordWriteForXTIDEmod ; DEVICE_XTIDE_WITH_REVERSED_A3_AND_A0
419 dw SingleByteWrite ; DEVICE_8BIT_SINGLE_PORT
420 dw WordWrite ; DEVICE_16BIT_ATA
421 dw DWordWrite ; DEVICE_32BIT_ATA
Note: See TracBrowser for help on using the repository browser.