1/* 2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 1.1 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22 23#include <IOKit/sbp2/IOFireWireSBP2ORB.h> 24#include <IOKit/sbp2/IOFireWireSBP2Login.h> 25#include <IOKit/sbp2/IOFireWireSBP2LUN.h> 26#include "FWDebugging.h" 27 28#define FIREWIREPRIVATE 29#include <IOKit/firewire/IOFireWireController.h> 30#undef FIREWIREPRIVATE 31 32#include <IOKit/firewire/IOFWSimpleContiguousPhysicalAddressSpace.h> 33 34OSDefineMetaClassAndStructors( IOFireWireSBP2ORB, IOCommand ); 35 36OSMetaClassDefineReservedUnused(IOFireWireSBP2ORB, 0); 37OSMetaClassDefineReservedUnused(IOFireWireSBP2ORB, 1); 38OSMetaClassDefineReservedUnused(IOFireWireSBP2ORB, 2); 39OSMetaClassDefineReservedUnused(IOFireWireSBP2ORB, 3); 40OSMetaClassDefineReservedUnused(IOFireWireSBP2ORB, 4); 41OSMetaClassDefineReservedUnused(IOFireWireSBP2ORB, 5); 42OSMetaClassDefineReservedUnused(IOFireWireSBP2ORB, 6); 43OSMetaClassDefineReservedUnused(IOFireWireSBP2ORB, 7); 44OSMetaClassDefineReservedUnused(IOFireWireSBP2ORB, 8); 45 46enum 47{ 48 kFWSBP2CommandMaxPacketSizeOverride = (1 << 12) 49}; 50 51// initWithLogin 52// 53// initializer 54 55bool IOFireWireSBP2ORB::initWithLogin( IOFireWireSBP2Login * login ) 56{ 57 bool res = true; 58 fLogin = login; 59 fLUN = getFireWireLUN(); 60 fUnit = getFireWireUnit(); 61 fControl = fUnit->getController(); 62 63 // these should already be zeroed 64 65 fTimeoutTimerSet = false; 66 fRefCon = NULL; 67 fBufferAddressSpaceAllocated = false; 68 fBufferDescriptor = NULL; 69 fMaxPayloadSize = 0; 70 fCommandFlags = 0; 71 fTimeoutDuration = 0; 72 fDMACommand = NULL; 73 fConstraintOptions = 0; 74 // init super 75 if( !IOCommand::init() ) 76 return false; 77 78 IOReturn status = allocateResources(); 79 if( status != kIOReturnSuccess ) 80 res = false; 81 82 return res; 83} 84 85// allocateResources 86// 87// create orb and pageTable 88 89IOReturn IOFireWireSBP2ORB::allocateResources( void ) 90{ 91 IOReturn status = kIOReturnSuccess; 92 93 status = setBufferConstraints( kFWSBP2MaxPageClusterSize, 1, 0 ); 94 95// IOLog("IOFireWireSBP2ORB::allocateResources - setBufferConstraints, status = 0x%08lx\n", status ); 96 // 97 // create ORB 98 // 99 100 if( status == kIOReturnSuccess ) 101 { 102 // calculate orb size 103 UInt32 orbSize = sizeof(FWSBP2ORB) - 4 + fLogin->getMaxCommandBlockSize(); 104 status = allocateORB( orbSize ); 105 } 106 107// IOLog("IOFireWireSBP2ORB::allocateResources - allocateORB, status = 0x%08lx\n", status ); 108 109 // 110 // create page table 111 // 112 113 if( status == kIOReturnSuccess ) 114 { 115 status = allocatePageTable( PAGE_SIZE / sizeof(FWSBP2PTE) ); // default size 116 } 117 118// IOLog("IOFireWireSBP2ORB::allocateResources - allocatePageTable, status = 0x%08lx\n", status ); 119 120 // 121 // create timer 122 // 123 124 if( status == kIOReturnSuccess ) 125 { 126 status = allocateTimer(); 127 } 128 129 // 130 // clean up on error 131 // 132 133 if( status != kIOReturnSuccess ) 134 { 135 deallocateTimer(); 136 deallocateORB(); 137 deallocatePageTable(); 138 } 139 140// IOLog("IOFireWireSBP2ORB::allocateResources - status = 0x%08lx\n", status ); 141 142 return status; 143} 144 145void IOFireWireSBP2ORB::release() const 146{ 147 if( getRetainCount() >= 2 ) 148 IOCommand::release(2); 149} 150 151void IOFireWireSBP2ORB::free( void ) 152{ 153 FWKLOG(( "IOFireWireSBP2ORB<%p> : free\n", this )); 154 155 removeORB( this ); 156 157 deallocateTimer(); 158 deallocatePageTable(); 159 deallocateBufferAddressSpace(); 160 deallocateORB(); 161 162 IOCommand::free(); 163} 164 165////////////////////////////////////////////////////////////////////// 166// ORB 167// 168 169// allocateORB 170// 171// 172 173IOReturn IOFireWireSBP2ORB::allocateORB( UInt32 orbSize ) 174{ 175 IOReturn status = kIOReturnSuccess; 176 177 IOFWSimpleContiguousPhysicalAddressSpace * physical_space; 178 if( status == kIOReturnSuccess ) 179 { 180 physical_space = fUnit->createSimpleContiguousPhysicalAddressSpace( orbSize, kIODirectionOut ); 181 if( physical_space == NULL ) 182 status = kIOReturnNoMemory; 183 } 184 185// IOLog( "IOFireWireSBP2ORB::allocateORB - 1 status = 0x%08lx\n", status ); 186 187 if( status == kIOReturnSuccess ) 188 { 189 fORBPhysicalAddressSpace = (IOFWAddressSpace*)physical_space; 190 fORBDescriptor = physical_space->getMemoryDescriptor(); 191 fORBPhysicalAddress = physical_space->getFWAddress(); 192 fORBBuffer = (FWSBP2ORB *)physical_space->getVirtualAddress(); 193 } 194 195// IOLog( "IOFireWireSBP2ORB::allocateORB - 2 status = 0x%08lx\n", status ); 196 197 if( status == kIOReturnSuccess ) 198 { 199 status = fORBPhysicalAddressSpace->activate(); 200 } 201 202// IOLog( "IOFireWireSBP2ORB::allocateORB - 3 status = 0x%08lx\n", status ); 203 204 if( status == kIOReturnSuccess ) 205 { 206 //zzz shouldn't be able to write to ORBs 207 //zzz of course when running via the physical unit there's nothing to stop writes anyway 208 209 fORBPseudoAddressSpace = IOFWPseudoAddressSpace::simpleRW( fControl, &fORBPseudoAddress, fORBDescriptor ); 210 if ( fORBPseudoAddressSpace == NULL ) 211 status = kIOReturnNoMemory; 212 } 213 214// IOLog( "IOFireWireSBP2ORB::allocateORB - 4 status = 0x%08lx\n", status ); 215 216 if( status == kIOReturnSuccess ) 217 { 218 status = fORBPseudoAddressSpace->activate(); 219 220 FWKLOG( ( "IOFireWireSBP2ORB<%p> : created orb at phys: 0x%04lx.%08lx psuedo: 0x%04lx.%08lx of size %d\n", 221 this, fORBPhysicalAddress.addressHi, fORBPhysicalAddress.addressLo, fORBPseudoAddress.addressHi, fORBPseudoAddress.addressLo, orbSize ) ); 222 } 223 224// IOLog( "IOFireWireSBP2ORB::allocateORB - 5 status = 0x%08lx\n", status ); 225 226 if( status != kIOReturnSuccess ) 227 { 228 deallocateORB(); 229 } 230 231 return status; 232} 233 234void IOFireWireSBP2ORB::deallocateORB( void ) 235{ 236 IOReturn status = kIOReturnSuccess; 237 238 // deallocate physical address space 239 if( fORBPhysicalAddressSpace != NULL && status == kIOReturnSuccess ) 240 { 241 fORBPhysicalAddressSpace->deactivate(); 242 fORBPhysicalAddressSpace->release(); 243 fORBPhysicalAddressSpace = NULL; 244 } 245 246 // deallocate pseudo address space 247 if( fORBPseudoAddressSpace != NULL && status == kIOReturnSuccess ) 248 { 249 fORBPseudoAddressSpace->deactivate(); 250 fORBPseudoAddressSpace->release(); 251 fORBPseudoAddressSpace = NULL; 252 } 253} 254 255 256//////////////////////////////////////////////////////////////////// 257// command execution 258// 259 260// calculateTransferSizeLog 261// 262// 263 264UInt32 IOFireWireSBP2ORB::calculateTransferSizeLog( bool * clipping ) 265{ 266 // 267 // calculate transfer size 268 // 269 270 UInt32 transferSizeBytes; 271 *clipping = false; 272 transferSizeBytes = 4096; // start at max packet size 273 274 bool size_override = (fCommandFlags & kFWSBP2CommandMaxPacketSizeOverride); 275 276 if( !size_override ) 277 { 278 // clip by ARMDMAMax for performance 279 UInt32 ARDMAMax = fLogin->getARDMMax(); 280 if( (fCommandFlags & kFWSBP2CommandTransferDataFromTarget) && // if this is a read 281 (ARDMAMax != 0) ) // and we've got an ARDMA clip 282 { 283 transferSizeBytes = ARDMAMax; 284 *clipping = true; 285 } 286 } 287 288 // trim by max payload sizes 289 UInt32 loginMaxPayloadSize = fLogin->getMaxPayloadSize(); 290 if( loginMaxPayloadSize != 0 && loginMaxPayloadSize < transferSizeBytes ) 291 transferSizeBytes = loginMaxPayloadSize; 292 293 if( fMaxPayloadSize != 0 && fMaxPayloadSize < transferSizeBytes ) 294 transferSizeBytes = fMaxPayloadSize; 295 296 // find the largest power of two less than or equal to transferSizeBytes/4 297 UInt32 transferSizeLog = 0; 298 while( (transferSizeBytes >= 8) && (transferSizeLog < 15) ) 299 { 300 transferSizeBytes >>= 1; 301 transferSizeLog++; 302 } 303 304 if( !size_override ) 305 { 306 // trim by maxPackLog 307 UInt32 maxPackLog = fUnit->maxPackLog(!(fCommandFlags & kFWSBP2CommandTransferDataFromTarget)); 308 maxPackLog -= 2; // convert to quads 309 if( maxPackLog < transferSizeLog ) 310 { 311 *clipping = true; 312 transferSizeLog = maxPackLog; 313 } 314 } 315 else 316 { 317 UInt32 maxPackLog = 7; 318 319 IOFWSpeed speed = fUnit->FWSpeed(); 320 switch( speed ) 321 { 322 case kFWSpeed800MBit: 323 maxPackLog = 10; 324 break; 325 326 case kFWSpeed400MBit: 327 maxPackLog = 9; 328 break; 329 330 case kFWSpeed200MBit: 331 maxPackLog = 8; 332 break; 333 334 default: 335 break; 336 } 337 338 if( maxPackLog < transferSizeLog ) 339 transferSizeLog = maxPackLog; 340 } 341 342 343 return transferSizeLog; 344} 345 346// prepareORBForExecution 347// 348// 349 350void IOFireWireSBP2ORB::prepareORBForExecution( void ) 351{ 352 353 // make sure orb points nowhere 354 fORBBuffer->nextORBAddressHi = OSSwapHostToBigInt32(0x80000000); 355 fORBBuffer->nextORBAddressLo = OSSwapHostToBigInt32(0x00000000); 356 357 // update data descriptor with local node ID 358 UInt32 generation; // Hmm, shouldn't this be checked? 359 UInt16 unitNode; 360 UInt16 localNode; 361 fUnit->getNodeIDGeneration( generation, unitNode, localNode ); 362 fORBBuffer->dataDescriptorHi &= OSSwapHostToBigInt32(0x0000ffff); 363 fORBBuffer->dataDescriptorHi |= OSSwapHostToBigInt32(((UInt32)localNode) << 16); 364 365 // clear options 366 fORBBuffer->options &= OSSwapHostToBigInt16(0x000f); 367 368 // mark for notify if requested 369 if( fCommandFlags & kFWSBP2CommandCompleteNotify ) 370 fORBBuffer->options |= OSSwapHostToBigInt16(0x8000); 371 372 // mark ORB rq_fmt. if kFWSBP2CommandNormalORB is set, the zero is already in place. 373 // the driver is not supposed to set more than one of these flags 374 if( fCommandFlags & kFWSBP2CommandReservedORB ) 375 fORBBuffer->options |= OSSwapHostToBigInt16(0x2000); 376 377 if( fCommandFlags & kFWSBP2CommandVendorORB ) 378 fORBBuffer->options |= OSSwapHostToBigInt16(0x4000); 379 380 if( fCommandFlags & kFWSBP2CommandDummyORB ) 381 fORBBuffer->options |= OSSwapHostToBigInt16(0x6000); 382 383 // mark as "read" if requested 384 if( fCommandFlags & kFWSBP2CommandTransferDataFromTarget ) 385 fORBBuffer->options |= OSSwapHostToBigInt16(0x0800); 386 387 // 388 // set speed 389 // 390 391 IOFWSpeed speed = fUnit->FWSpeed(); 392 switch( speed ) 393 { 394 case kFWSpeed800MBit: 395 fORBBuffer->options |= OSSwapHostToBigInt16(0x0300); 396 break; 397 398 case kFWSpeed400MBit: 399 fORBBuffer->options |= OSSwapHostToBigInt16(0x0200); 400 break; 401 402 case kFWSpeed200MBit: 403 fORBBuffer->options |= OSSwapHostToBigInt16(0x0100); 404 break; 405 406 default: 407 // default options is |= 0x0000 408 break; 409 } 410 411 UInt32 transferSizeLog; 412 bool clipping; 413 414 transferSizeLog = calculateTransferSizeLog( &clipping ); 415 416 // set transfer size, actual max is 2 ^ (size + 2) bytes (or 2 ^ size quads) 417 fORBBuffer->options |= OSSwapHostToBigInt16(transferSizeLog << 4); 418} 419 420// prepareFastStartPacket 421// 422// 423 424void IOFireWireSBP2ORB::prepareFastStartPacket( IOBufferMemoryDescriptor * descriptor ) 425{ 426 UInt32 offset = 16; 427 UInt32 length = descriptor->getLength(); 428 429 // 430 // write orb 431 // 432 433 UInt32 orbLength = fORBDescriptor->getLength(); 434 if( length < (offset + orbLength) ) 435 { 436 IOLog( "IOFireWireSBP2ORB<0x%08lx>::prepareFastStartPacket - fast start packet length (%d) < orblength (%d) + 16\n", this, length, orbLength ); 437 } 438 descriptor->writeBytes( offset, fORBBuffer, orbLength ); 439 440 offset += orbLength; 441 442 // 443 // write page table 444 // 445 446 FWSBP2PTE pte; 447 UInt32 pageTableOffset = 0; 448 UInt32 pageTableSize = fPTECount * sizeof(FWSBP2PTE); 449 450 while( offset < length && pageTableOffset < pageTableSize ) 451 { 452 if( (length - offset) < sizeof(FWSBP2PTE) ) 453 { 454 IOLog( "IOFireWireSBP2ORB<0x%08lx>::prepareFastStartPacket - fast start packet not full, yet pte doesn't fit\n", this ); 455 break; 456 } 457 458 fPageTableDescriptor->readBytes( pageTableOffset, &pte, sizeof(FWSBP2PTE) ); 459 descriptor->writeBytes( offset, &pte, sizeof(FWSBP2PTE) ); 460 461 462 offset += sizeof(FWSBP2PTE); 463 pageTableOffset += sizeof(FWSBP2PTE); 464 } 465 466 if( offset > length ) 467 { 468 IOLog( "IOFireWireSBP2ORB<0x%08lx>::prepareFastStartPacket - offset > length\n", this ); 469 } 470 471 // 472 // trim descriptor size if necessary 473 // 474 475 descriptor->setLength( offset ); 476} 477 478#if 0 479IOReturn checkMemoryInRange( IOMemoryDescriptor * memory, UInt64 mask, IODMACommand * dma_command_arg ) 480{ 481 IOReturn status = kIOReturnSuccess; 482 483 if( memory == NULL ) 484 { 485 status = kIOReturnBadArgument; 486 } 487 488 // 489 // setup 490 // 491 492 bool memory_prepared = false; 493 if( dma_command_arg == NULL ) 494 { 495 if( status == kIOReturnSuccess ) 496 { 497 status = memory->prepare( kIODirectionInOut ); 498 } 499 500 if( status == kIOReturnSuccess ) 501 { 502 memory_prepared = true; 503 } 504 } 505 506 507 UInt64 length = 0; 508 509 if( status == kIOReturnSuccess ) 510 { 511 length = memory->getLength(); 512 } 513 514 IODMACommand * dma_command = dma_command_arg; 515 bool dma_command_prepared = false; 516 if( dma_command == NULL ) 517 { 518 if( status == kIOReturnSuccess ) 519 { 520 dma_command = IODMACommand::withSpecification( 521 kIODMACommandOutputHost64, // segment function 522 64, // max address bits 523 0, // max segment size 524 (IODMACommand::MappingOptions)(IODMACommand::kMapped | IODMACommand::kIterateOnly), // IO mapped & don't bounce buffer 525 0, // max transfer size 526 0, // page alignment 527 NULL, // mapper 528 NULL ); // refcon 529 if( dma_command == NULL ) 530 status = kIOReturnError; 531 532 } 533 534 if( status == kIOReturnSuccess ) 535 { 536 // set memory descriptor and don't prepare it 537 status = dma_command->setMemoryDescriptor( memory, false ); 538 } 539 540 if( status == kIOReturnSuccess ) 541 { 542 status = dma_command->prepare( 0, length, true ); 543 } 544 545 if( status == kIOReturnSuccess ) 546 { 547 dma_command_prepared = true; 548 } 549 } 550 else 551 { 552#if 0 553 dma_command->setMemoryDescriptor( memory, false ); 554 dma_command->prepare( 0, length, true ); 555 dma_command_prepared = true; 556#endif 557 } 558 // 559 // check ranges 560 // 561 562 if( status == kIOReturnSuccess ) 563 { 564 IOLog( "checkSegments - length = %d\n", length ); 565 566 UInt64 offset = 0; 567 while( (offset < length) && (status == kIOReturnSuccess) ) 568 { 569 IODMACommand::Segment64 segments[10]; 570 UInt32 num_segments = 10; 571 status = dma_command->gen64IOVMSegments( &offset, segments, &num_segments ); 572 if( status == kIOReturnSuccess ) 573 { 574 for( UInt32 i = 0; i < num_segments; i++ ) 575 { 576 IOLog( "checkSegments - offset = 0x%016llx segments[%d].fIOVMAddr = 0x%016llx, fLength = %d\n", offset, i, segments[i].fIOVMAddr, segments[i].fLength ); 577 578 if( (segments[i].fIOVMAddr & (~mask)) ) 579 { 580 IOLog( "checkSegmentsFailed - 0x%016llx & 0x%016llx\n", segments[i].fIOVMAddr, mask ); 581 status = kIOReturnNotPermitted; 582 // break; 583 } 584 } 585 } 586 else 587 { 588 IOLog( "checkSegments - offset = %lld 0x%08lx\n", offset, status ); 589 } 590 } 591 } 592 593 // 594 // clean up 595 // 596 597 if( dma_command_prepared ) 598 { 599 dma_command->complete(); 600 dma_command_prepared = false; 601 } 602 603 if( dma_command && (dma_command_arg == NULL) ) 604 { 605 dma_command->release(); 606 dma_command = NULL; 607 } 608 609 if( memory_prepared ) 610 { 611 memory->complete(); 612 memory_prepared = false; 613 } 614 615 return status; 616} 617 618#endif 619 620////////////////////////////////////////////////////////////////////////////////////////// 621// timeouts 622// 623 624IOReturn IOFireWireSBP2ORB::allocateTimer( void ) 625{ 626 IOReturn status = kIOReturnSuccess; 627 628 if( status == kIOReturnSuccess ) 629 { 630 fTimeoutCommand = (IOFWDelayCommand*)fControl->createDelayedCmd( fTimeoutDuration * 1000, 631 IOFireWireSBP2ORB::orbTimeoutStatic, 632 this ); 633 if( fTimeoutCommand == NULL ) 634 status = kIOReturnError; 635 } 636 637 if( status != kIOReturnSuccess ) 638 { 639 deallocateTimer(); 640 } 641 642 return status; 643} 644 645void IOFireWireSBP2ORB::deallocateTimer( void ) 646{ 647 // cancel timer 648 if( fTimeoutTimerSet ) 649 cancelTimer(); 650 651 if( fTimeoutCommand ) 652 { 653 fTimeoutCommand->release(); 654 fTimeoutCommand = NULL; 655 } 656} 657 658// startTimer 659// 660// 661 662void IOFireWireSBP2ORB::startTimer( void ) 663{ 664 // 665 // set timeout if necessary 666 // 667 668 if( fCommandFlags & kFWSBP2CommandCompleteNotify ) 669 { 670 fInProgress = true; 671 672 if( fTimeoutDuration != 0 ) 673 { 674 IOReturn ORBtimeoutSubmitStatus; 675 676 FWKLOG( ( "IOFireWireSBP2ORB<%p> : set timeout\n", this ) ); 677 678 fTimeoutTimerSet = true; 679 ORBtimeoutSubmitStatus = fTimeoutCommand->submit(); 680 681 FWPANICASSERT( ORBtimeoutSubmitStatus == kIOReturnSuccess ); 682 } 683 } 684} 685 686// isTimerSet 687// 688// 689 690bool IOFireWireSBP2ORB::isTimerSet( void ) 691{ 692 return fInProgress; 693} 694 695// cancelTimer 696// 697// 698 699void IOFireWireSBP2ORB::cancelTimer( void ) 700{ 701 FWKLOG( ( "IOFireWireSBP2ORB<%p> : cancel timer\n", this ) ); 702 703 // cancel timer 704 if( fTimeoutTimerSet ) 705 { 706 fTimeoutCommand->cancel( kIOReturnAborted ); 707 } 708 else 709 { 710 fInProgress = false; 711 } 712} 713 714// orb timeout handler 715// 716// static wrapper & virtual method 717 718void IOFireWireSBP2ORB::orbTimeoutStatic( void *refcon, IOReturn status, IOFireWireBus *bus, IOFWBusCommand *fwCmd ) 719{ 720 ((IOFireWireSBP2ORB*)refcon)->orbTimeout( status, bus, fwCmd ); 721} 722 723void IOFireWireSBP2ORB::orbTimeout( IOReturn status, IOFireWireBus *bus, IOFWBusCommand *fwCmd ) 724{ 725 fTimeoutTimerSet = false; 726 fInProgress = false; 727 728 if( status == kIOReturnTimeout ) 729 { 730 FWKLOG( ( "IOFireWireSBP2ORB<%p> : orb timeout\n", this ) ); 731 sendTimeoutNotification( this ); 732 } 733 else 734 { 735 FWKLOG( ( "IOFireWireSBP2ORB<%p> : orb timeout cancelled\n", this ) ); 736 } 737} 738 739////////////////////////////////////////////////////////////////////// 740// page table 741// 742 743// allocatePageTable 744// 745// 746 747IOReturn IOFireWireSBP2ORB::allocatePageTable( UInt32 entryCount ) 748{ 749 IOReturn status = kIOReturnSuccess; 750 751 deallocatePageTable(); 752 753 // 754 // create page table 755 // 756 757 // allocate mem for page table 758 fPageTableSize = sizeof(FWSBP2PTE) * entryCount; 759 UInt64 phys_mask = fControl->getFireWirePhysicalAddressMask(); 760 fPageTableDescriptor = IOBufferMemoryDescriptor::inTaskWithPhysicalMask( kernel_task, kIODirectionOutIn, fPageTableSize, phys_mask ); 761 if( fPageTableDescriptor == NULL ) 762 status = kIOReturnNoMemory; 763 764 if( status == kIOReturnSuccess ) 765 { 766 fPageTableDescriptor->setLength( fPageTableSize ); 767 } 768 769 bool dma_command_prepared = false; 770 IODMACommand * dma_command = NULL; 771 if( status == kIOReturnSuccess ) 772 { 773 dma_command = IODMACommand::withSpecification( 774 kIODMACommandOutputHost64, // segment function 775 48, // max address bits 776 fPageTableSize, // max segment size 777 (IODMACommand::MappingOptions)(IODMACommand::kMapped | IODMACommand::kIterateOnly), // IO mapped & don't bounce buffer 778 fPageTableSize, // max transfer size 779 0, // no alignment 780 NULL, // mapper 781 NULL ); // refcon 782 if( dma_command == NULL ) 783 status = kIOReturnNoMemory; 784 } 785 786// IOLog( "IOFireWireSBP2ORB::allocatePageTable (1) - status = 0x%08lx\n", status ); 787 788 if( status == kIOReturnSuccess ) 789 { 790 // set memory descriptor and don't prepare it 791 status = dma_command->setMemoryDescriptor( fPageTableDescriptor, false ); 792 } 793 794 if( status == kIOReturnSuccess ) 795 { 796 status = dma_command->prepare( 0, fPageTableSize, true ); 797 } 798 799 if( status == kIOReturnSuccess ) 800 { 801 dma_command_prepared = true; 802 } 803 804// IOLog( "IOFireWireSBP2ORB::allocatePageTable (2) - status = 0x%08lx\n", status ); 805 806 IODMACommand::Segment64 segment; 807 UInt32 numSegments = 1; 808 if( status == kIOReturnSuccess ) 809 { 810 UInt64 offset = 0; 811 status = dma_command->gen64IOVMSegments( &offset, &segment, &numSegments ); 812 } 813 814 if( status == kIOReturnSuccess ) 815 { 816 if( numSegments != 1 ) 817 { 818 status = kIOReturnNoMemory; 819 } 820 } 821 822// IOLog( "IOFireWireSBP2ORB::allocatePageTable (3) - status = 0x%08lx\n", status ); 823 824 if( status == kIOReturnSuccess ) 825 { 826 fPageTablePhysicalLength = segment.fLength; 827 fPageTablePhysicalAddress.nodeID = 0x0000; // invalid node id 828 fPageTablePhysicalAddress.addressHi = (segment.fIOVMAddr >> 32) & 0x000000000000ffffULL; 829 fPageTablePhysicalAddress.addressLo = segment.fIOVMAddr & 0x00000000ffffffffULL; 830 } 831 832 if( dma_command_prepared ) 833 { 834 dma_command->complete(); 835 dma_command_prepared = false; 836 } 837 838 if( dma_command ) 839 { 840 dma_command->release(); 841 dma_command = NULL; 842 } 843 844// IOLog( "IOFireWireSBP2ORB::allocatePageTable (1) - status = 0x%08lx segment = 0x%016llx len = %d\n", status, segment.fIOVMAddr, segment.fLength ); 845 846 // allocate and register a physical address space for the page table 847 848 if( status == kIOReturnSuccess ) 849 { 850 fPageTablePhysicalAddressSpace = fUnit->createPhysicalAddressSpace( fPageTableDescriptor ); 851 if ( fPageTablePhysicalAddressSpace == NULL ) 852 status = kIOReturnNoMemory; 853 } 854 855 if( status == kIOReturnSuccess ) 856 { 857 status = fPageTablePhysicalAddressSpace->activate(); 858 } 859 860 // allocate and register a pseudo address space for the page table 861 862 if( status == kIOReturnSuccess ) 863 { 864 //zzz shouldn't be able to write to the page table 865 //zzz of course when run physically there's nothing to stop writes anyway 866 867 fPageTablePseudoAddressSpace = IOFWPseudoAddressSpace::simpleRW( fControl, &fPageTablePseudoAddress, fPageTableDescriptor ); 868 if ( fPageTablePseudoAddressSpace == NULL ) 869 status = kIOReturnNoMemory; 870 } 871 872 if( status == kIOReturnSuccess ) 873 { 874 status = fPageTablePseudoAddressSpace->activate(); 875 } 876 877 if( status != kIOReturnSuccess ) 878 { 879 deallocatePageTable(); 880 } 881 882 return status; 883} 884 885// deallocatePageTable 886// 887// 888 889void IOFireWireSBP2ORB::deallocatePageTable( void ) 890{ 891 IOReturn status = kIOReturnSuccess; 892 893 // deallocate physical address space 894 if( fPageTablePhysicalAddressSpace != NULL && status == kIOReturnSuccess ) 895 { 896 fPageTablePhysicalAddressSpace->deactivate(); 897 fPageTablePhysicalAddressSpace->release(); 898 fPageTablePhysicalAddressSpace = NULL; 899 } 900 901 // deallocate pseudo address space 902 if( fPageTablePseudoAddressSpace != NULL && status == kIOReturnSuccess ) 903 { 904 fPageTablePseudoAddressSpace->deactivate(); 905 fPageTablePseudoAddressSpace->release(); 906 fPageTablePseudoAddressSpace = NULL; 907 } 908 909 // free mem 910 if( fPageTableDescriptor != NULL ) 911 { 912 fPageTableDescriptor->release(); 913 fPageTableDescriptor = NULL; 914 } 915 916 fPageTableSize = 0; 917} 918 919// setBufferConstraints 920// 921// 922 923IOReturn IOFireWireSBP2ORB::setBufferConstraints( UInt64 maxSegmentSize, UInt32 alignment, UInt32 options ) 924{ 925 IOReturn status = kIOReturnSuccess; 926 927 if( fBufferAddressSpaceAllocated ) 928 { 929 status = kIOReturnBusy; 930 } 931 932 if( status == kIOReturnSuccess ) 933 { 934 fConstraintOptions = options; 935 936 deallocateBufferAddressSpace(); 937 938 // 939 // create DMACommand 940 // 941 942 if( status == kIOReturnSuccess ) 943 { 944 UInt32 address_bits = fControl->getFireWirePhysicalAddressBits(); 945#if 0 946 // testing 947 // address_bits = 29; 948#endif 949 950 UInt64 segment_size = maxSegmentSize; 951 if( (segment_size > kFWSBP2MaxPageClusterSize) || (segment_size == 0) ) 952 segment_size = kFWSBP2MaxPageClusterSize; 953 954 fDMACommand = IODMACommand::withSpecification( 955 kIODMACommandOutputHost64, // segment function 956 address_bits, // max address bits 957 segment_size, // max segment size 958 IODMACommand::kMapped, // IO mapped & allow bounce buffering 959 0, // max transfer size 960 alignment, // alignment 961 NULL, // mapper 962 NULL ); // refcon 963 if( fDMACommand == NULL ) 964 status = kIOReturnError; 965 } 966 } 967 968 // allocate and register an address space for the buffers 969 970// IOLog( "IOFireWireSBP2ORB::setBufferConstraints - (1) status = 0x%08lx\n", status ); 971 972 if( status == kIOReturnSuccess ) 973 { 974 fBufferAddressSpace = fUnit->createPhysicalAddressSpace( NULL ); 975 if( fBufferAddressSpace == NULL ) 976 { 977 status = kIOReturnNoMemory; 978 } 979 } 980 981// IOLog( "IOFireWireSBP2ORB::setBufferConstraints - (2) status = 0x%08lx\n", status ); 982 983 if( status == kIOReturnSuccess ) 984 { 985 ((IOFWPhysicalAddressSpace*)fBufferAddressSpace)->setDMACommand( fDMACommand ); 986 } 987 988 return status; 989} 990 991// prepareBufferAddressSpace 992// 993// 994 995IOReturn IOFireWireSBP2ORB::prepareBufferAddressSpace( IOMemoryDescriptor * memoryDescriptor ) 996{ 997 if( fBufferAddressSpaceAllocated ) 998 { 999 completeBufferAddressSpace(); 1000 } 1001 1002 fBufferDescriptor = memoryDescriptor; 1003 fBufferDescriptor->retain(); 1004 1005 ((IOFWPhysicalAddressSpace*)fBufferAddressSpace)->setMemoryDescriptor( fBufferDescriptor ); 1006 fBufferAddressSpace->activate(); 1007 1008 if( fConstraintOptions & kFWSBP2ConstraintForceDoubleBuffer ) 1009 { 1010 ((IOFWPhysicalAddressSpace*)fBufferAddressSpace)->synchronize( IODMACommand::kForceDoubleBuffer | kIODirectionOut ); 1011 } 1012 1013 fBufferAddressSpaceAllocated = true; 1014 1015 return kIOReturnSuccess; 1016} 1017 1018// completeBufferAddressSpace 1019// 1020// 1021 1022IOReturn IOFireWireSBP2ORB::completeBufferAddressSpace( void ) 1023{ 1024 if( fBufferAddressSpace ) 1025 { 1026 fBufferAddressSpace->deactivate(); 1027 ((IOFWPhysicalAddressSpace*)fBufferAddressSpace)->setMemoryDescriptor( NULL ); 1028 } 1029 1030 if( fBufferDescriptor ) 1031 { 1032 fBufferDescriptor->release(); 1033 fBufferDescriptor = NULL; 1034 } 1035 1036 fBufferAddressSpaceAllocated = false; 1037 1038 if( fORBBuffer ) 1039 { 1040 fORBBuffer->dataDescriptorHi = 0; 1041 fORBBuffer->dataDescriptorLo = 0; 1042 fORBBuffer->options &= OSSwapHostToBigInt16(0xfff0); // no page table 1043 fORBBuffer->dataSize = 0; 1044 } 1045 1046 return kIOReturnSuccess; 1047} 1048 1049// deallocateBufferAddressSpace 1050// 1051// 1052 1053void IOFireWireSBP2ORB::deallocateBufferAddressSpace( void ) 1054{ 1055 fControl->closeGate(); 1056 1057 fPTECount = 0; 1058 1059 if( fBufferAddressSpaceAllocated ) 1060 { 1061 completeBufferAddressSpace(); 1062 } 1063 1064 if( fBufferAddressSpace ) 1065 { 1066 fBufferAddressSpace->release(); 1067 fBufferAddressSpace = NULL; 1068 } 1069 1070 if( fDMACommand ) 1071 { 1072 fDMACommand->release(); 1073 fDMACommand = NULL; 1074 } 1075 1076 // no page table 1077 if( fORBBuffer ) 1078 { 1079 fORBBuffer->dataDescriptorHi = 0; 1080 fORBBuffer->dataDescriptorLo = 0; 1081 fORBBuffer->options &= OSSwapHostToBigInt16(0xfff0); 1082 // no page table 1083 fORBBuffer->dataSize = 0; 1084 } 1085 1086 fPTECount = 0; 1087 1088 fControl->openGate(); 1089} 1090 1091// setCommandBuffersAsRanges 1092// 1093// allocates and prepares a memory descriptor from given virtual ranges 1094// and then calls setCommandBuffers with the descriptor 1095 1096IOReturn IOFireWireSBP2ORB::setCommandBuffersAsRanges( IOVirtualRange * ranges, 1097 UInt32 withCount, 1098 IODirection withDirection, 1099 task_t withTask, 1100 UInt32 offset, 1101 UInt32 length ) 1102{ 1103 IOReturn status = kIOReturnSuccess; 1104 IOMemoryDescriptor * memory = NULL; 1105 1106 if( withCount == 0 ) 1107 { 1108 status = kIOReturnBadArgument; 1109 } 1110 1111 IOAddressRange * address_ranges = NULL; 1112 if( status == kIOReturnSuccess ) 1113 { 1114 IOAddressRange * address_ranges = IONew( IOAddressRange, withCount ); 1115 if( address_ranges == NULL ) 1116 { 1117 status = kIOReturnNoMemory; 1118 } 1119 } 1120 1121 if( status == kIOReturnSuccess ) 1122 { 1123 for( uint32_t i = 0; i < withCount; i++ ) 1124 { 1125 address_ranges[i].address = ranges[i].address; 1126 address_ranges[i].length = ranges[i].length; 1127 } 1128 1129 memory = IOMemoryDescriptor::withAddressRanges( address_ranges, withCount, withDirection, withTask ); 1130 if( !memory ) 1131 status = kIOReturnNoMemory; 1132 } 1133 1134 if( address_ranges ) 1135 { 1136 IODelete( address_ranges, IOAddressRange, withCount ); 1137 address_ranges = NULL; 1138 } 1139 1140 if( status == kIOReturnSuccess ) 1141 { 1142 status = memory->prepare( withDirection ); 1143 } 1144 1145 if( status == kIOReturnSuccess ) 1146 { 1147 status = setCommandBuffers( memory, offset, length ); 1148 } 1149 1150 if( memory ) 1151 { 1152 memory->release(); 1153 } 1154 1155 return status; 1156} 1157 1158// setCommandBuffersAsRanges64 1159// 1160// 1161 1162IOReturn IOFireWireSBP2ORB::setCommandBuffersAsRanges64( IOAddressRange * ranges, 1163 uint64_t withCount, 1164 IODirection withDirection, 1165 task_t withTask, 1166 uint64_t offset, 1167 uint64_t length ) 1168{ 1169 IOReturn status = kIOReturnSuccess; 1170 IOMemoryDescriptor * memory = NULL; 1171 1172 if( status == kIOReturnSuccess ) 1173 { 1174 memory = IOMemoryDescriptor::withAddressRanges( ranges, withCount, withDirection, withTask ); 1175 if( !memory ) 1176 status = kIOReturnNoMemory; 1177 } 1178 1179 if( status == kIOReturnSuccess ) 1180 { 1181 status = memory->prepare( withDirection ); 1182 } 1183 1184 if( status == kIOReturnSuccess ) 1185 { 1186 status = setCommandBuffers( memory, offset, length ); 1187 } 1188 1189 if( memory ) 1190 { 1191 memory->release(); 1192 } 1193 1194 return status; 1195 1196} 1197 1198// releaseCommandBuffers 1199// 1200// tell SBP2 that the IO is done and command buffers can be released 1201 1202IOReturn IOFireWireSBP2ORB::releaseCommandBuffers( void ) 1203{ 1204 return setCommandBuffers( NULL ); 1205} 1206 1207// setCommandBuffers 1208// 1209// write a page table from the given memoryDecriptor 1210 1211IOReturn IOFireWireSBP2ORB::setCommandBuffers( IOMemoryDescriptor * memoryDescriptor, UInt32 offset, UInt32 length ) 1212{ 1213 IOReturn status = kIOReturnSuccess; 1214 1215 fControl->closeGate(); 1216 1217 // 1218 // deallocate previous mapping 1219 // 1220 1221 // I obsolete the old address space even if we fail at mapping a new one 1222 // that seems like it would be the more expected behavior 1223 1224 completeBufferAddressSpace(); 1225 1226 // 1227 // bail if no memory descriptor 1228 // 1229 1230 if( memoryDescriptor == NULL ) 1231 { 1232 fControl->openGate(); 1233 1234 // IOLog( "IOFireWireSBP2ORB::setCommandBuffers status = 0x%08lx\n", status ); 1235 1236 return kIOReturnSuccess; 1237 } 1238 1239#if 0 1240 // memoryDescriptor is valid from here on 1241 1242 IOReturn check_status = checkMemoryInRange( memoryDescriptor, 0x000000001fffffff, NULL ); 1243#endif 1244 1245 // 1246 // map buffers 1247 // 1248 1249 // allocate and register an address space for the buffers 1250 1251 if( status == kIOReturnSuccess ) 1252 { 1253 status = prepareBufferAddressSpace( memoryDescriptor ); 1254 } 1255 1256#if 0 1257 if( check_status != kIOReturnSuccess ) 1258 { 1259 IOLog( "After prepare\n" ); 1260 check_status = checkMemoryInRange( memoryDescriptor, 0x000000001fffffff, fDMACommand ); 1261 IOLog( "After prepare = 0x%08lx\n", check_status ); 1262 } 1263#endif 1264 1265 // 1266 // fix up length if necessary 1267 // 1268 1269 if( status == kIOReturnSuccess ) 1270 { 1271 // use memory descriptor's length if length = 0 1272 1273 if( length == 0 ) 1274 { 1275 length = fDMACommand->getMemoryDescriptor()->getLength(); 1276 } 1277 1278#if FWLOGGING 1279 // I occasionally get memory descriptors with bogus lengths 1280 1281 UInt32 tempLength = fDMACommand->getMemoryDescriptor()->getLength(); 1282 1283 if(length != tempLength) 1284 { 1285 FWKLOG( ( "IOFireWireSBP2ORB<%p> : ### buffer length = %d, memDescriptor length = %d ###\n", this, length, tempLength ) ); 1286 // length = tempLength; 1287 } 1288#endif 1289 1290 } 1291 1292 // 1293 // write page table 1294 // 1295 1296 UInt32 pte = 0; 1297 UInt32 maxPageClipSize = kFWSBP2MaxPageClusterSize; 1298 UInt32 maxPackLog; 1299 bool clipping; 1300 UInt32 targetFlags = fLogin->fTarget->getTargetFlags(); 1301 1302 maxPackLog = calculateTransferSizeLog( &clipping ); 1303 1304 if( !(targetFlags & kIOFWSBP2DontUsePTPacketLimit) && clipping ) 1305 { 1306 switch( maxPackLog ) 1307 { 1308 case 10: 1309 maxPageClipSize = 4096; 1310 break; 1311 1312 case 9: 1313 maxPageClipSize = 2048; 1314 break; 1315 1316 case 8: 1317 maxPageClipSize = 1024; 1318 break; 1319 1320 default: 1321 maxPageClipSize = 512; 1322 break; 1323 } 1324 1325 } 1326 1327 1328 if( status == kIOReturnSuccess ) 1329 { 1330 UInt32 ptes_allocated = 0; 1331 bool done = false; 1332 1333 // algorithm is usually 1 pass, but may take 2 1334 // passes if we need to grow the page table 1335 1336 // we never shrink the page table 1337 1338 while( !done ) 1339 { 1340 ptes_allocated = fPageTableSize / sizeof(FWSBP2PTE); 1341 1342 vm_size_t pos = offset; 1343 1344 pte = 0; 1345 1346 while( pos < (length + offset) ) 1347 { 1348 UInt64 phys = 0; 1349 UInt64 lengthOfSegment = 0; 1350 1351 // get next segment 1352 1353 IODMACommand::Segment64 segment; 1354 UInt32 numSegments = 1; 1355 if( status == kIOReturnSuccess ) 1356 { 1357 UInt64 dma_pos = pos; // don't mangle pos 1358 status = fDMACommand->gen64IOVMSegments( &dma_pos, &segment, &numSegments ); 1359 // IOLog( "IOFireWireSBP2ORB::setCommandBuffers - pos = %d, status = 0x%08lx\n", pos, status ); 1360 // IOSleep( 10 ); 1361 } 1362 1363 if( status == kIOReturnSuccess ) 1364 { 1365 if( numSegments != 1 ) 1366 { 1367 status = kIOReturnNoMemory; 1368 } 1369 } 1370 1371 if( status == kIOReturnSuccess ) 1372 { 1373 phys = segment.fIOVMAddr; 1374 lengthOfSegment = segment.fLength; 1375 } 1376 1377 // nothing more to map 1378 1379 if( phys == 0 ) 1380 { 1381 status = kIOReturnBadArgument; // buffer not large enough 1382 done = true; 1383 break; 1384 } 1385 1386 // map until we are done or we run out of segment 1387 1388 // DMA command constraints should make this code unnecessary 1389 1390 while( (pos < (length + offset)) && (lengthOfSegment != 0) ) 1391 { 1392 UInt32 step = 0; 1393 UInt32 toMap = 0; 1394 1395 // 64k max page table entry, so we do it in chunks 1396 1397 if( lengthOfSegment > maxPageClipSize ) 1398 step = maxPageClipSize; 1399 else 1400 step = lengthOfSegment; 1401 1402 lengthOfSegment -= step; 1403 1404 // clip mapping by length if necessary 1405 1406 if( (pos + step) > (length + offset) ) 1407 toMap = length + offset - pos; 1408 else 1409 toMap = step; 1410 1411 // map it if we've got anything to map 1412 1413 if( toMap != 0 ) 1414 { 1415 pte++; 1416 1417 if( pte <= ptes_allocated ) 1418 { 1419 FWSBP2PTE entry; 1420 1421 entry.segmentLength = OSSwapHostToBigInt16( toMap ); 1422 entry.segmentBaseAddressHi = OSSwapHostToBigInt16( ((phys >> 32) & 0x000000000000ffffULL) ); 1423 entry.segmentBaseAddressLo = OSSwapHostToBigInt32( (phys & 0x00000000ffffffffULL) ); 1424 1425 fPageTableDescriptor->writeBytes( (pte-1) * sizeof(FWSBP2PTE), &entry, sizeof(FWSBP2PTE) ); 1426 1427 // IOLog( "IOFireWireSBP2ORB<%p> : PTE = %d, size = %d\n", this, pte-1, toMap ); 1428 1429 // FWKLOG( ( "IOFireWireSBP2ORB<%p> : PTE = %d, size = %d\n", this, pte-1, toMap ) ); 1430 } 1431 1432 // move to new page table entry and beginning of unmapped memory 1433 phys += toMap; 1434 pos += toMap; 1435 } 1436 } 1437 } 1438 1439 FWKLOG( ( "IOFireWireSBP2ORB<%p> : number of required PTE's = %d\n", this, pte ) ); 1440 1441 if( pte <= ptes_allocated ) 1442 { 1443 done = true; 1444 } 1445 else 1446 { 1447 if( fCommandFlags & kFWSBP2CommandFixedSize ) 1448 { 1449 status = kIOReturnNoMemory; 1450 done = true; 1451 } 1452 else 1453 { 1454 // reallocate 1455 status = allocatePageTable( pte ); 1456 if( status != kIOReturnSuccess ) 1457 { 1458 status = kIOReturnNoMemory; 1459 done = true; 1460 } 1461 } 1462 } 1463 } 1464 } 1465 1466 // 1467 // fill in orb 1468 // 1469 1470 if( status == kIOReturnSuccess ) 1471 { 1472 if( pte == 0 ) 1473 { 1474 // no page table 1475 fORBBuffer->dataDescriptorHi = 0; 1476 fORBBuffer->dataDescriptorLo = 0; 1477 fORBBuffer->options &= OSSwapHostToBigInt16(0xfff0); // no page table 1478 fORBBuffer->dataSize = 0; 1479 fPTECount = 0; 1480 } 1481 else 1482 { 1483 FWSBP2PTE firstEntry; 1484 1485 fPageTableDescriptor->readBytes( 0, &firstEntry, sizeof(FWSBP2PTE) ); 1486 1487 // very strictly speaking, if we don't use a page table, the buffer 1488 // must be quadlet-aligned. SBP-2 is vague about this. We'll enforce it. 1489 1490 if( pte == 1 && !(firstEntry.segmentBaseAddressLo & OSSwapHostToBigInt32(0x00000003)) ) // make sure quadlet aligned 1491 { 1492 // directly addressed buffer 1493 fORBBuffer->dataDescriptorHi = 0; // tbd later 1494 fORBBuffer->dataDescriptorLo = firstEntry.segmentBaseAddressLo; 1495 fORBBuffer->options &= OSSwapHostToBigInt16(0xfff0); // no page table 1496 fORBBuffer->dataSize = firstEntry.segmentLength; 1497 fPTECount = 0; 1498 } 1499 else if( pte * sizeof(FWSBP2PTE) <= fPageTablePhysicalLength ) 1500 { 1501 // use physical unit 1502 fORBBuffer->dataDescriptorHi = OSSwapHostToBigInt32(fPageTablePhysicalAddress.addressHi); // tbd later 1503 fORBBuffer->dataDescriptorLo = OSSwapHostToBigInt32(fPageTablePhysicalAddress.addressLo); 1504 fORBBuffer->options &= OSSwapHostToBigInt16(0xfff0); 1505 fORBBuffer->options |= OSSwapHostToBigInt16(0x0008); // unrestricted page table 1506 fORBBuffer->dataSize = OSSwapHostToBigInt16(pte); 1507 fPTECount = pte; 1508 } 1509 else 1510 { 1511 // use software address space 1512 fORBBuffer->dataDescriptorHi = OSSwapHostToBigInt32(fPageTablePseudoAddress.addressHi); // tbd later 1513 fORBBuffer->dataDescriptorLo = OSSwapHostToBigInt32(fPageTablePseudoAddress.addressLo); 1514 fORBBuffer->options &= OSSwapHostToBigInt16(0xfff0); 1515 fORBBuffer->options |= OSSwapHostToBigInt16(0x0008); // unrestricted page table 1516 fORBBuffer->dataSize = OSSwapHostToBigInt16(pte); 1517 fPTECount = pte; 1518 } 1519 } 1520 } 1521 1522 if( status != kIOReturnSuccess ) 1523 { 1524 completeBufferAddressSpace(); 1525 } 1526 1527 fControl->openGate(); 1528 1529// IOLog( "IOFireWireSBP2ORB::setCommandBuffers return status = 0x%08lx\n", status ); 1530 1531 return status; 1532} 1533 1534// getCommandBufferDesceiptor 1535// 1536// 1537 1538IOMemoryDescriptor * IOFireWireSBP2ORB::getCommandBufferDescriptor( void ) 1539{ 1540 return fBufferDescriptor; 1541} 1542 1543///////////////////////////////////////////////////////////////////// 1544// command block 1545// 1546 1547// setCommandBlock 1548// 1549// set the command block portion of the orb with buffer and length 1550 1551IOReturn IOFireWireSBP2ORB::setCommandBlock( void * buffer, UInt32 length ) 1552{ 1553 fControl->closeGate(); 1554 1555 UInt32 maxCommandBlockSize = fLogin->getMaxCommandBlockSize(); 1556 1557 if( length > maxCommandBlockSize ) 1558 return kIOReturnNoMemory; 1559 1560 bzero( &fORBBuffer->commandBlock[0], maxCommandBlockSize ); 1561 bcopy( buffer, &fORBBuffer->commandBlock[0], length ); 1562 1563 fControl->openGate(); 1564 1565 return kIOReturnSuccess; 1566} 1567 1568// setCommandBlock 1569// 1570// set the command block portion of the orb with memory descriptor 1571 1572IOReturn IOFireWireSBP2ORB::setCommandBlock( IOMemoryDescriptor * memory ) 1573{ 1574 fControl->closeGate(); 1575 1576 UInt32 maxCommandBlockSize = fLogin->getMaxCommandBlockSize(); 1577 IOByteCount length = memory->getLength(); 1578 1579 if( length > maxCommandBlockSize ) 1580 return kIOReturnNoMemory; 1581 1582 bzero( &fORBBuffer->commandBlock[0], maxCommandBlockSize ); 1583 memory->readBytes(0, &fORBBuffer->commandBlock[0], length ); 1584 1585 fControl->openGate(); 1586 1587 return kIOReturnSuccess; 1588} 1589 1590///////////////////////////////////////////////////////////////////// 1591// accessors 1592// 1593 1594void IOFireWireSBP2ORB::setCommandFlags( UInt32 flags ) 1595{ 1596 fCommandFlags = flags; 1597} 1598 1599UInt32 IOFireWireSBP2ORB::getCommandFlags( void ) 1600{ 1601 return fCommandFlags; 1602} 1603 1604// get / set refCon 1605 1606void IOFireWireSBP2ORB::setRefCon( void * refCon ) 1607{ 1608 fRefCon = (UInt64)refCon; 1609} 1610 1611void * IOFireWireSBP2ORB::getRefCon( void ) 1612{ 1613 return (void*)fRefCon; 1614} 1615 1616// get / set refCon 64 1617 1618void IOFireWireSBP2ORB::setRefCon64( UInt64 refCon ) 1619{ 1620 fRefCon = refCon; 1621} 1622 1623UInt64 IOFireWireSBP2ORB::getRefCon64( void ) 1624{ 1625 return fRefCon; 1626} 1627 1628// get / set max payload size 1629 1630void IOFireWireSBP2ORB::setMaxPayloadSize( UInt32 maxPayloadSize ) 1631{ 1632 fMaxPayloadSize = maxPayloadSize; 1633} 1634 1635UInt32 IOFireWireSBP2ORB::getMaxPayloadSize( void ) 1636{ 1637 return fMaxPayloadSize; 1638} 1639 1640// get / set command timeout 1641 1642void IOFireWireSBP2ORB::setCommandTimeout( UInt32 timeout ) 1643{ 1644 IOReturn ORBTimeoutReinitStatus; 1645 1646 fControl->closeGate(); 1647 1648 fTimeoutDuration = timeout; 1649 ORBTimeoutReinitStatus = fTimeoutCommand->reinit( fTimeoutDuration * 1000, IOFireWireSBP2ORB::orbTimeoutStatic, this ); 1650 1651 //zzz perhaps this should pass error back to user 1652 FWPANICASSERT( ORBTimeoutReinitStatus == kIOReturnSuccess ); 1653 1654 fControl->openGate(); 1655} 1656 1657UInt32 IOFireWireSBP2ORB::getCommandTimeout( void ) 1658{ 1659 return fTimeoutDuration; 1660} 1661 1662// get / set command generation 1663 1664void IOFireWireSBP2ORB::setCommandGeneration( UInt32 gen ) 1665{ 1666 fGeneration = gen; 1667} 1668 1669UInt32 IOFireWireSBP2ORB::getCommandGeneration( void ) 1670{ 1671 return fGeneration; 1672} 1673 1674// returns the ORB address 1675 1676void IOFireWireSBP2ORB::getORBAddress( FWAddress * address ) 1677{ 1678 if( fCommandFlags & kFWSBP2CommandVirtualORBs ) 1679 { 1680 *address = fORBPseudoAddress; 1681 } 1682 else 1683 { 1684 *address = fORBPhysicalAddress; 1685 } 1686} 1687 1688// sets the address of the next ORB field 1689void IOFireWireSBP2ORB::setNextORBAddress( FWAddress address ) 1690{ 1691 fORBBuffer->nextORBAddressHi = OSSwapHostToBigInt32((UInt32)address.addressHi); 1692 fORBBuffer->nextORBAddressLo = OSSwapHostToBigInt32(address.addressLo); 1693} 1694 1695// get login 1696IOFireWireSBP2Login * IOFireWireSBP2ORB::getLogin( void ) 1697{ 1698 return fLogin; 1699} 1700 1701void IOFireWireSBP2ORB::setToDummy( void ) 1702{ 1703 // set rq_fmt to 3 (NOP) in case it wasn't fetched yet 1704 fORBBuffer->options |= OSSwapHostToBigInt16(0x6000); 1705} 1706 1707bool IOFireWireSBP2ORB::isAppended( void ) 1708{ 1709 return fIsAppended; 1710} 1711 1712void IOFireWireSBP2ORB::setIsAppended( bool state ) 1713{ 1714 fIsAppended = state; 1715} 1716 1717UInt32 IOFireWireSBP2ORB::getFetchAgentWriteRetries( void ) 1718{ 1719 return fFetchAgentWriteRetries; 1720} 1721 1722void IOFireWireSBP2ORB::setFetchAgentWriteRetries( UInt32 retries ) 1723{ 1724 fFetchAgentWriteRetries = retries; 1725} 1726 1727// getFetchAgentWriteRetryInterval 1728// 1729// 1730 1731UInt32 IOFireWireSBP2ORB::getFetchAgentWriteRetryInterval( void ) 1732{ 1733 return fFetchAgentWriteRetryInterval; 1734} 1735 1736// setFetchAgentWriteRetryInterval 1737// 1738// 1739 1740void IOFireWireSBP2ORB::setFetchAgentWriteRetryInterval( UInt32 interval ) 1741{ 1742 fFetchAgentWriteRetryInterval = interval; 1743} 1744 1745////////////////////////////////////////////////////////////////////////////////////////// 1746// friend class wrappers 1747 1748// login friend class wrappers 1749 1750IOFireWireUnit * IOFireWireSBP2ORB::getFireWireUnit( void ) 1751{ 1752 return fLogin->getFireWireUnit(); 1753} 1754 1755IOFireWireSBP2LUN * IOFireWireSBP2ORB::getFireWireLUN( void ) 1756{ 1757 return fLogin->getFireWireLUN(); 1758} 1759 1760IOReturn IOFireWireSBP2ORB::removeORB( IOFireWireSBP2ORB * orb ) 1761{ 1762 return fLogin->removeORB( orb ); 1763} 1764 1765void IOFireWireSBP2ORB::sendTimeoutNotification( IOFireWireSBP2ORB * orb ) 1766{ 1767 fLogin->sendTimeoutNotification( orb ); 1768} 1769