Changeset 479 in xtideuniversalbios for trunk/XTIDE_Universal_BIOS/Src
- Timestamp:
- Oct 21, 2012, 5:59:26 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
r478 r479 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 .wTotal WordsXferred resb 2 ; 0-1,24 .wBytesLeftToXfer LessOne resb 2 ; 2-3,23 .wTotalBytesXferred resb 2 ; 0-1, 24 .wBytesLeftToXfer resb 2 ; 2-3, 0 = 65536 25 25 .bbbPhysicalAddress resb 3 ; 4-6, 26 26 resb 1 ; 7, IDEPACK.bDeviceControl … … 50 50 ; Initialize DMAVARS 51 51 xor cx, cx 52 mov [bp+DMAVARS.wTotal WordsXferred], cx52 mov [bp+DMAVARS.wTotalBytesXferred], cx 53 53 mov ch, [bp+IDEPACK.bSectorCount] ; CX = WORDs to transfer 54 54 shl cx, 1 ; WORDs to BYTEs, 0 = 65536 55 dec cx 56 mov [bp+DMAVARS.wBytesLeftToXferLessOne], cx 55 mov [bp+DMAVARS.wBytesLeftToXfer], cx 57 56 58 57 ; Convert Segment:Offset type pointer to physical address … … 60 59 mov cx, es 61 60 %rep 4 62 shl cx, 163 rcl bx, 161 shl cx, 1 62 rcl bx, 1 64 63 %endrep 65 64 add cx, si … … 68 67 mov [bp+DMAVARS.bbbPhysicalAddress+2], bl 69 68 70 ; Calculate bytes for first page - 169 ; Calculate bytes for first page 71 70 neg cx ; Max number of bytes for first page, 0 = 65536 72 dec cx 73 MIN_U cx, [bp+DMAVARS.wBytesLeftToXferLessOne] 71 MIN_U cx, [bp+DMAVARS.wBytesLeftToXfer] 74 72 75 73 ; Are we reading or writing? 74 mov bl, CHANNEL_3 | READ | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE ; Assume write command 76 75 test al, 16 ; Bit 4 is cleared on all the read commands but set on 3 of the 4 write commands 77 jnz SHORT WriteBlockToXTCF76 jnz SHORT TransferBlockToOrFromXTCF 78 77 cmp al, COMMAND_WRITE_MULTIPLE 79 je SHORT WriteBlockToXTCF 80 ; Fall to ReadBlockFromXTCF 81 82 83 ;-------------------------------------------------------------------- 84 ; ReadBlockFromXTCF 78 je SHORT TransferBlockToOrFromXTCF 79 80 ; Read command 81 mov bl, CHANNEL_3 | WRITE | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE 82 ; Fall to TransferBlockToOrFromXTCF 83 84 85 ;-------------------------------------------------------------------- 86 ; TransferBlockToOrFromXTCF 85 87 ; Parameters: 86 ; CX: Bytes in first page - 1 88 ; BX: Mode byte for DMA Mode Register 89 ; CX: Bytes in first page 87 90 ; DS:DI: Ptr to DPT (in RAMVARS segment) 88 91 ; SS:BP: Ptr to DMAVARS … … 96 99 ; AL, BX, DX 97 100 ;-------------------------------------------------------------------- 98 ReadBlockFromXTCF:101 TransferBlockToOrFromXTCF: 99 102 ; 8-bit DMA transfers must be done withing 64k physical page. 100 103 ; We support maximum of 128 sectors (65536 bytes) per one INT 13h call … … 102 105 103 106 ; Transfer first DMA page 104 mov ah, CHANNEL_3 | WRITE | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE 105 call StartDMAtransferForXTCFwithDmaModeInAH 106 call UpdateVariablesForSecondPageIfRequired 107 jc SHORT ReturnNumberOfSectorsXferred ; Second page not needed 107 call StartDMAtransferForXTCFwithDmaModeInBL 108 jcxz .ReturnNumberOfSectorsXferred ; One page was enough (128 sectors) 109 mov [bp+DMAVARS.wTotalBytesXferred], cx ; Store total BYTEs transferred so far 110 111 ; Get bytes left to transfer for second DMA page 112 mov ax, [bp+DMAVARS.wBytesLeftToXfer] 113 sub ax, cx 114 jz SHORT .ReturnNumberOfSectorsXferred ; Transfer was within 64k page 115 116 ; Increment address 117 xchg cx, ax 118 add [bp+DMAVARS.bbbPhysicalAddress], ax 119 adc [bp+DMAVARS.bbbPhysicalAddress+2], bh ; Never sets CF 108 120 109 121 ; Transfer second DMA page if necessary (always less than 64k) 110 mov ah, CHANNEL_3 | WRITE | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE 111 call StartDMAtransferForXTCFwithDmaModeInAH 112 ; Fall to BothDmaPagesTransferred 113 114 BothDmaPagesTransferred: 115 inc cx ; Never overflows since second page always less than 64k 116 shr cx, 1 ; BYTEs to WORDs 117 add [bp+DMAVARS.wTotalWordsXferred], cx 118 ReturnNumberOfSectorsXferred: 122 call StartDMAtransferForXTCFwithDmaModeInBL 123 add [bp+DMAVARS.wTotalBytesXferred], cx 124 125 .ReturnNumberOfSectorsXferred: 126 ; Check errors 119 127 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_BSY) 120 128 call IdeWait_PollStatusFlagInBLwithTimeoutInBH 121 129 jc SHORT .ErrorInTransfer 122 mov cx, [bp+DMAVARS.wTotalWordsXferred] 123 xchg cl, ch ; WORDs to sectors 130 131 ; Return number of sectors transferred 132 mov cx, [bp+DMAVARS.wTotalBytesXferred] 133 jcxz .FullPageOf128SectorsXferred 134 %ifdef USE_186 135 shr cx, 9 ; BYTEs to sectors 136 %else 137 xchg cl, ch ; BYTEs to WORDs 138 shr cx, 1 ; WORDs to sectors 139 %endif 140 clc 141 ret 142 143 .FullPageOf128SectorsXferred: 144 mov cx, 128 124 145 ret 125 146 126 147 .ErrorInTransfer: 127 mov cx, 0 ; No way to know how many bytes got xferred128 ret 129 130 131 ;-------------------------------------------------------------------- 132 ; WriteBlockToXTCF148 mov cx, 0 ; No way to know how many sectors got transferred 149 ret 150 151 152 ;-------------------------------------------------------------------- 153 ; StartDMAtransferForXTCFwithDmaModeInBL 133 154 ; Parameters: 134 ; CX: Bytes in first page - 1 155 ; BL: Byte for DMA Mode Register 156 ; CX: Number of BYTEs to transfer 135 157 ; DS:DI: Ptr to DPT (in RAMVARS segment) 136 158 ; SS:BP: Ptr to DMAVARS 137 ; Returns:138 ; DS:DI: Ptr to DPT (in RAMVARS segment)139 ; AH: BIOS Error code140 ; CX: Number of successfully transferred sectors141 ; CF: 0 if transfer successful142 ; 1 if any error143 ; Corrupts registers:144 ; AL, BX, DX145 ;--------------------------------------------------------------------146 ALIGN JUMP_ALIGN147 WriteBlockToXTCF:148 ; Transfer first DMA page149 mov ah, CHANNEL_3 | READ | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE150 call StartDMAtransferForXTCFwithDmaModeInAH151 call UpdateVariablesForSecondPageIfRequired152 jc SHORT ReturnNumberOfSectorsXferred ; Second page not needed153 154 ; Transfer second DMA page if necessary (always less than 64k)155 mov ah, CHANNEL_3 | READ | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE156 call StartDMAtransferForXTCFwithDmaModeInAH157 jmp SHORT BothDmaPagesTransferred158 159 160 ;--------------------------------------------------------------------161 ; StartDMAtransferForXTCFwithDmaModeInAH162 ; Parameters:163 ; AH: Byte for DMA Mode Register164 ; CX: Number of BYTEs to transfer - 1165 ; DS:DI: Ptr to DPT (in RAMVARS segment)166 159 ; Returns: 167 160 ; Nothing … … 170 163 ;-------------------------------------------------------------------- 171 164 ALIGN JUMP_ALIGN 172 StartDMAtransferForXTCFwithDmaModeInAH: 173 push cx 174 165 StartDMAtransferForXTCFwithDmaModeInBL: 175 166 ; Program 8-bit DMA Controller 176 177 167 ; Disable Interrupts and DMA Channel 3 during DMA setup 178 168 cli ; Disable interrupts … … 181 171 182 172 ; Set DMA Mode (read or write using channel 3) 183 mov al, ah173 mov al, bl 184 174 out MODE_REGISTER_DMA8_out, al 185 175 … … 196 186 out CLEAR_FLIPFLOP_DMA8_out, al ; Reset flip-flop to low byte 197 187 mov ax, cx 188 dec ax ; DMA controller is programmed for one byte less 198 189 out BASE_AND_CURRENT_COUNT_REGISTER_DMA8_CH3_out, al ; Low byte 199 190 mov al, ah … … 206 197 207 198 208 ; XT-CFv2 will present data in 16-byte blocks, but byte count may not 209 ; be divisable by 16 due to boundary crossing. So catch any < 16-byte 210 ; block by adding 15, then dividing bytes (in CX) by 16 to get the 211 ; total block requests. The 8237 is programmed with the actual byte 212 ; count and will end the transfer by asserting TC when done. 213 add cx, BYTE 1 + 15 ; Number of BYTEs to xfer + 15 (bit 16 in CF) 214 rcr cx, 1 215 eSHR_IM cx, 3 ; CX = Number of 16 byte blocks 199 ; XT-CF transfers 16 bytes at a time. We need to manually 200 ; start transfer for every block. 216 201 mov dx, [di+DPT.wBasePort] 217 202 add dl, XTCF_CONTROL_REGISTER 218 219 .MoreToDo: ; at this point, cx must be >0220 mov al, 40h ; 0x40 = Raise DRQ and clear XT-CFv2 transfer counter221 .NextDemandBlock:222 out dx, al ; get up to 16 bytes from XT-CF card223 loop .NextDemandBlock ; decrement CX and loop if <> 0224 ; (Loop provides a wait-state between 16-byte blocks; do not unroll)225 226 .CleanUp:227 ; check the transfer is actually done - in case another DMA operation messed things up228 inc cx ; set up CX, in case we need to do an extra iteration229 in al, STATUS_REGISTER_DMA8_in ; get DMA status register230 test al, FLG_CH3_HAS_REACHED_TERMINAL_COUNT ; test DMA ch.3 TC bit231 jz SHORT .MoreToDo ; it wasn't set so get more bytes232 233 .EndDMA:234 mov al, 10h ;235 out dx, al ; set back to DMA enabled status236 pop cx237 ret238 239 240 ;--------------------------------------------------------------------241 ; UpdateVariablesForSecondPageIfRequired242 ; Parameters:243 ; CX: Number of BYTEs in first page - 1244 ; SS:BP: Ptr to DMAVARS245 ; Returns:246 ; CX: Bytes left to transfer - 1 (if CF = 0)247 ; CF: 0 if second DMA transfer required248 ; 1 if one DMA transfer was enough249 ; Corrupts registers:250 ; AX, (CX)251 ;--------------------------------------------------------------------252 203 ALIGN JUMP_ALIGN 253 UpdateVariablesForSecondPageIfRequired: 254 inc cx ; BYTEs in first page 255 jcxz .FullPageXferred ; 0 = 65536 256 257 ; Store total WORDs transferred so far 258 mov ax, cx 259 shr ax, 1 ; BYTEs to WORDs 260 mov [bp+DMAVARS.wTotalWordsXferred], ax 261 262 ; Get bytes left to transfer for second DMA page 263 mov ax, [bp+DMAVARS.wBytesLeftToXferLessOne] 264 sub ax, cx 265 jb SHORT .OnePageWasEnough 266 267 ; Increment address 268 add [bp+DMAVARS.bbbPhysicalAddress], cx 269 adc BYTE [bp+DMAVARS.bbbPhysicalAddress+2], 0 ; Never sets CF 270 xchg cx, ax 271 ret 272 273 .FullPageXferred: 274 mov WORD [bp+DMAVARS.wTotalWordsXferred], 65536 / 2 275 stc 276 .OnePageWasEnough: 277 ret 278 279 280 281 282 %if 0 283 ;-------------------------------------------------------------------- 284 ALIGN JUMP_ALIGN 285 ReadBlockFromXTCF: 286 ; Parameters: 287 ; CX: Block size in 512 byte sectors (1..64) 288 ; DX: IDE Data port address 289 ; ES:DI: Normalized ptr to buffer to receive data 290 ; Returns: 291 ; Nothing 292 ; Corrupts registers: 293 ; AX, BX, CX 294 295 ; use config register to see what we're doing: 296 ; < A0 = DMA via ch.3 297 ; > A0 = mem-mapped IO (word-length) 298 ; 299 300 or dl, 0x1f ; XT-CF board control register address (base + 1fh) 301 in al, dx ; get control register 302 cmp al, 0xA0 ; test al against 0xA0: 303 jae .MemMapIO ; - use memory-mapped IO if >=A0h 304 or al, al ; test al against 0 (quicker than cmp): 305 jz .PortIO ; - use port-based IO (the default) if it was zero 306 ; otherwise, 0 < al < A0h, so fall to DMA mode 307 308 .DMAIO: 309 ; work out how much we're transferring. We can't cross a physical 64KB boundary 310 ; but since the max transfer size is 64KB, we only ever need to do one or two DMA operations 311 312 ; first, normalise the pointer - we need ES to be a physical page address 313 314 mov ax, es 315 mov ch, cl ; max sectors is 128; also sectors << 8 = words, and we need cl... 316 mov cl, 4 ; ... for the rotate parameter 317 rol ax, cl ; ax = es rol 4 318 mov bx, ax ; bx = ax = es rol 4 319 and al, 0xf0 ; ax (15..4) now has es (11..0) 320 and bx, 0x000f ; bx (3..0) now has es (15..12) 321 add di, ax ; add offset portion of es (in ax) to di... 322 adc bl, 0 ; ... and if it overflowed, increment bl 323 mov es, bx ; es now has physical segment address >> 12 324 325 ; now check how much we can transfer without crossing a physical page boundary 326 mov bx, di ; 327 not bx ; 65535 - di = number of bytes we could transfer -1 now in bx 328 xor cl, cl ; zero cl; cx now has transfer size in words 329 shl cx, 1 ; words to bytes; CX has total byte count 330 dec cx ; calling DMA with 0 implies 1 byte transferred (so max is 64k exactly) 331 cmp bx, cx ; can we do it in one hit? 332 jae .LastDMA 333 334 ; at this point, the (bytes-1) for this transfer are in bx, total byte count -1 in cx 335 ; and we need to do 2 DMA operations as the buffer straddles a physical 64k boundary 336 337 sub cx, bx ; cx has bytes for 2nd transfer (as (x-1)-(y-1) = x-y) 338 dec cx ; cx has bytes-1 for 2nd transfer 339 xchg bx, cx ; bx = bytes-1 for 2nd transfer; cx = bytes-1 for this transfer 340 mov ah, 0x07 ; request a read DMA transfer 341 call DemandBasedTransferWithBytesInCX 342 343 ; DMA 1 of 2 done - set up registers for second transfer 344 mov cx, bx ; bytes-1 for the 2nd transfer back in cx 345 ; 1st transfer is done, now for the second 346 ALIGN JUMP_ALIGN 347 .LastDMA: 348 ; at this point, (bytes-1) for this transfer are in CX 349 mov ah, 0x07 ; request a read DMA transfer 350 call DemandBasedTransferWithBytesInCX 351 352 ; transfer is done, set ES back to a physical segment address 353 mov ax, es ; 354 mov cl, 4 ; 355 ror ax, cl ; ax = es ror 4. Since ES was >> 12 (for DMA controller) so 356 mov es, ax ; now it's back to normal format 357 358 ; pointer format restored - we're done 359 and dl, 0xE0 ; restore register values 360 ret 361 362 363 ;-------------------------------------------------------------------- 364 ALIGN JUMP_ALIGN 365 WriteBlockToXTCF: 366 ; use config register to see what we're doing: 367 ; 0 = not set; use byte-length port-IO 368 ; < A0 = DMA via ch.3 369 ; > A0 = mem-mapped IO (word-length) 370 ; 371 372 or dl, 0x1f ; XT-CF board control register address (base + 1fh) 373 in al, dx ; get control register 374 cmp al, 0xA0 ; test al against 0xA0: 375 jae .MemMapIO ; - use memory-mapped IO if >=A0h 376 or al, al ; test al against 0 (quicker than cmp): 377 jz .PortIO ; - use port-based IO (the default) if it was zero 378 ; otherwise, 0 < al < A0h, so fall to DMA mode 379 380 .DMAIO: 381 ; work out how much we're transferring. We can't cross a physical 64KB boundary 382 ; but since the max transfer size is 64KB, we only ever need to do one or two DMA operations 383 384 push di ; save di... 385 mov di, si ; ...and move si to di (for DMA routine) 386 387 ; first, normalise the pointer - we need ES to be a physical page address 388 389 mov ax, es 390 mov ch, cl ; max sectors is 64; also sectors << 8 = words, and we need cl... 391 mov cl, 4 ; ... for the rotate parameter 392 rol ax, cl ; ax = es rol 4 393 mov bx, ax ; bx = ax = es rol 4 394 and al, 0xf0 ; ax (15..4) now has es (11..0) 395 and bx, 0x000f ; bx (3..0) now has es (15..12) 396 add di, ax ; add offset portion of es (in ax) to si... 397 adc bl, 0 ; ... and if it overflowed, increment bl 398 mov es, bx ; es now has physical segment address >> 12 399 400 ; now check how much we can transfer without crossing a physical page boundary 401 mov bx, di ; 402 not bx ; 65535 - di = number of bytes we could transfer -1 now in bx 403 xor cl, cl ; zero cl; cx now has transfer size in words 404 shl cx, 1 ; words to bytes; CX has total byte count 405 dec cx ; calling DMA with 0 implies 1 byte transferred (so max is 64k exactly) 406 cmp bx, cx ; can we do it in one hit? 407 jae .LastDMA 408 409 ; at this point, the (bytes-1) for this transfer are in bx, total byte count -1 in cx 410 ; and we need to do 2 DMA operations as the buffer straddles a physical 64k boundary 411 412 sub cx, bx ; cx has bytes for 2nd transfer (as (x-1)-(y-1) = x-y) 413 dec cx ; cx has bytes-1 for 2nd transfer 414 xchg bx, cx ; bx = bytes-1 for 2nd transfer; cx = bytes-1 for this transfer 415 mov ah, 0x0b ; request a write DMA transfer 416 call DemandBasedTransferWithBytesInCX 417 418 ; DMA 1 of 2 done - set up registers for second transfer 419 mov cx, bx ; bytes-1 for the 2nd transfer back in cx 420 ; 1st transfer is done, now for the second 421 ALIGN JUMP_ALIGN 422 .LastDMA: 423 ; at this point, (bytes-1) for this transfer are in CX 424 mov ah, 0x0b ; request a write DMA transfer 425 call DemandBasedTransferWithBytesInCX 426 427 ; transfer is done, set ES back to a physical segment address 428 mov ax, es ; 429 mov cl, 4 ; 430 ror ax, cl ; ax = es ror 4. Since ES was >> 12 (for DMA controller) so 431 mov es, ax ; now it's back to normal format 432 433 mov si, di ; move di (used by DMA routine) back to si 434 435 ; pointers updated - we're done 436 pop di ; 437 and dl, 0xE0 ; restore register values 438 ret 439 440 441 ; ------------------------------------------------------------------------------------------------------------- 442 ; 443 ; DemandBasedTransferWithBytesInCX 444 ; ================================ 445 ; 446 ; DMA Transfer function: 447 ; - AH = 0x07 for read from media - demand/inc/non-auto-init/write(to memory)/ch3 448 ; - AH = 0x0b for write to media - demand/inc/non-auto-init/read(from memory)/ch3 449 ; - byte count -1 in CX 450 ; - XT-CF control register in DX 451 ; - physical segment address in ES *but* high four bits in low four bits (i.e. shr 12) 452 ; - buffer offset (from physical segment) in DI 453 ; 454 ; Note - cannot cross a physical segment boundary, but ES will be updated (maintaining the >>12 455 ; format) if after the last byte has been transferred the pointer needs to be updated to 456 ; the next physical segment. 457 ; 458 ; Preserves: BX, DX 459 ; Corrupts: AX, CX 460 ; Updates: ES, DI 461 ; 462 ; ------------------------------------------------------------------------------------------------------------- 463 464 ALIGN JUMP_ALIGN 465 DemandBasedTransferWithBytesInCX: 466 cli ; clear interrupts while we set up the actual DMA transfer 467 mov al, 0x07 ; mask (4) + channel (3) 468 out 0x0a, al ; send to DMA mask register 469 mov al, ah ; retrieve the transfer mode passed in... 470 out 0x0b, al ; and send mode to DMA mode register 471 out 0x0c, al ; clear DMA byte-order flip-flop (write any value) 472 mov ax, di ; di has buffer offset 473 out 0x06, al ; 474 mov al, ah ; 475 out 0x06, al ; send offset to DMA controller address port for ch.3 476 mov ax, es ; es has physical segment address >> 12 477 out 0x82, al ; send the relavent 4-bits to DMA controller page for ch.3 478 out 0x0c, al ; clear DMA byte-order flip-flop (write any value) 479 mov ax, cx ; byte count to AX 480 out 0x07, al ; send low-byte of transfer size in bytes... 481 mov al, ah ; mov high byte to low byte... 482 out 0x07, al ; ...and high byte to DMA controller count port for ch.3 483 mov al, 0x03 ; clear bit mask (0) + channel (3) 484 out 0x0a, al ; send to DMA mask register - enable the DMA! 485 sti ; enable interrutps; let the CPU see to anything outstanding 486 487 mov ax, es ; update ES:DI (values have been loaded into DMA controller) 488 inc cx ; CX back to actual bytes 489 add di, cx ; add bytes to DI... 490 adc ax, 0 ; ...and if it overflowed, increment... 491 mov es, ax ; ...ES 492 493 add cx, 15 ; XT-CFv2 will present data in 16-byte blocks, but byte count may not 494 shr cx, 1 ; be divisable by 16 due to boundary crossing. So catch any < 16-byte 495 shr cx, 1 ; block by adding 15, then dividing bytes (in CX) by 16 to get the 496 shr cx, 1 ; total block requests. The 8237 is programmed with the actual byte 497 shr cx, 1 ; count and will end the transfer by asserting TC when done. 498 499 .MoreToDo: ; at this point, cx must be >0 500 mov al, 0x40 ; 0x40 = Raise DRQ and clear XT-CFv2 transfer counter 501 .NextDemandBlock: 502 out dx, al ; get up to 16 bytes from XT-CF card 503 loop .NextDemandBlock ; decrement CX and loop if <> 0 504 ; (Loop provides a wait-state between 16-byte blocks; do not unroll) 505 .CleanUp: 506 ; check the transfer is actually done - in case another DMA operation messed things up 507 inc cx ; set up CX, in case we need to do an extra iteration 508 in al, 0x08 ; get DMA status register 509 and al, 0x08 ; test DMA ch.3 TC bit 510 jz .MoreToDo ; it wasn't set so get more bytes 511 .EndDMA: 512 mov al, 0x10 ; 513 out dx, al ; set back to DMA enabled status 514 ret 515 516 %endif ; 0 517 518 519 204 .TransferNextBlock: 205 mov al, RAISE_DRQ_AND_CLEAR_XTCF_XFER_COUNTER 206 cli ; We want no ISR to read DMA Status Register before we do 207 out dx, al ; Transfer up to 16 bytes to/from XT-CF card 208 ; * Here XT-CF sets CPU to wait states during transfer * 209 in al, STATUS_REGISTER_DMA8_in 210 sti 211 test al, FLG_CH3_HAS_REACHED_TERMINAL_COUNT 212 jz SHORT .TransferNextBlock ; All bytes transferred? 213 214 ; Restore XT-CF to normal operation 215 mov al, XTCF_DMA_MODE 216 out dx, al 217 ret
Note:
See TracChangeset
for help on using the changeset viewer.