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

Last change on this file since 168 was 167, checked in by aitotat@…, 13 years ago

Changes to XTIDE Universal BIOS:

  • Old Int 13h transfer functions work again.
  • Fixes to eINT13h (EBIOS) support.
File size: 11.2 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 .wBlockLeftAndSectorsInLastBlock:
8 .bBlocksLeft resb 1
9 .bSectorsInLastBlock: resb 1
10 .wBlockSize resb 2 ; Block size in WORDs (256...32768)
11 .wDataPort resb 2
12 resb 1
13 resb 1 ; Offset 7 = IDEPACK.bDeviceControl
14 .fnXfer resb 2 ; Offset to transfer function
15endstruc
16
17
18; Section containing code
19SECTION .text
20
21;--------------------------------------------------------------------
22; IdeTransfer_StartWithCommandInAL
23; Parameters:
24; AL: IDE command that was used to start the transfer
25; ES:SI: Ptr to destination buffer or source data
26; DS:DI: Ptr to DPT (in RAMVARS segment)
27; SS:BP: Ptr to IDEPACK
28; Returns:
29; AH: INT 13h Error Code
30; CF: Cleared if success, Set if error
31; Corrupts registers:
32; AL, BX, CX, DX, SI, ES
33;--------------------------------------------------------------------
34ALIGN JUMP_ALIGN
35IdeTransfer_StartWithCommandInAL:
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 call InitializePiovarsToSSBPfromIdepackInSSBP
45 xchg si, di
46%ifdef USE_186
47 push ReadFromDriveToESDI
48 jmp Registers_NormalizeESDI
49%else
50 call Registers_NormalizeESDI
51 jmp SHORT ReadFromDriveToESDI
52%endif
53
54ALIGN JUMP_ALIGN
55.PrepareToWriteDataFromESSI:
56 mov bx, g_rgfnPioWrite
57 call InitializePiovarsToSSBPfromIdepackInSSBP
58 call Registers_NormalizeESSI
59 ; Fall to WriteToDriveFromESSI
60
61
62;--------------------------------------------------------------------
63; WriteToDriveFromESSI
64; Parameters:
65; DS:DI: Ptr to DPT (in RAMVARS segment)
66; ES:SI: Normalized ptr to buffer containing data
67; SS:BP: Ptr to PIOVARS
68; Returns:
69; AH: BIOS Error code
70; CF: 0 if transfer succesfull
71; 1 if any error
72; Corrupts registers:
73; AL, BX, CX, DX, SI, ES
74;--------------------------------------------------------------------
75WriteToDriveFromESSI:
76 ; Always poll when writing first block (IRQs are generated for following blocks)
77 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
78 call IdeWait_PollStatusFlagInBLwithTimeoutInBH
79 jc SHORT .ReturnWithTransferErrorInAH
80ALIGN JUMP_ALIGN
81.WriteNextBlock:
82 mov dx, [bp+PIOVARS.wDataPort]
83 dec BYTE [bp+PIOVARS.bBlocksLeft] ; Transferring last (possibly partial) block?
84 jz SHORT .XferLastBlock ; If so, jump to transfer
85 mov cx, [bp+PIOVARS.wBlockSize] ; Load block size in WORDs
86 call [bp+PIOVARS.fnXfer] ; Transfer full block
87%ifdef USE_186
88 push .WriteNextBlock
89 jmp IdeWait_IRQorDRQ
90%else
91 call IdeWait_IRQorDRQ
92 jnc SHORT .WriteNextBlock
93%endif
94.ReturnWithTransferErrorInAH:
95 ret
96
97ALIGN JUMP_ALIGN
98.XferLastBlock:
99 xor cx, cx
100 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRDY)
101 mov ch, [bp+PIOVARS.bSectorsInLastBlock]; CX = Partial block size in WORDs
102%ifdef USE_186
103 push IdeWait_IRQorStatusFlagInBLwithTimeoutInBH
104 jmp [bp+PIOVARS.fnXfer]
105%else
106 call [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
107 jmp IdeWait_IRQorStatusFlagInBLwithTimeoutInBH ; Check for errors
108%endif
109
110
111;--------------------------------------------------------------------
112; ReadFromDriveToESDI
113; Parameters:
114; ES:DI: Normalized ptr to buffer to recieve data
115; DS:SI: Ptr to DPT (in RAMVARS segment)
116; SS:BP: Ptr to PIOVARS
117; Returns:
118; DS:DI: Ptr to DPT (in RAMVARS segment)
119; AH: BIOS Error code
120; CF: 0 if transfer succesfull
121; 1 if any error
122; Corrupts registers:
123; AL, BX, CX, DX, SI, ES
124;--------------------------------------------------------------------
125ALIGN JUMP_ALIGN
126ReadFromDriveToESDI:
127 ; Wait until drive is ready to transfer
128 xchg di, si ; DS:DI now points DPT
129 call IdeWait_IRQorDRQ ; Wait until ready to transfer
130 jc SHORT WriteToDriveFromESSI.ReturnWithTransferErrorInAH
131 xchg si, di ; ES:DI now points buffer
132
133 ; Transfer full or last (possible partial) block
134 mov dx, [bp+PIOVARS.wDataPort]
135 dec BYTE [bp+PIOVARS.bBlocksLeft]
136 jz SHORT .XferLastBlock
137 mov cx, [bp+PIOVARS.wBlockSize] ; Load block size in WORDs
138%ifdef USE_186
139 push ReadFromDriveToESDI
140 jmp [bp+PIOVARS.fnXfer]
141%else
142 call [bp+PIOVARS.fnXfer] ; Transfer full block
143 jmp SHORT ReadFromDriveToESDI ; Loop while blocks left
144%endif
145
146ALIGN JUMP_ALIGN
147.XferLastBlock:
148 xor cx, cx
149 mov ch, [bp+PIOVARS.bSectorsInLastBlock]; CX = Partial block size in WORDs
150 call [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
151 mov di, si ; DS:DI now points DPT
152 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRDY)
153 jmp IdeWait_PollStatusFlagInBLwithTimeoutInBH
154
155
156;--------------------------------------------------------------------
157; InitializePiovarsToSSBPfromIdepackInSSBP
158; Parameters:
159; BX: Offset to transfer function lookup table
160; DS:DI: Ptr to DPT (in RAMVARS segment)
161; SS:BP: Ptr to IDEPACK
162; Returns:
163; SS:BP: Ptr to PIOVARS
164; Corrupts registers:
165; AX, BX, CX, DX
166;--------------------------------------------------------------------
167ALIGN JUMP_ALIGN
168InitializePiovarsToSSBPfromIdepackInSSBP:
169 ; Store number of blocks to transfer
170 eMOVZX cx, BYTE [di+DPT_ATA.bSetBlock] ; Block size in sectors, zero CH
171 eMOVZX ax, BYTE [bp+IDEPACK.bSectorCount] ; AX = sectors to transfer (1...128)
172 div cl ; AL = Full blocks to transfer
173 test ah, ah ; AH = Sectors in partial block
174 jz SHORT .NoPartialBlocksToTransfer
175 inc ax ; Add partial block to total block count
176 SKIP2B dx ; Skip mov ah, cl
177.NoPartialBlocksToTransfer:
178 mov ah, cl ; Full block size if no partial blocks to transfer
179 mov [bp+PIOVARS.wBlockLeftAndSectorsInLastBlock], ax
180
181 ; Store block size in WORDs
182 xchg ch, cl ; CX = Block size in WORDs
183 mov [bp+PIOVARS.wBlockSize], cx
184
185 ; Get transfer function based on bus type
186 xchg ax, bx ; Lookup table offset to AX
187 eMOVZX bx, BYTE [di+DPT.bIdevarsOffset] ; CS:BX now points to IDEVARS
188 mov dx, [cs:bx+IDEVARS.wPort] ; Load IDE Data port address
189 mov bl, [cs:bx+IDEVARS.bDevice] ; Load device type to BX
190 add bx, ax
191 mov ax, [cs:bx] ; Load offset to transfer function
192 mov [bp+PIOVARS.wDataPort], dx
193 mov [bp+PIOVARS.fnXfer], ax
194 ret
195
196
197;--------------------------------------------------------------------
198; DualByteReadForXtide Dual port 8-bit XTIDE PIO read transfer
199; SingleByteRead Single port 8-bit PIO read transfer
200; WordReadForXTIDEmod 8088/8086 compatible 16-bit IDE PIO read transfer
201; WordReadForXTplusAndAT Normal 16-bit IDE PIO read transfer
202; DWordRead VLB/PCI 32-bit IDE PIO read transfer
203; Parameters:
204; CX: Block size in WORDs
205; DX: IDE Data port address
206; ES:DI: Normalized ptr to buffer to recieve data
207; Returns:
208; Nothing
209; Corrupts registers:
210; AX, BX, CX
211;--------------------------------------------------------------------
212ALIGN JUMP_ALIGN
213DualByteReadForXtide:
214%ifdef USE_186
215 shr cx, 2 ; Smaller but slower on 186/286
216%else
217 times 2 shr cx, 1 ; Loop unrolling
218%endif
219 mov bx, 8 ; Bit mask for toggling data low/high reg
220ALIGN JUMP_ALIGN
221.InswLoop:
222 XTIDE_INSW
223 XTIDE_INSW
224 XTIDE_INSW
225 XTIDE_INSW
226 loop .InswLoop
227 ret
228
229;----
230ALIGN JUMP_ALIGN
231SingleByteRead:
232%ifdef USE_186 ; INS instruction available
233 shl cx, 1 ; WORD count to BYTE count
234 rep insb
235%else ; If 8088/8086
236 shr cx, 1 ; WORD count to DWORD count
237ALIGN JUMP_ALIGN
238.InsdLoop:
239 in al, dx
240 stosb ; Store to [ES:DI]
241 in al, dx
242 stosb
243 in al, dx
244 stosb
245 in al, dx
246 stosb
247 loop .InsdLoop
248%endif
249 ret
250
251;----
252%ifndef USE_186
253ALIGN JUMP_ALIGN
254WordReadForXTIDEmod:
255 times 2 shr cx, 1 ; WORD count to QWORD count
256ALIGN JUMP_ALIGN
257.ReadNextQword:
258 in ax, dx ; Read 1st WORD
259 stosw ; Store 1st WORD to [ES:DI]
260 in ax, dx
261 stosw ; 2nd
262 in ax, dx
263 stosw ; 3rd
264 in ax, dx
265 stosw ; 4th
266 loop .ReadNextQword
267 ret
268%endif
269
270;----
271ALIGN JUMP_ALIGN
272WordReadForXTplusAndAT:
273 rep
274 db 6Dh ; INSW (we want this in XT build)
275 ret
276
277;----
278ALIGN JUMP_ALIGN
279DWordRead:
280 shr cx, 1 ; WORD count to DWORD count
281 rep
282 db 66h ; Override operand size to 32-bit
283 db 6Dh ; INSW/INSD
284 ret
285
286
287;--------------------------------------------------------------------
288; DualByteWriteForXtide Dual port 8-bit XTIDE PIO write transfer
289; SingleByteWrite Single port 8-bit PIO write transfer
290; WordWriteForXTIDEmod 8088/8086 compatible 16-bit IDE PIO read transfer
291; WordWrite Normal 16-bit IDE PIO write transfer
292; DWordWrite VLB/PCI 32-bit IDE PIO write transfer
293; Parameters:
294; CX: Block size in WORDs
295; DX: IDE Data port address
296; ES:SI: Normalized ptr to buffer containing data
297; Returns:
298; Nothing
299; Corrupts registers:
300; AX, CX
301;--------------------------------------------------------------------
302ALIGN JUMP_ALIGN
303DualByteWriteForXtide:
304 push ds
305 push bx
306%ifdef USE_186
307 shr cx, 2 ; Smaller but slower on 186/286
308%else
309 times 2 shr cx, 1 ; Loop unrolling
310%endif
311 mov bx, 8 ; Bit mask for toggling data low/high reg
312 push es ; Copy ES...
313 pop ds ; ...to DS
314ALIGN JUMP_ALIGN
315.OutswLoop:
316 XTIDE_OUTSW
317 XTIDE_OUTSW
318 XTIDE_OUTSW
319 XTIDE_OUTSW
320 loop .OutswLoop
321 pop bx
322 pop ds
323 ret
324
325;----
326ALIGN JUMP_ALIGN
327SingleByteWrite:
328%ifdef USE_186 ; OUTS instruction available
329 shl cx, 1 ; WORD count to BYTE count
330 eSEG es ; Source is ES segment
331 rep outsb
332%else ; If 8088/8086
333 shr cx, 1 ; WORD count to DWORD count
334 push ds ; Store DS
335 push es ; Copy ES...
336 pop ds ; ...to DS
337ALIGN JUMP_ALIGN
338.OutsdLoop:
339 lodsb ; Load from [DS:SI] to AL
340 out dx, al
341 lodsb
342 out dx, al
343 lodsb
344 out dx, al
345 lodsb
346 out dx, al
347 loop .OutsdLoop
348 pop ds ; Restore DS
349%endif
350 ret
351
352;---
353ALIGN JUMP_ALIGN
354WordWriteForXTIDEmod:
355 push ds
356%ifdef USE_186
357 shr cx, 2 ; Smaller but slower on 186/286
358%else
359 times 2 shr cx, 1 ; Loop unrolling
360%endif
361 push es ; Copy ES...
362 pop ds ; ...to DS
363ALIGN JUMP_ALIGN
364.WriteNextQword:
365 XTIDE_MOD_OUTSW
366 XTIDE_MOD_OUTSW
367 XTIDE_MOD_OUTSW
368 XTIDE_MOD_OUTSW
369 loop .WriteNextQword
370 pop ds
371 ret
372
373;----
374ALIGN JUMP_ALIGN
375WordWrite:
376 eSEG es ; Source is ES segment
377 rep
378 db 6Fh ; OUTSW (we want this in XT build)
379 ret
380
381ALIGN JUMP_ALIGN
382DWordWrite:
383 shr cx, 1 ; WORD count to DWORD count
384 eSEG es ; Source is ES segment
385 rep
386 db 66h ; Override operand size to 32-bit
387 db 6Fh ; OUTSW/OUTSD
388 ret
389
390
391
392; Lookup tables to get transfer function based on bus type
393ALIGN WORD_ALIGN
394g_rgfnPioRead:
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
405g_rgfnPioWrite:
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.