source: xtideuniversalbios/trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeDmaBlock.asm@ 617

Last change on this file since 617 was 589, checked in by Krister Nordvall, 9 years ago

Changes:

  • BIOS: Fixed a purely cosmetic bug from r542 where, in builds containing MODULE_EBIOS, the boot menu would display an incorrect drive size (0.4 kB with MODULE_STRINGS_COMPRESSED or 0.5 kB without) for old drives with no support for LBA.
  • Fixed a bug from r392 where Vision_DetectAndReturnIDinAXandPortInDXifControllerPresent would return the ID in AL instead of AH (if DANGEROUS_DETECTION had been defined).
  • Fixed a bug from r587 in AdvAtaInit.asm that would prevent detection of QDI Vision controllers.
  • Also changed how the QDI Vision IDs are defined (removed the need for shifting) to avoid confusion. This fixed a potential bug from r587 in AdvAtaInit.asm where some IDs were not being shifted.
  • Fixed a bug in PDC20x30.asm from r587 where GetPdcIDtoAX would not return with the IDE base port in DX so DisablePdcProgrammingMode would fail.
  • Made some changes to ModuleDependency.inc and other files so that MODULE_ADVANCED_ATA now requires USE_386. Consequently it is no longer included in the regular AT-builds, only in the 386_8k-build.
  • Moved the UNROLL_SECTORS_IN_CX_TO_xWORDS macros from IDE_8bit.inc to IdeIO.inc which means it's now possible to build a BIOS without MODULE_8BIT_IDE.
  • XTIDECFG: Added a minimum DOS version check (since it needs DOS version 2+) to allow the program to quit gracefully in the unlikely scenario where someone tries to run it under DOS version 1.
  • Made some changes to Drive.asm to improve drive enumeration. The old method using GET_DOS_DRIVE_PARAMETER_BLOCK_FOR_SPECIFIC_DRIVE worked well in Windows XP but not in Windows 98 SE (in Windows or in DOS mode). The two problems were; 1) The function call would access the drives which on single floppy drive systems would cause Windows to swap between A: and B: (throwing a blue screen asking the user to insert a disk etc). 2) Only floppy drives and FAT16 drives would be available in the list of drives, no FAT32/optical/network drives.
  • Improved code in IdeControllerMenu.asm so that the default port addresses for all IDE interfaces are now restored when (re-)selecting the (same) type of IDE device.
  • Also made it impossible to select a device type unless the required module is included in the loaded BIOS.
  • The version check done when loading a BIOS now uses the FLASH_SIGNATURE definition from Version.inc. Any changes affecting RomVars now only requires updating that definition. This means that changes to RomVars must be implemented in both the BIOS and XTIDECFG before being committed to the repository.
  • Added a compatibility fix for 3Com 3C503 cards to the ROM checksumming code in Buffers.asm (Buffers_GenerateChecksum).
  • SerDrive: Made some minor changes to file names and paths to improve compatibility with case sensitive environments.
  • BIOSDRVS: Made a minor size optimization which as a side effect also makes it compatible with all DOS versions including DOS version 1.
  • Library: Renamed the WAIT_RETRACE_IF_NECESSARY_THEN macro to CALL_WAIT_FOR_RETRACE_IF_NECESSARY_THEN and made a tail-call-optimized version of it (JMP_WAIT_FOR_RETRACE_IF_NECESSARY_THEN).
  • A speed optimization to the eRCL_IM macro for 386 and higher. This change breaks emulation in the sense that the macro will fail when given a memory operand as the first parameter.
  • Other minor optimizations and fixes.
File size: 7.9 KB
RevLine 
[480]1; Project name : XTIDE Universal BIOS
[558]2; Description : IDE Read/Write functions for transferring block using DMA.
3; These functions should only be called from IdeTransfer.asm.
4
[480]5;
6; XTIDE Universal BIOS and Associated Tools
[526]7; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2013 by XTIDE Universal BIOS Team.
[480]8;
9; This program is free software; you can redistribute it and/or modify
10; it under the terms of the GNU General Public License as published by
11; the Free Software Foundation; either version 2 of the License, or
12; (at your option) any later version.
13;
14; This program is distributed in the hope that it will be useful,
15; but WITHOUT ANY WARRANTY; without even the implied warranty of
16; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17; GNU General Public License for more details.
18; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19;
20
21; Section containing code
22SECTION .text
23
24;--------------------------------------------------------------------
25; IdeDmaBlock_WriteToXTCF
26; Parameters:
27; CX: Block size in 512 byte sectors
28; DX: XTCF Base Port Address
29; ES:SI: Physical address to buffer to receive data
30; Returns:
31; Nothing
32; Corrupts registers:
33; AX, BX, CX, DX
34;--------------------------------------------------------------------
35ALIGN JUMP_ALIGN
36IdeDmaBlock_WriteToXTCF:
37 xchg si, di
38 mov bl, CHANNEL_3 | READ | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE
39 call TransferBlockToOrFromXTCF
40 xchg di, si
41 ret
42
43
44;--------------------------------------------------------------------
45; IdeDmaBlock_ReadFromXTCF
46; Parameters:
47; CX: Block size in 512 byte sectors
48; DX: XTCF Base Port Address
49; ES:DI: Physical address to buffer to receive data
50; Returns:
51; Nothing
52; Corrupts registers:
53; AX, BX, CX, DX
54;--------------------------------------------------------------------
55ALIGN JUMP_ALIGN
56IdeDmaBlock_ReadFromXTCF:
57 mov bl, CHANNEL_3 | WRITE | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE
58 ; Fall to TransferBlockToOrFromXTCF
59
60
61;--------------------------------------------------------------------
62; TransferBlockToOrFromXTCF
63; Parameters:
64; BL: Mode byte for DMA Mode Register
65; CX: Block size in 512 byte sectors
66; DX: XTCF Base Port Address
67; ES:DI: Physical address to buffer to receive data
68; Returns:
69; Nothing
70; Corrupts registers:
71; AX, BX, CX, DX
72;--------------------------------------------------------------------
73TransferBlockToOrFromXTCF:
[491]74 ; 8-bit DMA transfers must be done within 64k physical page.
[486]75 ; XT-CF support maximum of 64 sector (32768 bytes) blocks in DMA mode
76 ; so we never need to separate transfer to more than 2 separate DMA operations.
[480]77
[545]78 ; Load XT-CFv3 Control Register port to DX
[480]79 add dl, XTCF_CONTROL_REGISTER
80
[551]81 ; convert sectors in CX to BYTES
[480]82%ifdef USE_186
83 shl cx, 9 ; CX = Block size in BYTEs
84%else
[558]85 xchg cl, ch
[480]86 shl cx, 1
87%endif
[551]88
89 ; Calculate bytes for first page
90 mov ax, di
[567]91 neg ax ; 2s complement
[551]92
[558]93 ; If DI was zero carry flag will be cleared (and set otherwise)
[551]94 ; When DI is zero only one transfer is required since we've limited the
95 ; XT-CFv3 block size to 32k
[589]96 jnc SHORT StartDMAtransferForXTCFwithDmaModeInBL
[551]97
98 ; CF was set, so DI != 0 and we might need one or two transfers
[589]99 cmp cx, ax ; if we won't cross a physical page boundary...
100 jbe SHORT StartDMAtransferForXTCFwithDmaModeInBL ; ...perform the transfer in one operation
[480]101
[545]102 ; Calculate how much we can transfer on first and second rounds
[558]103 xchg cx, ax ; CX = BYTEs for first page
104 sub ax, cx ; AX = BYTEs for second page
105 push ax ; Save bytes for second transfer on stack
[480]106
107 ; Transfer first DMA page
108 call StartDMAtransferForXTCFwithDmaModeInBL
109 pop cx ; Pop size for second DMA page
110 ; Fall to StartDMAtransferForXTCFwithDmaModeInBL
111
112
113;--------------------------------------------------------------------
114; StartDMAtransferForXTCFwithDmaModeInBL
115; Parameters:
[482]116; BL: Byte for DMA Mode Register
[551]117; CX: Number of BYTEs to transfer (1...32768 since max block size is limited to 64)
[545]118; DX: XT-CFv3 Control Register
119; ES: Bits 3..0 have physical address bits 19..16
120; DI: Physical address bits 15..0
[480]121; Returns:
[545]122; ES:DI updated (CX is added)
[480]123; Corrupts registers:
[558]124; AX, CX
[480]125;--------------------------------------------------------------------
126ALIGN JUMP_ALIGN
127StartDMAtransferForXTCFwithDmaModeInBL:
128 ; Program 8-bit DMA Controller
129 ; Disable Interrupts and DMA Channel 3 during DMA setup
130 mov al, SET_CH3_MASK_BIT
[545]131 cli ; Disable interrupts - programming must be atomic
132 out MASK_REGISTER_DMA8_out, al ; Disable DMA Channel 3
[480]133
134 ; Set DMA Mode (read or write using channel 3)
135 mov al, bl
136 out MODE_REGISTER_DMA8_out, al
137
[545]138 ; Send start address to DMA controller
[480]139 mov ax, es
140 out PAGE_DMA8_CH_3, al
141 mov ax, di
[545]142 out CLEAR_FLIPFLOP_DMA8_out, al ; Reset flip-flop to low byte
[480]143 out BASE_AND_CURRENT_ADDRESS_REGISTER_DMA8_CH3_out, al ; Low byte
144 mov al, ah
145 out BASE_AND_CURRENT_ADDRESS_REGISTER_DMA8_CH3_out, al ; High byte
146
147 ; Set number of bytes to transfer (DMA controller must be programmed number of bytes - 1)
148 mov ax, cx
[545]149 dec ax ; DMA controller is programmed for one byte less
[480]150 out BASE_AND_CURRENT_COUNT_REGISTER_DMA8_CH3_out, al ; Low byte
151 mov al, ah
152 out BASE_AND_CURRENT_COUNT_REGISTER_DMA8_CH3_out, al ; High byte
153
154 ; Enable DMA Channel 3
155 mov al, CLEAR_CH3_MASK_BIT
[545]156 out MASK_REGISTER_DMA8_out, al ; Enable DMA Channel 3
157 sti ; Enable interrupts
[480]158
[558]159 ; Update physical address in ES:DI - since IO might need several calls through this function either from here
160 ; if crossing a physical page boundary, or from IdeTransfer.asm if requested sectors was > PIOVARS.wSectorsInBlock
161 ; We update the pointer here (before the actual transfer) to avoid having to save the byte count on the stack
162 mov ax, es ; copy physical page address to ax
163 add di, cx ; add requested bytes to di
164 adc al, 0 ; and increment physical page address, if required
165 mov es, ax ; and save it back in es
166
[545]167 ; XT-CF transfers 16 bytes at a time. We need to manually start transfer for every block by writing (anything)
168 ; to the XT-CFv3 Control Register, which raises DRQ thereby passing system control to the 8237 DMA controller.
169 ; The XT-CFv3 logic releases DRQ after 16 transfers, thereby handing control back to the CPU and allowing any other IRQs or
170 ; DRQs to be serviced (which, on the PC and PC/XT will include DRAM refresh via DMA channel 0). The 16-byte transfers can
171 ; also be interrupted by the DMA controller raising TC (i.e. when done). Each transfer cannot be otherwise interrupted
172 ; and is therefore atomic (and hence fast).
[480]173
[545]174%if 0 ; Slow DMA code - works by checking 8237 status register after each 16-byte transfer, until it reports TC has been raised.
[558]175ALIGN JUMP_ALIGN
176.TransferNextBlock:
177 cli ; We want no ISR to read DMA Status Register before we do
178 out dx, al ; Transfer up to 16 bytes to/from XT-CF card
179 in al, STATUS_REGISTER_DMA8_in
180 sti
181 test al, FLG_CH3_HAS_REACHED_TERMINAL_COUNT
182 jz SHORT .TransferNextBlock ; All bytes transferred?
183%else ; Fast DMA code - perform computed number of transfers, then check DMA status register to be sure
[567]184 ; We'll divide transfers in 16-byte atomic transfers, so include any partial block, which will be terminated by the DMA controller raising T/C
185 add cx, BYTE 15
186
187%ifdef USE_186
188 shr cx, 4
189%else
190 xchg cx, ax
191 mov cl, 4
192 shr ax, cl
193 xchg cx, ax
194%endif
195
196ALIGN JUMP_ALIGN
[486]197.TransferNextDmaBlock:
[545]198 out dx, al ; Transfer up to 16 bytes to/from XT-CF card
199 loop .TransferNextDmaBlock ; dec CX and loop if CX > 0, also adds required wait-state
[486]200 inc cx ; set up CX, in case we need to do an extra iteration
[545]201 in al, STATUS_REGISTER_DMA8_in ; check 8237 DMA controller status flags...
202 test al, FLG_CH3_HAS_REACHED_TERMINAL_COUNT ; ... for channel 3 terminal count
203 jz SHORT .TransferNextDmaBlock ; If not set, get more bytes
[558]204%endif
[486]205
[480]206 ret
Note: See TracBrowser for help on using the repository browser.