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

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

Changes:

  • Optimizations (both for size and speed) in IdeTransfer.asm and MemIdeTransfer.asm
  • Fixed a bug where the SingleByteRead/Write functions in IdeTransfer.asm would fail on 128 sector transfers.
  • Fixed some typos and errors in general, comments etc.
File size: 11.2 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
[218]7 .wWordsInBlock resb 2 ; 0, Block size in WORDs
8 .wWordsLeft resb 2 ; 2, WORDs left to transfer
9 .wWordsDone resb 2 ; 4, Number of sectors xferred
[223]10 resb 1 ; 6,
[218]11 resb 1 ; 7, IDEPACK.bDeviceControl
12 .wDataPort resb 2 ; 8, IDE Data Port
13 .fnXfer resb 2 ; 10, Offset to transfer function
[150]14endstruc
15
16
17; Section containing code
18SECTION .text
19
20;--------------------------------------------------------------------
21; IdeTransfer_StartWithCommandInAL
22; Parameters:
23; AL: IDE command that was used to start the transfer
[171]24; (all PIO read and write commands including Identify Device)
[218]25; ES:SI: Ptr to normalized data buffer
[150]26; DS:DI: Ptr to DPT (in RAMVARS segment)
27; SS:BP: Ptr to IDEPACK
28; Returns:
29; AH: INT 13h Error Code
[218]30; CX: Number of successfully transferred sectors
[150]31; CF: Cleared if success, Set if error
32; Corrupts registers:
[218]33; AL, BX, DX, SI, ES
[150]34;--------------------------------------------------------------------
35ALIGN JUMP_ALIGN
36IdeTransfer_StartWithCommandInAL:
[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
[242]39 mov ah, [bp+IDEPACK.bSectorCount]
40 jnz SHORT WriteToDrive
[171]41 cmp al, COMMAND_WRITE_MULTIPLE
[242]42 je SHORT WriteToDrive
43 ; Fall to ReadFromDrive
[150]44
45;--------------------------------------------------------------------
[242]46; ReadFromDrive
[150]47; Parameters:
[242]48; AH: Number of sectors to transfer (1...128)
49; ES:SI: Normalized ptr to buffer to receive data
[150]50; DS:DI: Ptr to DPT (in RAMVARS segment)
51; SS:BP: Ptr to PIOVARS
52; Returns:
[242]53; DS:DI: Ptr to DPT (in RAMVARS segment)
[150]54; AH: BIOS Error code
[218]55; CX: Number of successfully transferred sectors
[150]56; CF: 0 if transfer succesfull
57; 1 if any error
58; Corrupts registers:
[218]59; AL, BX, DX, SI, ES
[150]60;--------------------------------------------------------------------
[242]61ReadFromDrive:
62 ; Prepare to read data to ESSI
63 mov bx, g_rgfnPioRead
64 call InitializePiovarsInSSBPwithSectorCountInAH
65
66 ; Wait until drive is ready to transfer
67 call IdeWait_IRQorDRQ ; Wait until ready to transfer
[218]68 jc SHORT ReturnWithTransferErrorInAH
[242]69 xchg si, di ; ES:DI now points buffer
[218]70
[242]71 mov cx, [bp+PIOVARS.wWordsInBlock]
72
[150]73ALIGN JUMP_ALIGN
[242]74.ReadNextBlockFromDrive:
[150]75 mov dx, [bp+PIOVARS.wDataPort]
[218]76 cmp [bp+PIOVARS.wWordsLeft], cx
[242]77 jbe SHORT .ReadLastBlockFromDrive
[218]78 call [bp+PIOVARS.fnXfer]
[169]79
[218]80 ; Wait until ready for next block and check for errors
[242]81 xchg di, si ; DS:DI now points DPT
[218]82 call IdeWait_IRQorDRQ ; Wait until ready to transfer
83 jc SHORT ReturnWithTransferErrorInAH
[242]84 xchg si, di ; ES:DI now points buffer
[169]85
[242]86 ; Increment number of successfully read WORDs
87 mov cx, [bp+PIOVARS.wWordsInBlock]
88 sub [bp+PIOVARS.wWordsLeft], cx
89 add [bp+PIOVARS.wWordsDone], cx
90 jmp SHORT .ReadNextBlockFromDrive
[150]91
92ALIGN JUMP_ALIGN
[242]93.ReadLastBlockFromDrive:
[218]94 mov cx, [bp+PIOVARS.wWordsLeft]
[150]95 call [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
96
[242]97 ; Check for errors in last block
98 mov di, si ; DS:DI now points DPT
99CheckErrorsAfterTransferringLastBlock:
100 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRDY)
101 call IdeWait_PollStatusFlagInBLwithTimeoutInBH
[150]102
[242]103 ; Return number of successfully read sectors
104ReturnWithTransferErrorInAH:
105 mov cx, [bp+PIOVARS.wWordsDone]
106 jc SHORT .ConvertTransferredWordsInCXtoSectors
107 add cx, [bp+PIOVARS.wWordsLeft] ; Never sets CF
108.ConvertTransferredWordsInCXtoSectors:
109 xchg cl, ch
110 ret
111
112
[150]113;--------------------------------------------------------------------
[242]114; WriteToDrive
[150]115; Parameters:
[242]116; AH: Number of sectors to transfer (1...128)
117; DS:DI: Ptr to DPT (in RAMVARS segment)
118; ES:SI: Normalized ptr to buffer containing data
[150]119; SS:BP: Ptr to PIOVARS
120; Returns:
121; AH: BIOS Error code
[218]122; CX: Number of successfully transferred sectors
[150]123; CF: 0 if transfer succesfull
124; 1 if any error
125; Corrupts registers:
[218]126; AL, BX, DX, SI, ES
[150]127;--------------------------------------------------------------------
128ALIGN JUMP_ALIGN
[242]129WriteToDrive:
130 ; Prepare to write data from ESSI
131 mov bx, g_rgfnPioWrite
132 call InitializePiovarsInSSBPwithSectorCountInAH
133
134 ; Always poll when writing first block (IRQs are generated for following blocks)
135 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
136 call IdeWait_PollStatusFlagInBLwithTimeoutInBH
[218]137 jc SHORT ReturnWithTransferErrorInAH
[150]138
[242]139 mov cx, [bp+PIOVARS.wWordsInBlock]
140
[218]141ALIGN JUMP_ALIGN
[242]142.WriteNextBlockToDrive:
[150]143 mov dx, [bp+PIOVARS.wDataPort]
[218]144 cmp [bp+PIOVARS.wWordsLeft], cx
[242]145 jbe SHORT .WriteLastBlockToDrive
[218]146 call [bp+PIOVARS.fnXfer]
[169]147
[218]148 ; Wait until ready for next block and check for errors
149 call IdeWait_IRQorDRQ ; Wait until ready to transfer
150 jc SHORT ReturnWithTransferErrorInAH
[150]151
[242]152 ; Increment number of successfully written WORDs
153 mov cx, [bp+PIOVARS.wWordsInBlock]
154 sub [bp+PIOVARS.wWordsLeft], cx
155 add [bp+PIOVARS.wWordsDone], cx
156 jmp SHORT .WriteNextBlockToDrive
[169]157
[150]158ALIGN JUMP_ALIGN
[242]159.WriteLastBlockToDrive:
[218]160 mov cx, [bp+PIOVARS.wWordsLeft]
[242]161%ifdef USE_186
162 push CheckErrorsAfterTransferringLastBlock
163 jmp [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
164%else
[150]165 call [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
[242]166 jmp SHORT CheckErrorsAfterTransferringLastBlock
167%endif
[218]168
[150]169
170;--------------------------------------------------------------------
[218]171; InitializePiovarsInSSBPwithSectorCountInAH
[150]172; Parameters:
[218]173; AH: Number of sectors to transfer (1...128)
[150]174; BX: Offset to transfer function lookup table
175; DS:DI: Ptr to DPT (in RAMVARS segment)
[169]176; SS:BP: Ptr to PIOVARS
[167]177; Returns:
[169]178; Nothing
[150]179; Corrupts registers:
[242]180; AX, BX, DX
[150]181;--------------------------------------------------------------------
182ALIGN JUMP_ALIGN
[218]183InitializePiovarsInSSBPwithSectorCountInAH:
184 ; Store sizes
185 xor al, al
186 mov [bp+PIOVARS.wWordsLeft], ax
[242]187 mov ah, [di+DPT_ATA.bSetBlock]
188 mov [bp+PIOVARS.wWordsInBlock], ax
[218]189 cbw
190 mov [bp+PIOVARS.wWordsDone], ax ; Zero
[150]191
192 ; Get transfer function based on bus type
[158]193 xchg ax, bx ; Lookup table offset to AX
[242]194 mov bl, [di+DPT.bIdevarsOffset] ; CS:BX now points to IDEVARS
[150]195 mov dx, [cs:bx+IDEVARS.wPort] ; Load IDE Data port address
196 mov bl, [cs:bx+IDEVARS.bDevice] ; Load device type to BX
197 add bx, ax
[242]198 mov [bp+PIOVARS.wDataPort], dx
[150]199 mov ax, [cs:bx] ; Load offset to transfer function
200 mov [bp+PIOVARS.fnXfer], ax
201 ret
202
203
204;--------------------------------------------------------------------
[152]205; DualByteReadForXtide Dual port 8-bit XTIDE PIO read transfer
206; SingleByteRead Single port 8-bit PIO read transfer
207; WordReadForXTIDEmod 8088/8086 compatible 16-bit IDE PIO read transfer
208; WordReadForXTplusAndAT Normal 16-bit IDE PIO read transfer
209; DWordRead VLB/PCI 32-bit IDE PIO read transfer
[150]210; Parameters:
211; CX: Block size in WORDs
212; DX: IDE Data port address
[242]213; ES:DI: Normalized ptr to buffer to receive data
[150]214; Returns:
215; Nothing
216; Corrupts registers:
217; AX, BX, CX
218;--------------------------------------------------------------------
219ALIGN JUMP_ALIGN
[152]220DualByteReadForXtide:
[181]221 eSHR_IM cx, 2 ; Loop unrolling
[152]222 mov bx, 8 ; Bit mask for toggling data low/high reg
[150]223ALIGN JUMP_ALIGN
224.InswLoop:
[152]225 XTIDE_INSW
226 XTIDE_INSW
227 XTIDE_INSW
228 XTIDE_INSW
[150]229 loop .InswLoop
230 ret
231
[152]232;----
[150]233ALIGN JUMP_ALIGN
234SingleByteRead:
235%ifdef USE_186 ; INS instruction available
[242]236 dec cx ; Avoid overflowing CX on a 128 sector transfer
[152]237 shl cx, 1 ; WORD count to BYTE count
[242]238 inc cx
[150]239 rep insb
[242]240 insb
[150]241%else ; If 8088/8086
[152]242 shr cx, 1 ; WORD count to DWORD count
[150]243ALIGN JUMP_ALIGN
244.InsdLoop:
245 in al, dx
[152]246 stosb ; Store to [ES:DI]
[150]247 in al, dx
248 stosb
249 in al, dx
250 stosb
251 in al, dx
252 stosb
253 loop .InsdLoop
254%endif
255 ret
256
[152]257;----
258%ifndef USE_186
259ALIGN JUMP_ALIGN
260WordReadForXTIDEmod:
261 times 2 shr cx, 1 ; WORD count to QWORD count
262ALIGN JUMP_ALIGN
263.ReadNextQword:
264 in ax, dx ; Read 1st WORD
265 stosw ; Store 1st WORD to [ES:DI]
266 in ax, dx
267 stosw ; 2nd
268 in ax, dx
269 stosw ; 3rd
270 in ax, dx
271 stosw ; 4th
272 loop .ReadNextQword
273 ret
274%endif
[150]275
[152]276;----
277ALIGN JUMP_ALIGN
278WordReadForXTplusAndAT:
279 rep
280 db 6Dh ; INSW (we want this in XT build)
281 ret
282
283;----
284ALIGN JUMP_ALIGN
285DWordRead:
286 shr cx, 1 ; WORD count to DWORD count
287 rep
288 db 66h ; Override operand size to 32-bit
289 db 6Dh ; INSW/INSD
290 ret
291
292
[150]293;--------------------------------------------------------------------
[152]294; DualByteWriteForXtide Dual port 8-bit XTIDE PIO write transfer
295; SingleByteWrite Single port 8-bit PIO write transfer
296; WordWriteForXTIDEmod 8088/8086 compatible 16-bit IDE PIO read transfer
297; WordWrite Normal 16-bit IDE PIO write transfer
298; DWordWrite VLB/PCI 32-bit IDE PIO write transfer
[150]299; Parameters:
300; CX: Block size in WORDs
301; DX: IDE Data port address
302; ES:SI: Normalized ptr to buffer containing data
303; Returns:
304; Nothing
305; Corrupts registers:
306; AX, CX
307;--------------------------------------------------------------------
308ALIGN JUMP_ALIGN
[152]309DualByteWriteForXtide:
[150]310 push ds
311 push bx
[181]312 eSHR_IM cx, 2 ; Loop unrolling
[152]313 mov bx, 8 ; Bit mask for toggling data low/high reg
314 push es ; Copy ES...
315 pop ds ; ...to DS
[150]316ALIGN JUMP_ALIGN
317.OutswLoop:
[152]318 XTIDE_OUTSW
319 XTIDE_OUTSW
320 XTIDE_OUTSW
321 XTIDE_OUTSW
[150]322 loop .OutswLoop
323 pop bx
324 pop ds
325 ret
326
[152]327;----
[150]328ALIGN JUMP_ALIGN
329SingleByteWrite:
330%ifdef USE_186 ; OUTS instruction available
[242]331 dec cx ; Avoid overflowing CX on a 128 sector transfer
[152]332 shl cx, 1 ; WORD count to BYTE count
[242]333 inc cx
[223]334 es ; Source is ES segment
[150]335 rep outsb
[242]336 es outsb
[150]337%else ; If 8088/8086
[152]338 shr cx, 1 ; WORD count to DWORD count
339 push ds ; Store DS
340 push es ; Copy ES...
341 pop ds ; ...to DS
[150]342ALIGN JUMP_ALIGN
343.OutsdLoop:
[152]344 lodsb ; Load from [DS:SI] to AL
[150]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
[152]353 pop ds ; Restore DS
[150]354%endif
355 ret
356
[152]357;---
358ALIGN JUMP_ALIGN
359WordWriteForXTIDEmod:
360 push ds
[181]361 eSHR_IM cx, 2 ; Loop unrolling
[152]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
[150]373
[152]374;----
375ALIGN JUMP_ALIGN
376WordWrite:
[223]377 es ; Source is ES segment
[152]378 rep
[155]379 db 6Fh ; OUTSW (we want this in XT build)
[152]380 ret
381
382ALIGN JUMP_ALIGN
383DWordWrite:
384 shr cx, 1 ; WORD count to DWORD count
[223]385 es ; Source is ES segment
[152]386 rep
387 db 66h ; Override operand size to 32-bit
388 db 6Fh ; OUTSW/OUTSD
389 ret
390
391
[150]392; Lookup tables to get transfer function based on bus type
393ALIGN WORD_ALIGN
394g_rgfnPioRead:
[152]395 dw DualByteReadForXtide ; DEVICE_8BIT_DUAL_PORT_XTIDE
396%ifdef USE_186
397 dw WordReadForXTplusAndAT ; DEVICE_XTIDE_WITH_REVERSED_A3_AND_A0
398%else
399 dw WordReadForXTIDEmod
400%endif
401 dw SingleByteRead ; DEVICE_8BIT_SINGLE_PORT
402 dw WordReadForXTplusAndAT ; DEVICE_16BIT_ATA
403 dw DWordRead ; DEVICE_32BIT_ATA
404
[150]405g_rgfnPioWrite:
[152]406 dw DualByteWriteForXtide ; DEVICE_8BIT_DUAL_PORT_XTIDE
407 dw WordWriteForXTIDEmod ; DEVICE_XTIDE_WITH_REVERSED_A3_AND_A0
408 dw SingleByteWrite ; DEVICE_8BIT_SINGLE_PORT
409 dw WordWrite ; DEVICE_16BIT_ATA
410 dw DWordWrite ; DEVICE_32BIT_ATA
Note: See TracBrowser for help on using the repository browser.