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

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

Changes to the XTIDE Universal BIOS:

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