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

Last change on this file since 192 was 181, checked in by krille_n_@…, 13 years ago

Changes to all parts of the project:

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