示例#1
0
IOReturn IOSharedInterruptController::handleInterrupt(void * /*refCon*/,
						      IOService * nub,
						      int /*source*/)
{
  IOInterruptVectorNumber vectorNumber;
  IOInterruptVector *vector;
  
  for (vectorNumber = 0; vectorNumber < numVectors; vectorNumber++) {
    vector = &vectors[vectorNumber];
    
    vector->interruptActive = 1;
	if (!vector->interruptDisabledSoft) {
	  
	  // Call the handler if it exists.
	  if (vector->interruptRegistered) {
		  
		  bool	trace = (gIOKitTrace & kIOTraceInterrupts) ? true : false;
		  
		  if (trace)
			  IOTimeStampStartConstant(IODBG_INTC(IOINTC_HANDLER),
									   (uintptr_t) vectorNumber, (uintptr_t) vector->handler, (uintptr_t)vector->target);
		  
		  // Call handler.
		  vector->handler(vector->target, vector->refCon, vector->nub, vector->source);
		  
		  if (trace)
			  IOTimeStampEndConstant(IODBG_INTC(IOINTC_HANDLER),
									 (uintptr_t) vectorNumber, (uintptr_t) vector->handler, (uintptr_t)vector->target);
		  
		}
	}
    
    vector->interruptActive = 0;
  }
  
  // if any of the vectors are dissabled, then dissable this controller.
  IOSimpleLockLock(controllerLock);
  if (vectorsEnabled != vectorsRegistered) {
    nub->disableInterrupt(0);
    controllerDisabled = 1;
  }
  IOSimpleLockUnlock(controllerLock);
  
  return kIOReturnSuccess;
}
示例#2
0
static void 
iopa_free(uintptr_t addr, vm_size_t bytes)
{
    io_pagealloc_t * pa;
    uint32_t         count;
    uintptr_t        chunk;

    if (!bytes) bytes = 1;

    chunk = (addr & page_mask);
    assert(0 == (chunk & (kIOPageAllocChunkBytes - 1)));

    pa = (typeof(pa)) (addr | (page_size - kIOPageAllocChunkBytes));
    assert(kIOPageAllocSignature == pa->signature);

    count = (bytes + kIOPageAllocChunkBytes - 1) / kIOPageAllocChunkBytes;
    chunk /= kIOPageAllocChunkBytes;

    IOSimpleLockLock(gIOPageAllocLock);
    if (!pa->avail)
    {
	assert(!pa->link.next);
	enqueue_tail(&gIOPageAllocList, &pa->link);
    }
    pa->avail |= ((-1ULL << (64 - count)) >> chunk);
    if (pa->avail != -2ULL) pa = 0;
    else
    {
        remque(&pa->link);
        pa->link.next = 0;
        pa->signature = 0;
	gIOPageAllocCount--;
    }
    gIOPageAllocBytes -= bytes;
    IOSimpleLockUnlock(gIOPageAllocLock);
    if (pa) iopa_freepage(pa);

#if IOALLOCDEBUG
    debug_iomalloc_size -= bytes;
#endif
    IOStatisticsAlloc(kIOStatisticsFreeAligned, bytes);
}
IOReturn IOSharedInterruptController::handleInterrupt(void * /*refCon*/,
						      IOService * nub,
						      int /*source*/)
{
  long              vectorNumber;
  IOInterruptVector *vector;
  
  for (vectorNumber = 0; vectorNumber < numVectors; vectorNumber++) {
    vector = &vectors[vectorNumber];
    
    vector->interruptActive = 1;
#if __ppc__
    sync();
    isync();
#endif
    if (!vector->interruptDisabledSoft) {
#if __ppc__
      isync();
#endif
      
      // Call the handler if it exists.
      if (vector->interruptRegistered) {
	vector->handler(vector->target, vector->refCon,
			vector->nub, vector->source);
      }
    }
    
    vector->interruptActive = 0;
  }
  
  // if any of the vectors are dissabled, then dissable this controller.
  IOSimpleLockLock(controllerLock);
  if (vectorsEnabled != vectorsRegistered) {
    nub->disableInterrupt(0);
    controllerDisabled = 1;
  }
  IOSimpleLockUnlock(controllerLock);
  
  return kIOReturnSuccess;
}
IOReturn AgereET131x::setMulticastList(IOEthernetAddress * addrs, UInt32 count)
{
    UINT32              PacketFilter = 0;

    IOSimpleLockLock( adapter.Lock );
	
	
    /**************************************************************************
	 Before we modify the platform-independent filter flags, store them 
	 locally. This allows us to determine if anything's changed and if we
	 even need to bother the hardware
     *************************************************************************/
    PacketFilter = adapter.PacketFilter;
	
	
    /**************************************************************************
	 Clear the 'multicast' flag locally; becuase we only have a single flag
	 to check multicast, and multiple multicast addresses can be set, this is
	 the easiest way to determine if more than one multicast address is being
	 set.
     *************************************************************************/
    PacketFilter &= ~ET131X_PACKET_TYPE_MULTICAST;
	
	
    /**************************************************************************
	 Check the net_device flags and set the device independent flags
	 accordingly
     *************************************************************************/
	
	
	
	
    if( count > NIC_MAX_MCAST_LIST )
    {
        adapter.PacketFilter |= ET131X_PACKET_TYPE_ALL_MULTICAST;
    } else  if( count < 1 ) {
        adapter.PacketFilter &= ~ET131X_PACKET_TYPE_ALL_MULTICAST;
        adapter.PacketFilter &= ~ET131X_PACKET_TYPE_MULTICAST;
    } else {
		/**************************************************************************
		 Set values in the private adapter struct
		 *************************************************************************/
		adapter.MCAddressCount = count;
		
		for( UInt32 k = 0; k < count; k++ )
		{
			bcopy( addrs[k].bytes, adapter.MCList[k], ETH_ALEN );
		}
	}
	
    /**************************************************************************
	 Are the new flags different from the previous ones? If not, then no
	 action is required
	 
	 NOTE - This block will always update the MCList with the hardware, even
	 if the addresses aren't the same.
     *************************************************************************/
    if( PacketFilter != adapter.PacketFilter )
    {
        /**********************************************************************
		 Call the device's filter function
         *********************************************************************/
		
        set_packet_filter();
    }
	
    IOSimpleLockUnlock( adapter.Lock );

	return kIOReturnSuccess;
}
// Called at hardware interrupt time
bool
AppleUSBUHCI::FilterInterrupt(void)
{
	UInt16						activeInterrupts;
    Boolean						needSignal = false;
	UInt64						currentFrame;
	uint64_t					timeStamp;
	
	// we leave all interrupts enabled, so see which ones are active
	activeInterrupts = ioRead16(kUHCI_STS) & kUHCI_STS_INTR_MASK;
	
	if (activeInterrupts != 0) 
	{
		USBTrace( kUSBTUHCIInterrupts, kTPUHCIInterruptsFilterInterrupt , (uintptr_t)this, activeInterrupts, 0, 3 );

		if (activeInterrupts & kUHCI_STS_HCPE)
		{
			// Host Controller Process Error - usually a bad data structure on the list
			_hostControllerProcessInterrupt = kUHCI_STS_HCPE;
			ioWrite16(kUHCI_STS, kUHCI_STS_HCPE);
			needSignal = true;
			//USBLog(1, "AppleUSBUHCI[%p]::FilterInterrupt - HCPE error - legacy reg = %p", this, (void*)_device->configRead16(kUHCI_PCI_LEGKEY));
			USBTrace( kUSBTUHCIInterrupts,  kTPUHCIInterruptsFilterInterrupt, (uintptr_t)this, _hostControllerProcessInterrupt, _device->configRead16(kUHCI_PCI_LEGKEY), 1 );
		}
		if (activeInterrupts & kUHCI_STS_HSE)
		{
			// Host System Error - usually a PCI issue
			_hostSystemErrorInterrupt = kUHCI_STS_HSE;
			ioWrite16(kUHCI_STS, kUHCI_STS_HSE);
			needSignal = true;
			//USBLog(1, "AppleUSBUHCI[%p]::FilterInterrupt - HSE error - legacy reg = %p", this, (void*)_device->configRead16(kUHCI_PCI_LEGKEY));
			USBTrace( kUSBTUHCIInterrupts,  kTPUHCIInterruptsFilterInterrupt, (uintptr_t)this, _hostSystemErrorInterrupt, _device->configRead16(kUHCI_PCI_LEGKEY), 2 );
		}
		if (activeInterrupts & kUHCI_STS_RD)
		{
			// Resume Detect - remote wakeup
			_resumeDetectInterrupt = kUHCI_STS_RD;
			ioWrite16(kUHCI_STS, kUHCI_STS_RD);
			needSignal = true;
		}
		if (activeInterrupts & kUHCI_STS_EI)
		{
			// USB Error Interrupt - transaction error (CRC, timeout, etc)
			_usbErrorInterrupt = kUHCI_STS_EI;
			ioWrite16(kUHCI_STS, kUHCI_STS_EI);
			needSignal = true;
		}
		if (activeInterrupts & kUHCI_STS_INT)
		{
			// Normal IOC interrupt - we need to check out low latency Isoch as well
			timeStamp = mach_absolute_time();
			ioWrite16(kUHCI_STS, kUHCI_STS_INT);
			needSignal = true;
						
			// This function will give us the current frame number and check for rollover at the same time
			// since we are calling from filterInterrupts we will not be preempted, it will also update the 
			// cached copy of the frame_number_with_time 
			GetFrameNumberInternal();
			
			// we need to check the periodic list to see if there are any Isoch TDs which need to come off
			// and potentially have their frame lists updated (for Low Latency) we will place them in reverse
			// order on a "done queue" which will be looked at by the isoch scavanger
			// only do this if the periodic schedule is enabled
			if (!_inAbortIsochEP  && (_outSlot < kUHCI_NVFRAMES))
			{
				AppleUHCIIsochTransferDescriptor	*cachedHead;
				UInt32								cachedProducer;
				UInt16								curSlot, testSlot, nextSlot;
				
				curSlot = (ReadFrameNumber() & kUHCI_NVFRAMES_MASK);
				
				cachedHead = (AppleUHCIIsochTransferDescriptor*)_savedDoneQueueHead;
				cachedProducer = _producerCount;
				testSlot = _outSlot;
				
				while (testSlot != curSlot)
				{
					IOUSBControllerListElement				*thing, *nextThing;
					AppleUHCIIsochTransferDescriptor		*isochTD;
					
					nextSlot = (testSlot+1) & kUHCI_NVFRAMES_MASK;
					thing = _logicalFrameList[testSlot];
					while (thing != NULL)
					{
						nextThing = thing->_logicalNext;
						isochTD = OSDynamicCast(AppleUHCIIsochTransferDescriptor, thing);
						
						if (!isochTD)
							break;						// only care about Isoch in this list - if we get here we are at the interrupt TDs
												
						// need to unlink this TD
						_logicalFrameList[testSlot] = nextThing;
						_frameList[testSlot] = HostToUSBLong(thing->GetPhysicalLink());
						
						if (isochTD->_lowLatency)
							isochTD->frStatus = isochTD->UpdateFrameList(*(AbsoluteTime*)&timeStamp);
						// place this guy on the backward done queue
						// the reason that we do not use the _logicalNext link is that the done queue is not a null terminated list
						// and the element linked "last" in the list might not be a true link - trust me
						isochTD->_doneQueueLink = cachedHead;
						cachedHead = isochTD;
						cachedProducer++;
						if (isochTD->_pEndpoint)
						{
							isochTD->_pEndpoint->onProducerQ++;
							OSDecrementAtomic( &(isochTD->_pEndpoint->scheduledTDs));
						}
						
						thing = nextThing;
					}
					testSlot = nextSlot;
					_outSlot = testSlot;
				}
				IOSimpleLockLock( _wdhLock );
				
				_savedDoneQueueHead = cachedHead;	// updates the shadow head
				_producerCount = cachedProducer;	// Validates _producerCount;
				
				IOSimpleLockUnlock( _wdhLock );

			}
		
			// 8394970:  Make sure we set the flag AFTER we have incremented our producer count.
			_usbCompletionInterrupt = kUHCI_STS_INT;
		}
	}
	
	// We will return false from this filter routine,
	// but will indicate that there the action routine should be called
	// by calling _filterInterruptSource->signalInterrupt(). 
	// This is needed because IOKit will disable interrupts for a level interrupt
	// after the filter interrupt is run, until the action interrupt is called.
	// We want to be able to have our filter interrupt routine called
	// before the action routine runs, if needed.  That is what will enable
	// low latency isoch transfers to work, as when the
	// system is under heavy load, the action routine can be delayed for tens of ms.
	//
	if (needSignal)
		_interruptSource->signalInterrupt();
	
	return false;
}
示例#6
0
bool AppleGPIO::unregisterClient(void *param1, void *param2,
		void *param3 = 0)
{
	AppleGPIOCallbackInfo *prevClient, *thisClient;
	bool found = false;

	DLOG("AppleGPIO::unregisterClient %08lx %08lx %08lx\n",
			(UInt32)param1, (UInt32)param2, (UInt32)param3);

	// grab the client list mutex so nothing changes under our nose
	IOSimpleLockLock(fClientsLock);

	if (!areRegisteredClients())
	{
		IOSimpleLockUnlock(fClientsLock);
		DLOG("AppleGPIO::unregisterClient nobody is registered!!\n");
		return(false);
	}
	
	// Search for the calling client and remove if found
	// check for match against first client
	if (CLIENT_MATCH(fClients))
	{
		thisClient = fClients;
		fClients = fClients->next;
		found = true;
	}
	// walk through the list
	else
	{
		thisClient = fClients;
		while (thisClient->next != 0)
		{
			prevClient = thisClient;
			thisClient = thisClient->next;
			
			if (CLIENT_MATCH(thisClient))
			{
				prevClient->next = thisClient->next;
				found = true;
				break;
			}
		}
	}

	// release the client list mutex
	IOSimpleLockUnlock(fClientsLock);

	if (found)
	{
		IOFree(thisClient, sizeof(AppleGPIOCallbackInfo));

		// update notification relationship with parent
		if (!areEnabledClients() && amEnabled())
		{
			disableWithParent();
		}
		if (!areRegisteredClients())
		{
			unregisterWithParent();
		}
	}

	return(found);
}
示例#7
0
// param1 is a GPIOEventHandler
// param2, param3, param4 are anything the caller wants to give me, they'll
// be passed back exactly as given to me
bool AppleGPIO::registerClient(void *param1, void *param2,
		void *param3 = 0)
{
	AppleGPIOCallbackInfo *newClient, *tmpClient;

	DLOG("AppleGPIO::registerClient %08lx %08lx %08lx\n",
			(UInt32)param1, (UInt32)param2, (UInt32)param3);
	
	// verify the handler address 
	if (param1 == 0) return(false);

	// Make sure this isn't a dupe
	tmpClient = fClients;
	while (tmpClient)
	{
		if (CLIENT_MATCH(tmpClient)) return(false);
		tmpClient = tmpClient->next;
	}

	// Allocate memory for client
	newClient = (AppleGPIOCallbackInfo *)IOMalloc(sizeof(AppleGPIOCallbackInfo));
	if (!newClient) return(false);

	// store the client's data
	newClient->handler = (GPIOEventHandler)param1;
	newClient->param1 = param2;
	newClient->param2 = param3;
	newClient->isEnabled = true;	// events enabled upon registration
	newClient->next = 0;

	// grab the client list mutex
	IOSimpleLockLock(fClientsLock);

	// insert him into the list
	if (!fClients)
	{
		fClients = newClient;
	}
	else
	{
		tmpClient = fClients;
		while (tmpClient->next != 0) tmpClient = tmpClient->next;
		tmpClient->next = newClient;
	}
	
	// release the client list mutex
	IOSimpleLockUnlock(fClientsLock);

	// If necessary, register with GPIO parent for notification
	if (!amRegistered())
	{
		if (!registerWithParent())
		{
			// [3332930] If we can't register with the parent...
			// then return an error and leave the notifications disabled.
			return false;
		}
	}

	// Make sure parent is sending down events
	if (areEnabledClients() && !amEnabled())
		enableWithParent();

	return(true);
}
示例#8
0
void AppleGPIO::stop(IOService *provider)
{
	UInt32 flags, i;
	IOPlatformFunction *func;
	AppleGPIOCallbackInfo *thisClient, *nextClient;

	// Execute any functions flagged as "on termination"
	UInt32 count = fPlatformFuncArray->getCount();
	for (i = 0; i < count; i++)
	{
		if (func = OSDynamicCast(IOPlatformFunction, fPlatformFuncArray->getObject(i)))
		{
			flags = func->getCommandFlags();

			if (flags & kIOPFFlagOnTerm) 
				performFunction(func, (void *)1, (void *)0, (void *)0, (void *)0);
		}
	}

	// Unregister for interrupts
	if (fIntGen && amRegistered())
	{
		disableWithParent();
		unregisterWithParent();
		fIntGen = false;
	}
	
	if (fPFLock) { IOLockFree (fPFLock); fPFLock = NULL; }
	
	IOSimpleLockLock(fClientsLock);
	
	if (fClients)
	{
		thisClient = fClients;
		while (thisClient)
		{
			nextClient = thisClient->next;
			IOFree(thisClient, sizeof(AppleGPIOCallbackInfo));
			thisClient = nextClient;
		}

		fClients = 0;
	}
	
	IOSimpleLockUnlock(fClientsLock);

	IOSimpleLockFree(fClientsLock); fClientsLock = 0;
	IOLockFree(fAmRegisteredLock); fAmRegisteredLock = 0;
	IOSimpleLockFree(fAmEnabledLock); fAmEnabledLock = 0;

	fParent = 0;
	fGPIOID = kGPIOIDInvalid;

	if (fSymIntRegister)	{ fSymIntRegister->release(); fSymIntRegister = 0; }
	if (fSymIntUnRegister)	{ fSymIntUnRegister->release(); fSymIntUnRegister = 0; }
	if (fSymIntEnable)		{ fSymIntEnable->release(); fSymIntEnable = 0; }
	if (fSymIntDisable)		{ fSymIntDisable->release(); fSymIntDisable = 0; }

#ifdef OLD_STYLE_COMPAT

	releaseStrings();
	
#endif

	super::stop(provider);
}