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

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

Changes to XTIDE Universal BIOS:

  • Old Int 13h functions can now transfer 256 sectors per call.
  • eINT 13h functions can now transfer 65535 sectors per call.
File size: 11.6 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
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:
[169]34 mov ah, [bp+IDEPACK.bSectorCountHighExt]
35
[157]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
[150]39 cmp al, COMMAND_WRITE_MULTIPLE
40 je SHORT .PrepareToWriteDataFromESSI
41
42 ; Prepare to read data to ESSI
43 mov bx, g_rgfnPioRead
[169]44 mov al, [bp+IDEPACK.bSectorCount]
45 call InitializePiovarsInSSBPwithSectorCountInAX
[150]46 xchg si, di
47 call Registers_NormalizeESDI
[169]48 jmp SHORT ReadFromDrive
[150]49
50ALIGN JUMP_ALIGN
51.PrepareToWriteDataFromESSI:
52 mov bx, g_rgfnPioWrite
[169]53 mov al, [bp+IDEPACK.bSectorCount]
54 call InitializePiovarsInSSBPwithSectorCountInAX
[150]55 call Registers_NormalizeESSI
[169]56 ; Fall to WriteToDrive
[150]57
58
59;--------------------------------------------------------------------
[169]60; WriteToDrive
[150]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;--------------------------------------------------------------------
[169]72WriteToDrive:
[150]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]
[169]80 dec WORD [bp+PIOVARS.wBlocksLeft] ; Transferring last (possibly partial) block?
[150]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
[169]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:
[150]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;--------------------------------------------------------------------
[169]119; ReadFromDrive
[150]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
[169]133ReadFromDrive:
[150]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
[169]137 jc SHORT WriteToDrive.ReturnWithTransferErrorInAH
[150]138 xchg si, di ; ES:DI now points buffer
139
140 ; Transfer full or last (possible partial) block
141 mov dx, [bp+PIOVARS.wDataPort]
[169]142 dec WORD [bp+PIOVARS.wBlocksLeft]
[150]143 jz SHORT .XferLastBlock
144 mov cx, [bp+PIOVARS.wBlockSize] ; Load block size in WORDs
[169]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
[167]152%ifdef USE_186
[169]153 push ReadFromDrive
154 jmp Registers_NormalizeESDI
[167]155%else
[169]156 call Registers_NormalizeESDI
157 jmp SHORT ReadFromDrive ; Loop while blocks left
[167]158%endif
[150]159
[169]160
[150]161ALIGN JUMP_ALIGN
162.XferLastBlock:
163 xor cx, cx
164 mov ch, [bp+PIOVARS.bSectorsInLastBlock]; CX = Partial block size in WORDs
165 call [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
166 mov di, si ; DS:DI now points DPT
167 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRDY)
168 jmp IdeWait_PollStatusFlagInBLwithTimeoutInBH
169
170
171;--------------------------------------------------------------------
[169]172; InitializePiovarsInSSBPwithSectorCountInAX
[150]173; Parameters:
[169]174; AX: Number of sectors to transfer (1...65535)
[150]175; BX: Offset to transfer function lookup table
176; DS:DI: Ptr to DPT (in RAMVARS segment)
[169]177; SS:BP: Ptr to PIOVARS
[167]178; Returns:
[169]179; Nothing
[150]180; Corrupts registers:
181; AX, BX, CX, DX
182;--------------------------------------------------------------------
183ALIGN JUMP_ALIGN
[169]184InitializePiovarsInSSBPwithSectorCountInAX:
[150]185 ; Store number of blocks to transfer
[169]186 eMOVZX cx, BYTE [di+DPT_ATA.bSetBlock] ; Block size in sectors
187 xor dx, dx ; DX:AX = Sectors to transfer (1...65535)
188 div cx ; AX = Full blocks to transfer
189 test dx, dx
190 mov dh, cl ; DH = Full block size if no partial blocks to transfer
[150]191 jz SHORT .NoPartialBlocksToTransfer
[169]192 inc ax ; Partial block
193 mov dh, dl ; DH = Size of partial block in sectors
[150]194.NoPartialBlocksToTransfer:
[169]195 mov [bp+PIOVARS.wBlocksLeft], ax
196 mov [bp+PIOVARS.bSectorsInLastBlock], dh
[150]197
198 ; Store block size in WORDs
199 xchg ch, cl ; CX = Block size in WORDs
200 mov [bp+PIOVARS.wBlockSize], cx
201
202 ; Get transfer function based on bus type
[158]203 xchg ax, bx ; Lookup table offset to AX
[150]204 eMOVZX bx, BYTE [di+DPT.bIdevarsOffset] ; CS:BX now points to IDEVARS
205 mov dx, [cs:bx+IDEVARS.wPort] ; Load IDE Data port address
206 mov bl, [cs:bx+IDEVARS.bDevice] ; Load device type to BX
207 add bx, ax
208 mov ax, [cs:bx] ; Load offset to transfer function
209 mov [bp+PIOVARS.wDataPort], dx
210 mov [bp+PIOVARS.fnXfer], ax
211 ret
212
213
214;--------------------------------------------------------------------
[152]215; DualByteReadForXtide Dual port 8-bit XTIDE PIO read transfer
216; SingleByteRead Single port 8-bit PIO read transfer
217; WordReadForXTIDEmod 8088/8086 compatible 16-bit IDE PIO read transfer
218; WordReadForXTplusAndAT Normal 16-bit IDE PIO read transfer
219; DWordRead VLB/PCI 32-bit IDE PIO read transfer
[150]220; Parameters:
221; CX: Block size in WORDs
222; DX: IDE Data port address
223; ES:DI: Normalized ptr to buffer to recieve data
224; Returns:
225; Nothing
226; Corrupts registers:
227; AX, BX, CX
228;--------------------------------------------------------------------
229ALIGN JUMP_ALIGN
[152]230DualByteReadForXtide:
[161]231%ifdef USE_186
232 shr cx, 2 ; Smaller but slower on 186/286
233%else
[152]234 times 2 shr cx, 1 ; Loop unrolling
[161]235%endif
[152]236 mov bx, 8 ; Bit mask for toggling data low/high reg
[150]237ALIGN JUMP_ALIGN
238.InswLoop:
[152]239 XTIDE_INSW
240 XTIDE_INSW
241 XTIDE_INSW
242 XTIDE_INSW
[150]243 loop .InswLoop
244 ret
245
[152]246;----
[150]247ALIGN JUMP_ALIGN
248SingleByteRead:
249%ifdef USE_186 ; INS instruction available
[152]250 shl cx, 1 ; WORD count to BYTE count
[150]251 rep insb
252%else ; If 8088/8086
[152]253 shr cx, 1 ; WORD count to DWORD count
[150]254ALIGN JUMP_ALIGN
255.InsdLoop:
256 in al, dx
[152]257 stosb ; Store to [ES:DI]
[150]258 in al, dx
259 stosb
260 in al, dx
261 stosb
262 in al, dx
263 stosb
264 loop .InsdLoop
265%endif
266 ret
267
[152]268;----
269%ifndef USE_186
270ALIGN JUMP_ALIGN
271WordReadForXTIDEmod:
272 times 2 shr cx, 1 ; WORD count to QWORD count
273ALIGN JUMP_ALIGN
274.ReadNextQword:
275 in ax, dx ; Read 1st WORD
276 stosw ; Store 1st WORD to [ES:DI]
277 in ax, dx
278 stosw ; 2nd
279 in ax, dx
280 stosw ; 3rd
281 in ax, dx
282 stosw ; 4th
283 loop .ReadNextQword
284 ret
285%endif
[150]286
[152]287;----
288ALIGN JUMP_ALIGN
289WordReadForXTplusAndAT:
290 rep
291 db 6Dh ; INSW (we want this in XT build)
292 ret
293
294;----
295ALIGN JUMP_ALIGN
296DWordRead:
297 shr cx, 1 ; WORD count to DWORD count
298 rep
299 db 66h ; Override operand size to 32-bit
300 db 6Dh ; INSW/INSD
301 ret
302
303
[150]304;--------------------------------------------------------------------
[152]305; DualByteWriteForXtide Dual port 8-bit XTIDE PIO write transfer
306; SingleByteWrite Single port 8-bit PIO write transfer
307; WordWriteForXTIDEmod 8088/8086 compatible 16-bit IDE PIO read transfer
308; WordWrite Normal 16-bit IDE PIO write transfer
309; DWordWrite VLB/PCI 32-bit IDE PIO write transfer
[150]310; Parameters:
311; CX: Block size in WORDs
312; DX: IDE Data port address
313; ES:SI: Normalized ptr to buffer containing data
314; Returns:
315; Nothing
316; Corrupts registers:
317; AX, CX
318;--------------------------------------------------------------------
319ALIGN JUMP_ALIGN
[152]320DualByteWriteForXtide:
[150]321 push ds
322 push bx
[161]323%ifdef USE_186
324 shr cx, 2 ; Smaller but slower on 186/286
325%else
[152]326 times 2 shr cx, 1 ; Loop unrolling
[161]327%endif
[152]328 mov bx, 8 ; Bit mask for toggling data low/high reg
329 push es ; Copy ES...
330 pop ds ; ...to DS
[150]331ALIGN JUMP_ALIGN
332.OutswLoop:
[152]333 XTIDE_OUTSW
334 XTIDE_OUTSW
335 XTIDE_OUTSW
336 XTIDE_OUTSW
[150]337 loop .OutswLoop
338 pop bx
339 pop ds
340 ret
341
[152]342;----
[150]343ALIGN JUMP_ALIGN
344SingleByteWrite:
345%ifdef USE_186 ; OUTS instruction available
[152]346 shl cx, 1 ; WORD count to BYTE count
347 eSEG es ; Source is ES segment
[150]348 rep outsb
349%else ; If 8088/8086
[152]350 shr cx, 1 ; WORD count to DWORD count
351 push ds ; Store DS
352 push es ; Copy ES...
353 pop ds ; ...to DS
[150]354ALIGN JUMP_ALIGN
355.OutsdLoop:
[152]356 lodsb ; Load from [DS:SI] to AL
[150]357 out dx, al
358 lodsb
359 out dx, al
360 lodsb
361 out dx, al
362 lodsb
363 out dx, al
364 loop .OutsdLoop
[152]365 pop ds ; Restore DS
[150]366%endif
367 ret
368
[152]369;---
370ALIGN JUMP_ALIGN
371WordWriteForXTIDEmod:
372 push ds
[161]373%ifdef USE_186
374 shr cx, 2 ; Smaller but slower on 186/286
375%else
[152]376 times 2 shr cx, 1 ; Loop unrolling
[161]377%endif
[152]378 push es ; Copy ES...
379 pop ds ; ...to DS
380ALIGN JUMP_ALIGN
381.WriteNextQword:
382 XTIDE_MOD_OUTSW
383 XTIDE_MOD_OUTSW
384 XTIDE_MOD_OUTSW
385 XTIDE_MOD_OUTSW
386 loop .WriteNextQword
387 pop ds
388 ret
[150]389
[152]390;----
391ALIGN JUMP_ALIGN
392WordWrite:
393 eSEG es ; Source is ES segment
394 rep
[155]395 db 6Fh ; OUTSW (we want this in XT build)
[152]396 ret
397
398ALIGN JUMP_ALIGN
399DWordWrite:
400 shr cx, 1 ; WORD count to DWORD count
401 eSEG es ; Source is ES segment
402 rep
403 db 66h ; Override operand size to 32-bit
404 db 6Fh ; OUTSW/OUTSD
405 ret
406
407
408
[150]409; Lookup tables to get transfer function based on bus type
410ALIGN WORD_ALIGN
411g_rgfnPioRead:
[152]412 dw DualByteReadForXtide ; DEVICE_8BIT_DUAL_PORT_XTIDE
413%ifdef USE_186
414 dw WordReadForXTplusAndAT ; DEVICE_XTIDE_WITH_REVERSED_A3_AND_A0
415%else
416 dw WordReadForXTIDEmod
417%endif
418 dw SingleByteRead ; DEVICE_8BIT_SINGLE_PORT
419 dw WordReadForXTplusAndAT ; DEVICE_16BIT_ATA
420 dw DWordRead ; DEVICE_32BIT_ATA
421
[150]422g_rgfnPioWrite:
[152]423 dw DualByteWriteForXtide ; DEVICE_8BIT_DUAL_PORT_XTIDE
424 dw WordWriteForXTIDEmod ; DEVICE_XTIDE_WITH_REVERSED_A3_AND_A0
425 dw SingleByteWrite ; DEVICE_8BIT_SINGLE_PORT
426 dw WordWrite ; DEVICE_16BIT_ATA
427 dw DWordWrite ; DEVICE_32BIT_ATA
Note: See TracBrowser for help on using the repository browser.