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

Last change on this file since 152 was 152, checked in by Tomi Tilli, 14 years ago

Changes to XTIDE Universal BIOS:

  • XTIDE mod should now be supported (untested).
  • Interrupt Service Routine no longer requires variable from RAMVARS.
  • Some small improvements.
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; 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:
34 mov ah, [bp+IDEPACK.bSectorCountHighExt]
35
36 ; Are we reading or writing
37 cmp al, COMMAND_WRITE_MULTIPLE
38 je SHORT .PrepareToWriteDataFromESSI
39 cmp al, COMMAND_WRITE_MULTIPLE_EXT
40 je SHORT .PrepareToWriteDataFromESSI
41 cmp al, COMMAND_WRITE_SECTORS
42 je SHORT .PrepareToWriteDataFromESSI
43 cmp al, COMMAND_WRITE_SECTORS_EXT
44 je SHORT .PrepareToWriteDataFromESSI
45
46 ; Prepare to read data to ESSI
47 mov bx, g_rgfnPioRead
48 mov al, [bp+IDEPACK.bSectorCount]
49 call InitializePiovarsInSSBPwithSectorCountInAX
50 xchg si, di
51 call Registers_NormalizeESDI
52 jmp SHORT ReadFromDrive
53
54ALIGN JUMP_ALIGN
55.PrepareToWriteDataFromESSI:
56 mov bx, g_rgfnPioWrite
57 mov al, [bp+IDEPACK.bSectorCount]
58 call InitializePiovarsInSSBPwithSectorCountInAX
59 call Registers_NormalizeESSI
60 ; Fall to WriteToDrive
61
62
63;--------------------------------------------------------------------
64; WriteToDrive
65; Parameters:
66; DS:DI: Ptr to DPT (in RAMVARS segment)
67; ES:SI: Normalized ptr to buffer containing data
68; SS:BP: Ptr to PIOVARS
69; Returns:
70; AH: BIOS Error code
71; CF: 0 if transfer succesfull
72; 1 if any error
73; Corrupts registers:
74; AL, BX, CX, DX, SI, ES
75;--------------------------------------------------------------------
76WriteToDrive:
77 ; Always poll when writing first block (IRQs are generated for following blocks)
78 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
79 call IdeWait_PollStatusFlagInBLwithTimeoutInBH
80 jc SHORT .ReturnWithTransferErrorInAH
81ALIGN JUMP_ALIGN
82.WriteNextBlock:
83 mov dx, [bp+PIOVARS.wDataPort]
84 dec WORD [bp+PIOVARS.wBlocksLeft] ; Transferring last (possibly partial) block?
85 jz SHORT .XferLastBlock ; If so, jump to transfer
86 mov cx, [bp+PIOVARS.wBlockSize] ; Load block size in WORDs
87 call [bp+PIOVARS.fnXfer] ; Transfer full block
88
89 ; Normalize pointer when necessary
90 mov ax, si
91 shr ax, 1 ; WORD offset
92 add ax, [bp+PIOVARS.wBlockSize]
93 jns SHORT .WaitUntilReadyToTransferNextBlock
94 call Registers_NormalizeESSI
95
96ALIGN JUMP_ALIGN
97.WaitUntilReadyToTransferNextBlock:
98%ifdef USE_186
99 push .WriteNextBlock
100 jmp IdeWait_IRQorDRQ
101%else
102 call IdeWait_IRQorDRQ
103 jnc SHORT .WriteNextBlock
104%endif
105.ReturnWithTransferErrorInAH:
106 ret
107
108ALIGN JUMP_ALIGN
109.XferLastBlock:
110 xor cx, cx
111 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRDY)
112 mov ch, [bp+PIOVARS.bSectorsInLastBlock]; CX = Partial block size in WORDs
113%ifdef USE_186
114 push IdeWait_IRQorStatusFlagInBLwithTimeoutInBH
115 jmp [bp+PIOVARS.fnXfer]
116%else
117 call [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
118 jmp IdeWait_IRQorStatusFlagInBLwithTimeoutInBH ; Check for errors
119%endif
120
121
122;--------------------------------------------------------------------
123; ReadFromDrive
124; Parameters:
125; ES:DI: Normalized ptr to buffer to recieve data
126; DS:SI: Ptr to DPT (in RAMVARS segment)
127; SS:BP: Ptr to PIOVARS
128; Returns:
129; DS:DI: Ptr to DPT (in RAMVARS segment)
130; AH: BIOS Error code
131; CF: 0 if transfer succesfull
132; 1 if any error
133; Corrupts registers:
134; AL, BX, CX, DX, SI, ES
135;--------------------------------------------------------------------
136ALIGN JUMP_ALIGN
137ReadFromDrive:
138 ; Wait until drive is ready to transfer
139 xchg di, si ; DS:DI now points DPT
140 call IdeWait_IRQorDRQ ; Wait until ready to transfer
141 jc SHORT WriteToDrive.ReturnWithTransferErrorInAH
142 xchg si, di ; ES:DI now points buffer
143
144 ; Transfer full or last (possible partial) block
145 mov dx, [bp+PIOVARS.wDataPort]
146 dec WORD [bp+PIOVARS.wBlocksLeft]
147 jz SHORT .XferLastBlock
148 mov cx, [bp+PIOVARS.wBlockSize] ; Load block size in WORDs
149 call [bp+PIOVARS.fnXfer] ; Transfer full block
150
151 ; Normalize pointer when necessary
152 mov ax, di
153 shr ax, 1 ; WORD offset
154 add ax, [bp+PIOVARS.wBlockSize]
155 jns SHORT ReadFromDrive
156 call Registers_NormalizeESDI
157 jmp SHORT ReadFromDrive ; Loop while blocks left
158
159ALIGN JUMP_ALIGN
160.XferLastBlock:
161 xor cx, cx
162 mov ch, [bp+PIOVARS.bSectorsInLastBlock]; CX = Partial block size in WORDs
163 call [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
164 mov di, si ; DS:DI now points DPT
165 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRDY)
166 jmp IdeWait_PollStatusFlagInBLwithTimeoutInBH
167
168
169;--------------------------------------------------------------------
170; InitializePiovarsInSSBPwithSectorCountInAX
171; Parameters:
172; AX: Number of sectors to transfer (0=65536)
173; BX: Offset to transfer function lookup table
174; DS:DI: Ptr to DPT (in RAMVARS segment)
175; SS:BP: Ptr to PIOVARS
176; Returns:
177; Nothing
178; Corrupts registers:
179; AX, BX, CX, DX
180;--------------------------------------------------------------------
181ALIGN JUMP_ALIGN
182InitializePiovarsInSSBPwithSectorCountInAX:
183 ; Store number of blocks to transfer
184 eMOVZX cx, BYTE [di+DPT_ATA.bSetBlock] ; Block size in sectors
185 xor dx, dx
186 test ax, ax
187 eCMOVZ dl, 1 ; DX:AX = Sectors to transfer (1...65536)
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
191 jz SHORT .NoPartialBlocksToTransfer
192 inc ax ; Partial block
193 mov dh, dl ; DH = Size of partial block in sectors
194.NoPartialBlocksToTransfer:
195 mov [bp+PIOVARS.wBlocksLeft], ax
196 mov [bp+PIOVARS.bSectorsInLastBlock], dh
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
203 xchg ax, bx
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;--------------------------------------------------------------------
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
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
230DualByteReadForXtide:
231 times 2 shr cx, 1 ; Loop unrolling
232 mov bx, 8 ; Bit mask for toggling data low/high reg
233ALIGN JUMP_ALIGN
234.InswLoop:
235 XTIDE_INSW
236 XTIDE_INSW
237 XTIDE_INSW
238 XTIDE_INSW
239 loop .InswLoop
240 ret
241
242;----
243ALIGN JUMP_ALIGN
244SingleByteRead:
245%ifdef USE_186 ; INS instruction available
246 shl cx, 1 ; WORD count to BYTE count
247 rep insb
248%else ; If 8088/8086
249 shr cx, 1 ; WORD count to DWORD count
250ALIGN JUMP_ALIGN
251.InsdLoop:
252 in al, dx
253 stosb ; Store to [ES:DI]
254 in al, dx
255 stosb
256 in al, dx
257 stosb
258 in al, dx
259 stosb
260 loop .InsdLoop
261%endif
262 ret
263
264;----
265%ifndef USE_186
266ALIGN JUMP_ALIGN
267WordReadForXTIDEmod:
268 times 2 shr cx, 1 ; WORD count to QWORD count
269ALIGN JUMP_ALIGN
270.ReadNextQword:
271 in ax, dx ; Read 1st WORD
272 stosw ; Store 1st WORD to [ES:DI]
273 in ax, dx
274 stosw ; 2nd
275 in ax, dx
276 stosw ; 3rd
277 in ax, dx
278 stosw ; 4th
279 loop .ReadNextQword
280 ret
281%endif
282
283;----
284ALIGN JUMP_ALIGN
285WordReadForXTplusAndAT:
286 rep
287 db 6Dh ; INSW (we want this in XT build)
288 ret
289
290;----
291ALIGN JUMP_ALIGN
292DWordRead:
293 shr cx, 1 ; WORD count to DWORD count
294 rep
295 db 66h ; Override operand size to 32-bit
296 db 6Dh ; INSW/INSD
297 ret
298
299
300;--------------------------------------------------------------------
301; DualByteWriteForXtide Dual port 8-bit XTIDE PIO write transfer
302; SingleByteWrite Single port 8-bit PIO write transfer
303; WordWriteForXTIDEmod 8088/8086 compatible 16-bit IDE PIO read transfer
304; WordWrite Normal 16-bit IDE PIO write transfer
305; DWordWrite VLB/PCI 32-bit IDE PIO write transfer
306; Parameters:
307; CX: Block size in WORDs
308; DX: IDE Data port address
309; ES:SI: Normalized ptr to buffer containing data
310; Returns:
311; Nothing
312; Corrupts registers:
313; AX, CX
314;--------------------------------------------------------------------
315ALIGN JUMP_ALIGN
316DualByteWriteForXtide:
317 push ds
318 push bx
319 times 2 shr cx, 1 ; Loop unrolling
320 mov bx, 8 ; Bit mask for toggling data low/high reg
321 push es ; Copy ES...
322 pop ds ; ...to DS
323ALIGN JUMP_ALIGN
324.OutswLoop:
325 XTIDE_OUTSW
326 XTIDE_OUTSW
327 XTIDE_OUTSW
328 XTIDE_OUTSW
329 loop .OutswLoop
330 pop bx
331 pop ds
332 ret
333
334;----
335ALIGN JUMP_ALIGN
336SingleByteWrite:
337%ifdef USE_186 ; OUTS instruction available
338 shl cx, 1 ; WORD count to BYTE count
339 eSEG es ; Source is ES segment
340 rep outsb
341%else ; If 8088/8086
342 shr cx, 1 ; WORD count to DWORD count
343 push ds ; Store DS
344 push es ; Copy ES...
345 pop ds ; ...to DS
346ALIGN JUMP_ALIGN
347.OutsdLoop:
348 lodsb ; Load from [DS:SI] to AL
349 out dx, al
350 lodsb
351 out dx, al
352 lodsb
353 out dx, al
354 lodsb
355 out dx, al
356 loop .OutsdLoop
357 pop ds ; Restore DS
358%endif
359 ret
360
361;---
362ALIGN JUMP_ALIGN
363WordWriteForXTIDEmod:
364 push ds
365 times 2 shr cx, 1 ; Loop unrolling
366 push es ; Copy ES...
367 pop ds ; ...to DS
368ALIGN JUMP_ALIGN
369.WriteNextQword:
370 XTIDE_MOD_OUTSW
371 XTIDE_MOD_OUTSW
372 XTIDE_MOD_OUTSW
373 XTIDE_MOD_OUTSW
374 loop .WriteNextQword
375 pop ds
376 ret
377
378;----
379ALIGN JUMP_ALIGN
380WordWrite:
381 eSEG es ; Source is ES segment
382 rep
383 db 6Fh ; OUTSW
384 ret
385
386ALIGN JUMP_ALIGN
387DWordWrite:
388 shr cx, 1 ; WORD count to DWORD count
389 eSEG es ; Source is ES segment
390 rep
391 db 66h ; Override operand size to 32-bit
392 db 6Fh ; OUTSW/OUTSD
393 ret
394
395
396
397; Lookup tables to get transfer function based on bus type
398ALIGN WORD_ALIGN
399g_rgfnPioRead:
400 dw DualByteReadForXtide ; DEVICE_8BIT_DUAL_PORT_XTIDE
401%ifdef USE_186
402 dw WordReadForXTplusAndAT ; DEVICE_XTIDE_WITH_REVERSED_A3_AND_A0
403%else
404 dw WordReadForXTIDEmod
405%endif
406 dw SingleByteRead ; DEVICE_8BIT_SINGLE_PORT
407 dw WordReadForXTplusAndAT ; DEVICE_16BIT_ATA
408 dw DWordRead ; DEVICE_32BIT_ATA
409
410g_rgfnPioWrite:
411 dw DualByteWriteForXtide ; DEVICE_8BIT_DUAL_PORT_XTIDE
412 dw WordWriteForXTIDEmod ; DEVICE_XTIDE_WITH_REVERSED_A3_AND_A0
413 dw SingleByteWrite ; DEVICE_8BIT_SINGLE_PORT
414 dw WordWrite ; DEVICE_16BIT_ATA
415 dw DWordWrite ; DEVICE_32BIT_ATA
Note: See TracBrowser for help on using the repository browser.