1/* 2 * Copyright (c) 2003 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/IOLib.h> 24#include <IOKit/firewire/IOFireWireController.h> 25#include <IOKit/firewire/IOLocalConfigDirectory.h> 26 27#include <IOKit/avc/IOFireWireAVCConsts.h> 28#include <IOKit/avc/IOFireWireAVCTargetSpace.h> 29 30#define AVCTARGETMUTEX_LOCK fController->closeGate() 31#define AVCTARGETMUTEX_UNLOCK fController->openGate() 32 33// Local Prototypes 34static void AVCTargetSendAVCResponseComplete(void *refcon, IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd); 35 36OSDefineMetaClassAndStructors(AVCCommandHandlerInfo, OSObject) 37OSDefineMetaClassAndStructors(AVCSubunitInfo, OSObject) 38OSDefineMetaClassAndStructors(UCInfo, OSObject) 39OSDefineMetaClassAndStructors(AVCConnectionRecord, OSObject) 40 41////////////////////////////////////////////////////// 42// AVCSubunitInfo::create 43////////////////////////////////////////////////////// 44AVCSubunitInfo *AVCSubunitInfo::create() 45{ 46 AVCSubunitInfo * subUnitInfo; 47 48 subUnitInfo = new AVCSubunitInfo; 49 50 if( subUnitInfo != NULL && !subUnitInfo->init()) 51 { 52 subUnitInfo->release(); 53 subUnitInfo = NULL; 54 } 55 56 return subUnitInfo; 57} 58 59////////////////////////////////////////////////////// 60// AVCSubunitInfo::init 61////////////////////////////////////////////////////// 62bool AVCSubunitInfo::init() 63{ 64 bool success = true; 65 66 //IOLog( "AVCSubunitInfo::init (0x%08X)\n",(int) this); 67 68 // init super 69 if( !OSObject::init() ) 70 success = false; 71 72 if( success ) 73 { 74 // Initialize this object 75 } 76 77 return success; 78} 79 80////////////////////////////////////////////////////// 81// AVCSubunitInfo::free 82////////////////////////////////////////////////////// 83void AVCSubunitInfo::free() 84{ 85 //IOLog( "AVCSubunitInfo::free (0x%08X)\n",(int) this); 86 87 if (sourcePlugRecords) 88 delete[] sourcePlugRecords; 89 90 if (destPlugRecords) 91 delete[] destPlugRecords; 92 93 OSObject::free(); 94} 95 96OSDefineMetaClassAndStructors(IOFireWireAVCTargetSpace, IOFWPseudoAddressSpace) 97OSMetaClassDefineReservedUnused(IOFireWireAVCTargetSpace, 0); 98OSMetaClassDefineReservedUnused(IOFireWireAVCTargetSpace, 1); 99OSMetaClassDefineReservedUnused(IOFireWireAVCTargetSpace, 2); 100OSMetaClassDefineReservedUnused(IOFireWireAVCTargetSpace, 3); 101 102////////////////////////////////////////////////////// 103// AVCTargetSendAVCResponseComplete 104////////////////////////////////////////////////////// 105void AVCTargetSendAVCResponseComplete(void *refcon, IOReturn status, IOFireWireNub *device, IOFWCommand *fwCmd) 106{ 107 //IOLog( "AVCTargetSendAVCResponseComplete Command=0x%08X Status=0x%08X\n",(int)fwCmd,status); 108 109 IOBufferMemoryDescriptor *pBufMemDesc = (IOBufferMemoryDescriptor*) refcon; 110 111 // Free the command and the associated memory descriptor 112 if(fwCmd) 113 fwCmd->release(); 114 if(pBufMemDesc) 115 pBufMemDesc->release(); 116} 117 118////////////////////////////////////////////////////// 119// IOFireWireAVCTargetSpace::init 120////////////////////////////////////////////////////// 121bool IOFireWireAVCTargetSpace::init(IOFireWireController *controller) 122{ 123 //IOLog( "IOFireWireAVCTargetSpace::init (0x%08X)\n",(int) this); 124 125 126 if(!IOFWPseudoAddressSpace::initFixed(controller, 127 FWAddress(kCSRRegisterSpaceBaseAddressHi, kFCPCommandAddress), 128 512, NULL, NULL, this)) 129 return false; 130 131 // Save the pointer to the bus 132 fController = controller; 133 134 return true; 135} 136 137////////////////////////////////////////////////////// 138// IOFireWireAVCTargetSpace::getAVCTargetSpace 139////////////////////////////////////////////////////// 140IOFireWireAVCTargetSpace * IOFireWireAVCTargetSpace::getAVCTargetSpace(IOFireWireController *controller) 141{ 142 IOFWAddressSpace *existing; 143 IOFireWireAVCTargetSpace *space; 144 145 //IOLog( "IOFireWireAVCTargetSpace::getAVCTargetSpace\n"); 146 147 existing = controller->getAddressSpace(FWAddress(kCSRRegisterSpaceBaseAddressHi, kFCPCommandAddress)); 148 if(existing && OSDynamicCast(IOFireWireAVCTargetSpace, existing)) { 149 existing->retain(); 150 return OSDynamicCast(IOFireWireAVCTargetSpace, existing); 151 } 152 space = new IOFireWireAVCTargetSpace; 153 if(space) { 154 if(!space->init(controller)) { 155 space->release(); 156 space = NULL; 157 } 158 } 159 return space; 160} 161 162////////////////////////////////////////////////////// 163// IOFireWireAVCTargetSpace::doWrite 164////////////////////////////////////////////////////// 165UInt32 IOFireWireAVCTargetSpace::doWrite(UInt16 nodeID, IOFWSpeed &speed, FWAddress addr, UInt32 len, 166 const void *buf, IOFWRequestRefCon refcon) 167{ 168 UInt32 generation = fController->getGeneration(); 169 UInt8 cts; 170 UInt8 *pBuf = (UInt8*) buf; 171 172 //IOLog( "IOFireWireAVCTargetSpace::doWrite (0x%08X)\n",(int) this); 173 174 if(addr.addressHi != kCSRRegisterSpaceBaseAddressHi) 175 return kFWResponseAddressError; 176 if(addr.addressLo != kFCPCommandAddress) 177 return kFWResponseAddressError; 178 179 // Make sure this is an AVC command (CTS is 0) 180 cts = ((pBuf[0] & 0xF0) >> 4); 181 if (cts != 0) 182 return kFWResponseAddressError; 183 184 // Find a handler for this command, or send not implemented response 185 findAVCRequestHandler(NULL,generation,nodeID,speed,0xFFFFFFFF,(const char *) pBuf,len); 186 187 return kFWResponseComplete; 188} 189 190////////////////////////////////////////////////////// 191// IOFireWireAVCTargetSpace::findAVCRequestHandler 192////////////////////////////////////////////////////// 193IOReturn IOFireWireAVCTargetSpace::findAVCRequestHandler(IOFireWireAVCProtocolUserClient *userClient, 194 UInt32 generation, 195 UInt16 nodeID, 196 IOFWSpeed speed, 197 UInt32 handlerSearchIndex, 198 const char *pCmdBuf, 199 UInt32 cmdLen) 200{ 201 UInt32 currentGeneration = fController->getGeneration(); 202 UInt8 subUnit; 203 UInt8 opCode; 204 UInt8 *pResponse; 205 bool handled = false; 206 IOBufferMemoryDescriptor *pBufMemDesc = NULL; 207 int i; 208 int firstIndex; 209 210 // Parse the command a bit 211 subUnit = pCmdBuf[1]; 212 opCode = pCmdBuf[2]; 213 214 //IOLog( "IOFireWireAVCTargetSpace::findAVCRequestHandler (0x%08X) subUnit=%02X opCode=%02X\n",(int) this,subUnit,opCode); 215 216 // See if we are still in the same bus generation as the command 217 if (currentGeneration != generation) 218 return kIOFireWireBusReset; 219 220 AVCTARGETMUTEX_LOCK; 221 222 if (handlerSearchIndex == 0xFFFFFFFF) 223 firstIndex = (fCommandHandlers->getCount()-1); 224 else 225 { 226 firstIndex = handlerSearchIndex - 1; 227 228 // Make sure that we don't index to a command handler record that doesn't exist 229 if (firstIndex >= (int) fCommandHandlers->getCount()) 230 firstIndex = (fCommandHandlers->getCount()-1); 231 } 232 233 // First, search the array of registered command handlers 234 for (i=firstIndex;i>=0;i--) 235 { 236 AVCCommandHandlerInfo *cmdInfo; 237 cmdInfo = (AVCCommandHandlerInfo*) fCommandHandlers->getObject(i); 238 239 if ( ((cmdInfo->subUnitTypeAndID == subUnit) && (cmdInfo->opCode == opCode)) || 240 ((cmdInfo->subUnitTypeAndID == subUnit) && (cmdInfo->opCode == kAVCAllOpcodes)) || 241 ((cmdInfo->subUnitTypeAndID == kAVCAllSubunitsAndUnit) && (cmdInfo->opCode == opCode)) || 242 ((cmdInfo->subUnitTypeAndID == kAVCAllSubunitsAndUnit) && (cmdInfo->opCode == kAVCAllOpcodes))) 243 { 244 // Call back the command's handler to pass the command up to user space 245 cmdInfo->callBack(cmdInfo,generation,nodeID,pCmdBuf,cmdLen,speed,i); 246 handled = true; 247 break; 248 } 249 } 250 251 // If not hadled by registered handler, try and Find an Internall Command Handler for this command 252 if ((!handled) && (subUnit == 0xFF)) 253 { 254 // See if we have an internal unit command handler for this opcode 255 switch (opCode) 256 { 257 case kAVCUnitInfoOpcode: 258 if (handleUnitInfoCommand(nodeID, generation, pCmdBuf, cmdLen) == kIOReturnSuccess) 259 handled = true; 260 break; 261 262 case kAVCSubunitInfoOpcode: 263 if (handleSubUnitInfoCommand(nodeID, generation, pCmdBuf, cmdLen) == kIOReturnSuccess) 264 handled = true; 265 break; 266 267 case kAVCPowerOpcode: 268 if (handlePowerCommand(nodeID, generation, pCmdBuf, cmdLen) == kIOReturnSuccess) 269 handled = true; 270 break; 271 272 case kAVCConnectOpcode: 273 if (handleConnectCommand(nodeID, generation, pCmdBuf, cmdLen) == kIOReturnSuccess) 274 handled = true; 275 break; 276 277 case kAVCDisconnectOpcode: 278 if (handleDisconnectCommand(nodeID, generation, pCmdBuf, cmdLen) == kIOReturnSuccess) 279 handled = true; 280 break; 281 282 case kAVCInputPlugSignalFormatOpcode: 283 if (handleInputPlugSignalFormatCommand(nodeID, generation, pCmdBuf, cmdLen) == kIOReturnSuccess) 284 handled = true; 285 break; 286 287 case kAVCOutputPlugSignalFormatOpcode: 288 if (handleOutputPlugSignalFormatCommand(nodeID, generation, pCmdBuf, cmdLen) == kIOReturnSuccess) 289 handled = true; 290 break; 291 292 case kAVCConnectionsOpcode: 293 if (handleConnectionsCommand(nodeID, generation, pCmdBuf, cmdLen) == kIOReturnSuccess) 294 handled = true; 295 break; 296 297 case kAVCSignalSourceOpcode: 298 if (handleSignalSourceCommand(nodeID, generation, pCmdBuf, cmdLen) == kIOReturnSuccess) 299 handled = true; 300 break; 301 302 default: 303 break; 304 }; 305 } 306 307 if ((!handled) && (opCode == kAVCPlugInfoOpcode)) 308 { 309 // Internally handle the Plug Info command for the unit and all subunits 310 if (handlePlugInfoCommand(nodeID, generation, pCmdBuf, cmdLen) == kIOReturnSuccess) 311 handled = true; 312 } 313 314 // If not handled, send a Not Implemented Response 315 if (!handled) 316 { 317 //IOLog("DEBUG: findAVCRequestHandler found no handler for command!\n"); 318 pBufMemDesc = IOBufferMemoryDescriptor::withCapacity(cmdLen, kIODirectionOutIn); 319 if(!pBufMemDesc) 320 { 321 AVCTARGETMUTEX_UNLOCK; 322 return kFWResponseDataError; 323 } 324 pResponse = (UInt8 *) pBufMemDesc->getBytesNoCopy(); 325 bcopy(pCmdBuf,pResponse,cmdLen); 326 pResponse[kAVCCommandResponse] = kAVCNotImplementedStatus; // Not Implemented 327 targetSendAVCResponse(generation, nodeID, pBufMemDesc, cmdLen); 328 } 329 330 AVCTARGETMUTEX_UNLOCK; 331 332 return kIOReturnSuccess; 333} 334 335////////////////////////////////////////////////////// 336// IOFireWireAVCTargetSpace::activateWithUserClient 337////////////////////////////////////////////////////// 338IOReturn IOFireWireAVCTargetSpace::activateWithUserClient(IOFireWireAVCProtocolUserClient *userClient) 339{ 340 IOReturn res = kIOReturnSuccess; 341 UCInfo *uc; 342 UInt32 i; 343 344 //IOLog( "IOFireWireAVCTargetSpace::activateWithUserClient (0x%08X)\n",(int) this); 345 346 if(!fActivations++) 347 { 348 fUserClients = OSArray::withCapacity(1); 349 fCommandHandlers = OSArray::withCapacity(1); 350 fSubunits = OSArray::withCapacity(1); 351 fConnectionRecords = OSArray::withCapacity(1); 352 353 // Setup Unit plug management 354 fUnitPlugs.numIsochInPlugs = kAVCMaxNumPlugs; 355 fUnitPlugs.numIsochOutPlugs = kAVCMaxNumPlugs; 356 fUnitPlugs.numExternalInPlugs = kAVCMaxNumPlugs; 357 fUnitPlugs.numExternalOutPlugs = kAVCMaxNumPlugs; 358 for (i=0;i<kAVCMaxNumPlugs;i++) 359 { 360 fUnitPlugs.isochInPlugRecord[i].connectionCount = 0; 361 fUnitPlugs.isochOutPlugRecord[i].connectionCount = 0; 362 fUnitPlugs.externalInPlugRecord[i].connectionCount = 0; 363 fUnitPlugs.externalOutPlugRecord[i].connectionCount = 0; 364 } 365 366#if 0 367 // Create the lock to protect data structures 368 fLock = IORecursiveLockAlloc(); 369#endif 370 371 res = IOFWAddressSpace::activate(); 372 } 373 374 // Save User Client pointer in array 375 uc = new UCInfo; 376 if(!uc) 377 return kIOReturnNoMemory; 378 uc->fUserClient = userClient; 379 if(!fUserClients->setObject(uc)) 380 return kIOReturnNoMemory; 381 uc->release(); 382 //IOLog( "DEBUG: activateWithUserClient added client to array (0x%08X)\n",(int) userClient); 383 384 385 return res; 386} 387 388////////////////////////////////////////////////////// 389// IOFireWireAVCTargetSpace::deactivateWithUserClient 390////////////////////////////////////////////////////// 391void IOFireWireAVCTargetSpace::deactivateWithUserClient(IOFireWireAVCProtocolUserClient *userClient) 392{ 393 IOReturn res = kIOReturnSuccess; 394 int i,j; 395 UCInfo *uc; 396 AVCConnectionRecord *connection; 397 AVCSubunitInfo *subUnitInfo; 398 AVCSubunitInfo *connectedSubUnitInfo; 399 bool avcResourcesFreed = false; 400 UInt32 subunitTypeAndID; 401 402 //IOLog( "IOFireWireAVCTargetSpace::deactivateWithUserClient (0x%08X)\n",(int) this); 403 404 AVCTARGETMUTEX_LOCK; 405 406 // Free any allocated command handlers for this user client 407 for (i=(fCommandHandlers->getCount()-1);i>=0;i--) 408 { 409 AVCCommandHandlerInfo *cmdInfo; 410 cmdInfo = (AVCCommandHandlerInfo*) fCommandHandlers->getObject(i); 411 if(cmdInfo->userClient == userClient) 412 { 413 fCommandHandlers->removeObject(i); 414 //IOLog( "DEBUG: deactivateWithUserClient found cmd handler to remove (0x%08X)\n",(int) userClient); 415 } 416 } 417 418 // Free any allocated subunits for this user client 419 for (i=(fSubunits->getCount()-1);i>=0;i--) 420 { 421 subUnitInfo = (AVCSubunitInfo*) fSubunits->getObject(i); 422 if(subUnitInfo->userClient == userClient) 423 { 424 subunitTypeAndID = subUnitInfo->subunitTypeAndID; 425 426 // Disconnect all plugs on this subunit 427 for (j=(fConnectionRecords->getCount()-1);j>=0;j--) 428 { 429 connection = (AVCConnectionRecord*) fConnectionRecords->getObject(j); 430 431 // See if this connection record is for this subunit 432 if ((connection->sourceSubunitTypeAndID == subunitTypeAndID) || 433 (connection->destSubunitTypeAndID == subunitTypeAndID)) 434 { 435 if (connection->sourceSubunitTypeAndID != subunitTypeAndID) 436 { 437 switch (connection->sourcePlugType) 438 { 439 case IOFWAVCPlugIsochInputType: 440 fUnitPlugs.isochInPlugRecord[connection->sourcePlugNum].connectionCount--; 441 break; 442 case IOFWAVCPlugExternalInputType: 443 fUnitPlugs.externalInPlugRecord[connection->sourcePlugNum - 0x80].connectionCount--; 444 break; 445 case IOFWAVCPlugSubunitSourceType: 446 connectedSubUnitInfo = getSubunitInfo(connection->sourceSubunitTypeAndID); 447 if (connectedSubUnitInfo) 448 { 449 connectedSubUnitInfo->sourcePlugRecords[connection->sourcePlugNum].connectionCount--; 450 451 // If the connected plug is a subunit plug, and this 452 // user client doesn't own that subunit, notify the owner 453 // of the plug's disconnection 454 if (connectedSubUnitInfo->userClient != userClient) 455 connectedSubUnitInfo->callBack(connectedSubUnitInfo, 456 kIOFWAVCSubunitPlugMsgDisconnected, 457 connection->sourcePlugType, 458 connection->sourcePlugNum, 459 ((connection->destSubunitTypeAndID << 16) + (connection->destPlugType << 8) + connection->destPlugNum), 460 0,0); 461 } 462 break; 463 default: 464 break; 465 }; 466 467 } 468 469 if (connection->destSubunitTypeAndID != subunitTypeAndID) 470 { 471 switch (connection->destPlugType) 472 { 473 case IOFWAVCPlugIsochOutputType: 474 fUnitPlugs.isochOutPlugRecord[connection->destPlugNum].connectionCount--; 475 break; 476 case IOFWAVCPlugExternalOutputType: 477 fUnitPlugs.externalOutPlugRecord[connection->destPlugNum - 0x80].connectionCount--; 478 break; 479 case IOFWAVCPlugSubunitDestType: 480 connectedSubUnitInfo = getSubunitInfo(connection->destSubunitTypeAndID); 481 if (connectedSubUnitInfo) 482 { 483 connectedSubUnitInfo->destPlugRecords[connection->destPlugNum].connectionCount--; 484 485 // If the connected plug is a subunit plug, and this 486 // user client doesn't own that subunit, notify the owner 487 // of the plug's disconnection 488 if (connectedSubUnitInfo->userClient != userClient) 489 connectedSubUnitInfo->callBack(connectedSubUnitInfo, 490 kIOFWAVCSubunitPlugMsgDisconnected, 491 connection->destPlugType, 492 connection->destPlugNum, 493 ((connection->sourceSubunitTypeAndID << 16) + (connection->sourcePlugType << 8) + connection->sourcePlugNum), 494 0,0); 495 } 496 break; 497 default: 498 break; 499 }; 500 } 501 502 // Remove this connection record 503 fConnectionRecords->removeObject(j); 504 } 505 } 506 507 fSubunits->removeObject(i); 508 //IOLog( "DEBUG: deactivateWithUserClient found subunit to remove (0x%08X)\n",(int) userClient); 509 510 avcResourcesFreed = true; 511 } 512 } 513 514 // Find this user client in the user client array, and remove it 515 for (i=(fUserClients->getCount()-1);i>=0;i--) 516 { 517 uc = (UCInfo *)fUserClients->getObject(i); 518 if(uc->fUserClient == userClient) 519 { 520 fUserClients->removeObject(i); 521 //IOLog( "DEBUG: deactivateWithUserClient found client to remove (0x%08X)\n",(int) userClient); 522 } 523 } 524 525 // Decrement activations count 526 fActivations -= 1; 527 528 // If there is only one activation left, get the user-client info for it. 529 if (fActivations == 1) 530 uc = (UCInfo *)fUserClients->getObject(0); 531 532 AVCTARGETMUTEX_UNLOCK; 533 534 // If we are down to no activations, or if we have one remaining activation 535 // and it is the IOFireWirePCRSpace's activation, remove the AVC unit 536 // directory, if it exists. 537 if ((fActivations == 0) || ((fActivations == 1) && (uc->fUserClient == (IOFireWireAVCProtocolUserClient*)0xFFFFFFFF))) 538 { 539 // If we've published an AVC Unit directory, now's the time to remove it 540 if (fAVCLocalConfigDirectory) 541 { 542 res = fController->RemoveUnitDirectory(fAVCLocalConfigDirectory) ; 543 544 // Release the fAVCLocalConfigDirectory object 545 fAVCLocalConfigDirectory->release(); 546 fAVCLocalConfigDirectory = NULL; 547 } 548 } 549 else if (avcResourcesFreed == true) 550 fController->resetBus(); 551 552 if (fActivations == 0) 553 { 554 555#if 0 556 // Release the lock 557 if (fLock) 558 IORecursiveLockFree(fLock); 559#endif 560 561 // Release the OSArrays 562 fUserClients->release(); 563 fCommandHandlers->release(); 564 fSubunits->release(); 565 fConnectionRecords->release(); 566 567 IOFWAddressSpace::deactivate(); 568 } 569} 570 571////////////////////////////////////////////////////// 572// IOFireWireAVCTargetSpace::publishAVCUnitDirectory 573////////////////////////////////////////////////////// 574IOReturn IOFireWireAVCTargetSpace::publishAVCUnitDirectory(void) 575{ 576 //IOLog( "IOFireWireAVCTargetSpace::publishAVCUnitDirectory (0x%08X)\n",(int) this); 577 578 IOReturn res = kIOReturnSuccess; 579 580 AVCTARGETMUTEX_LOCK; 581 582 // Only do this once. 583 if (!fAVCLocalConfigDirectory) 584 { 585 // Create entries for UnitSpecID and UnitSwVersion 586 fAVCLocalConfigDirectory = IOLocalConfigDirectory::create(); 587 588 if (!fAVCLocalConfigDirectory) 589 { 590 res = kIOReturnError; 591 } 592 593 AVCTARGETMUTEX_UNLOCK; 594 595 if(res == kIOReturnSuccess) 596 res = fAVCLocalConfigDirectory->addEntry(0x12,0xA02D) ; 597 598 if(res == kIOReturnSuccess) 599 res = fAVCLocalConfigDirectory->addEntry(0x13,0x10001) ; 600 601 // lets publish it 602 if(res == kIOReturnSuccess) 603 res = fController->AddUnitDirectory(fAVCLocalConfigDirectory) ; 604 } 605 else 606 { 607 AVCTARGETMUTEX_UNLOCK; 608 609 // The AVC Unit directory already exists, so just do a bus reset now. 610 fController->resetBus(); 611 } 612 613 // end of unit directory addition 614 return res; 615} 616 617////////////////////////////////////////////////////// 618// IOFireWireAVCTargetSpace::targetSendAVCResponse 619////////////////////////////////////////////////////// 620IOReturn 621IOFireWireAVCTargetSpace::targetSendAVCResponse(UInt32 generation, UInt16 nodeID, IOBufferMemoryDescriptor *pBufMemDesc, UInt32 size) 622{ 623 //IOLog( "IOFireWireAVCTargetSpace::targetSendAVCResponse (0x%08X)\n",(int) this); 624 625 IOFWWriteCommand *cmd = NULL; 626 IOReturn status; 627 do { 628 cmd = new IOFWWriteCommand; 629 if(!cmd) { 630 status = kIOReturnNoMemory; 631 break; 632 } 633 if(!cmd->initAll(fController, generation, 634 FWAddress(kCSRRegisterSpaceBaseAddressHi, kFCPResponseAddress, nodeID), 635 pBufMemDesc, AVCTargetSendAVCResponseComplete, pBufMemDesc)) { 636 status = kIOReturnNoMemory; 637 break; 638 } 639 status = cmd->submit(true); 640 } while (false); 641 642 return status; 643} 644 645////////////////////////////////////////////////////// 646// IOFireWireAVCTargetSpace::installAVCCommandHandler 647////////////////////////////////////////////////////// 648IOReturn IOFireWireAVCTargetSpace::installAVCCommandHandler(IOFireWireAVCProtocolUserClient *userClient, 649 IOFireWireAVCTargetCommandHandlerCallback callBack, 650 OSAsyncReference64 asyncRef, 651 UInt32 subUnitTypeAndID, 652 UInt32 opCode, 653 uint64_t userCallBack, 654 uint64_t userRefCon) 655{ 656 IOReturn res = kIOReturnSuccess; 657 AVCCommandHandlerInfo *cmdInfo; 658 659 //IOLog( "IOFireWireAVCTargetSpace::installAVCCommandHandler (0x%08X)\n",(int) this); 660 661 cmdInfo = new AVCCommandHandlerInfo; 662 if(!cmdInfo) 663 return kIOReturnNoMemory; 664 665 cmdInfo->userClient = userClient; 666 cmdInfo->callBack = callBack; 667 bcopy(asyncRef, cmdInfo->asyncRef, sizeof(OSAsyncReference64)); 668 cmdInfo->subUnitTypeAndID = subUnitTypeAndID; 669 cmdInfo->opCode = opCode; 670 cmdInfo->userCallBack = userCallBack; 671 cmdInfo->userRefCon = userRefCon; 672 673 AVCTARGETMUTEX_LOCK; 674 675 // Save command handler info in array 676 if(!fCommandHandlers->setObject(cmdInfo)) 677 res = kIOReturnNoMemory; 678 else 679 { 680 //IOLog( "DEBUG: installAVCCommandHandler added cmd handler to array (0x%08X)\n",(int) userClient); 681 } 682 683 AVCTARGETMUTEX_UNLOCK; 684 685 cmdInfo->release(); 686 687 return res; 688} 689 690////////////////////////////////////////////////////// 691// IOFireWireAVCTargetSpace::addSubunit 692////////////////////////////////////////////////////// 693IOReturn IOFireWireAVCTargetSpace::addSubunit(IOFireWireAVCProtocolUserClient *userClient, 694 IOFireWireAVCSubunitPlugHandlerCallback callBack, 695 OSAsyncReference64 asyncRef, 696 UInt32 subunitType, 697 UInt32 numSourcePlugs, 698 UInt32 numDestPlugs, 699 uint64_t userCallBack, 700 uint64_t userRefCon, 701 UInt32 *subUnitID) 702{ 703 IOReturn res = kIOReturnSuccess; 704 AVCSubunitInfo *subUnitInfo; 705 UInt32 count; 706 UInt32 i; 707 708 //IOLog( "IOFireWireAVCTargetSpace::addSubunit (0x%08X)\n",(int) this); 709 710 AVCTARGETMUTEX_LOCK; 711 712 // Make sure that we don't have too many 713 // subunits already, or too many of the specified type 714 if (fSubunits->getCount() >= 32) 715 res = kIOReturnNoResources; 716 count = subUnitOfTypeCount(subunitType); 717 if (count >= 4) 718 res = kIOReturnNoResources; 719 720 // Create a new subunit info object 721 if (res == kIOReturnSuccess) 722 { 723 subUnitInfo = AVCSubunitInfo::create(); 724 if(!subUnitInfo) 725 res = kIOReturnNoMemory; 726 else 727 { 728 // Initialize the new object's parameters 729 subUnitInfo->userClient = userClient; 730 subUnitInfo->callBack = callBack; 731 bcopy(asyncRef, subUnitInfo->asyncRef, sizeof(OSAsyncReference64)); 732 subUnitInfo->numSourcePlugs = numSourcePlugs; 733 subUnitInfo->numDestPlugs = numDestPlugs; 734 subUnitInfo->userCallBack = userCallBack; 735 subUnitInfo->userRefCon = userRefCon; 736 737 // Allocate the plug records for the source plugs 738 if (numSourcePlugs) 739 { 740 subUnitInfo->sourcePlugRecords = new AVCSubunitPlugRecord[numSourcePlugs]; 741 for (i=0;i<numSourcePlugs;i++) 742 { 743 subUnitInfo->sourcePlugRecords[i].connectionCount = 0; 744 subUnitInfo->sourcePlugRecords[i].plugSignalFormat = kAVCPlugSignalFormatNTSCDV; 745 } 746 } 747 else 748 subUnitInfo->sourcePlugRecords = NULL; 749 750 // Allocate the plug records for the destination plugs 751 if (numDestPlugs) 752 { 753 subUnitInfo->destPlugRecords = new AVCSubunitPlugRecord[numDestPlugs]; 754 for (i=0;i<numDestPlugs;i++) 755 { 756 subUnitInfo->destPlugRecords[i].connectionCount = 0; 757 subUnitInfo->destPlugRecords[i].plugSignalFormat = kAVCPlugSignalFormatNTSCDV; 758 } 759 } 760 else 761 subUnitInfo->destPlugRecords = NULL; 762 763 // Determine the ID for this subunit 764 subUnitInfo->subunitTypeAndID = (subunitType << 3) + count; 765 766 // Save command handler info in array 767 if(!fSubunits->setObject(subUnitInfo)) 768 res = kIOReturnNoMemory; 769 else 770 { 771 //IOLog( "DEBUG: addSubunit added subunit to array (0x%08X)\n",(int) userClient); 772 } 773 } 774 775 *subUnitID = subUnitInfo->subunitTypeAndID; 776 subUnitInfo->release(); 777 } 778 779 AVCTARGETMUTEX_UNLOCK; 780 781 return res; 782} 783 784////////////////////////////////////////////////////// 785// IOFireWireAVCTargetSpace::setSubunitPlugSignalFormat 786////////////////////////////////////////////////////// 787IOReturn IOFireWireAVCTargetSpace::setSubunitPlugSignalFormat(IOFireWireAVCProtocolUserClient *userClient, 788 UInt32 subunitTypeAndID, 789 IOFWAVCPlugTypes plugType, 790 UInt32 plugNum, 791 UInt32 signalFormat) 792{ 793 IOReturn res = kIOReturnBadArgument; // Preinitialize with an error 794 AVCSubunitInfo *subUnitInfo; 795 796 //IOLog( "IOFireWireAVCTargetSpace::setSubunitPlugSignalFormat (0x%08X)\n",(int) this); 797 798 AVCTARGETMUTEX_LOCK; 799 800 // See if this subunit exists 801 subUnitInfo = getSubunitInfo(subunitTypeAndID); 802 if (subUnitInfo) 803 res = kIOReturnSuccess; 804 805 // See if the caller owns this subunit 806 if ((res == kIOReturnSuccess) && (userClient != subUnitInfo->userClient)) 807 res = kIOReturnBadArgument; 808 809 // If this is a valid plug, set its signal format 810 if (res == kIOReturnSuccess) 811 { 812 if ((plugType == IOFWAVCPlugSubunitSourceType) && (plugNum < subUnitInfo->numSourcePlugs)) 813 subUnitInfo->sourcePlugRecords[plugNum].plugSignalFormat = signalFormat; 814 else if ((plugType == IOFWAVCPlugSubunitDestType) && (plugNum < subUnitInfo->numDestPlugs)) 815 subUnitInfo->destPlugRecords[plugNum].plugSignalFormat = signalFormat; 816 else 817 res = kIOReturnBadArgument; 818 } 819 820 AVCTARGETMUTEX_UNLOCK; 821 822 return res; 823} 824 825////////////////////////////////////////////////////// 826// IOFireWireAVCTargetSpace::getSubunitPlugSignalFormat 827////////////////////////////////////////////////////// 828IOReturn IOFireWireAVCTargetSpace::getSubunitPlugSignalFormat(IOFireWireAVCProtocolUserClient *userClient, 829 UInt32 subunitTypeAndID, 830 IOFWAVCPlugTypes plugType, 831 UInt32 plugNum, 832 UInt32 *pSignalFormat) 833{ 834 IOReturn res = kIOReturnBadArgument; // Preinitialize with an error 835 AVCSubunitInfo *subUnitInfo; 836 837 //IOLog( "IOFireWireAVCTargetSpace::getSubunitPlugSignalFormat (0x%08X)\n",(int) this); 838 839 AVCTARGETMUTEX_LOCK; 840 841 // Special Handling for unit plugs 842 if (subunitTypeAndID == kAVCUnitAddress) 843 { 844 // TODO: For unit commands, find connected subunit plug (if exists) 845 // and return its signal format. For now just return an error! 846 res = kIOReturnBadArgument; 847 } 848 else 849 { 850 // See if this subunit exists 851 subUnitInfo = getSubunitInfo(subunitTypeAndID); 852 if (subUnitInfo) 853 res = kIOReturnSuccess; 854 855 // If this is a valid plug, get its signal format 856 if (res == kIOReturnSuccess) 857 { 858 if ((plugType == IOFWAVCPlugSubunitSourceType) && (plugNum < subUnitInfo->numSourcePlugs)) 859 *pSignalFormat = subUnitInfo->sourcePlugRecords[plugNum].plugSignalFormat; 860 else if ((plugType == IOFWAVCPlugSubunitDestType) && (plugNum < subUnitInfo->numDestPlugs)) 861 *pSignalFormat = subUnitInfo->destPlugRecords[plugNum].plugSignalFormat; 862 else 863 res = kIOReturnBadArgument; 864 } 865 } 866 867 AVCTARGETMUTEX_UNLOCK; 868 869 return res; 870} 871 872////////////////////////////////////////////////////// 873// IOFireWireAVCTargetSpace::connectTargetPlugs 874////////////////////////////////////////////////////// 875IOReturn IOFireWireAVCTargetSpace::connectTargetPlugs(IOFireWireAVCProtocolUserClient *userClient, 876 AVCConnectTargetPlugsInParams *inParams, 877 AVCConnectTargetPlugsOutParams *outParams) 878{ 879 IOReturn res = kIOReturnSuccess; 880 AVCSubunitInfo *sourceSubUnitInfo = NULL; 881 AVCSubunitInfo *destSubUnitInfo = NULL; 882 UInt32 sourcePlugIndex; 883 UInt32 destPlugIndex; 884 UInt32 sourcePlugNum; 885 UInt32 destPlugNum; 886 int i; 887 bool found; 888 bool plugFound; 889 AVCConnectionRecord *connection; 890 UInt32 actualPlug; 891 892 //IOLog( "IOFireWireAVCTargetSpace::connectTargetPlugs (0x%08X)\n",(int) this); 893 894 AVCTARGETMUTEX_LOCK; 895 896 // See if this connection already exists 897 for (i=(fConnectionRecords->getCount()-1);i>=0;i--) 898 { 899 connection = (AVCConnectionRecord *) fConnectionRecords->getObject(i); 900 if ((inParams->sourceSubunitTypeAndID == connection->sourceSubunitTypeAndID) && 901 (inParams->sourcePlugType == connection->sourcePlugType) && 902 (inParams->sourcePlugNum == connection->sourcePlugNum) && 903 (inParams->destSubunitTypeAndID == connection->destSubunitTypeAndID) && 904 (inParams->destPlugType == connection->destPlugType) && 905 (inParams->destPlugNum == connection->destPlugNum)) 906 { 907 // Connection exists. Set lock and/or perm 908 // if specified, and return success 909 910 if (inParams->lockConnection == true) 911 connection->lockConnection = true; 912 913 if (inParams->permConnection == true) 914 connection->permConnection = true; 915 916 outParams->sourcePlugNum = connection->sourcePlugNum; 917 outParams->destPlugNum = connection->destPlugNum; 918 919 AVCTARGETMUTEX_UNLOCK; 920 return res; 921 } 922 } 923 924 // Identify Source Plug for Connection 925 if (inParams->sourceSubunitTypeAndID == kAVCUnitAddress) 926 { 927 switch (inParams->sourcePlugType) 928 { 929 case IOFWAVCPlugIsochInputType: 930 if (inParams->sourcePlugNum == kAVCAnyAvailableIsochPlug) 931 { 932 // Search for an unconnected plug first, 933 // then, if all connected, overlay a connection. 934 plugFound = false; 935 for (i=0;i<kAVCMaxNumPlugs;i++) 936 { 937 if (fUnitPlugs.isochInPlugRecord[i].connectionCount == 0) 938 { 939 sourcePlugIndex=i; 940 sourcePlugNum=i; 941 plugFound = true; 942 break; 943 } 944 } 945 if (!plugFound) 946 { 947 // No available plugs, just overlay on first plug. 948 sourcePlugIndex=0; 949 sourcePlugNum=0; 950 } 951 } 952 else if (inParams->sourcePlugNum < kAVCMaxNumPlugs) 953 { 954 sourcePlugIndex = inParams->sourcePlugNum; 955 sourcePlugNum = sourcePlugIndex; 956 } 957 else 958 res = kIOReturnBadArgument; 959 break; 960 961 case IOFWAVCPlugExternalInputType: 962 if (inParams->sourcePlugNum == kAVCAnyAvailableExternalPlug) 963 { 964 // Search for an unconnected plug first, 965 // then, if all connected, overlay a connection. 966 plugFound = false; 967 for (i=0;i<kAVCMaxNumPlugs;i++) 968 { 969 if (fUnitPlugs.externalInPlugRecord[i].connectionCount == 0) 970 { 971 sourcePlugIndex=i; 972 sourcePlugNum= 0x80 + i; 973 plugFound = true; 974 break; 975 } 976 } 977 if (!plugFound) 978 { 979 // No available plugs, just overlay on first plug. 980 sourcePlugIndex=0; 981 sourcePlugNum = 0x80; 982 } 983 } 984 else if ((inParams->sourcePlugNum >= 0x80) && (inParams->sourcePlugNum < 0x9F)) 985 { 986 sourcePlugIndex = inParams->sourcePlugNum - 0x80; 987 sourcePlugNum = inParams->sourcePlugNum; 988 } 989 else 990 res = kIOReturnBadArgument; 991 break; 992 993 default: 994 res = kIOReturnBadArgument; 995 break; 996 }; 997 } 998 else 999 { 1000 found = false; 1001 for (i=(fSubunits->getCount()-1);i>=0;i--) 1002 { 1003 sourceSubUnitInfo = (AVCSubunitInfo *) fSubunits->getObject(i); 1004 if (inParams->sourceSubunitTypeAndID == sourceSubUnitInfo->subunitTypeAndID) 1005 { 1006 found = true; 1007 break; 1008 } 1009 } 1010 if (found == false) 1011 res = kIOReturnBadArgument; 1012 1013 // For internally initiated connection, verify that the userClient owns this subunit 1014 if ((res == kIOReturnSuccess) && (userClient != NULL) && (sourceSubUnitInfo->userClient != userClient)) 1015 res = kIOReturnBadArgument; 1016 1017 if (res == kIOReturnSuccess) 1018 { 1019 switch (inParams->sourcePlugType) 1020 { 1021 case IOFWAVCPlugSubunitSourceType: 1022 if ((inParams->sourcePlugNum == kAVCAnyAvailableSubunitPlug) && (sourceSubUnitInfo->numSourcePlugs > 0)) 1023 { 1024 // Search for an unconnected plug first, 1025 // then, if all connected, overlay a connection. 1026 plugFound = false; 1027 for (i=0;i<(int)sourceSubUnitInfo->numSourcePlugs;i++) 1028 { 1029 if (sourceSubUnitInfo->sourcePlugRecords[i].connectionCount == 0) 1030 { 1031 sourcePlugIndex=i; 1032 sourcePlugNum=i; 1033 plugFound = true; 1034 break; 1035 } 1036 } 1037 if (!plugFound) 1038 { 1039 // No available plugs, just overlay on first plug. 1040 sourcePlugIndex=0; 1041 sourcePlugNum=0; 1042 } 1043 } 1044 else if (inParams->sourcePlugNum < sourceSubUnitInfo->numSourcePlugs) 1045 { 1046 sourcePlugIndex = inParams->sourcePlugNum; 1047 sourcePlugNum = sourcePlugIndex; 1048 } 1049 else 1050 res = kIOReturnBadArgument; 1051 break; 1052 1053 default: 1054 res = kIOReturnBadArgument; 1055 break; 1056 }; 1057 } 1058 } 1059 1060 // Identify Destination Plug for Connection 1061 if (res == kIOReturnSuccess) 1062 { 1063 if (inParams->destSubunitTypeAndID == kAVCUnitAddress) 1064 { 1065 switch (inParams->destPlugType) 1066 { 1067 case IOFWAVCPlugIsochOutputType: 1068 if (inParams->destPlugNum == kAVCAnyAvailableIsochPlug) 1069 { 1070 // Search for an unconnected plug first 1071 plugFound = false; 1072 for (i=0;i<kAVCMaxNumPlugs;i++) 1073 { 1074 if (fUnitPlugs.isochOutPlugRecord[i].connectionCount == 0) 1075 { 1076 destPlugIndex=i; 1077 destPlugNum=i; 1078 plugFound = true; 1079 break; 1080 } 1081 } 1082 if (!plugFound) 1083 { 1084 // We had no unconnected plugs available, so 1085 // next, we need to see if we can find a non-locked, 1086 // non-permanent connection to an isoch output plug, 1087 // and if so, disconnect it and use that isoch out 1088 // plug for this new connection. 1089 actualPlug = kAVCInvalidPlug; 1090 if (canConnectDestPlug(kAVCUnitAddress, 1091 IOFWAVCPlugIsochOutputType, 1092 &actualPlug)) 1093 { 1094 destPlugIndex = actualPlug; 1095 destPlugNum = destPlugIndex; 1096 } 1097 else 1098 res = kIOReturnBadArgument; 1099 } 1100 } 1101 else if (inParams->destPlugNum < kAVCMaxNumPlugs) 1102 { 1103 if (canConnectDestPlug(kAVCUnitAddress, 1104 IOFWAVCPlugIsochOutputType, 1105 &inParams->destPlugNum)) 1106 { 1107 destPlugIndex = inParams->destPlugNum; 1108 destPlugNum = destPlugIndex; 1109 } 1110 else 1111 res = kIOReturnBadArgument; 1112 } 1113 else 1114 res = kIOReturnBadArgument; 1115 break; 1116 1117 case IOFWAVCPlugExternalOutputType: 1118 if (inParams->destPlugNum == kAVCAnyAvailableExternalPlug) 1119 { 1120 // Search for an unconnected plug first 1121 plugFound = false; 1122 for (i=0;i<kAVCMaxNumPlugs;i++) 1123 { 1124 if (fUnitPlugs.externalOutPlugRecord[i].connectionCount == 0) 1125 { 1126 destPlugIndex=i; 1127 destPlugNum= 0x80 + i; 1128 plugFound = true; 1129 break; 1130 } 1131 } 1132 if (!plugFound) 1133 { 1134 // We had no unconnected plugs available, so 1135 // next, we need to see if we can find a non-locked, 1136 // non-permanent connection to an external output plug, 1137 // and if so, disconnect it and use that extern out 1138 // plug for this new connection. 1139 actualPlug = kAVCInvalidPlug; 1140 if (canConnectDestPlug(kAVCUnitAddress, 1141 IOFWAVCPlugExternalOutputType, 1142 &actualPlug)) 1143 { 1144 destPlugIndex = actualPlug - 0x80; 1145 destPlugNum = actualPlug; 1146 } 1147 else 1148 res = kIOReturnBadArgument; 1149 } 1150 } 1151 else if ((inParams->destPlugNum >= 0x80) && (inParams->destPlugNum < 0x9F)) 1152 { 1153 if (canConnectDestPlug(kAVCUnitAddress, 1154 IOFWAVCPlugExternalOutputType, 1155 &inParams->destPlugNum)) 1156 { 1157 destPlugIndex = inParams->destPlugNum - 0x80; 1158 destPlugNum = inParams->destPlugNum; 1159 } 1160 else 1161 res = kIOReturnBadArgument; 1162 } 1163 else 1164 res = kIOReturnBadArgument; 1165 break; 1166 1167 default: 1168 res = kIOReturnBadArgument; 1169 break; 1170 }; 1171 } 1172 else 1173 { 1174 found = false; 1175 for (i=(fSubunits->getCount()-1);i>=0;i--) 1176 { 1177 destSubUnitInfo = (AVCSubunitInfo *) fSubunits->getObject(i); 1178 if (inParams->destSubunitTypeAndID == destSubUnitInfo->subunitTypeAndID) 1179 { 1180 found = true; 1181 break; 1182 } 1183 } 1184 if (found == false) 1185 res = kIOReturnBadArgument; 1186 1187 // For internally initiated connection, verify that the userClient owns this subunit 1188 if ((res == kIOReturnSuccess) && (userClient != NULL) && (destSubUnitInfo->userClient != userClient)) 1189 res = kIOReturnBadArgument; 1190 1191 if (res == kIOReturnSuccess) 1192 { 1193 switch (inParams->destPlugType) 1194 { 1195 case IOFWAVCPlugSubunitDestType: 1196 if ((inParams->destPlugNum == kAVCAnyAvailableSubunitPlug) && (destSubUnitInfo->numDestPlugs > 0)) 1197 { 1198 // Search for an unconnected plug first 1199 plugFound = false; 1200 for (i=0;i<(int)destSubUnitInfo->numDestPlugs;i++) 1201 { 1202 if (destSubUnitInfo->destPlugRecords[i].connectionCount == 0) 1203 { 1204 destPlugIndex =i; 1205 destPlugNum =i; 1206 plugFound = true; 1207 break; 1208 } 1209 } 1210 if (!plugFound) 1211 { 1212 // We had no unconnected plugs available, so 1213 // next, we need to see if we can find a non-locked, 1214 // non-permanent connection to one of this subunits dest plugs, 1215 // and if so, disconnect it and use that 1216 // plug for this new connection. 1217 actualPlug = kAVCInvalidPlug; 1218 if (canConnectDestPlug(destSubUnitInfo->subunitTypeAndID, 1219 IOFWAVCPlugSubunitDestType, 1220 &actualPlug)) 1221 { 1222 destPlugIndex = actualPlug; 1223 destPlugNum = destPlugIndex; 1224 } 1225 else 1226 res = kIOReturnBadArgument; 1227 } 1228 } 1229 else if (inParams->destPlugNum < destSubUnitInfo->numDestPlugs) 1230 { 1231 if (canConnectDestPlug(destSubUnitInfo->subunitTypeAndID, 1232 IOFWAVCPlugSubunitDestType, 1233 &inParams->destPlugNum)) 1234 { 1235 destPlugIndex = inParams->destPlugNum; 1236 destPlugNum = destPlugIndex; 1237 } 1238 else 1239 res = kIOReturnBadArgument; 1240 } 1241 else 1242 res = kIOReturnBadArgument; 1243 break; 1244 1245 default: 1246 res = kIOReturnBadArgument; 1247 break; 1248 }; 1249 } 1250 } 1251 } 1252 1253 // Here, we know that we have a valid source and 1254 // destination plug, so make the connection 1255 if (res == kIOReturnSuccess) 1256 { 1257 connection = new AVCConnectionRecord; 1258 if(!connection) 1259 res = kIOReturnNoMemory; 1260 1261 if (res == kIOReturnSuccess) 1262 { 1263 // Update connection record parameters 1264 connection->sourceSubunitTypeAndID = inParams->sourceSubunitTypeAndID; 1265 connection->sourcePlugType = inParams->sourcePlugType; 1266 connection->sourcePlugNum = sourcePlugNum; 1267 connection->destSubunitTypeAndID = inParams->destSubunitTypeAndID; 1268 connection->destPlugType = inParams->destPlugType; 1269 connection->destPlugNum = destPlugNum; 1270 connection->lockConnection = inParams->lockConnection; 1271 connection->permConnection = inParams->permConnection; 1272 1273 if(!fConnectionRecords->setObject(connection)) 1274 res = kIOReturnNoMemory; 1275 connection->release(); 1276 //IOLog( "DEBUG: connectTargetPlugs added connection record to array (0x%08X)\n",(int) userClient); 1277 1278 // Update plug records in subunit/unit 1279 if (res == kIOReturnSuccess) 1280 { 1281 switch (inParams->sourcePlugType) 1282 { 1283 case IOFWAVCPlugIsochInputType: 1284 fUnitPlugs.isochInPlugRecord[sourcePlugIndex].connectionCount++; 1285 break; 1286 case IOFWAVCPlugExternalInputType: 1287 fUnitPlugs.externalInPlugRecord[sourcePlugIndex].connectionCount++; 1288 break; 1289 case IOFWAVCPlugSubunitSourceType: 1290 sourceSubUnitInfo->sourcePlugRecords[sourcePlugIndex].connectionCount++; 1291 break; 1292 default: 1293 break; 1294 }; 1295 switch (inParams->destPlugType) 1296 { 1297 case IOFWAVCPlugIsochOutputType: 1298 fUnitPlugs.isochOutPlugRecord[destPlugIndex].connectionCount++; 1299 break; 1300 case IOFWAVCPlugExternalOutputType: 1301 fUnitPlugs.externalOutPlugRecord[destPlugIndex].connectionCount++; 1302 break; 1303 case IOFWAVCPlugSubunitDestType: 1304 destSubUnitInfo->destPlugRecords[destPlugIndex].connectionCount++; 1305 break; 1306 default: 1307 break; 1308 }; 1309 } 1310 1311 // If source is a subunit, notify source plug owner of new connection 1312 if ((res == kIOReturnSuccess) && (sourceSubUnitInfo)) 1313 sourceSubUnitInfo->callBack(sourceSubUnitInfo, 1314 kIOFWAVCSubunitPlugMsgConnected, 1315 inParams->sourcePlugType, 1316 sourcePlugNum, 1317 ((inParams->destSubunitTypeAndID << 16) + (inParams->destPlugType << 8) + destPlugNum), 1318 0,0); 1319 1320 // If dest is a subunit, notify dest plug owner of new connection 1321 if ((res == kIOReturnSuccess) && (destSubUnitInfo)) 1322 destSubUnitInfo->callBack(destSubUnitInfo, 1323 kIOFWAVCSubunitPlugMsgConnected, 1324 inParams->destPlugType, 1325 destPlugNum, 1326 ((inParams->sourceSubunitTypeAndID << 16) + (inParams->sourcePlugType << 8) + sourcePlugNum), 1327 0,0); 1328 1329 // Update the out Params 1330 if (res == kIOReturnSuccess) 1331 { 1332 outParams->sourcePlugNum = sourcePlugNum; 1333 outParams->destPlugNum = destPlugNum; 1334 } 1335 } 1336 } 1337 1338 AVCTARGETMUTEX_UNLOCK; 1339 1340 return res; 1341} 1342 1343////////////////////////////////////////////////////// 1344// IOFireWireAVCTargetSpace::disconnectTargetPlugs 1345////////////////////////////////////////////////////// 1346IOReturn IOFireWireAVCTargetSpace::disconnectTargetPlugs(IOFireWireAVCProtocolUserClient *userClient, 1347 UInt32 sourceSubunitTypeAndID, 1348 IOFWAVCPlugTypes sourcePlugType, 1349 UInt32 sourcePlugNum, 1350 UInt32 destSubunitTypeAndID, 1351 IOFWAVCPlugTypes destPlugType, 1352 UInt32 destPlugNum) 1353{ 1354 int i; 1355 AVCConnectionRecord *connection; 1356 AVCSubunitInfo *sourceSubUnitInfo = NULL; 1357 AVCSubunitInfo *destSubUnitInfo = NULL; 1358 bool found = false; 1359 1360 //IOLog( "IOFireWireAVCTargetSpace::disconnectTargetPlugs (0x%08X)\n",(int) this); 1361 1362 AVCTARGETMUTEX_LOCK; 1363 1364 // Search connection records for this source plug 1365 for (i=(fConnectionRecords->getCount()-1);i>=0;i--) 1366 { 1367 connection = (AVCConnectionRecord *) fConnectionRecords->getObject(i); 1368 if ((sourceSubunitTypeAndID == connection->sourceSubunitTypeAndID) && 1369 (sourcePlugType == connection->sourcePlugType) && 1370 (sourcePlugNum == connection->sourcePlugNum) && 1371 (connection->permConnection == false)) 1372 { 1373 // Find the info for the source and dest subunits (if not a unit) 1374 if (connection->sourceSubunitTypeAndID != kAVCUnitAddress) 1375 sourceSubUnitInfo = getSubunitInfo(connection->sourceSubunitTypeAndID); 1376 if (connection->destSubunitTypeAndID != kAVCUnitAddress) 1377 destSubUnitInfo = getSubunitInfo(connection->destSubunitTypeAndID); 1378 1379 // Update connection counts in plug records in subunit/unit 1380 switch (connection->sourcePlugType) 1381 { 1382 case IOFWAVCPlugIsochInputType: 1383 fUnitPlugs.isochInPlugRecord[connection->sourcePlugNum].connectionCount--; 1384 break; 1385 case IOFWAVCPlugExternalInputType: 1386 fUnitPlugs.externalInPlugRecord[connection->sourcePlugNum - 0x80].connectionCount--; 1387 break; 1388 case IOFWAVCPlugSubunitSourceType: 1389 if (sourceSubUnitInfo) 1390 sourceSubUnitInfo->sourcePlugRecords[connection->sourcePlugNum].connectionCount--; 1391 break; 1392 default: 1393 break; 1394 }; 1395 switch (connection->destPlugType) 1396 { 1397 case IOFWAVCPlugIsochOutputType: 1398 fUnitPlugs.isochOutPlugRecord[connection->destPlugNum].connectionCount--; 1399 break; 1400 case IOFWAVCPlugExternalOutputType: 1401 fUnitPlugs.externalOutPlugRecord[connection->destPlugNum - 0x80].connectionCount--; 1402 break; 1403 case IOFWAVCPlugSubunitDestType: 1404 if (destSubUnitInfo) 1405 destSubUnitInfo->destPlugRecords[connection->destPlugNum].connectionCount--; 1406 break; 1407 default: 1408 break; 1409 }; 1410 1411 // If source is a subunit, notify source plug owner of disconnection 1412 if (sourceSubUnitInfo) 1413 sourceSubUnitInfo->callBack(sourceSubUnitInfo, 1414 kIOFWAVCSubunitPlugMsgDisconnected, 1415 connection->sourcePlugType, 1416 connection->sourcePlugNum, 1417 ((connection->destSubunitTypeAndID << 16) + (connection->destPlugType << 8) + connection->destPlugNum), 1418 0,0); 1419 1420 // If dest is a subunit, notify dest plug owner of disconnection 1421 if (destSubUnitInfo) 1422 destSubUnitInfo->callBack(destSubUnitInfo, 1423 kIOFWAVCSubunitPlugMsgDisconnected, 1424 connection->destPlugType, 1425 connection->destPlugNum, 1426 ((connection->sourceSubunitTypeAndID << 16) + (connection->sourcePlugType << 8) + connection->sourcePlugNum), 1427 0,0); 1428 1429 // Remove the plug connection record from the array 1430 fConnectionRecords->removeObject(i); 1431 found = true; 1432 } 1433 } 1434 1435 AVCTARGETMUTEX_UNLOCK; 1436 1437 if (found) 1438 return kIOReturnSuccess; 1439 else 1440 return kIOReturnBadArgument; 1441} 1442 1443////////////////////////////////////////////////////// 1444// IOFireWireAVCTargetSpace::getTargetPlugConnection 1445////////////////////////////////////////////////////// 1446IOReturn IOFireWireAVCTargetSpace::getTargetPlugConnection(IOFireWireAVCProtocolUserClient *userClient, 1447 AVCGetTargetPlugConnectionInParams *inParams, 1448 AVCGetTargetPlugConnectionOutParams *outParams) 1449{ 1450 IOReturn res; 1451 int i; 1452 AVCConnectionRecord *connection; 1453 UInt32 count = 0; 1454 1455 //IOLog( "IOFireWireAVCTargetSpace::getTargetPlugConnection (0x%08X)\n",(int) this); 1456 1457 AVCTARGETMUTEX_LOCK; 1458 1459 // Search connection records for this source plug 1460 for (i=(fConnectionRecords->getCount()-1);i>=0;i--) 1461 { 1462 connection = (AVCConnectionRecord *) fConnectionRecords->getObject(i); 1463 1464 switch (inParams->plugType) 1465 { 1466 case IOFWAVCPlugSubunitSourceType: 1467 case IOFWAVCPlugIsochOutputType: 1468 case IOFWAVCPlugExternalOutputType: 1469 if ((inParams->subunitTypeAndID == connection->sourceSubunitTypeAndID) && 1470 (inParams->plugType == connection->sourcePlugType) && 1471 (inParams->plugNum == connection->sourcePlugNum)) 1472 { 1473 outParams->connectedSubunitTypeAndID = connection->destSubunitTypeAndID; 1474 outParams->connectedPlugType = connection->destPlugType; 1475 outParams->connectedPlugNum = connection->destPlugNum; 1476 outParams->lockConnection = connection->lockConnection; 1477 outParams->permConnection = connection->permConnection; 1478 count += 1; 1479 } 1480 break; 1481 1482 case IOFWAVCPlugSubunitDestType: 1483 case IOFWAVCPlugIsochInputType: 1484 case IOFWAVCPlugExternalInputType: 1485 if ((inParams->subunitTypeAndID == connection->destSubunitTypeAndID) && 1486 (inParams->plugType == connection->destPlugType) && 1487 (inParams->plugNum == connection->destPlugNum)) 1488 { 1489 outParams->connectedSubunitTypeAndID = connection->sourceSubunitTypeAndID; 1490 outParams->connectedPlugType = connection->sourcePlugType; 1491 outParams->connectedPlugNum = connection->sourcePlugNum; 1492 outParams->lockConnection = connection->lockConnection; 1493 outParams->permConnection = connection->permConnection; 1494 count += 1; 1495 } 1496 break; 1497 1498 default: 1499 break; 1500 }; 1501 } 1502 1503 if (count == 0) 1504 res = kIOReturnBadArgument; 1505 else 1506 { 1507 res = kIOReturnSuccess; 1508 if (count > 1) 1509 outParams->connectedPlugNum = kAVCMultiplePlugs; 1510 } 1511 1512 AVCTARGETMUTEX_UNLOCK; 1513 1514 return res; 1515} 1516 1517////////////////////////////////////////////////////// 1518// IOFireWireAVCTargetSpace::handleUnitInfoCommand 1519////////////////////////////////////////////////////// 1520IOReturn IOFireWireAVCTargetSpace::handleUnitInfoCommand(UInt16 nodeID, UInt32 generation, const char *buf, UInt32 len) 1521{ 1522 UInt8 *pResponse; 1523 UInt8 *pBuf = (UInt8*) buf; 1524 UInt8 cType; 1525 IOBufferMemoryDescriptor *pBufMemDesc = NULL; 1526 AVCSubunitInfo *subUnitInfo; 1527 1528 //IOLog( "IOFireWireAVCTargetSpace::handleUnitInfoCommand (0x%08X)\n",(int) this); 1529 1530 // Check the length of the command. Don't handle command if wrong. 1531 if (len != 8) 1532 return kIOReturnError; 1533 1534 // Parse the command buf 1535 cType = pBuf[0] & 0x0F; 1536 1537 // Check the cType. Don't handle command if not a status type. 1538 if (cType != kAVCStatusInquiryCommand) 1539 return kIOReturnError; 1540 1541 // Check the operands. Don't handle command if not properly initialized. 1542 if ((pBuf[kAVCOperand0] != 0xFF) || 1543 (pBuf[kAVCOperand1] != 0xFF) || 1544 (pBuf[kAVCOperand2] != 0xFF) || 1545 (pBuf[kAVCOperand3] != 0xFF) || 1546 (pBuf[kAVCOperand4] != 0xFF)) 1547 return kIOReturnError; 1548 1549 // All tests passed. Handle the command 1550 pBufMemDesc = IOBufferMemoryDescriptor::withCapacity(len, kIODirectionOutIn); 1551 if(!pBufMemDesc) 1552 return kFWResponseDataError; 1553 pResponse = (UInt8 *) pBufMemDesc->getBytesNoCopy(); 1554 1555 // Initialize the response 1556 pResponse[kAVCCommandResponse] = kAVCImplementedStatus; 1557 pResponse[kAVCAddress] = pBuf[kAVCAddress]; 1558 pResponse[kAVCOpcode] = pBuf[kAVCOpcode]; 1559 pResponse[kAVCOperand0] = 0x07; 1560 1561 AVCTARGETMUTEX_LOCK; 1562 1563 // This is the unit type field. Set to value of first subunit 1564 // in subunit info list if it exists 1565 if (fSubunits->getCount() > 0) 1566 { 1567 subUnitInfo = (AVCSubunitInfo*) fSubunits->getObject(0); 1568 pResponse[kAVCOperand1] = subUnitInfo->subunitTypeAndID; 1569 } 1570 else 1571 pResponse[kAVCOperand1] = 0xFF; 1572 1573 // Add Apple's OUI to the company_ID field of the response 1574 pResponse[kAVCOperand2] = 0x00; 1575 pResponse[kAVCOperand3] = 0x03; 1576 pResponse[kAVCOperand4] = 0x93; 1577 1578 targetSendAVCResponse(generation, nodeID, pBufMemDesc, len); 1579 1580 AVCTARGETMUTEX_UNLOCK; 1581 1582 return kIOReturnSuccess; 1583} 1584 1585////////////////////////////////////////////////////// 1586// IOFireWireAVCTargetSpace::handleSubUnitInfoCommand 1587////////////////////////////////////////////////////// 1588IOReturn IOFireWireAVCTargetSpace::handleSubUnitInfoCommand(UInt16 nodeID, UInt32 generation, const char *buf, UInt32 len) 1589{ 1590 UInt8 *pResponse; 1591 UInt8 *pBuf = (UInt8*) buf; 1592 UInt8 cType; 1593 UInt8 page; 1594 IOBufferMemoryDescriptor *pBufMemDesc = NULL; 1595 int i; 1596 AVCSubunitInfo *subUnitInfo; 1597 UInt32 subUnitType; 1598 UInt8 count[32]; 1599 UInt32 uniqueSubUnitCount = 0; 1600 UInt32 countArrayIndex; 1601 int skipped; 1602 1603 //IOLog( "IOFireWireAVCTargetSpace::handleSubUnitInfoCommand (0x%08X)\n",(int) this); 1604 1605 // Check the length of the command. Don't handle command if wrong. 1606 if (len != 8) 1607 return kIOReturnError; 1608 1609 // Parse the command buf 1610 cType = pBuf[0] & 0x0F; 1611 1612 // Check the cType. Don't handle command if not a status type. 1613 if (cType != kAVCStatusInquiryCommand) 1614 return kIOReturnError; 1615 1616 // Check the operands. Don't handle command if not properly initialized. 1617 if (((pBuf[kAVCOperand0] & 0x8F) != 0x07) || 1618 (pBuf[kAVCOperand1] != 0xFF) || 1619 (pBuf[kAVCOperand2] != 0xFF) || 1620 (pBuf[kAVCOperand3] != 0xFF) || 1621 (pBuf[kAVCOperand4] != 0xFF)) 1622 return kIOReturnError; 1623 1624 AVCTARGETMUTEX_LOCK; 1625 1626 // Initialize the count array 1627 for (i=0;i<32;i++) 1628 count[i] = 0; 1629 1630 // Parse the subunit list 1631 for (i=(fSubunits->getCount()-1);i>=0;i--) 1632 { 1633 subUnitInfo = (AVCSubunitInfo *) fSubunits->getObject(i); 1634 subUnitType = ((subUnitInfo->subunitTypeAndID & 0xF8) >> 3); 1635 if (count[subUnitType] == 0) 1636 uniqueSubUnitCount += 1; 1637 count[subUnitType] += 1; 1638 } 1639 1640 // Check the page to see if valid 1641 page = ((pBuf[kAVCOperand0] & 0x70) >> 4); 1642 if (page > uniqueSubUnitCount/4) 1643 { 1644 AVCTARGETMUTEX_UNLOCK; 1645 return kIOReturnError; // Spec says empty page should result in NOT_IMPLEMENTED response 1646 } 1647 1648 // All tests passed. Handle the command 1649 pBufMemDesc = IOBufferMemoryDescriptor::withCapacity(len, kIODirectionOutIn); 1650 if(!pBufMemDesc) 1651 { 1652 AVCTARGETMUTEX_UNLOCK; 1653 return kFWResponseDataError; 1654 } 1655 pResponse = (UInt8 *) pBufMemDesc->getBytesNoCopy(); 1656 1657 // Initialize the response 1658 pResponse[kAVCCommandResponse] = kAVCImplementedStatus; 1659 pResponse[kAVCAddress] = pBuf[kAVCAddress]; 1660 pResponse[kAVCOpcode] = pBuf[kAVCOpcode]; 1661 pResponse[kAVCOperand0] = pBuf[kAVCOperand0]; 1662 1663 // Fill in subunit info page data 1664 for (i=0;i<4;i++) 1665 { 1666 if (((page*4)+i) < (int) uniqueSubUnitCount) 1667 { 1668 // Reset the skipped count 1669 skipped = 0; 1670 1671 // Find the ((page*4)+i) non-zero entry in the count array. It's index is the subunit type, and it's value is the number 1672 // of that type of subunit. Note: We've already confirmed that this entry does indeed exist, so no failsafe code needed here. 1673 for (countArrayIndex = 0; countArrayIndex < 32; countArrayIndex++) 1674 { 1675 if (count[countArrayIndex] != 0) 1676 { 1677 // Found a non-zero entry, is this the one we're looking for? 1678 if (skipped != ((page*4)+i)) 1679 { 1680 // This is not the one we're looking for 1681 skipped += 1; 1682 } 1683 else 1684 { 1685 // This is the one we're looking for. The subunit's max ID for the response packet is the count - 1 1686 pResponse[kAVCOperand1+i] = ((countArrayIndex << 3) | (count[countArrayIndex] > 8 ? 7 : (count[countArrayIndex]-1))); 1687 break; 1688 } 1689 } 1690 } 1691 } 1692 else 1693 pResponse[kAVCOperand1+i] = 0xFF; 1694 } 1695 1696 targetSendAVCResponse(generation, nodeID, pBufMemDesc, len); 1697 1698 AVCTARGETMUTEX_UNLOCK; 1699 1700 return kIOReturnSuccess; 1701} 1702 1703////////////////////////////////////////////////////// 1704// IOFireWireAVCTargetSpace::handlePlugInfoCommand 1705////////////////////////////////////////////////////// 1706IOReturn IOFireWireAVCTargetSpace::handlePlugInfoCommand(UInt16 nodeID, UInt32 generation, const char *buf, UInt32 len) 1707{ 1708 UInt8 *pResponse; 1709 UInt8 *pBuf = (UInt8*) buf; 1710 UInt8 cType; 1711 IOBufferMemoryDescriptor *pBufMemDesc = NULL; 1712 int i; 1713 AVCSubunitInfo *subUnitInfo; 1714 bool found = false; 1715 1716 //IOLog( "IOFireWireAVCTargetSpace::handlePlugInfoCommand (0x%08X)\n",(int) this); 1717 1718 // Check the length of the command. Don't handle command if wrong. 1719 if (len != 8) 1720 return kIOReturnError; 1721 1722 // Parse the command buf 1723 cType = pBuf[0] & 0x0F; 1724 1725 // Check the cType. Don't handle command if not a status type. 1726 if (cType != kAVCStatusInquiryCommand) 1727 return kIOReturnError; 1728 1729 // Check the operands. Don't handle command if not properly initialized. 1730 if ((pBuf[kAVCOperand1] != 0xFF) || 1731 (pBuf[kAVCOperand2] != 0xFF) || 1732 (pBuf[kAVCOperand3] != 0xFF) || 1733 (pBuf[kAVCOperand4] != 0xFF)) 1734 return kIOReturnError; 1735 1736 // Currently, we only support subfunction 0 1737 if (pBuf[kAVCOperand0] != 0x00) 1738 return kIOReturnError; 1739 1740 // All tests passed. Handle the command 1741 pBufMemDesc = IOBufferMemoryDescriptor::withCapacity(len, kIODirectionOutIn); 1742 if(!pBufMemDesc) 1743 return kFWResponseDataError; 1744 pResponse = (UInt8 *) pBufMemDesc->getBytesNoCopy(); 1745 bcopy(buf,pResponse,len); 1746 1747 if (pBuf[kAVCAddress] == kAVCUnitAddress) 1748 { 1749 // Fill in the response values 1750 pResponse[kAVCCommandResponse] = kAVCImplementedStatus; 1751 pResponse[kAVCOperand1] = 31; // Currently this matches the iMPR/oMPR. Changes will be 1752 pResponse[kAVCOperand2] = 31; // needed here if we reduce the number of allocated plugs 1753 } 1754 else 1755 { 1756 // This command is addressed to a subunit. See if it's a valid subunit address, 1757 // and, if so, report its dest and source plug count. 1758 1759 AVCTARGETMUTEX_LOCK; 1760 1761 for (i=(fSubunits->getCount()-1);i>=0;i--) 1762 { 1763 subUnitInfo = (AVCSubunitInfo *) fSubunits->getObject(i); 1764 if (subUnitInfo->subunitTypeAndID == pBuf[kAVCAddress]) 1765 { 1766 pResponse[kAVCCommandResponse] = kAVCImplementedStatus; 1767 pResponse[kAVCOperand1] = subUnitInfo->numDestPlugs; 1768 pResponse[kAVCOperand2] = subUnitInfo->numSourcePlugs; 1769 found = true; 1770 break; 1771 } 1772 } 1773 if (!found) 1774 { 1775 pResponse[kAVCCommandResponse] = kAVCNotImplementedStatus; 1776 } 1777 1778 AVCTARGETMUTEX_UNLOCK; 1779 } 1780 1781 targetSendAVCResponse(generation, nodeID, pBufMemDesc, len); 1782 1783 return kIOReturnSuccess; 1784} 1785 1786////////////////////////////////////////////////////// 1787// IOFireWireAVCTargetSpace::handlePowerCommand 1788////////////////////////////////////////////////////// 1789IOReturn IOFireWireAVCTargetSpace::handlePowerCommand(UInt16 nodeID, UInt32 generation, const char *buf, UInt32 len) 1790{ 1791 UInt8 *pResponse; 1792 UInt8 *pBuf = (UInt8*) buf; 1793 UInt8 cType; 1794 IOBufferMemoryDescriptor *pBufMemDesc = NULL; 1795 1796 //IOLog( "IOFireWireAVCTargetSpace::handlePowerCommand (0x%08X)\n",(int) this); 1797 1798 // Check the length of the command. Don't handle command if wrong. 1799 if (len != 4) 1800 return kIOReturnError; 1801 1802 // Parse the command buf 1803 cType = pBuf[0] & 0x0F; 1804 1805 // Further check the request packet parameters 1806 switch (cType) 1807 { 1808 case kAVCStatusInquiryCommand: 1809 if (pBuf[kAVCOperand0] != 0x7F) 1810 return kIOReturnError; 1811 break; 1812 1813 case kAVCControlCommand: 1814 if ((pBuf[kAVCOperand0] != 0x60) && (pBuf[kAVCOperand0] != 0x70)) 1815 return kIOReturnError; 1816 break; 1817 1818 default: 1819 return kIOReturnError; 1820 }; 1821 1822 // All tests passed. Handle the command 1823 pBufMemDesc = IOBufferMemoryDescriptor::withCapacity(len, kIODirectionOutIn); 1824 if(!pBufMemDesc) 1825 return kFWResponseDataError; 1826 pResponse = (UInt8 *) pBufMemDesc->getBytesNoCopy(); 1827 bcopy(buf,pResponse,len); 1828 1829 // Fill in the response values 1830 pResponse[kAVCCommandResponse] = (cType == kAVCStatusInquiryCommand) ? kAVCImplementedStatus : kAVCAcceptedStatus; 1831 pResponse[kAVCOperand0] = (cType == kAVCStatusInquiryCommand) ? 0x70 : pBuf[kAVCOperand0]; 1832 1833 targetSendAVCResponse(generation, nodeID, pBufMemDesc, len); 1834 1835 return kIOReturnSuccess; 1836} 1837 1838////////////////////////////////////////////////////// 1839// IOFireWireAVCTargetSpace::handleConnectCommand 1840////////////////////////////////////////////////////// 1841IOReturn IOFireWireAVCTargetSpace::handleConnectCommand(UInt16 nodeID, UInt32 generation, const char *buf, UInt32 len) 1842{ 1843 UInt8 *pResponse; 1844 UInt8 *pBuf = (UInt8*) buf; 1845 UInt8 cType; 1846 IOBufferMemoryDescriptor *pBufMemDesc = NULL; 1847 int i; 1848 AVCConnectTargetPlugsInParams inParams; 1849 AVCConnectTargetPlugsOutParams outParams; 1850 AVCConnectionRecord *pConnection; 1851 UInt32 connCount = 0; 1852 1853 //IOLog( "IOFireWireAVCTargetSpace::handleConnectCommand (0x%08X)\n",(int) this); 1854 1855 // Check the length of the command. Don't handle command if wrong. 1856 if (len != 8) 1857 return kIOReturnError; 1858 1859 // Parse the command buf 1860 cType = pBuf[0] & 0x0F; 1861 1862 // Further check the request packet parameters 1863 switch (cType) 1864 { 1865 case kAVCStatusInquiryCommand: 1866 if ((pBuf[kAVCOperand0] & 0xFF) != 0xFF) 1867 return kIOReturnError; 1868 break; 1869 1870 case kAVCControlCommand: 1871 if ((pBuf[kAVCOperand0] & 0xFC) != 0xFC) 1872 return kIOReturnError; 1873 break; 1874 1875 default: 1876 return kIOReturnError; 1877 }; 1878 1879 // Prepare the connect parameters struct 1880 inParams.sourceSubunitTypeAndID = pBuf[kAVCOperand1]; 1881 inParams.sourcePlugNum = pBuf[kAVCOperand2]; 1882 inParams.destSubunitTypeAndID = pBuf[kAVCOperand3]; 1883 inParams.destPlugNum = pBuf[kAVCOperand4]; 1884 inParams.lockConnection = ((pBuf[kAVCOperand0] & 0x02) == 0x02) ? true : false; 1885 inParams.permConnection = false; 1886 1887 // Determine the type of each the source plug 1888 if (inParams.sourceSubunitTypeAndID == kAVCUnitAddress) 1889 { 1890 if ((inParams.sourcePlugNum < kAVCMaxNumPlugs) || (inParams.sourcePlugNum == kAVCAnyAvailableIsochPlug)) 1891 inParams.sourcePlugType = IOFWAVCPlugIsochInputType; 1892 else if (((inParams.sourcePlugNum >= 0x80) && (inParams.sourcePlugNum <= 0x9E)) || (inParams.sourcePlugNum == kAVCAnyAvailableExternalPlug)) 1893 inParams.sourcePlugType = IOFWAVCPlugExternalInputType; 1894 else if ((cType == kAVCStatusInquiryCommand) && (inParams.sourcePlugNum = kAVCInvalidPlug)) 1895 inParams.sourcePlugType = IOFWAVCPlugIsochInputType; 1896 else 1897 return kIOReturnError; 1898 } 1899 else 1900 inParams.sourcePlugType = IOFWAVCPlugSubunitSourceType; 1901 1902 // Determine the type of each the dest plug 1903 if (inParams.destSubunitTypeAndID == kAVCUnitAddress) 1904 { 1905 if ((inParams.destPlugNum < kAVCMaxNumPlugs) || (inParams.destPlugNum == kAVCAnyAvailableIsochPlug)) 1906 inParams.destPlugType = IOFWAVCPlugIsochOutputType; 1907 else if (((inParams.destPlugNum >= 0x80) && (inParams.destPlugNum <= 0x9E)) || (inParams.destPlugNum == kAVCAnyAvailableExternalPlug)) 1908 inParams.destPlugType = IOFWAVCPlugExternalOutputType; 1909 else if ((cType == kAVCStatusInquiryCommand) && (inParams.destPlugNum = kAVCInvalidPlug)) 1910 inParams.destPlugType = IOFWAVCPlugIsochOutputType; 1911 else 1912 return kIOReturnError; 1913 } 1914 else 1915 inParams.destPlugType = IOFWAVCPlugSubunitDestType; 1916 1917 // All tests passed. Handle the command 1918 pBufMemDesc = IOBufferMemoryDescriptor::withCapacity(len, kIODirectionOutIn); 1919 if(!pBufMemDesc) 1920 return kFWResponseDataError; 1921 pResponse = (UInt8 *) pBufMemDesc->getBytesNoCopy(); 1922 bcopy(buf,pResponse,len); 1923 1924 if (cType == kAVCStatusInquiryCommand) 1925 { 1926 AVCTARGETMUTEX_LOCK; 1927 1928 // Initialize response 1929 pResponse[kAVCCommandResponse] = kAVCImplementedStatus; 1930 1931 if ((inParams.sourceSubunitTypeAndID == 0xFF) && (inParams.sourcePlugNum == 0xFE)) 1932 { 1933 // We're searching for a destination plug's connections 1934 for (i=(fConnectionRecords->getCount()-1);i>=0;i--) 1935 { 1936 pConnection = (AVCConnectionRecord *) fConnectionRecords->getObject(i); 1937 if ((pConnection->destSubunitTypeAndID == inParams.destSubunitTypeAndID) && 1938 (pConnection->destPlugNum == inParams.destPlugNum)) 1939 { 1940 connCount++; 1941 pResponse[kAVCOperand1] = pConnection->sourceSubunitTypeAndID; 1942 pResponse[kAVCOperand2] = pConnection->sourcePlugNum; 1943 if (pConnection->lockConnection == false) 1944 { 1945 pResponse[kAVCOperand0] &= 0xFD; // Clear bit 1 1946 } 1947 if (pConnection->permConnection == false) 1948 { 1949 pResponse[kAVCOperand0] &= 0xFE; // Clear bit 0 1950 } 1951 } 1952 } 1953 if (connCount == 0) 1954 { 1955 pResponse[kAVCOperand2] = kAVCInvalidPlug; 1956 } 1957 else if (connCount > 1) 1958 { 1959 pResponse[kAVCOperand1] = kAVCUnitAddress; 1960 pResponse[kAVCOperand2] = kAVCMultiplePlugs; 1961 pResponse[kAVCOperand0] |= 0x03; // Set bits 0 and 1 1962 1963 } 1964 } 1965 else if ((inParams.destSubunitTypeAndID == 0xFF) && (inParams.destPlugNum == 0xFE)) 1966 1967 { 1968 // We're searching for a source plug's connections 1969 for (i=(fConnectionRecords->getCount()-1);i>=0;i--) 1970 { 1971 pConnection = (AVCConnectionRecord *) fConnectionRecords->getObject(i); 1972 if ((pConnection->sourceSubunitTypeAndID == inParams.sourceSubunitTypeAndID) && 1973 (pConnection->sourcePlugNum == inParams.sourcePlugNum)) 1974 { 1975 connCount++; 1976 pResponse[kAVCOperand3] = pConnection->destSubunitTypeAndID; 1977 pResponse[kAVCOperand4] = pConnection->destPlugNum; 1978 if (pConnection->lockConnection == false) 1979 { 1980 pResponse[kAVCOperand0] &= 0xFD; // Clear bit 1 1981 } 1982 if (pConnection->permConnection == false) 1983 { 1984 pResponse[kAVCOperand0] &= 0xFE; // Clear bit 0 1985 } 1986 } 1987 } 1988 if (connCount == 0) 1989 { 1990 pResponse[kAVCOperand4] = kAVCInvalidPlug; 1991 } 1992 else if (connCount > 1) 1993 { 1994 pResponse[kAVCOperand3] = kAVCUnitAddress; 1995 pResponse[kAVCOperand4] = kAVCMultiplePlugs; 1996 pResponse[kAVCOperand0] |= 0x03; // Set bits 0 and 1 1997 } 1998 } 1999 else 2000 { 2001 // Parameter error, return not implemented response 2002 pResponse[kAVCCommandResponse] = kAVCNotImplementedStatus; 2003 } 2004 } 2005 else 2006 { 2007 // Initialize response 2008 pResponse[kAVCCommandResponse] = kAVCAcceptedStatus; 2009 2010 // Try and connect the plugs 2011 if (connectTargetPlugs(NULL,&inParams,&outParams) == kIOReturnSuccess) 2012 { 2013 // Update the plug num fields in the response 2014 pResponse[kAVCOperand2] = outParams.sourcePlugNum; 2015 pResponse[kAVCOperand4] = outParams.destPlugNum; 2016 } 2017 else 2018 { 2019 // Set rejected status in response 2020 pResponse[kAVCCommandResponse] = kAVCRejectedStatus; 2021 } 2022 } 2023 2024 AVCTARGETMUTEX_UNLOCK; 2025 2026 // Send the response 2027 targetSendAVCResponse(generation, nodeID, pBufMemDesc, len); 2028 2029 return kIOReturnSuccess; 2030} 2031 2032////////////////////////////////////////////////////// 2033// IOFireWireAVCTargetSpace::handleDisconnectCommand 2034////////////////////////////////////////////////////// 2035IOReturn IOFireWireAVCTargetSpace::handleDisconnectCommand(UInt16 nodeID, UInt32 generation, const char *buf, UInt32 len) 2036{ 2037 UInt8 *pResponse; 2038 UInt8 *pBuf = (UInt8*) buf; 2039 UInt8 cType; 2040 IOBufferMemoryDescriptor *pBufMemDesc = NULL; 2041 IOReturn res; 2042 IOFWAVCPlugTypes sourcePlugType; 2043 IOFWAVCPlugTypes destPlugType; 2044 2045 //IOLog( "IOFireWireAVCTargetSpace::handleDisconnectCommand (0x%08X)\n",(int) this); 2046 2047 // Check the length of the command. Don't handle command if wrong. 2048 if (len != 8) 2049 return kIOReturnError; 2050 2051 // Get the cType. Only control type accepted 2052 cType = pBuf[kAVCCommandResponse] & 0x0F; 2053 if (cType != kAVCControlCommand) 2054 return kIOReturnError; 2055 2056 // Further check the request packet parameters 2057 if (pBuf[kAVCOperand0] != 0xFF) 2058 return kIOReturnError; 2059 2060 // Determine type of source plug 2061 if (pBuf[kAVCOperand1] != kAVCUnitAddress) 2062 { 2063 if (pBuf[kAVCOperand2] < kAVCMaxNumPlugs) 2064 sourcePlugType = IOFWAVCPlugSubunitSourceType; 2065 else 2066 return kIOReturnError; 2067 } 2068 else 2069 { 2070 if (pBuf[kAVCOperand2] < kAVCMaxNumPlugs) 2071 sourcePlugType = IOFWAVCPlugIsochInputType; 2072 else if ((pBuf[kAVCOperand2] >= 0x80) && (pBuf[kAVCOperand2] <= 0x9E)) 2073 sourcePlugType = IOFWAVCPlugExternalInputType; 2074 else 2075 return kIOReturnError; 2076 } 2077 2078 // Determine type of dest plug 2079 if (pBuf[kAVCOperand3] != kAVCUnitAddress) 2080 { 2081 if ((pBuf[kAVCOperand4] < kAVCMaxNumPlugs) || (pBuf[kAVCOperand4] == kAVCAnyAvailableSubunitPlug)) 2082 destPlugType = IOFWAVCPlugSubunitDestType; 2083 else 2084 return kIOReturnError; 2085 } 2086 else 2087 { 2088 if ((pBuf[kAVCOperand4] < kAVCMaxNumPlugs) || (pBuf[kAVCOperand4] == kAVCAnyAvailableIsochPlug)) 2089 destPlugType = IOFWAVCPlugIsochOutputType; 2090 else if (((pBuf[kAVCOperand4] >= 0x80) && (pBuf[kAVCOperand4] <= 0x9E)) || (pBuf[kAVCOperand4] == kAVCAnyAvailableExternalPlug)) 2091 destPlugType = IOFWAVCPlugExternalOutputType; 2092 else 2093 return kIOReturnError; 2094 } 2095 2096 // All tests passed. Handle the command 2097 pBufMemDesc = IOBufferMemoryDescriptor::withCapacity(len, kIODirectionOutIn); 2098 if(!pBufMemDesc) 2099 return kFWResponseDataError; 2100 pResponse = (UInt8 *) pBufMemDesc->getBytesNoCopy(); 2101 bcopy(buf,pResponse,len); 2102 2103 AVCTARGETMUTEX_LOCK; 2104 2105 // Attempt to disconnect the plugs 2106 res = disconnectTargetPlugs(NULL, 2107 pBuf[kAVCOperand1], 2108 sourcePlugType, 2109 pBuf[kAVCOperand2], 2110 pBuf[kAVCOperand3], 2111 destPlugType, 2112 pBuf[kAVCOperand4]); 2113 2114 if (res == kIOReturnSuccess) 2115 pResponse[kAVCCommandResponse] = kAVCAcceptedStatus; 2116 else 2117 pResponse[kAVCCommandResponse] = kAVCRejectedStatus; 2118 2119 AVCTARGETMUTEX_UNLOCK; 2120 2121 targetSendAVCResponse(generation, nodeID, pBufMemDesc, len); 2122 2123 return kIOReturnSuccess; 2124} 2125 2126////////////////////////////////////////////////////// 2127// IOFireWireAVCTargetSpace::handleInputPlugSignalFormatCommand 2128////////////////////////////////////////////////////// 2129IOReturn IOFireWireAVCTargetSpace::handleInputPlugSignalFormatCommand(UInt16 nodeID, UInt32 generation, const char *buf, UInt32 len) 2130{ 2131 UInt8 *pResponse; 2132 IOBufferMemoryDescriptor *pBufMemDesc = NULL; 2133 UInt8 *pBuf = (UInt8*) buf; 2134 UInt8 cType; 2135 UInt32 plug; 2136 int i; 2137 AVCConnectionRecord *pConnection; 2138 bool found = false; 2139 AVCSubunitInfo *subUnitInfo; 2140 UInt32 signalFormat; 2141 2142 //IOLog( "IOFireWireAVCTargetSpace::handleInputPlugSignalFormatCommand (0x%08X)\n",(int) this); 2143 2144 // Check the length of the command. Don't handle command if wrong. 2145 if (len != 8) 2146 return kIOReturnError; 2147 2148 // Parse the command buf 2149 cType = pBuf[0] & 0x0F; 2150 plug = pBuf[kAVCOperand0]; 2151 signalFormat = (((UInt32)pBuf[kAVCOperand1] << 24) + 2152 ((UInt32)pBuf[kAVCOperand2] << 16) + 2153 ((UInt32)pBuf[kAVCOperand3] << 8) + 2154 (UInt32)pBuf[kAVCOperand4]); 2155 2156 // Further check the request packet parameters 2157 if (plug > (kAVCMaxNumPlugs-1)) 2158 return kIOReturnError; 2159 switch (cType) 2160 { 2161 case kAVCStatusInquiryCommand: 2162 if ((pBuf[kAVCOperand1] != 0xFF) || 2163 (pBuf[kAVCOperand2] != 0xFF) || 2164 (pBuf[kAVCOperand3] != 0xFF) || 2165 (pBuf[kAVCOperand4] != 0xFF)) 2166 return kIOReturnError; 2167 break; 2168 2169 case kAVCControlCommand: 2170 if ((pBuf[kAVCOperand1] & 0xC0) != 0x80) 2171 return kIOReturnError; 2172 break; 2173 2174 default: 2175 return kIOReturnError; 2176 }; 2177 2178 AVCTARGETMUTEX_LOCK; 2179 2180 // Search connection records for a subunit dest plug connection to this plug 2181 for (i=(fConnectionRecords->getCount()-1);i>=0;i--) 2182 { 2183 pConnection = (AVCConnectionRecord *) fConnectionRecords->getObject(i); 2184 if ((pConnection->sourceSubunitTypeAndID == kAVCUnitAddress) && 2185 (pConnection->sourcePlugNum == plug) && 2186 (pConnection->destSubunitTypeAndID != kAVCUnitAddress)) 2187 { 2188 subUnitInfo = getSubunitInfo(pConnection->destSubunitTypeAndID); 2189 if (subUnitInfo) 2190 { 2191 found = true; 2192 break; 2193 } 2194 } 2195 } 2196 2197 if ((found == true) && (cType == kAVCControlCommand)) 2198 { 2199 // Send callback to user client 2200 subUnitInfo->callBack(subUnitInfo, 2201 kIOFWAVCSubunitPlugMsgSignalFormatModified, 2202 IOFWAVCPlugSubunitDestType, 2203 pConnection->destPlugNum, 2204 signalFormat, 2205 generation, 2206 nodeID); 2207 2208 // Were done for now. User client will send response packet 2209 AVCTARGETMUTEX_UNLOCK; 2210 return kIOReturnSuccess; 2211 } 2212 2213 // We will send a response to handle the command 2214 pBufMemDesc = IOBufferMemoryDescriptor::withCapacity(len, kIODirectionOutIn); 2215 if(!pBufMemDesc) 2216 { 2217 AVCTARGETMUTEX_UNLOCK; 2218 return kFWResponseDataError; 2219 } 2220 pResponse = (UInt8 *) pBufMemDesc->getBytesNoCopy(); 2221 bcopy(buf,pResponse,len); 2222 2223 if (cType == kAVCStatusInquiryCommand) 2224 { 2225 pResponse[kAVCCommandResponse] = kAVCImplementedStatus; 2226 2227 // See if this plug has a connection 2228 if (found == true) 2229 { 2230 signalFormat = subUnitInfo->destPlugRecords[pConnection->destPlugNum].plugSignalFormat; 2231 pResponse[kAVCOperand1] = ((signalFormat & 0xFF000000) >> 24); 2232 pResponse[kAVCOperand2] = ((signalFormat & 0x00FF0000) >> 16); 2233 pResponse[kAVCOperand3] = ((signalFormat & 0x0000FF00) >> 8); 2234 pResponse[kAVCOperand4] = (signalFormat & 0x000000FF); 2235 } 2236 else 2237 { 2238 // If no connections, default plug signal type to NTSC-DV 2239 pResponse[kAVCOperand1] = ((kAVCPlugSignalFormatNTSCDV & 0xFF000000) >> 24); 2240 pResponse[kAVCOperand2] = ((kAVCPlugSignalFormatNTSCDV & 0x00FF0000) >> 16); 2241 pResponse[kAVCOperand3] = ((kAVCPlugSignalFormatNTSCDV & 0x0000FF00) >> 8); 2242 pResponse[kAVCOperand4] = (kAVCPlugSignalFormatNTSCDV & 0x000000FF); 2243 } 2244 } 2245 else 2246 { 2247 // This is a control type command to 2248 // a isoch output plug with no internal connection. 2249 // TODO: Today we just accept and ignore. But should we 2250 // maintain signal format for unconnected plugs? 2251 pResponse[kAVCCommandResponse] = kAVCAcceptedStatus; 2252 } 2253 2254 AVCTARGETMUTEX_UNLOCK; 2255 2256 targetSendAVCResponse(generation, nodeID, pBufMemDesc, len); 2257 2258 return kIOReturnSuccess; 2259} 2260 2261////////////////////////////////////////////////////// 2262// IOFireWireAVCTargetSpace::handleOutputPlugSignalFormatCommand 2263////////////////////////////////////////////////////// 2264IOReturn IOFireWireAVCTargetSpace::handleOutputPlugSignalFormatCommand(UInt16 nodeID, UInt32 generation, const char *buf, UInt32 len) 2265{ 2266 UInt8 *pResponse; 2267 IOBufferMemoryDescriptor *pBufMemDesc = NULL; 2268 UInt8 *pBuf = (UInt8*) buf; 2269 UInt8 cType; 2270 UInt32 plug; 2271 int i; 2272 AVCConnectionRecord *pConnection; 2273 bool found = false; 2274 AVCSubunitInfo *subUnitInfo; 2275 UInt32 signalFormat; 2276 2277 //IOLog( "IOFireWireAVCTargetSpace::handleOutputPlugSignalFormatCommand (0x%08X)\n",(int) this); 2278 2279 // Check the length of the command. Don't handle command if wrong. 2280 if (len != 8) 2281 return kIOReturnError; 2282 2283 // Parse the command buf 2284 cType = pBuf[0] & 0x0F; 2285 plug = pBuf[kAVCOperand0]; 2286 signalFormat = (((UInt32)pBuf[kAVCOperand1] << 24) + 2287 ((UInt32)pBuf[kAVCOperand2] << 16) + 2288 ((UInt32)pBuf[kAVCOperand3] << 8) + 2289 (UInt32)pBuf[kAVCOperand4]); 2290 2291 // Further check the request packet parameters 2292 if (plug > (kAVCMaxNumPlugs-1)) 2293 return kIOReturnError; 2294 switch (cType) 2295 { 2296 case kAVCStatusInquiryCommand: 2297 if ((pBuf[kAVCOperand1] != 0xFF) || 2298 (pBuf[kAVCOperand2] != 0xFF) || 2299 (pBuf[kAVCOperand3] != 0xFF) || 2300 (pBuf[kAVCOperand4] != 0xFF)) 2301 return kIOReturnError; 2302 break; 2303 2304 case kAVCControlCommand: 2305 if ((pBuf[kAVCOperand1] & 0xC0) != 0x80) 2306 return kIOReturnError; 2307 break; 2308 2309 default: 2310 return kIOReturnError; 2311 }; 2312 2313 AVCTARGETMUTEX_LOCK; 2314 2315 // Search connection records for a subunit source plug connection to this plug 2316 for (i=(fConnectionRecords->getCount()-1);i>=0;i--) 2317 { 2318 pConnection = (AVCConnectionRecord *) fConnectionRecords->getObject(i); 2319 if ((pConnection->destSubunitTypeAndID == kAVCUnitAddress) && 2320 (pConnection->destPlugNum == plug) && 2321 (pConnection->sourceSubunitTypeAndID != kAVCUnitAddress)) 2322 { 2323 subUnitInfo = getSubunitInfo(pConnection->sourceSubunitTypeAndID); 2324 if (subUnitInfo) 2325 { 2326 found = true; 2327 break; 2328 } 2329 } 2330 } 2331 2332 if ((found == true) && (cType == kAVCControlCommand)) 2333 { 2334 // Send callback to user client 2335 subUnitInfo->callBack(subUnitInfo, 2336 kIOFWAVCSubunitPlugMsgSignalFormatModified, 2337 IOFWAVCPlugSubunitSourceType, 2338 pConnection->sourcePlugNum, 2339 signalFormat, 2340 generation, 2341 nodeID); 2342 2343 // Were done for now. User client will send response packet 2344 AVCTARGETMUTEX_UNLOCK; 2345 return kIOReturnSuccess; 2346 } 2347 2348 // We will send a response to handle the command 2349 pBufMemDesc = IOBufferMemoryDescriptor::withCapacity(len, kIODirectionOutIn); 2350 if(!pBufMemDesc) 2351 { 2352 AVCTARGETMUTEX_UNLOCK; 2353 return kFWResponseDataError; 2354 } 2355 pResponse = (UInt8 *) pBufMemDesc->getBytesNoCopy(); 2356 bcopy(buf,pResponse,len); 2357 2358 if (cType == kAVCStatusInquiryCommand) 2359 { 2360 pResponse[kAVCCommandResponse] = kAVCImplementedStatus; 2361 2362 // See if this plug has a connection 2363 if (found == true) 2364 { 2365 signalFormat = subUnitInfo->sourcePlugRecords[pConnection->sourcePlugNum].plugSignalFormat; 2366 pResponse[kAVCOperand1] = ((signalFormat & 0xFF000000) >> 24); 2367 pResponse[kAVCOperand2] = ((signalFormat & 0x00FF0000) >> 16); 2368 pResponse[kAVCOperand3] = ((signalFormat & 0x0000FF00) >> 8); 2369 pResponse[kAVCOperand4] = (signalFormat & 0x000000FF); 2370 } 2371 else 2372 { 2373 // If no connections, default plug signal type to NTSC-DV 2374 pResponse[kAVCOperand1] = ((kAVCPlugSignalFormatNTSCDV & 0xFF000000) >> 24); 2375 pResponse[kAVCOperand2] = ((kAVCPlugSignalFormatNTSCDV & 0x00FF0000) >> 16); 2376 pResponse[kAVCOperand3] = ((kAVCPlugSignalFormatNTSCDV & 0x0000FF00) >> 8); 2377 pResponse[kAVCOperand4] = (kAVCPlugSignalFormatNTSCDV & 0x000000FF); 2378 } 2379 } 2380 else 2381 { 2382 // This is a control type command to 2383 // a isoch output plug with no internal connection. 2384 // TODO: Today we just accept and ignore. But should we 2385 // maintain signal format for unconnected plugs? 2386 pResponse[kAVCCommandResponse] = kAVCAcceptedStatus; 2387 } 2388 2389 AVCTARGETMUTEX_UNLOCK; 2390 2391 targetSendAVCResponse(generation, nodeID, pBufMemDesc, len); 2392 2393 return kIOReturnSuccess; 2394} 2395 2396////////////////////////////////////////////////////// 2397// IOFireWireAVCTargetSpace::handleConnectionsCommand 2398////////////////////////////////////////////////////// 2399IOReturn IOFireWireAVCTargetSpace::handleConnectionsCommand(UInt16 nodeID, UInt32 generation, const char *buf, UInt32 len) 2400{ 2401 UInt8 cType; 2402 UInt8 connectionCount; 2403 UInt32 responseLen; 2404 UInt8 *pBuf = (UInt8*) buf; 2405 UInt8 *pResponse; 2406 IOBufferMemoryDescriptor *pBufMemDesc = NULL; 2407 int i; 2408 AVCConnectionRecord *pConnection; 2409 UInt8 respIndex; 2410 UInt8 connectionType; 2411 2412 //IOLog( "IOFireWireAVCTargetSpace::handleConnectionsCommand (0x%08X)\n",(int) this); 2413 2414 // Check the length of the command. Don't handle command if wrong. 2415 if (len != 4) 2416 return kIOReturnError; 2417 2418 // Parse the command buf 2419 cType = pBuf[0] & 0x0F; 2420 2421 // Check the cType. Don't handle command if not a status type. 2422 if (cType != kAVCStatusInquiryCommand) 2423 return kIOReturnError; 2424 2425 if (pBuf[kAVCOperand0] != 0xFF) 2426 return kIOReturnError; 2427 2428 AVCTARGETMUTEX_LOCK; 2429 2430 connectionCount = (UInt8) (fConnectionRecords->getCount() & 0x000000FF); 2431 2432 // Limit this command to only include up to 100 connection records in 2433 // the response, to prevent going beyond the max AVC response packet size 2434 if (connectionCount > 100) 2435 connectionCount = 100; 2436 2437 responseLen = 4 + (connectionCount*5); 2438 2439 // We will send a response to handle the command 2440 pBufMemDesc = IOBufferMemoryDescriptor::withCapacity(responseLen, kIODirectionOutIn); 2441 if(!pBufMemDesc) 2442 { 2443 AVCTARGETMUTEX_UNLOCK; 2444 return kFWResponseDataError; 2445 } 2446 pResponse = (UInt8 *) pBufMemDesc->getBytesNoCopy(); 2447 2448 pResponse[kAVCCommandResponse] = kAVCImplementedStatus; 2449 pResponse[kAVCAddress] = 0xFF; 2450 pResponse[kAVCOpcode] = 0x22; 2451 pResponse[kAVCOperand0] = connectionCount; 2452 2453 respIndex = 4; 2454 2455 for (i=(connectionCount-1);i>=0;i--) 2456 { 2457 pConnection = (AVCConnectionRecord *) fConnectionRecords->getObject(i); 2458 2459 connectionType = 0xFC; 2460 if (pConnection->lockConnection) 2461 connectionType += 2; 2462 if (pConnection->permConnection) 2463 connectionType += 1; 2464 2465 pResponse[respIndex++] = connectionType; 2466 pResponse[respIndex++] = pConnection->sourceSubunitTypeAndID; 2467 pResponse[respIndex++] = pConnection->sourcePlugNum; 2468 pResponse[respIndex++] = pConnection->destSubunitTypeAndID; 2469 pResponse[respIndex++] = pConnection->destPlugNum; 2470 } 2471 2472 AVCTARGETMUTEX_UNLOCK; 2473 2474 targetSendAVCResponse(generation, nodeID, pBufMemDesc, responseLen); 2475 2476 return kIOReturnSuccess; 2477} 2478 2479////////////////////////////////////////////////////// 2480// IOFireWireAVCTargetSpace::handleSignalSourceCommand 2481////////////////////////////////////////////////////// 2482IOReturn IOFireWireAVCTargetSpace::handleSignalSourceCommand(UInt16 nodeID, UInt32 generation, const char *buf, UInt32 len) 2483{ 2484 //IOLog( "IOFireWireAVCTargetSpace::handleSignalSourceCommand (0x%08X)\n",(int) this); 2485 2486 // TODO: Not yet Handled! 2487 return kIOReturnError; 2488} 2489 2490////////////////////////////////////////////////////// 2491// IOFireWireAVCTargetSpace::pcrModified 2492////////////////////////////////////////////////////// 2493void IOFireWireAVCTargetSpace::pcrModified(IOFWAVCPlugTypes plugType, 2494 UInt32 plugNum, 2495 UInt32 newValue) 2496{ 2497 AVCConnectionRecord *pConnection; 2498 AVCSubunitInfo *subUnitInfo; 2499 int i; 2500 2501 //IOLog( "IOFireWireAVCTargetSpace::pcrModified (0x%08X)\n",(int) this); 2502 2503 AVCTARGETMUTEX_LOCK; 2504 2505 // Search through all the connection records to find subunit(s) connected 2506 // to this plug, and alert the subunit owner of the plug value modification 2507 for (i=(fConnectionRecords->getCount()-1);i>=0;i--) 2508 { 2509 pConnection = (AVCConnectionRecord *) fConnectionRecords->getObject(i); 2510 2511 switch (plugType) 2512 { 2513 case IOFWAVCPlugIsochInputType: 2514 if ((pConnection->sourceSubunitTypeAndID == kAVCUnitAddress) && 2515 (pConnection->sourcePlugNum == plugNum) && 2516 (pConnection->destSubunitTypeAndID != kAVCUnitAddress) ) 2517 { 2518 subUnitInfo = getSubunitInfo(pConnection->destSubunitTypeAndID); 2519 if (subUnitInfo) 2520 subUnitInfo->callBack(subUnitInfo, 2521 kIOFWAVCSubunitPlugMsgConnectedPlugModified, 2522 IOFWAVCPlugSubunitDestType, 2523 pConnection->destPlugNum, 2524 newValue, 2525 0,0); 2526 } 2527 break; 2528 2529 case IOFWAVCPlugIsochOutputType: 2530 if ((pConnection->destSubunitTypeAndID == kAVCUnitAddress) && 2531 (pConnection->destPlugNum == plugNum) && 2532 (pConnection->sourceSubunitTypeAndID != kAVCUnitAddress)) 2533 { 2534 subUnitInfo = getSubunitInfo(pConnection->sourceSubunitTypeAndID); 2535 if (subUnitInfo) 2536 subUnitInfo->callBack(subUnitInfo, 2537 kIOFWAVCSubunitPlugMsgConnectedPlugModified, 2538 IOFWAVCPlugSubunitSourceType, 2539 pConnection->sourcePlugNum, 2540 newValue, 2541 0,0); 2542 } 2543 break; 2544 2545 default: 2546 break; 2547 }; 2548 } 2549 2550 AVCTARGETMUTEX_UNLOCK; 2551 2552 return; 2553} 2554 2555////////////////////////////////////////////////////// 2556// IOFireWireAVCTargetSpace::getSubunitInfo 2557////////////////////////////////////////////////////// 2558AVCSubunitInfo *IOFireWireAVCTargetSpace::getSubunitInfo(UInt32 subunitTypeAndID) 2559{ 2560 AVCSubunitInfo *subunitInfo = NULL; 2561 int i; 2562 bool found = false; 2563 2564 //IOLog( "IOFireWireAVCTargetSpace::getSubunitInfo (0x%08X)\n",(int) this); 2565 2566 AVCTARGETMUTEX_LOCK; 2567 2568 // Find the subunit in the list 2569 for (i=(fSubunits->getCount()-1);i>=0;i--) 2570 { 2571 subunitInfo = (AVCSubunitInfo *) fSubunits->getObject(i); 2572 if (subunitInfo->subunitTypeAndID == subunitTypeAndID) 2573 { 2574 found = true; 2575 break; 2576 } 2577 } 2578 2579 AVCTARGETMUTEX_UNLOCK; 2580 2581 if (found == true) 2582 return subunitInfo; 2583 else 2584 return NULL; 2585} 2586 2587////////////////////////////////////////////////////// 2588// IOFireWireAVCTargetSpace::subUnitOfTypeCount 2589////////////////////////////////////////////////////// 2590UInt32 IOFireWireAVCTargetSpace::subUnitOfTypeCount(UInt32 type) 2591{ 2592 UInt32 cnt = 0; 2593 UInt32 subUnitType; 2594 AVCSubunitInfo *subUnitInfo; 2595 int i; 2596 2597 //IOLog( "IOFireWireAVCTargetSpace::subUnitOfTypeCount (0x%08X)\n",(int) this); 2598 2599 AVCTARGETMUTEX_LOCK; 2600 2601 for (i=(fSubunits->getCount()-1);i>=0;i--) 2602 { 2603 subUnitInfo = (AVCSubunitInfo *) fSubunits->getObject(i); 2604 subUnitType = ((subUnitInfo->subunitTypeAndID & 0xF8) >> 3); 2605 if (subUnitType == type) 2606 cnt+= 1; 2607 } 2608 2609 AVCTARGETMUTEX_UNLOCK; 2610 2611 return cnt; 2612} 2613 2614////////////////////////////////////////////////////// 2615// IOFireWireAVCTargetSpace::canConnectDestPlug 2616////////////////////////////////////////////////////// 2617bool IOFireWireAVCTargetSpace::canConnectDestPlug(UInt32 destSubunitTypeAndID, 2618 IOFWAVCPlugTypes destPlugType, 2619 UInt32 *destPlugNum) 2620{ 2621 bool res=true; 2622 int i; 2623 AVCConnectionRecord *connection; 2624 UInt32 actualPlugNumber = *destPlugNum; 2625 2626 // Search the connection records for a connection with this dest plug. 2627 // If we find one (and there can be at most one), check the lock and 2628 // perm bits. If both clear, disconnect the connection, 2629 // then return true, if either is set return false. 2630 // If no connection is found, return true. 2631 // If this dest plug is kAVCInvalidPlug, look for any connection, with 2632 // a dest plug matching this subunit/type, that can be disconnected. 2633 // AVCTARGETMUTEX_LOCK assumed already set!!! 2634 2635 for (i=(fConnectionRecords->getCount()-1);i>=0;i--) 2636 { 2637 connection = (AVCConnectionRecord *) fConnectionRecords->getObject(i); 2638 2639 if ((connection->destSubunitTypeAndID == destSubunitTypeAndID) && 2640 (connection->destPlugType == destPlugType)) 2641 { 2642 if ((actualPlugNumber == kAVCInvalidPlug) || (connection->destPlugNum == *destPlugNum)) 2643 { 2644 if ((connection->lockConnection == false) && (connection->permConnection == false)) 2645 { 2646 actualPlugNumber = connection->destPlugNum; 2647 2648 // Disconnect this connection 2649 disconnectTargetPlugs(NULL, 2650 connection->sourceSubunitTypeAndID, 2651 connection->sourcePlugType, 2652 connection->sourcePlugNum, 2653 connection->destSubunitTypeAndID, 2654 connection->destPlugType, 2655 connection->destPlugNum); 2656 2657 break; // No need to look anymore 2658 } 2659 else if (connection->destPlugNum == *destPlugNum) 2660 { 2661 res = false; 2662 break; // No need to look anymore 2663 } 2664 } 2665 } 2666 } 2667 2668 if (actualPlugNumber == kAVCInvalidPlug) 2669 { 2670 res = false; 2671 } 2672 else 2673 { 2674 *destPlugNum = actualPlugNumber; 2675 } 2676 2677 return res; 2678} 2679