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

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

Changes to XTIDE Universal BIOS:

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