IOFWUserIsochChannel.cpp [plain text]
#include <libkern/c++/OSCollectionIterator.h>
#include <libkern/c++/OSSet.h>
#include <IOKit/firewire/IOFireWireController.h>
#include <IOKit/firewire/IOFWCommand.h>
#include <IOKit/firewire/IOFWIsochPort.h>
#include "IOFWUserIsochChannel.h"
#include"IOFireWireUserClient.h"
OSDefineMetaClassAndStructors(IOFWUserIsochChannel, IOFWIsochChannel)
IOReturn
IOFWUserIsochChannel::allocateChannel()
{
IOLog("IOFWUserIsochChannel::allocateChannel called!\n") ;
return kIOReturnUnsupported ;
}
IOReturn
IOFWUserIsochChannel::releaseChannel()
{
IOLog("IOFWUserIsochChannel::releaseChannel called!\n") ;
return kIOReturnUnsupported ;
}
IOReturn
IOFWUserIsochChannel::start()
{
IOLog("IOFWUserIsochChannel::start called!\n") ;
return kIOReturnUnsupported ;
}
IOReturn
IOFWUserIsochChannel::stop()
{
IOLog("IOFWUserIsochChannel::stop called!\n") ;
return kIOReturnUnsupported ;
}
IOReturn
IOFWUserIsochChannel::userAllocateChannelBegin(
IOFWSpeed inSpeed,
UInt32 inAllowedChansHi,
UInt32 inAllowedChansLo,
IOFWSpeed* outActualSpeed,
UInt32* outActualChannel)
{
IOReturn result = kIOReturnSuccess;
if (!fBandwidthAllocated)
{
UInt64 allowedChans = (UInt64)inAllowedChansHi<<32 | inAllowedChansLo ;
UInt64 savedChans ;
UInt16 irm ;
UInt32 generation ;
UInt32 newVal ;
FWAddress addr(kCSRRegisterSpaceBaseAddressHi, kCSRBandwidthAvailable) ;
UInt32 old[3] ;
UInt32 bandwidth ;
UInt32 channel ;
bool tryAgain ;
IOFireWireUserClientLog_( ("IOFWUserIsochChannel::userAllocateChannelBegin: allowedChans=%08lX%08lX\n",
(UInt32)(allowedChans >> 32), (UInt32)(allowedChans & 0xFFFFFFFF)) ) ;
fSpeed = inSpeed ;
do {
if(fDoIRM) {
IOFireWireUserClientLog_(("IOFWUserIsochChannel::userAllocateChannelBegin: doing IRM\n") ) ;
fControl->getIRMNodeID(generation, irm);
savedChans = allowedChans; bandwidth = (fPacketSize/4 + 3) * 16 / (1 << fSpeed);
addr.nodeID = irm;
do {
fReadCmd->reinit(generation, addr, old, 3);
fReadCmd->setMaxPacket(4);
result = fReadCmd->submit();
} while ( result == kIOFireWireBusReset ) ;
if(kIOReturnSuccess != result) {
break;
}
allowedChans &= (UInt64)(old[2]) | ((UInt64)old[1] << 32);
tryAgain = false;
do {
if(old[0] < bandwidth) {
IOFireWireUserClientLog_(("IOFWUserIsochChannel::userAllocateChannelBegin: bandwidth=0x%08lX, old[0]=0x%08lX\n", bandwidth, old[0])) ;
result = kIOReturnNoSpace;
break;
}
newVal = old[0] - bandwidth;
fLockCmd->reinit(generation, addr, &old[0], &newVal, 1);
result = fLockCmd->submit();
IOFireWireUserClientLogIfErr_( result, ("IOFWUserIsochChannel::userAllocateChannelBegin: bandwith update result 0x%x\n", result) ) ;
tryAgain = !fLockCmd->locked(&old[0]);
} while (tryAgain);
if(kIOReturnSuccess != result)
break;
fBandwidth = bandwidth;
}
tryAgain = false;
do {
for(channel=0; channel<64; channel++) {
if(allowedChans & ((UInt64)1 << ( 63 - channel )) ) {
break;
}
}
if(channel == 64) {
result = kIOReturnNoResources;
break;
}
if(fDoIRM) {
UInt32 *oldPtr;
if(channel < 32) {
addr.addressLo = kCSRChannelsAvailable31_0;
oldPtr = &old[1];
newVal = *oldPtr & ~(1<<(31-channel));
}
else {
addr.addressLo = kCSRChannelsAvailable63_32;
oldPtr = &old[2];
newVal = *oldPtr & ~( (UInt64)1 << (63-channel) );
}
fLockCmd->reinit(generation, addr, oldPtr, &newVal, 1);
result = fLockCmd->submit();
IOFireWireUserClientLogIfErr_( result, ("channel update result 0x%x\n", result) );
tryAgain = !fLockCmd->locked(oldPtr);
}
else
tryAgain = false;
} while (tryAgain);
if(kIOReturnSuccess != result)
break;
fChannel = channel;
if(fDoIRM)
fControl->addAllocatedChannel(this);
} while (false);
fBandwidthAllocated = (kIOReturnSuccess == result) ;
}
IOFireWireUserClientLogIfErr_( result, ( "-IOFWUserIsochChannel::userAllocateChannelBegin: result=0x%08lX, fSpeed=%u, fChannel=0x%08lX\n", (UInt32) result, fSpeed, fChannel) ) ;
*outActualSpeed = fSpeed ;
*outActualChannel = fChannel ;
return result;
}
IOReturn
IOFWUserIsochChannel::userReleaseChannelComplete()
{
if (fBandwidthAllocated)
if(fDoIRM) {
fControl->removeAllocatedChannel(this);
updateBandwidth(false);
IOFireWireUserClientLog_(("IOFWUserIsochChannel::userReleaseChannelComplete: freeing up bandwidth (is now %08lX)\n", fBandwidth)) ;
}
fBandwidthAllocated = false ;
return kIOReturnSuccess;
}
IOReturn
IOFWUserIsochChannel::allocateListenerPorts()
{
IOFWIsochPort* listen;
IOReturn result = kIOReturnSuccess ;
OSIterator* listenIterator = OSCollectionIterator::withCollection(fListeners) ;
if(listenIterator) {
listenIterator->reset();
while( (listen = (IOFWIsochPort *) listenIterator->getNextObject()) && (result == kIOReturnSuccess)) {
result = listen->allocatePort(fSpeed, fChannel);
}
listenIterator->release();
}
return result ;
}
IOReturn
IOFWUserIsochChannel::allocateTalkerPort()
{
IOReturn result = kIOReturnSuccess ;
if(fTalker)
result = fTalker->allocatePort(fSpeed, fChannel);
return result ;
}