IOWorkLoop *
IOFWUserLocalIsochPort::createRealtimeThread()
{
	IOWorkLoop * workloop = IOWorkLoop::workLoop() ;
	if ( workloop )
	{
		// Boost isoc workloop into realtime range
		thread_time_constraint_policy_data_t	constraints;
		AbsoluteTime							time;
		
		nanoseconds_to_absolutetime(625000, &time);
		constraints.period = AbsoluteTime_to_scalar(&time);
		nanoseconds_to_absolutetime(60000, &time);
		constraints.computation = AbsoluteTime_to_scalar(&time);
		nanoseconds_to_absolutetime(1250000, &time);
		constraints.constraint = AbsoluteTime_to_scalar(&time);

		constraints.preemptible = TRUE;

		{
			IOThread thread;
			thread = workloop->getThread();
			thread_policy_set( thread, THREAD_TIME_CONSTRAINT_POLICY, (thread_policy_t) & constraints, THREAD_TIME_CONSTRAINT_POLICY_COUNT );			
		}
	}
	
	return workloop ;
}
void IOFireWireController::processTimeout(IOTimerEventSource *src)
{
    // complete() might take significant time, enough to cause
    // a later command to timeout too, so we loop here until there is no timeout.
    while (fTimeoutQ.fHead) 
	{
        AbsoluteTime now, dead;
        IOFWGetAbsoluteTime(&now);

#if 0
        IOLog("processTimeout, time is %llx\n", AbsoluteTime_to_scalar(&now));
        {
            IOFWCommand *t = fTimeoutQ.fHead;
            while(t) {
                AbsoluteTime d = t->getDeadline();
                IOLog("%s:%p deadline %lx:%lx\n",
                    t->getMetaClass()->getClassName(), t, AbsoluteTime_to_scalar(&d));
                t = t->getNext();
            }
        }
#endif
        dead = fTimeoutQ.fHead->getDeadline();
        if(CMP_ABSOLUTETIME(&dead, &now) == 1)
            break;	// Command with earliest deadline is OK.

        // Make sure there isn't a packet waiting.
        fFWIM->handleInterrupts( NULL, 1 );
		fFWIM->flushWaitingPackets();

        // Which may have changed the queue - see if earliest deadline has changed.
        if(!fTimeoutQ.fHead)
            break;

        if(CMP_ABSOLUTETIME(&dead, &fTimeoutQ.fHead->getDeadline()) != 0)
            continue;

        //IOLog("Cmd 0x%x timing out\r", fTimeoutQ.fHead);

		FWTrace( kFWTController, kTPControllerTimeoutQProcessTimeout, (uintptr_t)fFWIM, (uintptr_t)(fTimeoutQ.fHead), 0, 0 );
		
        fTimeoutQ.fHead->cancel(kIOReturnTimeout);
    };
    
	if(fTimeoutQ.fHead) 
	{
        src->wakeAtTime(fTimeoutQ.fHead->getDeadline());
        //AbsoluteTime now;
        //IOFWGetAbsoluteTime(&now);
        //IOLog("processTimeout, timeoutQ waketime %lx:%lx (now %llx)\n",
        //        fTimeoutQ.fHead->getDeadline().hi, fTimeoutQ.fHead->getDeadline().lo, AbsoluteTime_to_scalar(&now));
    }
    else 
	{
        //IOLog("processTimeout, timeoutQ empty\n");
        src->cancelTimeout();
    }
}
Exemplo n.º 3
0
void IOHIKeyboard::setRepeat(unsigned eventType, unsigned keyCode)
// Description:	Set up or tear down key repeat operations. The method
//		that locks _deviceLock is a bit higher on the call stack.
//		This method is invoked as a side effect of our own
//		invocation of _keyMap->translateKeyCode().
// Preconditions:
// *	_deviceLock should be held upon entry.
{
	KeyboardReserved *tempReservedStruct;
	
    if ( _isRepeat == false )  // make sure we're not already repeating
    {
		tempReservedStruct = GetKeyboardReservedStructEventForService(this);
		
		if ((eventType == NX_KEYDOWN) && 
			(tempReservedStruct && (tempReservedStruct->repeatMode == true)))	// Start repeat
		{
			// Set this key to repeat (push out last key if present)
			_downRepeatTime = _initialKeyRepeat; // + _lastEventTime; 
			_codeToRepeat = keyCode;
			// reschedule key repeat event here
			scheduleAutoRepeat();
		}
		else if (((eventType == NX_KEYUP) && (_codeToRepeat == keyCode)) ||
			(tempReservedStruct && (tempReservedStruct->repeatMode == false))) // End repeat
		{
			AbsoluteTime_to_scalar(&_downRepeatTime) = 0;
			_codeToRepeat = (unsigned)-1;
			scheduleAutoRepeat();
		}
    }
}
Exemplo n.º 4
0
void IOHIKeyboard::scheduleAutoRepeat()
// Description:	Schedule a procedure to be called when a timeout has expired
//		so that we can generate a repeated key.
// Preconditions:
// *	_deviceLock should be held on entry
{
    KeyboardReserved *tempReservedStruct = GetKeyboardReservedStructEventForService(this); 
          
    if ( _calloutPending == true )
    {        
        if (tempReservedStruct) {
            thread_call_cancel(tempReservedStruct->repeat_thread_call);
        }
	_calloutPending = false;
    }
    if ( AbsoluteTime_to_scalar(&_downRepeatTime) )
    {
        AbsoluteTime deadline;
        clock_absolutetime_interval_to_deadline(_downRepeatTime, &deadline);
        if (tempReservedStruct) {
            thread_call_enter_delayed(tempReservedStruct->repeat_thread_call, deadline);
        }
	_calloutPending = true;
    }
}
Exemplo n.º 5
0
static IOReturn
IOPolledFilePollersIODone(IOPolledFilePollers * vars, bool abortable)
{
    IOReturn            err = kIOReturnSuccess;
    int32_t		idx = 0;
    IOPolledInterface * poller;
    AbsoluteTime        deadline;

    if (!vars->io) return (kIOReturnSuccess);

    abortable &= vars->abortable;

    clock_interval_to_deadline(2000, kMillisecondScale, &deadline);

    while (-1 == vars->ioStatus)
    {
        for (idx = 0;
                (poller = (IOPolledInterface *) vars->pollers->getObject(idx));
                idx++)
        {
            IOReturn newErr;
            newErr = poller->checkForWork();
            if ((newErr == kIOReturnAborted) && !abortable)
                newErr = kIOReturnSuccess;
            if (kIOReturnSuccess == err)
                err = newErr;
        }
        if ((false) && (kIOReturnSuccess == err) && (mach_absolute_time() > AbsoluteTime_to_scalar(&deadline)))
        {
            HIBLOG("IOPolledInterface::forced timeout\n");
            vars->ioStatus = kIOReturnTimeout;
        }
    }
    vars->io = false;

#if HIBERNATION
    if ((kIOReturnSuccess == err) && abortable && hibernate_should_abort())
    {
        err = kIOReturnAborted;
        HIBLOG("IOPolledInterface::checkForWork sw abort\n");
    }
#endif

    if (err)
    {
        HIBLOG("IOPolledInterface::checkForWork[%d] 0x%x\n", idx, err);
    }
    else
    {
        err = vars->ioStatus;
        if (kIOReturnSuccess != err) HIBLOG("IOPolledInterface::ioStatus 0x%x\n", err);
    }

    return (err);
}
//==============================================================================
// IOHIDEvent::withBytes
//==============================================================================
IOHIDEvent * IOHIDEvent::withBytes(     const void *            bytes,
                                        IOByteCount             size)
{
    IOHIDSystemQueueElement *   queueElement= NULL;
    IOHIDEvent *                parent      = NULL;
    UInt32                      index       = 0;
    UInt32                      total       = 0;
    UInt32                      offset      = 0;

    if ( !bytes || !size )
        return NULL;

    queueElement    = (IOHIDSystemQueueElement *)bytes;
    total           = size - sizeof(IOHIDSystemQueueElement);

    for (index=0; index<queueElement->eventCount && offset<total; index++)
    {
        IOHIDEventData *    eventData   = (IOHIDEventData *)(queueElement->payload + queueElement->attributeLength + offset);
        IOHIDEvent *        event       = IOHIDEvent::withType(eventData->type);

        if ( !event )
            continue;

        bcopy(eventData, event->_data, event->_data->size);
        AbsoluteTime_to_scalar(&(event->_timeStamp)) = queueElement->timeStamp;
        AbsoluteTime_to_scalar(&(event->_creationTimeStamp)) = queueElement->creationTimeStamp;
        event->_options = queueElement->options;
        event->_senderID = queueElement->senderID;

        if ( !parent )
            parent = event;
        else {
            //Append event here;
            event->release();
        }
        offset += eventData->size;
    }

    return parent;
}
Exemplo n.º 7
0
void IOHIKeyboard::setDeviceFlags(unsigned flags)
// Description: Set device event flags. In this world, there is only
//		one keyboard device so device flags == global flags.
{
    if (_eventFlags != flags) {
        _eventFlags = flags;
        
        // RY: On Modifier change, we should 
        // reset the auto repeat timer
        AbsoluteTime_to_scalar(&_downRepeatTime) = 0;
        _codeToRepeat = (unsigned)-1;
        scheduleAutoRepeat();
    }
}
Exemplo n.º 8
0
// Timeout handler function. This function is called by the kernel when
// the timeout interval expires.
//
void IOTimerEventSource::timeout(void *self)
{
    IOTimerEventSource *me = (IOTimerEventSource *) self;

    IOStatisticsTimeout();

    if (me->enabled && me->action)
    {
        IOWorkLoop *
        wl = me->workLoop;
        if (wl)
        {
            Action doit;
            wl->closeGate();
            IOStatisticsCloseGate();
            doit = (Action) me->action;
            if (doit && me->enabled && AbsoluteTime_to_scalar(&me->abstime))
            {
            	bool    trace = (gIOKitTrace & kIOTraceTimers) ? true : false;
            	
            	if (trace)
                	IOTimeStampStartConstant(IODBG_TIMES(IOTIMES_ACTION),
											 (uintptr_t) doit, (uintptr_t) me->owner);
				
                (*doit)(me->owner, me);
#if CONFIG_DTRACE
		DTRACE_TMR3(iotescallout__expire, Action, doit, OSObject, me->owner, void, me->workLoop);
#endif
                
				if (trace)
                	IOTimeStampEndConstant(IODBG_TIMES(IOTIMES_ACTION),
										   (uintptr_t) doit, (uintptr_t) me->owner);
            }
            IOStatisticsOpenGate();
            wl->openGate();
        }
Exemplo n.º 9
0
void IOHIKeyboard::autoRepeat()
// Description:	Repeat the currently pressed key and schedule ourselves
//		to be called again after another interval elapses.
// Preconditions:
// *	Should only be executed on callout thread
// *	_deviceLock should be unlocked on entry.
{    
    KeyboardReserved *tempReservedStruct = GetKeyboardReservedStructEventForService(this); 

    IOLockLock( _deviceLock);
    if (( _calloutPending == false ) || 
        ((tempReservedStruct) && tempReservedStruct->dispatchEventCalled ))
    {
	IOLockUnlock( _deviceLock);
	return;
    }
    _calloutPending = false;
    _isRepeat = true;

    if (tempReservedStruct) tempReservedStruct->dispatchEventCalled = true;

    if ( AbsoluteTime_to_scalar(&_downRepeatTime) )
    {
	// Device is due to generate a repeat
	if (_keyMap)  _keyMap->translateKeyCode(_codeToRepeat,
                                /* direction */ true,
                                /* keyBits */   _keyState);
	_downRepeatTime = _keyRepeat;
    }

    if (tempReservedStruct) tempReservedStruct->dispatchEventCalled = false;

    _isRepeat = false;
    scheduleAutoRepeat();
    IOLockUnlock( _deviceLock);
}
void IOFireWireController::timeoutQ::headChanged(IOFWCommand *oldHead)
{

#if 0
    {
        IOFWCommand *t = fHead;
        if(oldHead)
            IOLog("IOFireWireController::timeoutQ::headChanged(%s:%p)\n",
                oldHead->getMetaClass()->getClassName(), oldHead);
        else
            IOLog("IOFireWireController::timeoutQ::headChanged(0)\n");
            
        while(t) {
            AbsoluteTime d = t->getDeadline();
            IOLog("%s:%p deadline %llx\n",
                t->getMetaClass()->getClassName(), t, AbsoluteTime_to_scalar(&d));
            t = t->getNext();
        }
    }
#endif
    
	if(!fHead) 
	{
        //IOLog("timeoutQ empty\n");
        fTimer->cancelTimeout();
    }
    else 
	{
        fTimer->wakeAtTime(fHead->getDeadline());
        //AbsoluteTime now;
        //IOFWGetAbsoluteTime(&now);
        //IOLog("timeoutQ waketime %lx:%lx (now %lx:%lx)\n",
        //        fHead->getDeadline().hi, fHead->getDeadline().lo, now.hi, now.lo);
    }

}
Exemplo n.º 11
0
IOReturn
AppleUHCIIsochTransferDescriptor::UpdateFrameList(AbsoluteTime timeStamp)
{
    UInt32						statFlags;
    IOUSBIsocFrame 				*pFrames;    
    IOUSBLowLatencyIsocFrame 	*pLLFrames;    
    IOReturn					frStatus = kIOReturnSuccess;
    UInt16						frActualCount = 0;
    UInt16						frReqCount;
    
    statFlags = USBToHostLong(GetSharedLogical()->ctrlStatus);
	frActualCount = UHCI_TD_GET_ACTLEN(statFlags);
    // warning - this method can run at primary interrupt time, which can cause a panic if it logs too much
    // USBLog(7, "AppleUHCIIsochTransferDescriptor[%p]::UpdateFrameList statFlags (%x)", this, statFlags);
    pFrames = _pFrames;
	if (!pFrames)							// this will be the case for the dummy TD
		return kIOReturnSuccess;
	
    pLLFrames = (IOUSBLowLatencyIsocFrame*)_pFrames;
    if (_lowLatency)
    {
		frReqCount = pLLFrames[_frameIndex].frReqCount;
    }
    else
    {
		frReqCount = pFrames[_frameIndex].frReqCount;
    }
	
    if (statFlags & kUHCI_TD_ACTIVE)
    {
		frStatus = kIOUSBNotSent2Err;
    }
    else if (statFlags & kUHCI_TD_CRCTO)
    {
		frStatus = kIOReturnNotResponding;
    }
    else if (statFlags & kUHCI_TD_DBUF)									// data buffer (PCI error)
    {
		if (_pEndpoint->direction == kUSBOut)
			frStatus = kIOUSBBufferUnderrunErr;
		else
			frStatus = kIOUSBBufferOverrunErr;
    }
    else if (statFlags & kUHCI_TD_BABBLE)
    {
		if (_pEndpoint->direction == kUSBOut)
			frStatus = kIOReturnNotResponding;							// babble on OUT. this should never happen
		else
			frStatus = kIOReturnOverrun;
    }
    else if (statFlags & kUHCI_TD_STALLED)								// if STALL happens on Isoch, it is most likely covered by one of the other bits above
    {
		frStatus = kIOUSBWrongPIDErr;
    }
    else
    {
		if (frActualCount != frReqCount)
		{
			if (_pEndpoint->direction == kUSBOut)
			{
				// warning - this method can run at primary interrupt time, which can cause a panic if it logs too much
				// USBLog(7, "AppleUHCIIsochTransferDescriptor[%p]::UpdateFrameList - (OUT) reqCount (%d) actCount (%d)", this, frReqCount, frActualCount);
				frStatus = kIOUSBBufferUnderrunErr;						// this better have generated a DBUF or other error
			}
			else if (_pEndpoint->direction == kUSBIn)
			{
				// warning - this method can run at primary interrupt time, which can cause a panic if it logs too much
				// USBLog(7, "AppleUHCIIsochTransferDescriptor[%p]::UpdateFrameList - (IN) reqCount (%d) actCount (%d)", this, frReqCount, frActualCount);
				frStatus = kIOReturnUnderrun;							// benign error
			}
		}
    }

    if (alignBuffer && alignBuffer->userBuffer && alignBuffer->vaddr && (_pEndpoint->direction == kUSBIn))
	{
		// i can't log in here because this is called at interrupt time
		// i know that this is OK for Low Latency because the buffer will be allocated in low memory and wont' be bounced
		alignBuffer->userBuffer->writeBytes(alignBuffer->userOffset, (void*)alignBuffer->vaddr, frActualCount);
		alignBuffer->actCount = frActualCount;
	}
	
	
	if (_lowLatency)
    {
		if ( _requestFromRosettaClient )
		{
			pLLFrames[_frameIndex].frActCount = OSSwapInt16(frActualCount);
			pLLFrames[_frameIndex].frReqCount = OSSwapInt16(pLLFrames[_frameIndex].frReqCount);
			AbsoluteTime_to_scalar(&pLLFrames[_frameIndex].frTimeStamp) 
			= OSSwapInt64(AbsoluteTime_to_scalar(&timeStamp));
			pLLFrames[_frameIndex].frStatus = OSSwapInt32(frStatus);
		}
		else
		{
			pLLFrames[_frameIndex].frActCount = frActualCount;
			pLLFrames[_frameIndex].frTimeStamp = timeStamp;
			pLLFrames[_frameIndex].frStatus = frStatus;

#ifdef __LP64__
			USBTrace( kUSBTUHCIInterrupts, kTPUHCIUpdateFrameList , (uintptr_t)((_pEndpoint->direction << 24) | ( _pEndpoint->functionAddress << 8) | _pEndpoint->endpointNumber), (uintptr_t)&pLLFrames[_frameIndex], (uintptr_t)frActualCount, (uintptr_t)timeStamp );
#else
			USBTrace( kUSBTUHCIInterrupts, kTPUHCIUpdateFrameList , (uintptr_t)((_pEndpoint->direction << 24) | ( _pEndpoint->functionAddress << 8) | _pEndpoint->endpointNumber), (uintptr_t)&pLLFrames[_frameIndex], (uintptr_t)(timeStamp.hi), (uintptr_t)timeStamp.lo );
#endif
		}
    }
    else
    {
		if ( _requestFromRosettaClient )
		{
			pFrames[_frameIndex].frActCount = OSSwapInt16(frActualCount);
			pFrames[_frameIndex].frReqCount = OSSwapInt16(pFrames[_frameIndex].frReqCount);
			pFrames[_frameIndex].frStatus = OSSwapInt32(frStatus);
		}
		else
		{
			pFrames[_frameIndex].frActCount = frActualCount;
			pFrames[_frameIndex].frStatus = frStatus;
		}
    }
	
    if (frStatus != kIOReturnSuccess)
    {
		if (frStatus != kIOReturnUnderrun)
		{
			_pEndpoint->accumulatedStatus = frStatus;
		}
		else if (_pEndpoint->accumulatedStatus == kIOReturnSuccess)
		{
			_pEndpoint->accumulatedStatus = kIOReturnUnderrun;
		}
    }
    return frStatus;
}