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

Last change on this file since 567 was 567, checked in by krille_n_@…, 11 years ago

Changes:

  • Renamed MODULE_FEATURE_SETS to MODULE_POWER_MANAGEMENT.
  • Renamed MODULE_VERY_LATE_INITIALIZATION to MODULE_VERY_LATE_INIT and removed it from the official builds.
  • Removed the code that skips detection of slave drives on XT-CF controllers since slave drives can be used with Lo-tech ISA CompactFlash boards.
  • Added autodetection of the SVC ADP50L controller to XTIDECFG.
  • The autodetection of XT-CF controllers now requires MODULE_8BIT_IDE_ADVANCED in the loaded BIOS.
  • Fixed a bug in XTIDECFG from r502 where the "Base (cmd block) address" menu option would be displayed when a serial device was selected as the IDE controller.
  • XTIDECFG would display the "Enable interrupt" menu option for the XTIDE r1 but not for the XTIDE r2. It's now displayed for both controller types.
  • Disabled the "Internal Write Cache" menu option in the Master/Slave Drive menus for serial device type drives.
  • Optimizations and other fixes.
File size: 12.1 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
[526]6; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2013 by XTIDE Universal BIOS Team.
[376]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
[538]80%ifdef USE_AT
81 jc SHORT ReturnWithTransferErrorInAH
82%endif
[242]83
84 ; Wait until drive is ready to transfer
85 call IdeWait_IRQorDRQ ; Wait until ready to transfer
[218]86 jc SHORT ReturnWithTransferErrorInAH
[242]87 xchg si, di ; ES:DI now points buffer
[218]88
[363]89 mov cx, [bp+PIOVARS.wSectorsInBlock] ; Max 128
[242]90
[150]91ALIGN JUMP_ALIGN
[242]92.ReadNextBlockFromDrive:
[150]93 mov dx, [bp+PIOVARS.wDataPort]
[363]94 cmp [bp+PIOVARS.bSectorsLeft], cl
[242]95 jbe SHORT .ReadLastBlockFromDrive
[218]96 call [bp+PIOVARS.fnXfer]
[169]97
[218]98 ; Wait until ready for next block and check for errors
[242]99 xchg di, si ; DS:DI now points DPT
[218]100 call IdeWait_IRQorDRQ ; Wait until ready to transfer
101 jc SHORT ReturnWithTransferErrorInAH
[242]102 xchg si, di ; ES:DI now points buffer
[169]103
[363]104 ; Increment number of successfully read sectors
105 mov cx, [bp+PIOVARS.wSectorsInBlock]
106 sub [bp+PIOVARS.bSectorsLeft], cl
107 add [bp+PIOVARS.bSectorsDone], cl
[242]108 jmp SHORT .ReadNextBlockFromDrive
[150]109
110ALIGN JUMP_ALIGN
[242]111.ReadLastBlockFromDrive:
[363]112 mov cl, [bp+PIOVARS.bSectorsLeft] ; CH is already zero
[419]113 push cx
[150]114 call [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
115
[242]116 ; Check for errors in last block
117 mov di, si ; DS:DI now points DPT
118CheckErrorsAfterTransferringLastBlock:
[417]119 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_BSY)
[242]120 call IdeWait_PollStatusFlagInBLwithTimeoutInBH
[419]121 pop cx ; [bp+PIOVARS.bSectorsLeft]
122 jc SHORT ReturnWithTransferErrorInAH
[150]123
[445]124 ; All sectors successfully transferred
[419]125 add cx, [bp+PIOVARS.bSectorsDone] ; Never sets CF
126 ret
127
[242]128 ; Return number of successfully read sectors
129ReturnWithTransferErrorInAH:
[370]130%ifdef USE_386
131 movzx cx, [bp+PIOVARS.bSectorsDone]
132%else
[363]133 mov cl, [bp+PIOVARS.bSectorsDone]
134 mov ch, 0 ; Preserve CF
[370]135%endif
[242]136 ret
137
138
[150]139;--------------------------------------------------------------------
[242]140; WriteToDrive
[150]141; Parameters:
[242]142; AH: Number of sectors to transfer (1...128)
143; DS:DI: Ptr to DPT (in RAMVARS segment)
[480]144; ES:SI: Ptr to buffer containing data
[150]145; SS:BP: Ptr to PIOVARS
146; Returns:
147; AH: BIOS Error code
[218]148; CX: Number of successfully transferred sectors
[294]149; CF: 0 if transfer successful
[150]150; 1 if any error
151; Corrupts registers:
[218]152; AL, BX, DX, SI, ES
[150]153;--------------------------------------------------------------------
154ALIGN JUMP_ALIGN
[242]155WriteToDrive:
156 ; Prepare to write data from ESSI
157 mov bx, g_rgfnPioWrite
158 call InitializePiovarsInSSBPwithSectorCountInAH
[538]159%ifdef USE_AT
160 jc SHORT ReturnWithTransferErrorInAH
161%endif
[242]162
163 ; Always poll when writing first block (IRQs are generated for following blocks)
164 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_DRQ)
165 call IdeWait_PollStatusFlagInBLwithTimeoutInBH
[218]166 jc SHORT ReturnWithTransferErrorInAH
[150]167
[363]168 mov cx, [bp+PIOVARS.wSectorsInBlock] ; Max 128
[242]169
[218]170ALIGN JUMP_ALIGN
[242]171.WriteNextBlockToDrive:
[150]172 mov dx, [bp+PIOVARS.wDataPort]
[363]173 cmp [bp+PIOVARS.bSectorsLeft], cl
[242]174 jbe SHORT .WriteLastBlockToDrive
[218]175 call [bp+PIOVARS.fnXfer]
[169]176
[218]177 ; Wait until ready for next block and check for errors
178 call IdeWait_IRQorDRQ ; Wait until ready to transfer
179 jc SHORT ReturnWithTransferErrorInAH
[150]180
[363]181 ; Increment number of successfully written sectors
182 mov cx, [bp+PIOVARS.wSectorsInBlock]
183 sub [bp+PIOVARS.bSectorsLeft], cl
184 add [bp+PIOVARS.bSectorsDone], cl
[242]185 jmp SHORT .WriteNextBlockToDrive
[169]186
[150]187ALIGN JUMP_ALIGN
[242]188.WriteLastBlockToDrive:
[363]189 mov cl, [bp+PIOVARS.bSectorsLeft] ; CH is already zero
[419]190 push cx
[242]191%ifdef USE_186
192 push CheckErrorsAfterTransferringLastBlock
193 jmp [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
194%else
[150]195 call [bp+PIOVARS.fnXfer] ; Transfer possibly partial block
[242]196 jmp SHORT CheckErrorsAfterTransferringLastBlock
197%endif
[218]198
[150]199
200;--------------------------------------------------------------------
[218]201; InitializePiovarsInSSBPwithSectorCountInAH
[150]202; Parameters:
[218]203; AH: Number of sectors to transfer (1...128)
[150]204; BX: Offset to transfer function lookup table
205; DS:DI: Ptr to DPT (in RAMVARS segment)
[480]206; ES:SI: Ptr to data buffer
[169]207; SS:BP: Ptr to PIOVARS
[167]208; Returns:
[538]209; ES:SI: Normalized pointer
210; AH: INT 13h Error Code (only when CF set)
[558]211; CF: Set if failed to normalize pointer (segment overflow)
[538]212; Cleared if success
[150]213; Corrupts registers:
[538]214; AL, BX, DX
[150]215;--------------------------------------------------------------------
216ALIGN JUMP_ALIGN
[218]217InitializePiovarsInSSBPwithSectorCountInAH:
[473]218 ; Store sizes and Data Port
[363]219 mov [bp+PIOVARS.bSectorsLeft], ah
[538]220%ifdef USE_AT
221 xchg dx, ax
222%endif
[473]223 mov ax, [di+DPT.wBasePort]
224 mov [bp+PIOVARS.wDataPort], ax
[370]225 eMOVZX ax, [di+DPT_ATA.bBlockSize]
[363]226 mov [bp+PIOVARS.wSectorsInBlock], ax
227 mov [bp+PIOVARS.bSectorsDone], ah ; Zero
[150]228
229 ; Get transfer function based on bus type
[567]230 mov al, [di+DPT_ATA.bDevice]
231 add bx, ax
[493]232%ifdef MODULE_8BIT_IDE_ADVANCED
[567]233 cmp al, DEVICE_8BIT_XTCF_DMA
[480]234%endif
[150]235 mov ax, [cs:bx] ; Load offset to transfer function
236 mov [bp+PIOVARS.fnXfer], ax
[480]237
238 ; Normalize pointer for PIO-transfers and convert to physical address for DMA transfers
[493]239%ifdef MODULE_8BIT_IDE_ADVANCED
[480]240 jb SHORT IdeTransfer_NormalizePointerInESSI
241
242 ; Convert ES:SI to physical address
[567]243%ifdef USE_186
244 ; Bytes EU Cycles(286)
[491]245 mov ax, es ; 2 2
246 rol ax, 4 ; 3 9
247 mov dx, ax ; 2 2
248 and ax, BYTE 0Fh; 3 3
249 xor dx, ax ; 2 2
250 add si, dx ; 2 2
251 adc al, ah ; 2 2
252 mov es, ax ; 2 2
253 ;------------------------------------
254 ; 18 24
255%else ; 808x
256 ; Bytes EU Cycles(808x)
257 mov al, 4 ; 2 4
258 mov dx, es ; 2 2
259 xchg cx, ax ; 1 3
260 rol dx, cl ; 2 24
261 mov cx, dx ; 2 2
262 xchg cx, ax ; 1 3
263 and ax, BYTE 0Fh; 3 4
264 xor dx, ax ; 2 3
265 add si, dx ; 2 3
266 adc al, ah ; 2 3
267 mov es, ax ; 2 2
268 ;------------------------------------
269 ; 21 53
270;
271; Judging by the Execution Unit cycle count the above block of code is
272; apparently slower. However, the shifts and rotates in the block below
273; execute faster than the Bus Interface Unit on an 8088 can fetch them,
274; thus causing the EU to starve. The difference in true execution speed
275; (if any) might not be worth the extra 5 bytes.
276; In other words, we could use a real world test here.
277;
[567]278%if 0
[491]279 ; Bytes EU Cycles(808x/286)
280 xor dx, dx ; 2 3/2
281 mov ax, es ; 2 2/2
[480]282%rep 4
[491]283 shl ax, 1 ; 8 8/8
284 rcl dx, 1 ; 8 8/8
[480]285%endrep
[491]286 add si, ax ; 2 3/2
287 adc dl, dh ; 2 3/2
288 mov es, dx ; 2 2/2
289 ;------------------------------------
[567]290 ; 26 29/26
291%endif ; 0
292%endif
293
294 ret ; With CF cleared (taken care of by the physical address conversion)
[493]295%endif ; MODULE_8BIT_IDE_ADVANCED
[558]296 ; Fall to IdeTransfer_NormalizePointerInESSI if no MODULE_8BIT_IDE_ADVANCED
[150]297
298
[480]299;--------------------------------------------------------------------
300; IdeTransfer_NormalizePointerInESSI
301; Parameters:
[538]302; DH: Number of sectors to transfer (when USE_AT defined)
[480]303; ES:SI: Ptr to be normalized
304; Returns:
305; ES:SI: Normalized pointer (SI = 0...15)
[558]306; AH: INT 13h Error Code (when USE_AT defined and normalization was attempted)
307; CF: Set if failed to normalize pointer (segment overflow)
[538]308; Cleared if success
[480]309; Corrupts registers:
310; AX, DX
311;--------------------------------------------------------------------
312IdeTransfer_NormalizePointerInESSI:
[538]313; Normalization can cause segment overflow if it is done when not needed
314; (I don't know if any software calls with such seg:off address).
315; This does not apply to XT systems since nothing will write to main BIOS ROM.
316; On AT systems things are quite different, even in protected mode the address
317; is passed in seg:offset form and HMA is accessible in real mode.
318%ifdef USE_AT
319 xor dl, dl
[558]320 eSHL_IM dx, 1
[538]321 dec dx ; Prevents normalization when bytes + offset will be zero
322 add dx, si
323 jc SHORT .NormalizationRequired
324 ret
325.NormalizationRequired:
326%endif ; USE_AT
327
[480]328 NORMALIZE_FAR_POINTER es, si, ax, dx
[538]329%ifdef USE_AT ; CF is always clear for XT builds
[558]330 ; AH = RET_HD_INVALID (01) if CF set, RET_HD_SUCCESS (00) if not. CF unchanged.
331 sbb ah, ah
332 neg ah
[538]333%endif
[480]334 ret
[400]335
[480]336
[538]337
[150]338; Lookup tables to get transfer function based on bus type
339ALIGN WORD_ALIGN
340g_rgfnPioRead:
[473]341 dw IdePioBlock_ReadFrom16bitDataPort ; 0, DEVICE_16BIT_ATA
342 dw IdePioBlock_ReadFrom32bitDataPort ; 1, DEVICE_32BIT_ATA
[400]343%ifdef MODULE_8BIT_IDE
[480]344 dw IdePioBlock_ReadFrom8bitDataPort ; 2, DEVICE_8BIT_ATA
[491]345 dw IdePioBlock_ReadFromXtideRev1 ; 3, DEVICE_8BIT_XTIDE_REV1
[545]346 dw IdePioBlock_ReadFrom16bitDataPort ; 4, DEVICE_8BIT_XTIDE_REV2
347 dw IdePioBlock_ReadFrom8bitDataPort ; 5, DEVICE_8BIT_XTCF_PIO8
348 dw IdePioBlock_ReadFrom16bitDataPort ; 6, DEVICE_8BIT_XTCF_PIO8_WITH_BIU_OFFLOAD
[493]349%ifdef MODULE_8BIT_IDE_ADVANCED
[545]350 dw IdeDmaBlock_ReadFromXTCF ; 7, DEVICE_8BIT_XTCF_DMA
351%endif ; MODULE_8BIT_IDE_ADVANCED
352%endif ; MODULE_8BIT_IDE
[400]353
[480]354
[473]355g_rgfnPioWrite:
356 dw IdePioBlock_WriteTo16bitDataPort ; 0, DEVICE_16BIT_ATA
357 dw IdePioBlock_WriteTo32bitDataPort ; 1, DEVICE_32BIT_ATA
[400]358%ifdef MODULE_8BIT_IDE
[480]359 dw IdePioBlock_WriteTo8bitDataPort ; 2, DEVICE_8BIT_ATA
360 dw IdePioBlock_WriteToXtideRev1 ; 3, DEVICE_8BIT_XTIDE_REV1
361 dw IdePioBlock_WriteToXtideRev2 ; 4, DEVICE_8BIT_XTIDE_REV2
[545]362 dw IdePioBlock_WriteTo8bitDataPort ; 5, DEVICE_8BIT_XTCF_PIO8
363 dw IdePioBlock_WriteTo16bitDataPort ; 6, DEVICE_8BIT_XTCF_PIO8_WITH_BIU_OFFLOAD
[526]364%ifdef MODULE_8BIT_IDE_ADVANCED
[545]365 dw IdeDmaBlock_WriteToXTCF ; 7, DEVICE_8BIT_XTCF_DMA
366%endif ; MODULE_8BIT_IDE_ADVANCED
367%endif ; MODULE_8BIT_IDE
Note: See TracBrowser for help on using the repository browser.