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
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
[167]7 .wBlockLeftAndSectorsInLastBlock:
8 .bBlocksLeft resb 1
9 .bSectorsInLastBlock: resb 1
[150]10 .wBlockSize resb 2 ; Block size in WORDs (256...32768)
11 .wDataPort resb 2
[167]12 resb 1
[150]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:
[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
[167]44 call InitializePiovarsToSSBPfromIdepackInSSBP
[150]45 xchg si, di
[167]46%ifdef USE_186
47 push ReadFromDriveToESDI
48 jmp Registers_NormalizeESDI
49%else
[150]50 call Registers_NormalizeESDI
[167]51 jmp SHORT ReadFromDriveToESDI
52%endif
[150]53
54ALIGN JUMP_ALIGN
55.PrepareToWriteDataFromESSI:
56 mov bx, g_rgfnPioWrite
[167]57 call InitializePiovarsToSSBPfromIdepackInSSBP
[150]58 call Registers_NormalizeESSI
[167]59 ; Fall to WriteToDriveFromESSI
[150]60
61
62;--------------------------------------------------------------------
[167]63; WriteToDriveFromESSI
[150]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;--------------------------------------------------------------------
[167]75WriteToDriveFromESSI:
[150]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]
[167]83 dec BYTE [bp+PIOVARS.bBlocksLeft] ; Transferring last (possibly partial) block?
[150]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;--------------------------------------------------------------------
[167]112; ReadFromDriveToESDI
[150]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
[167]126ReadFromDriveToESDI:
[150]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
[167]130 jc SHORT WriteToDriveFromESSI.ReturnWithTransferErrorInAH
[150]131 xchg si, di ; ES:DI now points buffer
132
133 ; Transfer full or last (possible partial) block
134 mov dx, [bp+PIOVARS.wDataPort]
[167]135 dec BYTE [bp+PIOVARS.bBlocksLeft]
[150]136 jz SHORT .XferLastBlock
137 mov cx, [bp+PIOVARS.wBlockSize] ; Load block size in WORDs
[167]138%ifdef USE_186
139 push ReadFromDriveToESDI
140 jmp [bp+PIOVARS.fnXfer]
141%else
[150]142 call [bp+PIOVARS.fnXfer] ; Transfer full block
[167]143 jmp SHORT ReadFromDriveToESDI ; Loop while blocks left
144%endif
[150]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;--------------------------------------------------------------------
[167]157; InitializePiovarsToSSBPfromIdepackInSSBP
[150]158; Parameters:
159; BX: Offset to transfer function lookup table
160; DS:DI: Ptr to DPT (in RAMVARS segment)
[167]161; SS:BP: Ptr to IDEPACK
162; Returns:
[150]163; SS:BP: Ptr to PIOVARS
164; Corrupts registers:
165; AX, BX, CX, DX
166;--------------------------------------------------------------------
167ALIGN JUMP_ALIGN
[167]168InitializePiovarsToSSBPfromIdepackInSSBP:
[150]169 ; Store number of blocks to transfer
[167]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
[150]174 jz SHORT .NoPartialBlocksToTransfer
[167]175 inc ax ; Add partial block to total block count
176 SKIP2B dx ; Skip mov ah, cl
[150]177.NoPartialBlocksToTransfer:
[167]178 mov ah, cl ; Full block size if no partial blocks to transfer
179 mov [bp+PIOVARS.wBlockLeftAndSectorsInLastBlock], ax
[150]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
[158]186 xchg ax, bx ; Lookup table offset to AX
[150]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;--------------------------------------------------------------------
[152]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
[150]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
[152]213DualByteReadForXtide:
[161]214%ifdef USE_186
215 shr cx, 2 ; Smaller but slower on 186/286
216%else
[152]217 times 2 shr cx, 1 ; Loop unrolling
[161]218%endif
[152]219 mov bx, 8 ; Bit mask for toggling data low/high reg
[150]220ALIGN JUMP_ALIGN
221.InswLoop:
[152]222 XTIDE_INSW
223 XTIDE_INSW
224 XTIDE_INSW
225 XTIDE_INSW
[150]226 loop .InswLoop
227 ret
228
[152]229;----
[150]230ALIGN JUMP_ALIGN
231SingleByteRead:
232%ifdef USE_186 ; INS instruction available
[152]233 shl cx, 1 ; WORD count to BYTE count
[150]234 rep insb
235%else ; If 8088/8086
[152]236 shr cx, 1 ; WORD count to DWORD count
[150]237ALIGN JUMP_ALIGN
238.InsdLoop:
239 in al, dx
[152]240 stosb ; Store to [ES:DI]
[150]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
[152]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
[150]269
[152]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
[150]287;--------------------------------------------------------------------
[152]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
[150]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
[152]303DualByteWriteForXtide:
[150]304 push ds
305 push bx
[161]306%ifdef USE_186
307 shr cx, 2 ; Smaller but slower on 186/286
308%else
[152]309 times 2 shr cx, 1 ; Loop unrolling
[161]310%endif
[152]311 mov bx, 8 ; Bit mask for toggling data low/high reg
312 push es ; Copy ES...
313 pop ds ; ...to DS
[150]314ALIGN JUMP_ALIGN
315.OutswLoop:
[152]316 XTIDE_OUTSW
317 XTIDE_OUTSW
318 XTIDE_OUTSW
319 XTIDE_OUTSW
[150]320 loop .OutswLoop
321 pop bx
322 pop ds
323 ret
324
[152]325;----
[150]326ALIGN JUMP_ALIGN
327SingleByteWrite:
328%ifdef USE_186 ; OUTS instruction available
[152]329 shl cx, 1 ; WORD count to BYTE count
330 eSEG es ; Source is ES segment
[150]331 rep outsb
332%else ; If 8088/8086
[152]333 shr cx, 1 ; WORD count to DWORD count
334 push ds ; Store DS
335 push es ; Copy ES...
336 pop ds ; ...to DS
[150]337ALIGN JUMP_ALIGN
338.OutsdLoop:
[152]339 lodsb ; Load from [DS:SI] to AL
[150]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
[152]348 pop ds ; Restore DS
[150]349%endif
350 ret
351
[152]352;---
353ALIGN JUMP_ALIGN
354WordWriteForXTIDEmod:
355 push ds
[161]356%ifdef USE_186
357 shr cx, 2 ; Smaller but slower on 186/286
358%else
[152]359 times 2 shr cx, 1 ; Loop unrolling
[161]360%endif
[152]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
[150]372
[152]373;----
374ALIGN JUMP_ALIGN
375WordWrite:
376 eSEG es ; Source is ES segment
377 rep
[155]378 db 6Fh ; OUTSW (we want this in XT build)
[152]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
[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.