Changeset 478 in xtideuniversalbios for trunk/XTIDE_Universal_BIOS/Src/Device/IDE/IdeDmaTransfer.asm
- Timestamp:
- Oct 20, 2012, 7:37:28 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
r477 r478 104 104 mov ah, CHANNEL_3 | WRITE | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE 105 105 call StartDMAtransferForXTCFwithDmaModeInAH 106 jc SHORT ReturnNumberOfSectorsXferred 106 call UpdateVariablesForSecondPageIfRequired 107 jc SHORT ReturnNumberOfSectorsXferred ; Second page not needed 107 108 108 109 ; Transfer second DMA page if necessary (always less than 64k) 109 call UpdateVariablesForSecondPageIfRequired110 jc SHORT SecondDmaPageIsNotRequired111 110 mov ah, CHANNEL_3 | WRITE | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE 112 111 call StartDMAtransferForXTCFwithDmaModeInAH 113 jc SHORT ReturnNumberOfSectorsXferred 114 ; Fall to BothDmaPagesTransferredSuccessfully 115 116 BothDmaPagesTransferredSuccessfully: 112 ; Fall to BothDmaPagesTransferred 113 114 BothDmaPagesTransferred: 117 115 inc cx ; Never overflows since second page always less than 64k 118 116 shr cx, 1 ; BYTEs to WORDs 119 117 add [bp+DMAVARS.wTotalWordsXferred], cx 120 SecondDmaPageIsNotRequired:121 xor ah, ah122 118 ReturnNumberOfSectorsXferred: 119 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_BSY) 120 call IdeWait_PollStatusFlagInBLwithTimeoutInBH 121 jc SHORT .ErrorInTransfer 123 122 mov cx, [bp+DMAVARS.wTotalWordsXferred] 124 123 xchg cl, ch ; WORDs to sectors 124 ret 125 126 .ErrorInTransfer: 127 mov cx, 0 ; No way to know how many bytes got xferred 125 128 ret 126 129 … … 141 144 ; AL, BX, DX 142 145 ;-------------------------------------------------------------------- 146 ALIGN JUMP_ALIGN 143 147 WriteBlockToXTCF: 144 148 ; Transfer first DMA page 145 149 mov ah, CHANNEL_3 | READ | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE 146 150 call StartDMAtransferForXTCFwithDmaModeInAH 147 jc SHORT ReturnNumberOfSectorsXferred 151 call UpdateVariablesForSecondPageIfRequired 152 jc SHORT ReturnNumberOfSectorsXferred ; Second page not needed 148 153 149 154 ; Transfer second DMA page if necessary (always less than 64k) 150 call UpdateVariablesForSecondPageIfRequired151 jc SHORT SecondDmaPageIsNotRequired152 155 mov ah, CHANNEL_3 | READ | AUTOINIT_DISABLE | ADDRESS_INCREMENT | DEMAND_MODE 153 156 call StartDMAtransferForXTCFwithDmaModeInAH 154 jc SHORT ReturnNumberOfSectorsXferred 155 jmp SHORT BothDmaPagesTransferredSuccessfully 157 jmp SHORT BothDmaPagesTransferred 156 158 157 159 … … 163 165 ; DS:DI: Ptr to DPT (in RAMVARS segment) 164 166 ; Returns: 165 ; AH: BIOS Error code 166 ; CF: 0 if transfer successful 167 ; 1 if any error 167 ; Nothing 168 168 ; Corrupts registers: 169 ; AL, BX, DX 170 ;-------------------------------------------------------------------- 169 ; AL, DX 170 ;-------------------------------------------------------------------- 171 ALIGN JUMP_ALIGN 171 172 StartDMAtransferForXTCFwithDmaModeInAH: 172 173 push cx … … 210 211 ; total block requests. The 8237 is programmed with the actual byte 211 212 ; 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 213 add cx, BYTE 1 + 15 ; Number of BYTEs to xfer + 15 (bit 16 in CF) 216 214 rcr cx, 1 217 215 eSHR_IM cx, 3 ; CX = Number of 16 byte blocks … … 220 218 221 219 .MoreToDo: ; at this point, cx must be >0 222 mov al, 0x40; 0x40 = Raise DRQ and clear XT-CFv2 transfer counter220 mov al, 40h ; 0x40 = Raise DRQ and clear XT-CFv2 transfer counter 223 221 .NextDemandBlock: 224 222 out dx, al ; get up to 16 bytes from XT-CF card … … 234 232 235 233 .EndDMA: 236 mov al, 0x10;234 mov al, 10h ; 237 235 out dx, al ; set back to DMA enabled status 238 239 ; Check IDE Status Register for errors240 mov bx, TIMEOUT_AND_STATUS_TO_WAIT(TIMEOUT_DRQ, FLG_STATUS_BSY)241 call IdeWait_PollStatusFlagInBLwithTimeoutInBH242 236 pop cx 243 237 ret … … 256 250 ; AX, (CX) 257 251 ;-------------------------------------------------------------------- 252 ALIGN JUMP_ALIGN 258 253 UpdateVariablesForSecondPageIfRequired: 259 254 inc cx ; BYTEs in first page … … 281 276 .OnePageWasEnough: 282 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
Note:
See TracChangeset
for help on using the changeset viewer.