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

Last change on this file since 209 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
RevLine 
[150]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
[169]7 .wBlocksLeft resb 2
[150]8 .wBlockSize resb 2 ; Block size in WORDs (256...32768)
9 .wDataPort resb 2
[169]10 .bSectorsInLastBlock: resb 1
[150]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
[171]23; (all PIO read and write commands including Identify Device)
[150]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:
[169]35 mov ah, [bp+IDEPACK.bSectorCountHighExt]
36
[157]37 ; Are we reading or writing?
[171]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
[150]42
43 ; Prepare to read data to ESSI
44 mov bx, g_rgfnPioRead
[169]45 mov al, [bp+IDEPACK.bSectorCount]
46 call InitializePiovarsInSSBPwithSectorCountInAX
[150]47 xchg si, di
48 call Registers_NormalizeESDI
[169]49 jmp SHORT ReadFromDrive
[150]50
51ALIGN JUMP_ALIGN
52.PrepareToWriteDataFromESSI:
53 mov bx, g_rgfnPioWrite
[169]54 mov al, [bp+IDEPACK.bSectorCount]
55 call InitializePiovarsInSSBPwithSectorCountInAX
[150]56 call Registers_NormalizeESSI
[169]57 ; Fall to WriteToDrive
[150]58
59
60;--------------------------------------------------------------------
[169]61; WriteToDrive
[150]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;--------------------------------------------------------------------
[169]73WriteToDrive:
[150]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]
[169]81 dec WORD [bp+PIOVARS.wBlocksLeft] ; Transferring last (possibly partial) block?
[150]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
[169]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:
[150]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;--------------------------------------------------------------------
[169]120; ReadFromDrive
[150]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
[169]134ReadFromDrive:
[150]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
[169]138 jc SHORT WriteToDrive.ReturnWithTransferErrorInAH
[150]139 xchg si, di ; ES:DI now points buffer
140
141 ; Transfer full or last (possible partial) block
142 mov dx, [bp+PIOVARS.wDataPort]
[169]143 dec WORD [bp+PIOVARS.wBlocksLeft]
[150]144 jz SHORT .XferLastBlock
145 mov cx, [bp+PIOVARS.wBlockSize] ; Load block size in WORDs
[169]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
[167]153%ifdef USE_186
[169]154 push ReadFromDrive
155 jmp Registers_NormalizeESDI
[167]156%else
[169]157 call Registers_NormalizeESDI
158 jmp SHORT ReadFromDrive ; Loop while blocks left
[167]159%endif
[150]160
[169]161
[150]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;--------------------------------------------------------------------
[169]173; InitializePiovarsInSSBPwithSectorCountInAX
[150]174; Parameters:
[169]175; AX: Number of sectors to transfer (1...65535)
[150]176; BX: Offset to transfer function lookup table
177; DS:DI: Ptr to DPT (in RAMVARS segment)
[169]178; SS:BP: Ptr to PIOVARS
[167]179; Returns:
[169]180; Nothing
[150]181; Corrupts registers:
182; AX, BX, CX, DX
183;--------------------------------------------------------------------
184ALIGN JUMP_ALIGN
[169]185InitializePiovarsInSSBPwithSectorCountInAX:
[150]186 ; Store number of blocks to transfer
[169]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
[150]192 jz SHORT .NoPartialBlocksToTransfer
[169]193 inc ax ; Partial block
194 mov dh, dl ; DH = Size of partial block in sectors
[150]195.NoPartialBlocksToTransfer:
[169]196 mov [bp+PIOVARS.wBlocksLeft], ax
197 mov [bp+PIOVARS.bSectorsInLastBlock], dh
[150]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
[158]204 xchg ax, bx ; Lookup table offset to AX
[150]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;--------------------------------------------------------------------
[152]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
[150]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
[152]231DualByteReadForXtide:
[181]232 eSHR_IM cx, 2 ; Loop unrolling
[152]233 mov bx, 8 ; Bit mask for toggling data low/high reg
[150]234ALIGN JUMP_ALIGN
235.InswLoop:
[152]236 XTIDE_INSW
237 XTIDE_INSW
238 XTIDE_INSW
239 XTIDE_INSW
[150]240 loop .InswLoop
241 ret
242
[152]243;----
[150]244ALIGN JUMP_ALIGN
245SingleByteRead:
246%ifdef USE_186 ; INS instruction available
[152]247 shl cx, 1 ; WORD count to BYTE count
[150]248 rep insb
249%else ; If 8088/8086
[152]250 shr cx, 1 ; WORD count to DWORD count
[150]251ALIGN JUMP_ALIGN
252.InsdLoop:
253 in al, dx
[152]254 stosb ; Store to [ES:DI]
[150]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
[152]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
[150]283
[152]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
[150]301;--------------------------------------------------------------------
[152]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
[150]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
[152]317DualByteWriteForXtide:
[150]318 push ds
319 push bx
[181]320 eSHR_IM cx, 2 ; Loop unrolling
[152]321 mov bx, 8 ; Bit mask for toggling data low/high reg
322 push es ; Copy ES...
323 pop ds ; ...to DS
[150]324ALIGN JUMP_ALIGN
325.OutswLoop:
[152]326 XTIDE_OUTSW
327 XTIDE_OUTSW
328 XTIDE_OUTSW
329 XTIDE_OUTSW
[150]330 loop .OutswLoop
331 pop bx
332 pop ds
333 ret
334
[152]335;----
[150]336ALIGN JUMP_ALIGN
337SingleByteWrite:
338%ifdef USE_186 ; OUTS instruction available
[152]339 shl cx, 1 ; WORD count to BYTE count
340 eSEG es ; Source is ES segment
[150]341 rep outsb
342%else ; If 8088/8086
[152]343 shr cx, 1 ; WORD count to DWORD count
344 push ds ; Store DS
345 push es ; Copy ES...
346 pop ds ; ...to DS
[150]347ALIGN JUMP_ALIGN
348.OutsdLoop:
[152]349 lodsb ; Load from [DS:SI] to AL
[150]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
[152]358 pop ds ; Restore DS
[150]359%endif
360 ret
361
[152]362;---
363ALIGN JUMP_ALIGN
364WordWriteForXTIDEmod:
365 push ds
[181]366 eSHR_IM cx, 2 ; Loop unrolling
[152]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
[150]378
[152]379;----
380ALIGN JUMP_ALIGN
381WordWrite:
382 eSEG es ; Source is ES segment
383 rep
[155]384 db 6Fh ; OUTSW (we want this in XT build)
[152]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
[150]398; Lookup tables to get transfer function based on bus type
399ALIGN WORD_ALIGN
400g_rgfnPioRead:
[152]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
[150]411g_rgfnPioWrite:
[152]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.