void IOVideoSampleStream::postFreeInputBuffer(UInt64 vbiTime, UInt64 outputTime, UInt64 totalFrameCount, UInt64 droppedFrameCount,UInt64 lastDisplayedSequenceNumber)
{
	IOStreamBuffer* buf = OSDynamicCast(IOStreamBuffer, _freeBuffers->getObject(0));
	if (NULL == buf)
	{
		USBLog(1, "IOVideoSampleStream::postFreeInputBuffer - no free buffers\n");
		if ((getOutputQueue())->entryCount > 0)
		{
			//all the free buffers are in the queue already so just alert the host
			(void) sendOutputNotification();
		}
		return;
	}
	
	_freeBuffers->removeObject(0);

	IOMemoryDescriptor *ctrlDescriptor = OSDynamicCast(IOMemoryDescriptor, buf->getControlBuffer());
	if (NULL != ctrlDescriptor)
	{
		USBLog(1, "IOVideoSampleStream got control buffer descriptor\n");
		SampleVideoDeviceControlBuffer theBuffControl, readBackControl;
		USBLog(1, "IOVideoSampleStream::postFreeInputBuffer - passed in vbiTime = %lld outputTime = %lld framecount = %lld droppedframecount = %lld lastDisplayedSequenceNumber = %lld  \n", vbiTime, outputTime, totalFrameCount, droppedFrameCount, lastDisplayedSequenceNumber);

		
		theBuffControl.vbiTime = vbiTime; 
		theBuffControl.outputTime = outputTime; 
		theBuffControl.totalFrameCount = totalFrameCount; 
		theBuffControl.droppedFrameCount = droppedFrameCount; 
		theBuffControl.firstVBITime = 0;
		theBuffControl.sequenceNumber = lastDisplayedSequenceNumber;
		theBuffControl.discontinuityFlags = 0;
		
		(void) ctrlDescriptor->prepare();
		
        ctrlDescriptor->writeBytes(0, &theBuffControl, buf->getControlBuffer()->getLength());
		ctrlDescriptor->readBytes(0, &readBackControl, buf->getControlBuffer()->getLength());
		USBLog(1, "IOVideoSampleStream::postFreeInputBuffer - control buffer info vbiTime = %lld outputTime = %lld framecount = %lld droppedframecount = %lld  sequencenumber = %lld\n", readBackControl.vbiTime, readBackControl.outputTime, readBackControl.totalFrameCount, readBackControl.droppedFrameCount,readBackControl.sequenceNumber);
		(void) ctrlDescriptor->complete();
	}
		
	IOReturn result = enqueueOutputBuffer(buf, 0, buf->getDataBuffer()->getLength(), 0, buf->getControlBuffer()->getLength()); 
	if (result != kIOReturnSuccess)
	{
		USBLog(1, "IOVideoSampleStream::postFreeInputBuffer help enqueueOutputBuffer failed! (%x)\n", result);
		return;
	}
	
	result = sendOutputNotification();
	if (result != kIOReturnSuccess)
	{
		USBLog(1, "IOVideoSampleStream::postFreeInputBuffer help sendOutputNotification failed! (%x)\n", result);
		return;
	}
}
static inline bool hpetIsInvalid()
{
    hpetInfo_t hpetInfo;
    hpet_get_info(&hpetInfo);
    // The AppleIntelCPUPowerManagement will crash if rcbaArea and/or HPET is NULL
    // Ordinarily this can never happen but modified xnu can allow for this.
    if(hpetInfo.rcbaArea == 0)
    {
        IOLog("Forcing takeover of AppleIntelCPUPowerManagement resource due to lack of RCBA (no LPC?)\n");
        return true;
    }
    // Another case is that the LPC exists but the HPET isn't really valid.
    // That is to say that virtual hardware provides enough to get past xnu startup
    // but not enough to really make the HPET work.

    uint32_t hptc = *(uint32_t*)(hpetInfo.rcbaArea + 0x3404);
    if(!(hptc & hptcAE))
    {
        IOLog("Forcing takeover of AppleIntelCPUPowerManagement resource because HPET is not enabled\n");
        return true;
    }
    // Use the RCBA's HPTC to determine which of the four possible HPET physical addresses is used
    uint32_t hpetAreap = hpetAddr | ((hptc & 3) << 12);
    IOMemoryDescriptor *hpetMemDesc = IOMemoryDescriptor::withPhysicalAddress(hpetAreap, sizeof(hpetReg_t), kIODirectionIn);

    // grab the GCAP_ID (note offset is actually 0)
    uint64_t GCAP_ID;
    hpetMemDesc->readBytes(offsetof(hpetReg_t, GCAP_ID), &GCAP_ID, sizeof(GCAP_ID));

    // We're done with the memory descriptor now, so release it
    hpetMemDesc->release();
    hpetMemDesc = NULL;

    // Extract the VENDOR_ID_CAP field from the GCAP_ID and test it
    uint16_t vendorId = bitfield(GCAP_ID, 31, 16);
    if( (vendorId == 0x0000) || (vendorId == 0xffff))
    {
        IOLog("Forcing takeover of AppleIntelCPUPowerManagement resource due to bad HPET VENDOR_ID_CAP\n");
        return true;
    }
    else if(vendorId != 0x8086)
    {
        IOLog("WARNING: HPET is not Intel.  Going ahead and allowing AppleIntelCPUPowerManagement to start but beware it may behave strangely\n");
    }
    return false;
}
// Processes a message for a controller
void WirelessGamingReceiver::ProcessMessage(int index, const unsigned char *data, int length)
{
/*
    char s[1024];
    int i;
    
    for (i = 0; i < length; i++)
    {
        s[(i * 2) + 0] = "0123456789ABCDEF"[(data[i] & 0xF0) >> 4];
        s[(i * 2) + 1] = "0123456789ABCDEF"[data[i] & 0x0F];
    }
    s[i * 2] = '\0';
    IOLog("Got data (%d, %d bytes): %s\n", index, length, s);
*/
    // Handle device connections
    if ((length == 2) && (data[0] == 0x08))
    {
        if (data[1] == 0x00)
        {
            // Device disconnected
//            IOLog("process: Device detached\n");
            if (connections[index].service != NULL)
            {
                connections[index].service->SetIndex(-1);
                if (connections[index].controllerStarted)
                    connections[index].service->terminate(kIOServiceRequired | kIOServiceSynchronous);
                connections[index].service->detach(this);
                connections[index].service->release();
                connections[index].service = NULL;
                connections[index].controllerStarted = false;
            }
        }
        else
        {
            // Device connected
//            IOLog("process: Attempting to add new device\n");
            if (connections[index].service == NULL)
            {
                bool ready;
                int i, j;
                IOMemoryDescriptor *data;
                char c;
                
                ready = false;
                j = connections[index].inputArray->getCount();
                for (i = 0; !ready && (i < j); i++)
                {
                    data = OSDynamicCast(IOMemoryDescriptor, connections[index].inputArray->getObject(i));
                    data->readBytes(1, &c, 1);
                    if (c == 0x0f)
                        ready = true;
                }
                InstantiateService(index);
                if (ready)
                {
//                    IOLog("Registering wireless device");
                    connections[index].controllerStarted = true;
                    connections[index].service->registerService();
                }
            }
        }
        return;
    }
    
    // Add anything else to the queue
    IOMemoryDescriptor *copy = IOBufferMemoryDescriptor::inTaskWithOptions(kernel_task, 0, length);
    copy->writeBytes(0, data, length);
    connections[index].inputArray->setObject(copy);
    if (connections[index].service == NULL)
        InstantiateService(index);
    if (connections[index].service != NULL)
    {
        connections[index].service->NewData();
        if (!connections[index].controllerStarted)
        {
            char c;
            
            copy->readBytes(1, &c, 1);
            if (c == 0x0f)
            {
//                IOLog("Registering wireless device");
                connections[index].controllerStarted = true;
                connections[index].service->registerService();
            }
        }
    }
    copy->release();
}
IOReturn SamplePCIUserClientClassName::method2( SampleStructForMethod2 * structIn,
        SampleResultsForMethod2 * structOut,
        IOByteCount inputSize, IOByteCount * outputSize )

{
    IOReturn err;
    IOMemoryDescriptor * memDesc = 0;
    UInt32 param1 = structIn->parameter1;

    uint64_t clientAddr = structIn->data_pointer;
    uint64_t size = structIn->data_length;

    // Rosetta
    if (fCrossEndian) {
        param1 = OSSwapInt32(param1);
    }

    IOLog("SamplePCIUserClient::method2(" UInt32_x_FORMAT ")\n", param1);
    IOLog( "fClientShared->string == \"%s\"\n", fClientShared->string );

    structOut->results1 = 0x87654321;
    // Rosetta
    if (fCrossEndian) {
        structOut->results1 = OSSwapInt64(structOut->results1);
        clientAddr = OSSwapInt64(clientAddr);
        size = OSSwapInt64(size);
    }

    do
    {

#if defined(__ppc__) && (MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4)
        // construct a memory descriptor for the out of line client memory
        // old 32 bit API - this will fail and log a backtrace if the task is 64 bit
        IOLog("The Pre-Leopard way to construct a memory descriptor\n");
        memDesc = IOMemoryDescriptor::withAddress( (vm_address_t) clientAddr, (IOByteCount) size, kIODirectionNone, fTask );
        if (memDesc == NULL) {
            IOLog("IOMemoryDescriptor::withAddress failed\n");
            err = kIOReturnVMError;
            continue;
        }
#else
        // 64 bit API - works on all tasks, whether 64 bit or 32 bit
        IOLog("The Leopard and later way to construct a memory descriptor\n");
        memDesc = IOMemoryDescriptor::withAddressRange( clientAddr, size, kIODirectionNone, fTask );
        if (memDesc == NULL) {
            IOLog("IOMemoryDescriptor::withAddresswithAddressRange failed\n");
            err = kIOReturnVMError;
            continue;
        }
#endif
        // Wire it and make sure we can write it
        err = memDesc->prepare( kIODirectionOutIn );
        if (kIOReturnSuccess != err) {
            IOLog("IOMemoryDescriptor::prepare failed(0x%08x)\n", err);
            continue;
        }

        // Generate a DMA list for the client memory
        err = fDriver->generateDMAAddresses(memDesc);

        // Other methods to access client memory:

        // readBytes/writeBytes allow programmed I/O to/from an offset in the buffer
        char pioBuffer[ 200 ];
        memDesc->readBytes(32, &pioBuffer, sizeof(pioBuffer));
        IOLog("readBytes: \"%s\"\n", pioBuffer);

        // map() will create a mapping in the kernel address space.
        IOMemoryMap* memMap = memDesc->map();
        if (memMap) {
            char* address = (char *) memMap->getVirtualAddress();
            IOLog("kernel mapped: \"%s\"\n", address + 32);
            memMap->release();
        } else {
            IOLog("memDesc map(kernel) failed\n");
        }

        // this map() will create a mapping in the users (the client of this IOUserClient) address space.
#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
        memMap = memDesc->map(fTask, 0, kIOMapAnywhere);
#else
        memMap = memDesc->createMappingInTask(fTask, 0, kIOMapAnywhere);
#endif
        if (memMap) {
#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
            IOLog("The pre-Leopard way to construct a memory descriptor\n");
            // old 32 bit API - this will truncate and log a backtrace if the task is 64 bit
            IOVirtualAddress address32 = memMap->getVirtualAddress();
            IOLog("user32 mapped: " VirtAddr_FORMAT "\n", address32);
#else
            IOLog("The Leopard and later way to construct a memory descriptor\n");
            // new 64 bit API - same for 32 bit and 64 bit client tasks
            mach_vm_address_t address64 = memMap->getAddress();
            IOLog("user64 mapped: 0x%016llx\n", address64);
            memMap->release();
#endif
        } else {
            IOLog("memDesc map(user) failed\n");
        }

        // Done with the I/O now.
        memDesc->complete( kIODirectionOutIn );

    } while ( false );

    if (memDesc)
        memDesc->release();

    return err;
}
bool RadeonController::start( IOService * provider )
{
	if (!super::start(provider)) return false;
	
	device = OSDynamicCast(IOPCIDevice, provider);
	if (device == NULL) return false;
	
	//get user options
	OSBoolean *prop;
	
	OSDictionary *dict = OSDynamicCast(OSDictionary, getProperty("UserOptions"));
	
	bzero(&options, sizeof(UserOptions));
	options.HWCursorSupport = FALSE;
	options.enableGammaTable = FALSE;
	options.enableOSXI2C = FALSE;
	
	options.lowPowerMode = FALSE;
	if (dict) {
		prop = OSDynamicCast(OSBoolean, dict->getObject("enableHWCursor"));
		if (prop) options.HWCursorSupport = prop->getValue();
		prop = OSDynamicCast(OSBoolean, dict->getObject("debugMode"));
		if (prop) options.debugMode = prop->getValue();
		if (options.debugMode) options.HWCursorSupport = FALSE;
		prop = OSDynamicCast(OSBoolean, dict->getObject("enableGammaTable"));
		if (prop) options.enableGammaTable = prop->getValue();
		prop = OSDynamicCast(OSBoolean, dict->getObject("lowPowerMode"));
		if (prop) options.lowPowerMode = prop->getValue();
	}
	options.verbosity = 1;
#ifdef DEBUG
	if (0 == getRegistryRoot()->getProperty("RadeonDumpReady")) {
		getRegistryRoot()->setProperty("RadeonDumpReady", kOSBooleanTrue);
		DumpMsg.mVerbose = 1;
		DumpMsg.client = 1;
		DumpMsg.mMsgBufferSize = 65535;
		if (dict) {
			OSNumber *optionNum;
			optionNum = OSDynamicCast(OSNumber, dict->getObject("verboseLevel"));
			if (optionNum) DumpMsg.mVerbose = optionNum->unsigned32BitValue();
			optionNum = OSDynamicCast(OSNumber, dict->getObject("MsgBufferSize"));
			if (optionNum) DumpMsg.mMsgBufferSize = max(65535, optionNum->unsigned32BitValue());
		}	
		DumpMsg.mMsgBufferEnabled = false;
		DumpMsg.mMsgBufferPos = 0;
		DumpMsg.mMessageLock = IOLockAlloc();
		DumpMsg.mMsgBuffer = (char *) IOMalloc(DumpMsg.mMsgBufferSize);
		if (!DumpMsg.mMsgBuffer) {
			IOLog("error: couldn't allocate message buffer (%ld bytes)\n", DumpMsg.mMsgBufferSize);
			return false;
		}
		enableMsgBuffer(true);
	} else DumpMsg.client += 1;
	options.verbosity = DumpMsg.mVerbose;
#endif
	
	device->setMemoryEnable(true);
	IOMap = device->mapDeviceMemoryWithRegister( kIOPCIConfigBaseAddress2 );
	if (IOMap == NULL) return false;
	FBMap = device->mapDeviceMemoryWithRegister( kIOPCIConfigBaseAddress0 );
	if (FBMap == NULL) return false;
	memoryMap.MMIOBase = (pointer) IOMap->getVirtualAddress();
	memoryMap.MMIOMapSize = IOMap->getLength();
	memoryMap.FbBase = (pointer) FBMap->getVirtualAddress();
	memoryMap.FbMapSize = FBMap->getLength();
	memoryMap.FbPhysBase = (unsigned long)FBMap->getPhysicalAddress();
	memoryMap.bitsPerPixel = 32;
	memoryMap.bitsPerComponent = 8;
	memoryMap.colorFormat = 0;	//0 for non-64 bit
	
	memoryMap.BIOSCopy = NULL;
	memoryMap.BIOSLength = 0;
	
	IOMemoryDescriptor * mem;
	mem = IOMemoryDescriptor::withPhysicalAddress((IOPhysicalAddress) RHD_VBIOS_BASE, RHD_VBIOS_SIZE, kIODirectionOut);
	if (mem) {
		memoryMap.BIOSCopy = (unsigned char *)IOMalloc(RHD_VBIOS_SIZE);
		if (memoryMap.BIOSCopy) {
			mem->prepare(kIODirectionOut);
			if (!(memoryMap.BIOSLength = mem->readBytes(0, memoryMap.BIOSCopy, RHD_VBIOS_SIZE))) {
				LOG("Cannot read BIOS image\n");
				memoryMap.BIOSLength = 0;
			}
			if ((unsigned int)memoryMap.BIOSLength != RHD_VBIOS_SIZE)
				LOG("Read only %d of %d bytes of BIOS image\n", memoryMap.BIOSLength, RHD_VBIOS_SIZE);
			mem->complete(kIODirectionOut);
		}
	}

	if (dict) {
		const char typeKey[2][8] = {"@0,TYPE", "@1,TYPE"};
		const char EDIDKey[2][8] = {"@0,EDID", "@1,EDID"};
		const char fixedModesKey[2][17] = {"@0,UseFixedModes", "@1,UseFixedModes"};
		OSString *type;
		OSData *edidData;
		OSBoolean *boolData;
		int i;
		for (i = 0;i < 2;i++) {
			type = OSDynamicCast(OSString, dict->getObject(typeKey[i]));
			if (!type) continue;
			edidData = OSDynamicCast(OSData, dict->getObject(EDIDKey[i]));
			if (edidData == NULL) continue;
			options.EDID_Block[i] = (unsigned char *)IOMalloc(edidData->getLength());
			if (options.EDID_Block[i] == NULL) continue;
			strncpy(options.outputTypes[i], type->getCStringNoCopy(), outputTypeLength);
			bcopy(edidData->getBytesNoCopy(), options.EDID_Block[i], edidData->getLength());
			options.EDID_Length[i] = edidData->getLength();
			
			boolData = OSDynamicCast(OSBoolean, dict->getObject(fixedModesKey[i]));
			if (boolData) options.UseFixedModes[i] = boolData->getValue();
		}
	}
		
	xf86Screens[0] = IONew(ScrnInfoRec, 1);	//using global variable, will change it later
	ScrnInfoPtr pScrn = xf86Screens[0];
	if (pScrn == NULL) return false;
	bzero(pScrn, sizeof(ScrnInfoRec));
	MAKE_REG_ENTRY(&nub, device);
	pciRec.chipType = device->configRead16(kIOPCIConfigDeviceID);
	pciRec.subsysVendor = device->configRead16(kIOPCIConfigSubSystemVendorID);
	pciRec.subsysCard = device->configRead16(kIOPCIConfigSubSystemID);
	pciRec.biosSize = 16;	//RHD_VBIOS_SIZE = 1 << 16
	pScrn->PciTag = &nub;
	pScrn->PciInfo = &pciRec;
	pScrn->options = &options;
	pScrn->memPhysBase = (unsigned long)FBMap->getPhysicalAddress();
	pScrn->fbOffset = 0;	//scanout offset
	pScrn->bitsPerPixel = 32;
	pScrn->bitsPerComponent = 8;
	pScrn->colorFormat = 0;
	pScrn->depth = pScrn->bitsPerPixel;
	pScrn->memoryMap = &memoryMap;
	
	
	createNubs(provider);
	
	setModel(device);
	
	return true;
}
예제 #6
0
IOReturn
IOUSBController::CheckForDisjointDescriptor(IOUSBCommand *command, UInt16 maxPacketSize)
{
    IOMemoryDescriptor			*buf = command->GetBuffer();
    IOBufferMemoryDescriptor	*newBuf = NULL;
    IOByteCount					length = command->GetReqCount();
	IODMACommand				*dmaCommand = command->GetDMACommand();
    IOByteCount					segLength = 0;
    IOByteCount					offset = 0;
    IOReturn					err;
	UInt64						offset64;
	IODMACommand::Segment64		segment64;
	UInt32						numSegments;
	
	// USBTrace_Start( kUSBTController, kTPControllerCheckForDisjointDescriptor, (uintptr_t)this );
	
    // Zero length buffers are valid, but they are surely not disjoint, so just return success.  
    //
    if ( length == 0 )
        return kIOReturnSuccess;
	
	if (!dmaCommand)
	{
		USBLog(1, "%s[%p]::CheckForDisjointDescriptor - no dmaCommand", getName(), this);
		USBTrace( kUSBTController, kTPControllerCheckForDisjointDescriptor, (uintptr_t)this, kIOReturnBadArgument, 0, 1 );
		return kIOReturnBadArgument;
	}
	
	if (dmaCommand->getMemoryDescriptor() != buf)
	{
		USBLog(1, "%s[%p]::CheckForDisjointDescriptor - mismatched memory descriptor (%p) and dmaCommand memory descriptor (%p)", getName(), this, buf, dmaCommand->getMemoryDescriptor());
		USBTrace( kUSBTController, kTPControllerCheckForDisjointDescriptor, kIOReturnBadArgument, (uintptr_t)buf, (uintptr_t)dmaCommand->getMemoryDescriptor(), 2 );
		return kIOReturnBadArgument;
	}
	
    while (length)
    {
		offset64 = offset;
		numSegments = 1;
		
		err = dmaCommand->gen64IOVMSegments(&offset64, &segment64, &numSegments);
        if (err || (numSegments != 1))
        {
            USBLog(1, "%s[%p]::CheckForDisjointDescriptor - err (%p) trying to generate segments at offset (%qd), length (%d), segLength (%d), total length (%d), buf (%p), numSegments (%d)", getName(), this, (void*)err, offset64, (int)length, (int)segLength, (int)command->GetReqCount(), buf, (int)numSegments);
			USBTrace( kUSBTController, kTPControllerCheckForDisjointDescriptor, offset64, length, segLength, 3 );
			USBTrace( kUSBTController, kTPControllerCheckForDisjointDescriptor, segLength, command->GetReqCount(), numSegments, 4 );
            return kIOReturnBadArgument;
        }

		
		// 3036056 since length might be less than the length of the descriptor, we are OK if the physical
		// segment is longer than we need
        if (segment64.fLength >= length)
            return kIOReturnSuccess;		// this is the last segment, so we are OK
		
		// since length is a 32 bit quantity, then we know from the above statement that if we are here we are 32 bit only
		segLength = (IOByteCount)segment64.fLength;

        // so the segment is less than the rest of the length - we need to check against maxPacketSize
        if (segLength % maxPacketSize)
        {
            // this is the error case. I need to copy the descriptor to a new descriptor and remember that I did it
            USBLog(6, "%s[%p]::CheckForDisjointDescriptor - found a disjoint segment of length (%d) MPS (%d)", getName(), this, (int)segLength, maxPacketSize);
			length = command->GetReqCount();		// we will not return to the while loop, so don't worry about changing the value of length
													// allocate a new descriptor which is the same total length as the old one
			newBuf = IOBufferMemoryDescriptor::withOptions((command->GetDirection() == kUSBIn) ? kIODirectionIn : kIODirectionOut, length);
			if (!newBuf)
			{
				USBLog(1, "%s[%p]::CheckForDisjointDescriptor - could not allocate new buffer", getName(), this);
				USBTrace( kUSBTController, kTPControllerCheckForDisjointDescriptor, (uintptr_t)this, kIOReturnNoMemory, 0, 5 );
				return kIOReturnNoMemory;
			}
			USBLog(7, "%s[%p]::CheckForDisjointDescriptor, obtained buffer %p of length %d", getName(), this, newBuf, (int)length);
			
			// first close out (and complete) the original dma command descriptor
			USBLog(7, "%s[%p]::CheckForDisjointDescriptor, clearing memDec (%p) from dmaCommand (%p)", getName(), this, dmaCommand->getMemoryDescriptor(), dmaCommand);
			dmaCommand->clearMemoryDescriptor();
			
			// copy the bytes to the buffer if necessary
			if (command->GetDirection() == kUSBOut)
			{
				USBLog(7, "%s[%p]::CheckForDisjointDescriptor, copying %d bytes from desc %p to buffer %p", getName(), this, (int)length, buf, newBuf->getBytesNoCopy());
				if (buf->readBytes(0, newBuf->getBytesNoCopy(), length) != length)
				{
					USBLog(1, "%s[%p]::CheckForDisjointDescriptor - bad copy on a write", getName(), this);
					USBTrace( kUSBTController, kTPControllerCheckForDisjointDescriptor, (uintptr_t)this, 0, 0, 6 );
					newBuf->release();
					return kIOReturnNoMemory;
				}
			}
			err = newBuf->prepare();
			if (err)
			{
				USBLog(1, "%s[%p]::CheckForDisjointDescriptor - err 0x%x in prepare", getName(), this, err);
				USBTrace( kUSBTController, kTPControllerCheckForDisjointDescriptor, (uintptr_t)this, err, 0, 7 );
				newBuf->release();
				return err;
			}
			err = dmaCommand->setMemoryDescriptor(newBuf);
			if (err)
			{
				USBLog(1, "%s[%p]::CheckForDisjointDescriptor - err 0x%x in setMemoryDescriptor", getName(), this, err);
				USBTrace( kUSBTController, kTPControllerCheckForDisjointDescriptor, (uintptr_t)this, err, 0, 8 );
				newBuf->complete();
				newBuf->release();
				return err;
			}
			
			command->SetOrigBuffer(command->GetBuffer());
			command->SetDisjointCompletion(command->GetClientCompletion());
			USBLog(7, "%s[%p]::CheckForDisjointDescriptor - changing buffer from (%p) to (%p) and putting new buffer in dmaCommand (%p)", getName(), this, command->GetBuffer(), newBuf, dmaCommand);
			command->SetBuffer(newBuf);
			
			
			IOUSBCompletion completion;
			completion.target = this;
			completion.action = (IOUSBCompletionAction)DisjointCompletion;
			completion.parameter = command;
			command->SetClientCompletion(completion);
			
			command->SetDblBufLength(length);			// for the IOFree - the other buffer may change size
            return kIOReturnSuccess;
		}
        length -= segLength;		// adjust our master length pointer
		offset += segLength;
	}
	
	USBLog(5, "%s[%p]::CheckForDisjointDescriptor - returning kIOReturnBadArgument(0x%x)", getName(), this, kIOReturnBadArgument);
	// USBTrace_End( kUSBTController, kTPControllerCheckForDisjointDescriptor, (uintptr_t)this, kIOReturnBadArgument);
	
    return kIOReturnBadArgument;
}