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

Last change on this file since 502 was 493, checked in by gregli@…, 12 years ago

Separated MODULE_8BIT_IDE into the basic part used by XTIDE rev 1 and rev 2 which is PIO based, and MODULE_8BIT_IDE_ADVANCED for JRIDE and XTCF support which requires memory mapping and/or DMA. This allows for creating an 8KB image with boot menu support (but no hotkeys) for the XTIDE rev 1. Cleaned up how we reset the drive translation information, ensuring it is properly set between boot attempt on a primary and secondary drive - as a result we clean it when needed, rather than trying to always keep it clean. Also fixed translation bugs in int13h.asm where I had previously missed converting some MODULE_HOTKEYS into MODULE_DRIVEXLATE.

File size: 10.6 KB
RevLine 
[150]1; Project name : XTIDE Universal BIOS
2; Description : IDE Device transfer functions.
3
[376]4;
[445]5; XTIDE Universal BIOS and Associated Tools
[376]6; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
7;
8; This program is free software; you can redistribute it and/or modify
9; it under the terms of the GNU General Public License as published by
10; the Free Software Foundation; either version 2 of the License, or
11; (at your option) any later version.
[445]12;
[376]13; This program is distributed in the hope that it will be useful,
14; but WITHOUT ANY WARRANTY; without even the implied warranty of
15; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
[445]16; GNU General Public License for more details.
[376]17; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
[445]18;
[376]19
[150]20; Structure containing variables for PIO transfer functions.
21; This struct must not be larger than IDEPACK without INTPACK.
[414]22struc PIOVARS ; Must not be larger than 9 bytes! See IDEPACK in RamVars.inc.
23 .wDataPort resb 2 ; 0-1, IDE Data Port
24 .fnXfer resb 2 ; 2-3, Offset to transfer function
25 .wSectorsInBlock resb 2 ; 4-5, Block size in sectors
[363]26 .bSectorsLeft resb 1 ; 6, Sectors left to transfer
[218]27 resb 1 ; 7, IDEPACK.bDeviceControl
[363]28 .bSectorsDone resb 1 ; 8, Number of sectors xferred
[150]29endstruc
30
31
32; Section containing code
33SECTION .text
34
35;--------------------------------------------------------------------
36; IdeTransfer_StartWithCommandInAL
37; Parameters:
38; AL: IDE command that was used to start the transfer
[171]39; (all PIO read and write commands including Identify Device)
[480]40; ES:SI: Ptr to data buffer
[150]41; DS:DI: Ptr to DPT (in RAMVARS segment)
42; SS:BP: Ptr to IDEPACK
43; Returns:
44; AH: INT 13h Error Code
[218]45; CX: Number of successfully transferred sectors
[150]46; CF: Cleared if success, Set if error
47; Corrupts registers:
[218]48; AL, BX, DX, SI, ES
[150]49;--------------------------------------------------------------------
50ALIGN JUMP_ALIGN
51IdeTransfer_StartWithCommandInAL:
[157]52 ; Are we reading or writing?
[171]53 test al, 16 ; Bit 4 is cleared on all the read commands but set on 3 of the 4 write commands
[242]54 mov ah, [bp+IDEPACK.bSectorCount]
55 jnz SHORT WriteToDrive
[171]56 cmp al, COMMAND_WRITE_MULTIPLE
[242]57 je SHORT WriteToDrive
58 ; Fall to ReadFromDrive
[150]59
60;--------------------------------------------------------------------
[242]61; ReadFromDrive
[150]62; Parameters:
[242]63; AH: Number of sectors to transfer (1...128)
[480]64; ES:SI: Ptr to buffer to receive data
[150]65; DS:DI: Ptr to DPT (in RAMVARS segment)
66; SS:BP: Ptr to PIOVARS
67; Returns:
[242]68; DS:DI: Ptr to DPT (in RAMVARS segment)
[150]69; AH: BIOS Error code
[218]70; CX: Number of successfully transferred sectors
[294]71; CF: 0 if transfer successful
[150]72; 1 if any error
73; Corrupts registers:
[218]74; AL, BX, DX, SI, ES
[150]75;--------------------------------------------------------------------
[242]76ReadFromDrive:
77 ; Prepare to read data to ESSI
78 mov bx, g_rgfnPioRead
79 call InitializePiovarsInSSBPwithSectorCountInAH
80
81 ; Wait until drive is ready to transfer
82 call IdeWait_IRQorDRQ ; Wait until ready to transfer
[218]83 jc SHORT ReturnWithTransferErrorInAH
[242]84 xchg si, di ; ES:DI now points buffer
[218]85
[363]86 mov cx, [bp+PIOVARS.wSectorsInBlock] ; Max 128
[242]87
[150]88ALIGN JUMP_ALIGN
[242]89.ReadNextBlockFromDrive:
[150]90 mov dx, [bp+PIOVARS.wDataPort]
[363]91 cmp [bp+PIOVARS.bSectorsLeft], cl
[242]92 jbe SHORT .ReadLastBlockFromDrive
[218]93 call [bp+PIOVARS.fnXfer]
[169]94
[218]95 ; Wait until ready for next block and check for errors
[242]96 xchg di, si ; DS:DI now points DPT
[218]97 call IdeWait_IRQorDRQ ; Wait until ready to transfer
98 jc SHORT ReturnWithTransferErrorInAH
[242]99 xchg si, di ; ES:DI now points buffer
[169]100
[363]101 ; Increment number of successfully read sectors
102 mov cx, [bp+PIOVARS.wSectorsInBlock]
103 sub [bp+PIOVARS.bSectorsLeft], cl
104 add [bp+PIOVARS.bSectorsDone], cl
[242]105 jmp SHORT .ReadNextBlockFromDrive
[150]106
107ALIGN JUMP_ALIGN
[242]108.ReadLastBlockFromDrive:
[363]109 mov cl, [bp+PIOVARS.bSectorsLeft] ; CH is already zero
[419]110 push cx
[150]111 call [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
112
[242]113 ; Check for errors in last block
114 mov di, si ; DS:DI now points DPT
115CheckErrorsAfterTransferringLastBlock:
[417]116 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_BSY)
[242]117 call IdeWait_PollStatusFlagInBLwithTimeoutInBH
[419]118 pop cx ; [bp+PIOVARS.bSectorsLeft]
119 jc SHORT ReturnWithTransferErrorInAH
[150]120
[445]121 ; All sectors successfully transferred
[419]122 add cx, [bp+PIOVARS.bSectorsDone] ; Never sets CF
123 ret
124
[242]125 ; Return number of successfully read sectors
126ReturnWithTransferErrorInAH:
[370]127%ifdef USE_386
128 movzx cx, [bp+PIOVARS.bSectorsDone]
129%else
[363]130 mov cl, [bp+PIOVARS.bSectorsDone]
131 mov ch, 0 ; Preserve CF
[370]132%endif
[242]133 ret
134
135
[150]136;--------------------------------------------------------------------
[242]137; WriteToDrive
[150]138; Parameters:
[242]139; AH: Number of sectors to transfer (1...128)
140; DS:DI: Ptr to DPT (in RAMVARS segment)
[480]141; ES:SI: Ptr to buffer containing data
[150]142; SS:BP: Ptr to PIOVARS
143; Returns:
144; AH: BIOS Error code
[218]145; CX: Number of successfully transferred sectors
[294]146; CF: 0 if transfer successful
[150]147; 1 if any error
148; Corrupts registers:
[218]149; AL, BX, DX, SI, ES
[150]150;--------------------------------------------------------------------
151ALIGN JUMP_ALIGN
[242]152WriteToDrive:
153 ; Prepare to write data from ESSI
154 mov bx, g_rgfnPioWrite
155 call InitializePiovarsInSSBPwithSectorCountInAH
156
157 ; Always poll when writing first block (IRQs are generated for following blocks)
158 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
159 call IdeWait_PollStatusFlagInBLwithTimeoutInBH
[218]160 jc SHORT ReturnWithTransferErrorInAH
[150]161
[363]162 mov cx, [bp+PIOVARS.wSectorsInBlock] ; Max 128
[242]163
[218]164ALIGN JUMP_ALIGN
[242]165.WriteNextBlockToDrive:
[150]166 mov dx, [bp+PIOVARS.wDataPort]
[363]167 cmp [bp+PIOVARS.bSectorsLeft], cl
[242]168 jbe SHORT .WriteLastBlockToDrive
[218]169 call [bp+PIOVARS.fnXfer]
[169]170
[218]171 ; Wait until ready for next block and check for errors
172 call IdeWait_IRQorDRQ ; Wait until ready to transfer
173 jc SHORT ReturnWithTransferErrorInAH
[150]174
[363]175 ; Increment number of successfully written sectors
176 mov cx, [bp+PIOVARS.wSectorsInBlock]
177 sub [bp+PIOVARS.bSectorsLeft], cl
178 add [bp+PIOVARS.bSectorsDone], cl
[242]179 jmp SHORT .WriteNextBlockToDrive
[169]180
[150]181ALIGN JUMP_ALIGN
[242]182.WriteLastBlockToDrive:
[363]183 mov cl, [bp+PIOVARS.bSectorsLeft] ; CH is already zero
[419]184 push cx
[242]185%ifdef USE_186
186 push CheckErrorsAfterTransferringLastBlock
187 jmp [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
188%else
[150]189 call [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
[242]190 jmp SHORT CheckErrorsAfterTransferringLastBlock
191%endif
[218]192
[150]193
194;--------------------------------------------------------------------
[218]195; InitializePiovarsInSSBPwithSectorCountInAH
[150]196; Parameters:
[218]197; AH: Number of sectors to transfer (1...128)
[150]198; BX: Offset to transfer function lookup table
199; DS:DI: Ptr to DPT (in RAMVARS segment)
[480]200; ES:SI: Ptr to data buffer
[169]201; SS:BP: Ptr to PIOVARS
[167]202; Returns:
[169]203; Nothing
[150]204; Corrupts registers:
[242]205; AX, BX, DX
[150]206;--------------------------------------------------------------------
207ALIGN JUMP_ALIGN
[218]208InitializePiovarsInSSBPwithSectorCountInAH:
[473]209 ; Store sizes and Data Port
[363]210 mov [bp+PIOVARS.bSectorsLeft], ah
[473]211 mov ax, [di+DPT.wBasePort]
212 mov [bp+PIOVARS.wDataPort], ax
[370]213 eMOVZX ax, [di+DPT_ATA.bBlockSize]
[363]214 mov [bp+PIOVARS.wSectorsInBlock], ax
215 mov [bp+PIOVARS.bSectorsDone], ah ; Zero
[150]216
217 ; Get transfer function based on bus type
[158]218 xchg ax, bx ; Lookup table offset to AX
[400]219 mov bl, [di+DPT_ATA.bDevice]
[493]220%ifdef MODULE_8BIT_IDE_ADVANCED
[480]221 mov dl, bl
222%endif
[150]223 add bx, ax
224 mov ax, [cs:bx] ; Load offset to transfer function
225 mov [bp+PIOVARS.fnXfer], ax
[480]226
227 ; Normalize pointer for PIO-transfers and convert to physical address for DMA transfers
[493]228%ifdef MODULE_8BIT_IDE_ADVANCED
[480]229 cmp dl, DEVICE_8BIT_XTCF_DMA
230 jb SHORT IdeTransfer_NormalizePointerInESSI
231
232 ; Convert ES:SI to physical address
[491]233%ifdef USE_186 ; Bytes EU Cycles(286)
234 mov ax, es ; 2 2
235 rol ax, 4 ; 3 9
236 mov dx, ax ; 2 2
237 and ax, BYTE 0Fh; 3 3
238 xor dx, ax ; 2 2
239 add si, dx ; 2 2
240 adc al, ah ; 2 2
241 mov es, ax ; 2 2
242 ;------------------------------------
243 ; 18 24
244%else ; 808x
245
246%if 0
247 ; Bytes EU Cycles(808x)
248 mov al, 4 ; 2 4
249 mov dx, es ; 2 2
250 xchg cx, ax ; 1 3
251 rol dx, cl ; 2 24
252 mov cx, dx ; 2 2
253 xchg cx, ax ; 1 3
254 and ax, BYTE 0Fh; 3 4
255 xor dx, ax ; 2 3
256 add si, dx ; 2 3
257 adc al, ah ; 2 3
258 mov es, ax ; 2 2
259 ;------------------------------------
260 ; 21 53
261;
262; Judging by the Execution Unit cycle count the above block of code is
263; apparently slower. However, the shifts and rotates in the block below
264; execute faster than the Bus Interface Unit on an 8088 can fetch them,
265; thus causing the EU to starve. The difference in true execution speed
266; (if any) might not be worth the extra 5 bytes.
267; In other words, we could use a real world test here.
268;
269%endif ; 0
270 ; Bytes EU Cycles(808x/286)
271 xor dx, dx ; 2 3/2
272 mov ax, es ; 2 2/2
[480]273%rep 4
[491]274 shl ax, 1 ; 8 8/8
275 rcl dx, 1 ; 8 8/8
[480]276%endrep
[491]277 add si, ax ; 2 3/2
278 adc dl, dh ; 2 3/2
279 mov es, dx ; 2 2/2
280 ;------------------------------------
281%endif ; 26 29/26
[150]282 ret
[493]283%endif ; MODULE_8BIT_IDE_ADVANCED
[480]284 ; Fall to IdeTransfer_NormalizePointerInESSI if no MODULE_8BIT_IDE
[150]285
286
[480]287;--------------------------------------------------------------------
288; IdeTransfer_NormalizePointerInESSI
289; Parameters:
290; ES:SI: Ptr to be normalized
291; Returns:
292; ES:SI: Normalized pointer (SI = 0...15)
293; Corrupts registers:
294; AX, DX
295;--------------------------------------------------------------------
296IdeTransfer_NormalizePointerInESSI:
297 NORMALIZE_FAR_POINTER es, si, ax, dx
298 ret
[400]299
[480]300
[150]301; Lookup tables to get transfer function based on bus type
302ALIGN WORD_ALIGN
303g_rgfnPioRead:
[473]304 dw IdePioBlock_ReadFrom16bitDataPort ; 0, DEVICE_16BIT_ATA
305 dw IdePioBlock_ReadFrom32bitDataPort ; 1, DEVICE_32BIT_ATA
[400]306%ifdef MODULE_8BIT_IDE
[480]307 dw IdePioBlock_ReadFrom8bitDataPort ; 2, DEVICE_8BIT_ATA
[491]308 dw IdePioBlock_ReadFromXtideRev1 ; 3, DEVICE_8BIT_XTIDE_REV1
[480]309 dw IdePioBlock_ReadFromXtideRev2 ; 4, DEVICE_8BIT_XTIDE_REV2
[493]310%ifdef MODULE_8BIT_IDE_ADVANCED
[480]311 dw IdePioBlock_ReadFrom8bitDataPort ; 5, DEVICE_8BIT_XTCF_PIO8
312 dw IdeDmaBlock_ReadFromXTCF ; 6, DEVICE_8BIT_XTCF_DMA
[473]313%endif
[493]314%endif
[400]315
[480]316
[473]317g_rgfnPioWrite:
318 dw IdePioBlock_WriteTo16bitDataPort ; 0, DEVICE_16BIT_ATA
319 dw IdePioBlock_WriteTo32bitDataPort ; 1, DEVICE_32BIT_ATA
[400]320%ifdef MODULE_8BIT_IDE
[480]321 dw IdePioBlock_WriteTo8bitDataPort ; 2, DEVICE_8BIT_ATA
322 dw IdePioBlock_WriteToXtideRev1 ; 3, DEVICE_8BIT_XTIDE_REV1
323 dw IdePioBlock_WriteToXtideRev2 ; 4, DEVICE_8BIT_XTIDE_REV2
[493]324%ifdef MODULE_8BIT_IDE_ADVANCED
[480]325 dw IdePioBlock_WriteTo8bitDataPort ; 5, DEVICE_8BIT_XTCF_PIO8
326 dw IdeDmaBlock_WriteToXTCF ; 6, DEVICE_8BIT_XTCF_DMA
[361]327%endif
[493]328%endif
Note: See TracBrowser for help on using the repository browser.