Changeset 477 in xtideuniversalbios for trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeDmaTransfer.asm
- Timestamp:
- Oct 20, 2012, 5:04:32 PM (12 years ago)
- google:author:
- aitotat@gmail.com
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeDmaTransfer.asm
r474 r477 21 21 ; This struct must not be larger than IDEPACK without INTPACK. 22 22 struc DMAVARS ; Must not be larger than 9 bytes! See IDEPACK in RamVars.inc. 23 .wTotalWordsXferred resb 2 ; 0-1, 24 .wBytesLeftToXferLessOne resb 2 ; 2-3, 25 .bbbPhysicalAddress resb 3 ; 4-6, 26 resb 1 ; 7, IDEPACK.bDeviceControl 23 27 endstruc 24 28 … … 32 36 ; AL: IDE command that was used to start the transfer 33 37 ; (all PIO read and write commands including Identify Device) 34 ; ES:SI: Ptr to normalized data buffer38 ; ES:SI: Ptr to data buffer (not normalized) 35 39 ; DS:DI: Ptr to DPT (in RAMVARS segment) 36 40 ; SS:BP: Ptr to IDEPACK … … 40 44 ; CF: Cleared if success, Set if error 41 45 ; Corrupts registers: 42 ; AL, BX, DX , SI, ES46 ; AL, BX, DX 43 47 ;-------------------------------------------------------------------- 44 48 ALIGN JUMP_ALIGN 45 49 IdeDmaTransfer_StartWithCommandInAL: 50 ; Initialize DMAVARS 51 xor cx, cx 52 mov [bp+DMAVARS.wTotalWordsXferred], cx 53 mov ch, [bp+IDEPACK.bSectorCount] ; CX = WORDs to transfer 54 shl cx, 1 ; WORDs to BYTEs, 0 = 65536 55 dec cx 56 mov [bp+DMAVARS.wBytesLeftToXferLessOne], cx 57 58 ; Convert Segment:Offset type pointer to physical address 59 xor bx, bx 60 mov cx, es 61 %rep 4 62 shl cx, 1 63 rcl bx, 1 64 %endrep 65 add cx, si 66 adc bl, bh 67 mov [bp+DMAVARS.bbbPhysicalAddress], cx 68 mov [bp+DMAVARS.bbbPhysicalAddress+2], bl 69 70 ; Calculate bytes for first page - 1 71 neg cx ; Max number of bytes for first page, 0 = 65536 72 dec cx 73 MIN_U cx, [bp+DMAVARS.wBytesLeftToXferLessOne] 74 75 ; Are we reading or writing? 76 test al, 16 ; Bit 4 is cleared on all the read commands but set on 3 of the 4 write commands 77 jnz SHORT WriteBlockToXTCF 78 cmp al, COMMAND_WRITE_MULTIPLE 79 je SHORT WriteBlockToXTCF 80 ; Fall to ReadBlockFromXTCF 81 82 83 ;-------------------------------------------------------------------- 84 ; ReadBlockFromXTCF 85 ; Parameters: 86 ; CX: Bytes in first page - 1 87 ; DS:DI: Ptr to DPT (in RAMVARS segment) 88 ; SS:BP: Ptr to DMAVARS 89 ; Returns: 90 ; DS:DI: Ptr to DPT (in RAMVARS segment) 91 ; AH: BIOS Error code 92 ; CX: Number of successfully transferred sectors 93 ; CF: 0 if transfer successful 94 ; 1 if any error 95 ; Corrupts registers: 96 ; AL, BX, DX 97 ;-------------------------------------------------------------------- 98 ReadBlockFromXTCF: 99 ; 8-bit DMA transfers must be done withing 64k physical page. 100 ; We support maximum of 128 sectors (65536 bytes) per one INT 13h call 101 ; so we might need to separate transfer to 2 separate DMA operations. 102 103 ; Transfer first DMA page 104 mov ah, CHANNEL_3 | WRITE | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE 105 call StartDMAtransferForXTCFwithDmaModeInAH 106 jc SHORT ReturnNumberOfSectorsXferred 107 108 ; Transfer second DMA page if necessary (always less than 64k) 109 call UpdateVariablesForSecondPageIfRequired 110 jc SHORT SecondDmaPageIsNotRequired 111 mov ah, CHANNEL_3 | WRITE | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE 112 call StartDMAtransferForXTCFwithDmaModeInAH 113 jc SHORT ReturnNumberOfSectorsXferred 114 ; Fall to BothDmaPagesTransferredSuccessfully 115 116 BothDmaPagesTransferredSuccessfully: 117 inc cx ; Never overflows since second page always less than 64k 118 shr cx, 1 ; BYTEs to WORDs 119 add [bp+DMAVARS.wTotalWordsXferred], cx 120 SecondDmaPageIsNotRequired: 121 xor ah, ah 122 ReturnNumberOfSectorsXferred: 123 mov cx, [bp+DMAVARS.wTotalWordsXferred] 124 xchg cl, ch ; WORDs to sectors 125 ret 126 127 128 ;-------------------------------------------------------------------- 129 ; WriteBlockToXTCF 130 ; Parameters: 131 ; CX: Bytes in first page - 1 132 ; DS:DI: Ptr to DPT (in RAMVARS segment) 133 ; SS:BP: Ptr to DMAVARS 134 ; Returns: 135 ; DS:DI: Ptr to DPT (in RAMVARS segment) 136 ; AH: BIOS Error code 137 ; CX: Number of successfully transferred sectors 138 ; CF: 0 if transfer successful 139 ; 1 if any error 140 ; Corrupts registers: 141 ; AL, BX, DX 142 ;-------------------------------------------------------------------- 143 WriteBlockToXTCF: 144 ; Transfer first DMA page 145 mov ah, CHANNEL_3 | READ | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE 146 call StartDMAtransferForXTCFwithDmaModeInAH 147 jc SHORT ReturnNumberOfSectorsXferred 148 149 ; Transfer second DMA page if necessary (always less than 64k) 150 call UpdateVariablesForSecondPageIfRequired 151 jc SHORT SecondDmaPageIsNotRequired 152 mov ah, CHANNEL_3 | READ | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE 153 call StartDMAtransferForXTCFwithDmaModeInAH 154 jc SHORT ReturnNumberOfSectorsXferred 155 jmp SHORT BothDmaPagesTransferredSuccessfully 156 157 158 ;-------------------------------------------------------------------- 159 ; StartDMAtransferForXTCFwithDmaModeInAH 160 ; Parameters: 161 ; AH: Byte for DMA Mode Register 162 ; CX: Number of BYTEs to transfer - 1 163 ; DS:DI: Ptr to DPT (in RAMVARS segment) 164 ; Returns: 165 ; AH: BIOS Error code 166 ; CF: 0 if transfer successful 167 ; 1 if any error 168 ; Corrupts registers: 169 ; AL, BX, DX 170 ;-------------------------------------------------------------------- 171 StartDMAtransferForXTCFwithDmaModeInAH: 172 push cx 173 174 ; Program 8-bit DMA Controller 175 176 ; Disable Interrupts and DMA Channel 3 during DMA setup 177 cli ; Disable interrupts 178 mov al, SET_CH3_MASK_BIT 179 out MASK_REGISTER_DMA8_out, al ; Disable DMA Channel 3 180 181 ; Set DMA Mode (read or write using channel 3) 182 mov al, ah 183 out MODE_REGISTER_DMA8_out, al 184 185 ; Set address to DMA controller 186 out CLEAR_FLIPFLOP_DMA8_out, al ; Reset flip-flop to low byte 187 mov ax, [bp+DMAVARS.bbbPhysicalAddress] 188 out BASE_AND_CURRENT_ADDRESS_REGISTER_DMA8_CH3_out, al ; Low byte 189 mov al, ah 190 out BASE_AND_CURRENT_ADDRESS_REGISTER_DMA8_CH3_out, al ; High byte 191 mov al, [bp+DMAVARS.bbbPhysicalAddress+2] 192 out PAGE_DMA8_CH_3, al 193 194 ; Set number of bytes to transfer (DMA controller must be programmed number of bytes - 1) 195 out CLEAR_FLIPFLOP_DMA8_out, al ; Reset flip-flop to low byte 196 mov ax, cx 197 out BASE_AND_CURRENT_COUNT_REGISTER_DMA8_CH3_out, al ; Low byte 198 mov al, ah 199 out BASE_AND_CURRENT_COUNT_REGISTER_DMA8_CH3_out, al ; High byte 200 201 ; Enable DMA Channel 3 202 mov al, CLEAR_CH3_MASK_BIT 203 out MASK_REGISTER_DMA8_out, al ; Enable DMA Channel 3 204 sti ; Enable interrupts 205 206 207 ; XT-CFv2 will present data in 16-byte blocks, but byte count may not 208 ; be divisable by 16 due to boundary crossing. So catch any < 16-byte 209 ; block by adding 15, then dividing bytes (in CX) by 16 to get the 210 ; total block requests. The 8237 is programmed with the actual byte 211 ; count and will end the transfer by asserting TC when done. 212 xor ax, ax 213 add cx, BYTE 1 + 15 ; Number of BYTEs to xfer + 15 214 adc al, ah 215 shr ax, 1 216 rcr cx, 1 217 eSHR_IM cx, 3 ; CX = Number of 16 byte blocks 218 mov dx, [di+DPT.wBasePort] 219 add dl, XTCF_CONTROL_REGISTER 220 221 .MoreToDo: ; at this point, cx must be >0 222 mov al, 0x40 ; 0x40 = Raise DRQ and clear XT-CFv2 transfer counter 223 .NextDemandBlock: 224 out dx, al ; get up to 16 bytes from XT-CF card 225 loop .NextDemandBlock ; decrement CX and loop if <> 0 226 ; (Loop provides a wait-state between 16-byte blocks; do not unroll) 227 228 .CleanUp: 229 ; check the transfer is actually done - in case another DMA operation messed things up 230 inc cx ; set up CX, in case we need to do an extra iteration 231 in al, STATUS_REGISTER_DMA8_in ; get DMA status register 232 test al, FLG_CH3_HAS_REACHED_TERMINAL_COUNT ; test DMA ch.3 TC bit 233 jz SHORT .MoreToDo ; it wasn't set so get more bytes 234 235 .EndDMA: 236 mov al, 0x10 ; 237 out dx, al ; set back to DMA enabled status 238 239 ; Check IDE Status Register for errors 240 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_BSY) 241 call IdeWait_PollStatusFlagInBLwithTimeoutInBH 242 pop cx 243 ret 244 245 246 ;-------------------------------------------------------------------- 247 ; UpdateVariablesForSecondPageIfRequired 248 ; Parameters: 249 ; CX: Number of BYTEs in first page - 1 250 ; SS:BP: Ptr to DMAVARS 251 ; Returns: 252 ; CX: Bytes left to transfer - 1 (if CF = 0) 253 ; CF: 0 if second DMA transfer required 254 ; 1 if one DMA transfer was enough 255 ; Corrupts registers: 256 ; AX, (CX) 257 ;-------------------------------------------------------------------- 258 UpdateVariablesForSecondPageIfRequired: 259 inc cx ; BYTEs in first page 260 jcxz .FullPageXferred ; 0 = 65536 261 262 ; Store total WORDs transferred so far 263 mov ax, cx 264 shr ax, 1 ; BYTEs to WORDs 265 mov [bp+DMAVARS.wTotalWordsXferred], ax 266 267 ; Get bytes left to transfer for second DMA page 268 mov ax, [bp+DMAVARS.wBytesLeftToXferLessOne] 269 sub ax, cx 270 jb SHORT .OnePageWasEnough 271 272 ; Increment address 273 add [bp+DMAVARS.bbbPhysicalAddress], cx 274 adc BYTE [bp+DMAVARS.bbbPhysicalAddress+2], 0 ; Never sets CF 275 xchg cx, ax 276 ret 277 278 .FullPageXferred: 279 mov WORD [bp+DMAVARS.wTotalWordsXferred], 65536 / 2 280 stc 281 .OnePageWasEnough: 282 ret
Note:
See TracChangeset
for help on using the changeset viewer.