Ejemplo n.º 1
0
VOID
HalpOutputSegment(
    IN ULONG Number,
    IN UCHAR Data
    )

/*++

Routine Description:

    This routine is output a character data in led segment.

Arguments:

    Number - Segment number(range 0-3.)

    Data   - Output data on port.

Return Value:

    none.

--*/

{
    ULONG lednumber;

    //
    // Get segment number.
    //

    lednumber = Number & 0x3;

    if(HalpLedInitFlg == 0){
	KeInitializeSpinLock(&HalpLedLock);
	HalpLedInitFlg = 1;
    }    

    KiAcquireSpinLock(&HalpLedLock);

    //
    // Display data.
    //

    HalpSegmentDisplayData[Number] = Data;

    WRITE_REGISTER_UCHAR( &MRC_CONTROL->LedData3,
                         HalpSegmentDisplayData[3] );
    WRITE_REGISTER_UCHAR( &MRC_CONTROL->LedData2,
                         HalpSegmentDisplayData[2] );
    WRITE_REGISTER_UCHAR( &MRC_CONTROL->LedData1,
                         HalpSegmentDisplayData[1] );
    WRITE_REGISTER_UCHAR( &MRC_CONTROL->LedData0,
                         HalpSegmentDisplayData[0] );

    KiReleaseSpinLock(&HalpLedLock);

    return;
}
Ejemplo n.º 2
0
NTKERNELAPI
BOOLEAN
KeDeregisterBugCheckCallback (
    IN PKBUGCHECK_CALLBACK_RECORD CallbackRecord
    )

/*++

Routine Description:

    This function deregisters a bug check callback record.

Arguments:

    CallbackRecord - Supplies a pointer to a bug check callback record.

Return Value:

    If the specified bug check callback record is successfully deregistered,
    then a value of TRUE is returned. Otherwise, a value of FALSE is returned.

--*/

{

    BOOLEAN Deregister;
    KIRQL OldIrql;

    //
    // Raise IRQL to HIGH_LEVEL and acquire the bug check callback list
    // spinlock.
    //

    KeRaiseIrql(HIGH_LEVEL, &OldIrql);
    KiAcquireSpinLock(&KeBugCheckCallbackLock);

    //
    // If the specified callback record is currently registered, then
    // deregister the callback record.
    //

    Deregister = FALSE;
    if (CallbackRecord->State == BufferInserted) {
        CallbackRecord->State = BufferEmpty;
        RemoveEntryList(&CallbackRecord->Entry);
        Deregister = TRUE;
    }

    //
    // Release the bug check callback spinlock, lower IRQL to its previous
    // value, and return whether the callback record was successfully
    // deregistered.
    //

    KiReleaseSpinLock(&KeBugCheckCallbackLock);
    KeLowerIrql(OldIrql);
    return Deregister;
}
Ejemplo n.º 3
0
VOID
HalpPCIReleaseType2Lock (
    PKSPIN_LOCK SpinLock,
    KIRQL       Irql
    )
{
    if (!HalpDoingCrashDump) {
        KiReleaseSpinLock (SpinLock);
        KfLowerIrql (Irql);
    }
}
Ejemplo n.º 4
0
VOID
HalDisableSystemInterrupt (
    IN ULONG Vector,
    IN KIRQL Irql
    )

/*++

Routine Description:

    This routine disables the specified system interrupt.

Arguments:

    Vector - Supplies the vector of the system interrupt that is disabled.

    Irql - Supplies the IRQL of the interrupting source.

Return Value:

    None.

--*/

{

    KIRQL OldIrql;

    //
    // Raise IRQL to the highest level and acquire device enable spinlock.
    //

    KeRaiseIrql(HIGH_LEVEL, &OldIrql);
    KiAcquireSpinLock(&HalpSystemInterruptLock);

    if (Vector >= DEVICE_VECTORS ) {
        if ( Vector < DEVICE_VECTORS + MPIC_BASE_VECTOR ) {

            HalpDisableSioInterrupt(Vector);

        } else if ( Vector <= DEVICE_VECTORS + MPIC_MAX_VECTOR ) {

            HalpDisableMpicInterrupt(Vector);
       }
    }

    //
    // Release the device enable spin lock and lower IRQL to the previous level.
    //

    KiReleaseSpinLock(&HalpSystemInterruptLock);
    KeLowerIrql(OldIrql);
    return;
}
Ejemplo n.º 5
0
VOID
HalDisplayString (
    PUCHAR String
    )

/*++

Routine Description:

    This routine displays a character string on the display screen.

Arguments:

    String - Supplies a pointer to the characters that are to be displayed.

Return Value:

    None.

--*/

{
    KIRQL  OldIrql;

    KeRaiseIrql(HIGH_LEVEL, &OldIrql);

    if(HalpIsMulti) KiAcquireSpinLock(&HalpDisplayAdapterLock);

    //
    // If ownership of the display has been switched to the system display
    // driver, then reinitialize the display controller and revert ownership
    // to the HAL.
    //

    if (HalpDisplayOwnedByHal == FALSE) {

            HalpDisplayControllerSetup();

    }

    // display the string 

    if( HalpVideoChip == VIDEO_CHIP_UNKNOWN) {
	    ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->printf(String);	
    } else {
	    HalpDisplayVGAString(String);
    }

    if(HalpIsMulti) KiReleaseSpinLock(&HalpDisplayAdapterLock);

    KeLowerIrql(OldIrql);

    return;
}
Ejemplo n.º 6
0
VOID
NTAPI
InbvReleaseLock(VOID)
{
    KIRQL OldIrql;

    /* Capture the old IRQL */
    OldIrql = InbvOldIrql;

    /* Release the driver lock */
    KiReleaseSpinLock(&BootDriverLock);

    /* If we were at dispatch level or lower, restore the old IRQL */
    if (InbvOldIrql <= DISPATCH_LEVEL) KeLowerIrql(OldIrql);
}
Ejemplo n.º 7
0
VOID
NTAPI
HalpPCIReleaseSynchronzationType1(IN PBUS_HANDLER BusHandler,
                                  IN KIRQL Irql)
{
    PCI_TYPE1_CFG_BITS PciCfg1;

    /* Clear the PCI Configuration Register */
    PciCfg1.u.AsULONG = 0;
    WRITE_PORT_ULONG(((PPCIPBUSDATA)BusHandler->BusData)->Config.Type1.Address,
                     PciCfg1.u.AsULONG);

    /* Release the lock */
    KiReleaseSpinLock(&HalpPCIConfigLock);
    KeLowerIrql(Irql);
}
Ejemplo n.º 8
0
VOID
NTAPI
HalpPCIReleaseSynchronizationType2(IN PBUS_HANDLER BusHandler,
                                   IN KIRQL Irql)
{
    PCI_TYPE2_CSE_BITS PciCfg2Cse;
    PPCIPBUSDATA BusData = (PPCIPBUSDATA)BusHandler->BusData;

    /* Clear CSE and bus number */
    PciCfg2Cse.u.AsUCHAR = 0;
    WRITE_PORT_UCHAR(BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR);
    WRITE_PORT_UCHAR(BusData->Config.Type2.Forward, 0);

    /* Release the lock */
    KiReleaseSpinLock(&HalpPCIConfigLock);
    KeLowerIrql(Irql);
}
Ejemplo n.º 9
0
/*++

Routine Description:

    This routine enables the specified system interrupt.

Arguments:

    Vector - Supplies the vector of the system interrupt that is enabled.

    Irql - Supplies the IRQL of the interrupting source.

    InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
        Latched.

Return Value:

    TRUE if the system interrupt was enabled

--*/
BOOLEAN
HalEnableSystemInterrupt (
    IN ULONG Vector,
    IN KIRQL Irql,
    IN KINTERRUPT_MODE InterruptMode
    )
{

    KIRQL OldIrql;

    //
    // Raise IRQL to the highest level and acquire device enable spinlock.
    //

    KeRaiseIrql(HIGH_LEVEL, &OldIrql);
    KiAcquireSpinLock(&HalpSystemInterruptLock);

    //
    // If the vector number is within the range of the EISA interrupts, then
    // enable the EISA interrupt and set the Level/Edge register.
    //


    if (Vector >= DEVICE_VECTORS &&
	// 
	// For FirePOWER, allowable external device interrupts spans 32 bits
	// not the 16 of sandalfoot ( or SIO ) architecture.  The 16 bit limits
	// will be enforced in HalpEnableSioInterrupts.  We'll do our normal
	// system interrupt stuff there for now but should move the system
	// register activity to here and leave the SIO enable routine to deal
	// ONLY with the SIO stuff.
	//
        Vector < (DEVICE_VECTORS + MAXIMUM_DEVICE_VECTOR  + 16) ) {
        HalpEnableSioInterrupt(Vector, InterruptMode);
    } 

    //
    // Release the device enable spin lock and lower IRQL to the previous level.
    //

    KiReleaseSpinLock(&HalpSystemInterruptLock);
    KeLowerIrql(OldIrql);
    return TRUE;
}
Ejemplo n.º 10
0
/*
 * @implemented
 */
BOOLEAN
NTAPI
KeRemoveQueueDpc(IN PKDPC Dpc)
{
    PKDPC_DATA DpcData;
    BOOLEAN Enable;
    ASSERT_DPC(Dpc);

    /* Disable interrupts */
    Enable = KeDisableInterrupts();

    /* Get DPC data */
    DpcData = Dpc->DpcData;
    if (DpcData)
    {
        /* Acquire the DPC lock */
        KiAcquireSpinLock(&DpcData->DpcLock);

        /* Make sure that the data didn't change */
        if (DpcData == Dpc->DpcData)
        {
            /* Remove the DPC */
            DpcData->DpcQueueDepth--;
            RemoveEntryList(&Dpc->DpcListEntry);
            Dpc->DpcData = NULL;
        }

        /* Release the lock */
        KiReleaseSpinLock(&DpcData->DpcLock);
    }

    /* Re-enable interrupts */
    if (Enable) _enable();

    /* Return if the DPC was in the queue or not */
    return DpcData ? TRUE : FALSE;
}
Ejemplo n.º 11
0
BOOLEAN
KeInsertByKeyDeviceQueue (
    IN PKDEVICE_QUEUE DeviceQueue,
    IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry,
    IN ULONG SortKey
    )

/*++

Routine Description:

    This function inserts a device queue entry into the specified device
    queue according to a sort key. If the device is not busy, then it is
    set busy and the entry is not placed in the device queue. Otherwise
    the specified entry is placed in the device queue at a position such
    that the specified sort key is greater than or equal to its predecessor
    and less than its successor.

    N.B. This function can only be called from DISPATCH_LEVEL.

Arguments:

    DeviceQueue - Supplies a pointer to a control object of type device queue.

    DeviceQueueEntry - Supplies a pointer to a device queue entry.

    SortKey - Supplies the sort key by which the position to insert the device
        queue entry is to be determined.

Return Value:

    If the device is not busy, then a value of FALSE is returned. Otherwise a
    value of TRUE is returned.

--*/

{

    BOOLEAN Inserted;
    PLIST_ENTRY NextEntry;
    PKDEVICE_QUEUE_ENTRY QueueEntry;

    ASSERT_DEVICE_QUEUE(DeviceQueue);
    ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);

    //
    // Lock specified device queue.
    //

    KiAcquireSpinLock(&DeviceQueue->Lock);

    //
    // Insert the specified device queue entry in the device queue at the
    // position specified by the sort key if the device queue is busy.
    // Otherwise set the device queue busy an don't insert the device queue
    // entry.
    //

    DeviceQueueEntry->SortKey = SortKey;
    if (DeviceQueue->Busy == TRUE) {
        Inserted = TRUE;
        NextEntry = DeviceQueue->DeviceListHead.Flink;
        while (NextEntry != &DeviceQueue->DeviceListHead) {
            QueueEntry = CONTAINING_RECORD(NextEntry, KDEVICE_QUEUE_ENTRY,
                                           DeviceListEntry);
            if (SortKey < QueueEntry->SortKey) {
                break;
            }
            NextEntry = NextEntry->Flink;
        }
        NextEntry = NextEntry->Blink;
        InsertHeadList(NextEntry, &DeviceQueueEntry->DeviceListEntry);
    } else {
        DeviceQueue->Busy = TRUE;
        Inserted = FALSE;
    }
    DeviceQueueEntry->Inserted = Inserted;
    KiReleaseSpinLock(&DeviceQueue->Lock);
    return Inserted;
}
Ejemplo n.º 12
0
ULONG
HalpEccError(
    IN ULONG EccDiagnostic,
    IN ULONG MemoryFailed
    )

/*++

Routine Description:

    This routine check ecc error and error log put in NVRAM.

Arguments:

    EccDiagnostic - EccDiagnostic Register value
    MemoryFailed - MemoryFailed Register value


Return Value:

    return value is the following error occured.
      1: ecc 1bit error.
      2: ecc 2bit error.
      0: other error.

--*/

{
    ULONG returnValue;
    USHORT infoOffset;
    USHORT writeOffset;
    ULONG buffer; // S001
    ULONG i;	    // S002
    UCHAR dataBuf[36];
    UCHAR infoBuf[24];
    UCHAR tempBuf[24];
    KIRQL OldIrql;
    ULONG DataWord;
    ULONG Number;

    //
    // Check for Ecc 2bit/1bit error
    //

    if (EccDiagnostic & 0x44000000) {
        returnValue = STORM_ECC_2BIT_ERROR;
        infoOffset=ECC_2BIT_ERROR_LOG_INFO_OFFSET;
    } else if (EccDiagnostic & 0x22000000) {
	returnValue = STORM_ECC_1BIT_ERROR;
        infoOffset=ECC_1BIT_ERROR_LOG_INFO_OFFSET;
    } else {
        return 0; // Probably Error bit was disappered.
    }

    HalNvramRead( NVRAM_STATE_FLG_OFFSET, 1, dataBuf );
    HalNvramRead( NVRAM_MAGIC_NO_OFFSET, 4, tempBuf );

    // S002 vvv
    switch(returnValue) {

    case STORM_ECC_2BIT_ERROR:

	//
	// Disable and clear ECC 1bit error.
	//

	(ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->
	    EccDiagnostic.u.LargeInteger.LowPart
		= 0x00ee0000;
	KeFlushWriteBuffer();

	// set Flag indicate ECC 2bit error.

	HalpEcc2bitErrorFlag = 1;

	//
	// Log to NVRAM
	//

	// check for nvram was valid.

	if( ((dataBuf[0] & 0xff) == NVRAM_VALID) && ( *(PULONG)tempBuf == NVRAM_MAGIC ) ){

	    HalNvramRead( (ULONG)infoOffset, 20, infoBuf);

	    ((pECC2_ERR_REC)dataBuf)->record_flag = ECC_LOG_VALID_FLG;
	    
	    ((pECC2_ERR_REC)dataBuf)->err_address = MemoryFailed & 0xfffffff0;
	    // Error Address was 16Byte Alined.

	    GET_TIME(tempBuf);
	    RtlMoveMemory( (PVOID)( ((pECC2_ERR_REC)dataBuf)->when_happened ),
			  (PVOID)tempBuf,
			  TIME_STAMP_SIZE
			  );

	    ((pECC2_ERR_REC)dataBuf)->syndrome = EccDiagnostic;
	    
	    ((pECC2_ERR_REC)dataBuf)->specified_group =
		HalpFindMemoryGroup(MemoryFailed);

	    ((pECC2_ERR_REC)dataBuf)->specified_simm = 0;

	    writeOffset = ((pECC2_ERR_AREA_INFO)infoBuf)->offset_latest
		         +((pECC2_ERR_AREA_INFO)infoBuf)->size_rec;

	    if( writeOffset >= ((pECC2_ERR_AREA_INFO)infoBuf)->offset_2biterr
	                      +((pECC2_ERR_AREA_INFO)infoBuf)->size_rec
	                      *((pECC2_ERR_AREA_INFO)infoBuf)->num_rec ) {
		writeOffset = ((pECC2_ERR_AREA_INFO)infoBuf)->offset_2biterr;
	    }

	    HalNvramWrite( (ULONG)writeOffset,
			  sizeof(ECC2_ERR_REC),
			  (PVOID)dataBuf);

	    HalNvramWrite( ECC_2BIT_ERROR_LOG_INFO_LATEST_OFFSET,
			   sizeof(USHORT),
			   (PVOID)&writeOffset);
	}
	return returnValue; // S004

    case STORM_ECC_1BIT_ERROR:

	//
	// If MemoryFailed address
	// is over 512M Nothing can do.
	// 
	if ((MemoryFailed & 0xfffffff0) > 0x1fffffff) {
	    return returnValue;
	}

	//
	// Disable and clear ECC 1bit error.
	//

	Number = KeGetCurrentPrcb()->Number;
	(ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->
	    EccDiagnostic.u.LargeInteger.LowPart
		= 0x00ee0000;
	KeFlushWriteBuffer();
// M003 +++
	//
	// serialize ecc 1bit logging routine
	//

	for (;;) {
	    KiAcquireSpinLock(&Ecc1bitRoutineLock);
	    if (HalpEcc1bitCount[!Number] == 0) {

		//
		// Increment HalpEcc1bitCount
		//

		HalpEcc1bitCount[Number]++;
		KiReleaseSpinLock(&Ecc1bitRoutineLock);    
		break;
	    }
	    KiReleaseSpinLock(&Ecc1bitRoutineLock);    
	}
// M003 ---

	switch(HalpEcc1bitCount[Number]) {

	case 1:

	    HalpEcc1bitTotalCount++; // M002


	    HalpOldMemoryFailed[Number] = MemoryFailed;
	    
	    //
	    // ReWrite error address
	    // if error address is over 512M 
	    // Nothing can do.
	    // 

	    KiAcquireSpinLock(&Ecc1bitDisableLock);

	    // disable ecc 1bit error again.

	    (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->
	        EccDiagnostic.u.LargeInteger.LowPart
		    = 0x00ee0000;
	    KeFlushWriteBuffer();

	    DataWord = READ_REGISTER_ULONG(
		            KSEG1_BASE
			    | (MemoryFailed & 0xfffffff0)
			    );
	    WRITE_REGISTER_ULONG(
                 KSEG1_BASE
	         | (MemoryFailed & 0xfffffff0),
	         DataWord
		 );

	    KiReleaseSpinLock(&Ecc1bitDisableLock);

	    //
	    // Wait 20 us.
	    //

	    KeStallExecutionProcessor(20);

	    //
	    // Enable and clear ECC 1bit error.
	    //

	    KiAcquireSpinLock(&Ecc1bitDisableLock);
	    (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->
		EccDiagnostic.u.LargeInteger.LowPart
		    = 0x00cc0000;
	    KeFlushWriteBuffer();
	    KiReleaseSpinLock(&Ecc1bitDisableLock);

	    //
	    // ReRead error address
	    // if error address is over 512M 
	    // Nothing can do.
	    // 
	    // if Ecc 1bit error occur again , DataBusError will occur.
	    //

	    DataWord = READ_REGISTER_ULONG(
                           KSEG1_BASE
			   | (MemoryFailed & 0xfffffff0)
			   );

	    // decrement ecc 1bit count

	    HalpEcc1bitCount[Number]--;

	    return(returnValue);

	case 2:
	    
	    if (HalpOldMemoryFailed[Number] != MemoryFailed) {
		break;
	    }
	    if (MemoryFailed & 2) {
		
		// if multi error 
		// nothing can do.
		
		break;
	    }
	    
	    
	    if( ((dataBuf[0] & 0xff) == NVRAM_VALID) && ( *(PULONG)tempBuf == NVRAM_MAGIC ) ){
		
		
		//
		// Search for wheather error address was already logged
		//
		
		HalNvramRead( (ULONG)infoOffset, 20, infoBuf);
		
		for( i=0; i<((pECC1_ERR_AREA_INFO)infoBuf)->num_rec; i++) {
		    HalNvramRead( (ULONG)( ((pECC1_ERR_AREA_INFO)infoBuf)->
					  size_rec * i
					  +((pECC1_ERR_AREA_INFO)infoBuf)->
					  offset_1biterr),
				 sizeof(ECC1_ERR_REC),
				 (PVOID)dataBuf);
		    if ( ((MemoryFailed & 0xfffffff0) 
			  == ((pECC1_ERR_REC)dataBuf)->err_address) &&
			( (((pECC1_ERR_REC)dataBuf)->record_flag & 0x1) != 0) ) {
			break;
		    }
		}
		
		if( i != ((pECC1_ERR_AREA_INFO)infoBuf)->num_rec ) {
		    break;
		}
		
		//
		//	Log to NVRAM
		//
		
		// check for nvram was valid.
		
		((pECC1_ERR_REC)dataBuf)->record_flag = ECC_LOG_VALID_FLG;
		
		((pECC1_ERR_REC)dataBuf)->err_address = MemoryFailed & 0xfffffff0;
		// Error Address was 16Byte Alined.
		
		GET_TIME(tempBuf);
		RtlMoveMemory( (PVOID)( ((pECC1_ERR_REC)dataBuf)->when_happened ),
			      (PVOID)tempBuf,
			      TIME_STAMP_SIZE
			      );
		
		((pECC1_ERR_REC)dataBuf)->syndrome = EccDiagnostic;
		
		((pECC1_ERR_REC)dataBuf)->specified_group =
		    HalpFindMemoryGroup(MemoryFailed);

		((pECC1_ERR_REC)dataBuf)->specified_simm = 0;
		
		writeOffset = ((pECC1_ERR_AREA_INFO)infoBuf)->offset_latest
		    +((pECC1_ERR_AREA_INFO)infoBuf)->size_rec;
		
		if( writeOffset >= ((pECC1_ERR_AREA_INFO)infoBuf)->offset_1biterr
		   +((pECC1_ERR_AREA_INFO)infoBuf)->size_rec
		   *((pECC1_ERR_AREA_INFO)infoBuf)->num_rec ) {
		    writeOffset = ((pECC1_ERR_AREA_INFO)infoBuf)->offset_1biterr;
		}
		
		HalNvramWrite( (ULONG)writeOffset,
			      sizeof(ECC1_ERR_REC),
			      (PVOID)dataBuf);
		HalNvramWrite( ECC_1BIT_ERROR_LOG_INFO_LATEST_OFFSET,
			      sizeof(USHORT),
			      (PVOID)&writeOffset);
	    }
	    

	    // disable ecc 1bit error again.

	    (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->
	        EccDiagnostic.u.LargeInteger.LowPart
	        = 0x00ee0000;
	    KeFlushWriteBuffer();

	    // decrement ecc 1bit count

	    HalpEcc1bitCount[Number]--;
	
	    return(returnValue);
	}
	
	//
	// Enable and clear ECC 1bit error.
	//
	
	KiAcquireSpinLock(&Ecc1bitDisableLock);
	(ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->
	    EccDiagnostic.u.LargeInteger.LowPart
		= 0x00cc0000;
	KeFlushWriteBuffer();
	KiReleaseSpinLock(&Ecc1bitDisableLock);


	// decrement ecc 1bit count

	HalpEcc1bitCount[Number]--;
	
	return(returnValue);
    }    
}
Ejemplo n.º 13
0
VOID
KeThawExecution (
    IN BOOLEAN Enable
    )

/*++

Routine Description:

    This function thaws the execution of all other processors in the host
    configuration and then returns to the caller. It is intended for use by
    the kernel debugger.

Arguments:

    Enable - Supplies the previous interrupt enable that is to be restored
        after having thawed the execution of all other processors.

Return Value:

    None.

--*/

{
#if !defined(NT_UP)

    KIRQL OldIrql;
    ULONG TargetSet;
    ULONG BitNumber;
    ULONG Flag;
    PKPRCB Prcb;

    //
    // Before releasing FreezeExecutionLock clear any all targets IpiFrozen
    // flag.
    //

    KeGetCurrentPrcb()->IpiFrozen = RUNNING;

    TargetSet = KeActiveProcessors & ~(1 << KeGetCurrentPrcb()->Number);
    while (TargetSet != 0) {
        BitNumber = KeFindFirstSetRightMember(TargetSet);
        ClearMember(BitNumber, TargetSet);
        Prcb = KiProcessorBlock[BitNumber];
#if IDBG
        //
        // If the target processor was not forzen, then don't wait
        // for target to unfreeze.
        //

        if (FrozenState(Prcb->IpiFrozen) != TARGET_FROZEN) {
            Prcb->IpiFrozen = RUNNING;
            continue;
        }
#endif

        Prcb->IpiFrozen = TARGET_THAW;
        while (Prcb->IpiFrozen == TARGET_THAW) {
            KeYieldProcessor();
        }
    }

    //
    // Capture the previous IRQL before releasing the freeze lock.
    //

    OldIrql = KiOldIrql;

#if IDBG

    Flag = KiFreezeFlag;
    KiFreezeFlag = 0;

    if ((Flag & FREEZE_BACKUP) != 0) {
        KiReleaseSpinLock(&KiFreezeLockBackup);
    } else {
        KiReleaseSpinLock(&KiFreezeExecutionLock);
    }

#else

    KiFreezeFlag = 0;
    KiReleaseSpinLock(&KiFreezeExecutionLock);

#endif
#endif  // !defined (NT_UP)


    //
    // Flush the current TB, instruction cache, and data cache.
    //

    KeFlushCurrentTb();
    KeSweepCurrentIcache();
    KeSweepCurrentDcache();

    //
    // Lower IRQL and restore interrupt enable
    //

#if !defined(NT_UP)
    KeLowerIrql(OldIrql);
#endif
    KiRestoreInterrupts(Enable);
    return;
}
Ejemplo n.º 14
0
VOID
FASTCALL
KiTimedInterruptDispatch (
    PKINTERRUPT Interrupt
    )

/*++

Routine Description:

    This function is a wrapper for the guts of KiDispatchInterrupt.  It
    is called when the system has been patched to time interrupts.

Arguments:

    Interrupt - Supplies a pointer to a control object of type interrupt.

Return Value:

    None.

--*/

{
    //BEGINTIMING

    PKPRCB Prcb = KeGetCurrentPrcb();
    ULONGLONG StartTimeHigher = Prcb->IsrTime;
    ULONGLONG StartTime = RDTSC();
    ULONGLONG TimeHigher;
    ULONGLONG ElapsedTime;

    //BEGINTIMINGend

    //
    // Acquire the interrupt lock.
    //

    KiAcquireSpinLock(Interrupt->ActualLock);

    //
    // Call the Interrupt Service Routine.
    //

    Interrupt->ServiceRoutine(Interrupt,
                              Interrupt->ServiceContext);

    //
    // Release the interrupt lock.
    //

    KiReleaseSpinLock(Interrupt->ActualLock);

    //ENDTIMING

    //
    // ElapsedTime is time since we entered this routine.
    //

    ElapsedTime = RDTSC() - StartTime;

    //
    // TimeHigher is the amount Prcb->IsrTime has increased since we
    // entered this routine, ie the amount of time spent in higher level
    // ISRs.
    //

    TimeHigher = Prcb->IsrTime - StartTimeHigher;

    //
    // Adjust ElapsedTime to time spent in this routine, excluding 
    // higher level ISRs.
    //

    ElapsedTime -= TimeHigher;
    if (ElapsedTime > KiIsrTscLimit) {

        //
        // If there is a debugger attached, breakin.   Otherwise do nothing.
        // N.B. bugchecking is another possibility.
        //

        if (KdDebuggerEnabled) {
            DbgPrint("KE; ISR time limit exceeded (intobj %p)\n", Interrupt);
            DbgBreakPoint();
        }
    }

    //
    // Update time spent processing interrupts.   This doesn't need 
    // to be atomic as it doesn't matter if it's a little bit lossy.
    // (Though a simple atomic add would do, it's per processor and
    // at IRQL > DISPATCH_LEVEL so it doesn't need to be locked).
    //

    Prcb->IsrTime += ElapsedTime;

    //ENDTIMINGend
}
Ejemplo n.º 15
0
VOID
HalDisableSystemInterrupt (
    IN ULONG Vector,
    IN KIRQL Irql
    )

/*++

Routine Description:

    This routine disables the specified system interrupt.

Arguments:

    Vector - Supplies the vector of the system interrupt that is disabled.

    Irql - Supplies the IRQL of the interrupting source.

Return Value:

    None.

--*/

{

    KIRQL OldIrql;

    //
    // Raise IRQL to the highest level and acquire device enable spinlock.
    //

    KeRaiseIrql(HIGH_LEVEL, &OldIrql);
    KiAcquireSpinLock(&HalpSystemInterruptLock);

    //
    // If the vector number is within the range of builtin devices, then
    // disable the builtin device interrupt.
    //

    if ((Vector >= (DEVICE_VECTORS + 1)) && (Vector <= MAXIMUM_BUILTIN_VECTOR)) {
        HalpBuiltinInterruptEnable &= ~(1 << (Vector - DEVICE_VECTORS - 1));

#if defined(_R94A_)

        if ( READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ASIC3Revision.Long) == 0 ){

            //
            // The bit assign of TYPHOON(in STORM chipset)'s I/O Device Interrupt
            // Enable register is zero origin.
            // 
            // N.B. This obstruction is limiteded to beta-version of STORM chipset.
            //

            WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Fill,
                              HalpBuiltinInterruptEnable);
        } else {

            WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable,
                              HalpBuiltinInterruptEnable);
        }

#else

        WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable,
                              HalpBuiltinInterruptEnable);

#endif

    }

    //
    // If the vector number is within the range of the EISA interrupts, then
    // disable the EISA interrrupt.
    //

    if (Vector >= EISA_VECTORS &&
        Vector < EISA_VECTORS + MAXIMUM_EISA_VECTOR &&
        Irql == EISA_DEVICE_LEVEL) {
        HalpDisableEisaInterrupt(Vector);
    }

#if defined(_R94A_)

    //
    // If the vector number is within the range of the PCI interrupts, then
    // disable the PCI interrrupt.
    //

    if (Vector >= PCI_VECTORS &&
        Vector <= PCI_VECTORS + R94A_PCI_SLOT &&
        Irql == EISA_DEVICE_LEVEL) {
        HalpDisablePCIInterrupt(Vector);
    }

#endif

    //
    // Release the device enable spin loc and lower IRQL to the previous level.
    //

    KiReleaseSpinLock(&HalpSystemInterruptLock);
    KeLowerIrql(OldIrql);
    return;
}
Ejemplo n.º 16
0
VOID
HalDisplayString (
    PUCHAR String
)

/*++

Routine Description:

    This routine displays a character string on the display screen.

Arguments:

    String - Supplies a pointer to the characters that are to be displayed.

Return Value:

    None.

--*/

{
    if (!HalpDisplayInitialized && HalpOwnsDisplay) {

        //
        // If somebody has called HalDisplayString before Phase 0
        // initialization, we need to make sure we get our message out
        // anyway.  So we initialize the display before HalInitSystem does.
        // HalpInitializeDisplay is smart enough to only map the video
        // buffer and clear the screen the first time it is called.
        //

        HalpInitializeDisplay();
    }

    //
    // Synchronize access to the display so that MP systems won't
    // get garbage output due to simultaneous calls.  It also prevents
    // two processors from attempting to call BIOS and reset the display
    // simultaneously.
    //

    KiAcquireSpinLock(&HalpDisplayLock);

    if (HalpOwnsDisplay == FALSE) {

        //
        // The display has been put in graphics mode, and we need to
        // reset it to text mode before we can display any text on it.
        //

        if (HalpResetDisplayParameters) {
            HalpOwnsDisplay = HalpResetDisplayParameters(COLS, ROWS);
        }

        if (HalpOwnsDisplay == FALSE) {
            HalpBiosDisplayReset();
        }

        HalpOwnsDisplay = TRUE;
        HalpDoingCrashDump = TRUE;
        HalpClearDisplay();
    }

    while (*String) {

        switch (*String) {
        case '\n':
            HalpNextLine();
            break;
        case '\r':
            HalpCursorX = 0;
            break;
        default:
            HalpPutCharacter(*String);
            if (++HalpCursorX == COLS) {
                HalpNextLine();
            }
        }
        ++String;
    }

    KiReleaseSpinLock(&HalpDisplayLock);
    return;
}
Ejemplo n.º 17
0
BOOLEAN
KeInsertDeviceQueue (
    IN PKDEVICE_QUEUE DeviceQueue,
    IN PKDEVICE_QUEUE_ENTRY DeviceQueueEntry
    )

/*++

Routine Description:

    This function inserts a device queue entry at the tail of the specified
    device queue. If the device is not busy, then it is set busy and the entry
    is not placed in the device queue. Otherwise the specified entry is placed
    at the end of the device queue.

    N.B. This function can only be called from DISPATCH_LEVEL.

Arguments:

    DeviceQueue - Supplies a pointer to a control object of type device queue.

    DeviceQueueEntry - Supplies a pointer to a device queue entry.

Return Value:

    If the device is not busy, then a value of FALSE is returned. Otherwise a
    value of TRUE is returned.

--*/

{

    BOOLEAN Inserted;

    ASSERT_DEVICE_QUEUE(DeviceQueue);
    ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);

    //
    // Lock specified device queue.
    //

    KiAcquireSpinLock(&DeviceQueue->Lock);

    //
    // Insert the specified device queue entry at the end of the device queue
    // if the device queue is busy. Otherwise set the device queue busy and
    // don't insert the device queue entry.
    //

    if (DeviceQueue->Busy == TRUE) {
        Inserted = TRUE;
        InsertTailList(&DeviceQueue->DeviceListHead,
                       &DeviceQueueEntry->DeviceListEntry);
    } else {
        DeviceQueue->Busy = TRUE;
        Inserted = FALSE;
    }
    DeviceQueueEntry->Inserted = Inserted;
    KiReleaseSpinLock(&DeviceQueue->Lock);
    return Inserted;
}
Ejemplo n.º 18
0
VOID 
KeDetachSessionSpace(
    VOID
    )
/*++

 Routine Description:
    
    This routine removes the session space and synchronize the all threads on 
    the other processors.

 Arguments:
 
    DeleteSessionMapInfo - if TRUE, the session map info will be deleted.
        if FALSE, the session map info will not be deleted.

 Return Value:
  
    None.

 Environment:
 
    Kernel mode.

--*/
{
    KIRQL OldIrql;
    PKTHREAD Thread;
    PKPROCESS Process;
#if !defined(NT_UP)
    KAFFINITY TargetProcessors;
#endif

    //
    // Raise IRQL to dispatcher level and lock the dispatcher database.
    //

    KiLockDispatcherDatabase(&OldIrql);

    Thread = KeGetCurrentThread();
    Process = Thread->ApcState.Process;

    //
    // Lock the region Id resource.
    //
    
    KiAcquireSpinLock(&KiMasterRidLock);

    Process->SessionMapInfo = &Process->SessionRegion;
    
    KiSetRegionRegister((PVOID)MM_SESSION_SPACE_DEFAULT, 
                        KiMakeValidRegionRegister(Process->SessionMapInfo->RegionId, PAGE_SHIFT));

    //
    // Unlock the region Id resource.
    //

    KiReleaseSpinLock(&KiMasterRidLock);

#if !defined(NT_UP)

    //
    // broadcast Region Id sync
    //

    TargetProcessors = KeActiveProcessors;
    TargetProcessors &= PCR->NotMember;

    if (TargetProcessors != 0) {
        KiIpiSendPacket(TargetProcessors,
                        KiSyncSessionTarget,
                        Process,
                        NULL,
                        NULL);
    }

#endif

    //
    // Unlock the dispatcher database
    //

    KiUnlockDispatcherDatabase(OldIrql);
}    
Ejemplo n.º 19
0
VOID
KdLogDbgPrint(
    IN PSTRING String
    )
{
    KIRQL OldIrql;
    ULONG Length;
    ULONG LengthCopied;

    for (; ;) {
        if (KeTestSpinLock (&KdpPrintSpinLock)) {
            KeRaiseIrql (HIGH_LEVEL, &OldIrql);
            if (KiTryToAcquireSpinLock(&KdpPrintSpinLock)) {
                break;          // got the lock
            }
            KeLowerIrql(OldIrql);
        }
    }

    if (KdPrintCircularBuffer) {
        Length = String->Length;
        //
        // truncate ridiculous strings
        //
        if (Length > KDPRINTBUFFERSIZE) {
            Length = KDPRINTBUFFERSIZE;
        }

        if (KdPrintWritePointer + Length <= KdPrintCircularBuffer+KDPRINTBUFFERSIZE) {
            LengthCopied = KdpMoveMemory(KdPrintWritePointer, String->Buffer, Length);
            KdPrintWritePointer += LengthCopied;
            if (KdPrintWritePointer >= KdPrintCircularBuffer+KDPRINTBUFFERSIZE) {
                KdPrintWritePointer = KdPrintCircularBuffer;
                KdPrintRolloverCount++;
            }
        } else {
            ULONG First = (ULONG)(KdPrintCircularBuffer + KDPRINTBUFFERSIZE - KdPrintWritePointer);
            LengthCopied = KdpMoveMemory(KdPrintWritePointer,
                                         String->Buffer,
                                         First);
            if (LengthCopied == First) {
                LengthCopied += KdpMoveMemory(KdPrintCircularBuffer,
                                              String->Buffer + First,
                                              Length - First);
            }
            if (LengthCopied > First) {
                KdPrintWritePointer = KdPrintCircularBuffer + LengthCopied - First;
                KdPrintRolloverCount++;
            } else {
                KdPrintWritePointer += LengthCopied;
                if (KdPrintWritePointer >= KdPrintCircularBuffer+KDPRINTBUFFERSIZE) {
                    KdPrintWritePointer = KdPrintCircularBuffer;
                    KdPrintRolloverCount++;
                }
            }
        }
    }

    KiReleaseSpinLock(&KdpPrintSpinLock);
    KeLowerIrql(OldIrql);
}
Ejemplo n.º 20
0
VOID
KiSyncNewRegionIdTarget (
    IN PULONG SignalDone,
    IN PVOID Parameter1,
    IN PVOID Parameter2,
    IN PVOID Parameter3
    )

/*++

Routine Description:

    This is the target function for synchronizing the region Ids

Arguments:

    SignalDone Supplies a pointer to a variable that is cleared when the
        requested operation has been performed.

    Parameter1 - Parameter3 - Not used.

Return Value:

    None.

--*/

{
#if !defined(NT_UP)

    PKTHREAD Thread;
    PKPROCESS Process;
    PREGION_MAP_INFO ProcessRegion;
    PREGION_MAP_INFO MappedSession;
    ULONG NewRid;
 
    //
    // Flush the entire TB on the current processor.
    //

    Thread = KeGetCurrentThread();
    Process = Thread->ApcState.Process;
    ProcessRegion = &Process->ProcessRegion;
    MappedSession = Process->SessionMapInfo;

    KiAcquireSpinLock(&KiMasterRidLock);

    if (ProcessRegion->SequenceNumber != KiMasterSequence) {
        
        KiMasterRid += 1;

        ProcessRegion->RegionId = KiMasterRid;
        ProcessRegion->SequenceNumber = KiMasterSequence;

        KiSetRegionRegister(MM_LOWEST_USER_ADDRESS,
            KiMakeValidRegionRegister(ProcessRegion->RegionId, PAGE_SHIFT));

    }

    if (MappedSession->SequenceNumber != KiMasterSequence) {

        KiMasterRid += 1;
        
        MappedSession->RegionId = KiMasterRid;
        MappedSession->SequenceNumber = KiMasterSequence;

        KiSetRegionRegister((PVOID)MM_SESSION_SPACE_DEFAULT,
            KiMakeValidRegionRegister(MappedSession->RegionId, PAGE_SHIFT));
    }


    KiReleaseSpinLock(&KiMasterRidLock);

    KiIpiSignalPacketDone(SignalDone);

    KeFlushCurrentTb();

#endif
    return;
}
Ejemplo n.º 21
0
BOOLEAN
KiSyncNewRegionId(
    IN PREGION_MAP_INFO ProcessRegion,
    IN PREGION_MAP_INFO SessionRegion
    )
/*++

 Routine Description:

    Generate a new region id and synchronze the region Ids on all the processors
    if necessary. If the region ids wrap then flush all processor TLB's.

 Arguments:

    ProcessRegion - Supplies a pointer to REGION_MAP_INFO for the user space.
    SessionRegion - Supplies a pointer to REGION_MAP_INFO for the session space.

 Return Value:

    FALSE -- when region id has not been recycled.

    TRUE -- when region id has been recycled.

 Notes:

    This routine called by KiSwapProcess, KeAttachSessionSpace and 
    KeCreateSessionSpace.

 Environment:

    Kernel mode.
    KiLockDispaterLock or LockQueuedDispatcherLock is held

--*/

{
    BOOLEAN RidRecycled = FALSE;
    KAFFINITY TargetProcessors;
    ULONG i;

    //
    // Invalidate the ForwardProgressTb buffer
    //

    for (i = 0; i < MAXIMUM_FWP_BUFFER_ENTRY; i += 1) {
        
        PCR->ForwardProgressBuffer[(i*2)+1] = 0;

    }
    
    KiAcquireSpinLock(&KiMasterRidLock);

    if ((ProcessRegion->SequenceNumber == KiMasterSequence) && 
        (SessionRegion->SequenceNumber == KiMasterSequence)) {
        
        goto not_recycled;

    }

    if (ProcessRegion->SequenceNumber != KiMasterSequence) {

        if (KiMasterRid + 1 > KiMaximumRid) {

            RidRecycled = TRUE;

        } else {

            KiMasterRid += 1;
            ProcessRegion->RegionId = KiMasterRid;
            ProcessRegion->SequenceNumber = KiMasterSequence;
        }
                
    }

    if ((RidRecycled == FALSE) && 
        (SessionRegion->SequenceNumber != KiMasterSequence)) {
        
        if (KiMasterRid + 1 > KiMaximumRid) {

            RidRecycled = TRUE;

        } else {

            KiMasterRid += 1;
            SessionRegion->RegionId = KiMasterRid;
            SessionRegion->SequenceNumber = KiMasterSequence;
        }
    }

    if (RidRecycled == FALSE) {
    
        goto not_recycled;

    }

    //
    //  Region Id must be recycled
    //

    KiMasterRid = START_PROCESS_RID;

    //
    // Since KiMasterSequence is 64-bit wide, it will not be recycled in your life time.
    //

    if (KiMasterSequence + 1 > MAXIMUM_SEQUENCE) {

        KiMasterSequence = START_SEQUENCE;

    } else {

        KiMasterSequence += 1;
    }
        
    //
    // update new process's ProcessRid and ProcessSequence
    //

    ProcessRegion->RegionId = KiMasterRid;
    ProcessRegion->SequenceNumber = KiMasterSequence;

    KiSetRegionRegister(MM_LOWEST_USER_ADDRESS,
                        KiMakeValidRegionRegister(ProcessRegion->RegionId, PAGE_SHIFT));

    KiMasterRid += 1;

    SessionRegion->RegionId = KiMasterRid;
    SessionRegion->SequenceNumber = KiMasterSequence;

    KiSetRegionRegister((PVOID)MM_SESSION_SPACE_DEFAULT,
                        KiMakeValidRegionRegister(SessionRegion->RegionId, PAGE_SHIFT));

    //
    // release mutex for master region id lock
    //

    KiReleaseSpinLock(&KiMasterRidLock);

#if !defined(NT_UP)

    //
    // broadcast Region Id sync
    //

    TargetProcessors = KeActiveProcessors;
    TargetProcessors &= PCR->NotMember;

    if (TargetProcessors != 0) {
        KiIpiSendPacket(TargetProcessors,
                        KiSyncNewRegionIdTarget,
                        (PVOID)TRUE,
                        NULL,
                        NULL);
    }

#endif

    KeFlushCurrentTb();


#if !defined(NT_UP)

    //
    // Wait until all target processors have finished.
    //

    if (TargetProcessors != 0) {
        KiIpiStallOnPacketTargets(TargetProcessors);
    }

#endif

    return TRUE;


not_recycled:

    KiSetRegionRegister(MM_LOWEST_USER_ADDRESS,
                        KiMakeValidRegionRegister(ProcessRegion->RegionId, PAGE_SHIFT));

    KiSetRegionRegister((PVOID)MM_SESSION_SPACE_DEFAULT,
                            KiMakeValidRegionRegister(SessionRegion->RegionId, PAGE_SHIFT));

    //
    // release mutex for master region id lock
    //

    KiReleaseSpinLock(&KiMasterRidLock);
        
    return FALSE;

}
Ejemplo n.º 22
0
/*
 * @implemented
 */
BOOLEAN
NTAPI
KeInsertQueueDpc(IN PKDPC Dpc,
                 IN PVOID SystemArgument1,
                 IN PVOID SystemArgument2)
{
    KIRQL OldIrql;
    PKPRCB Prcb, CurrentPrcb;
    ULONG Cpu;
    PKDPC_DATA DpcData;
    BOOLEAN DpcConfigured = FALSE, DpcInserted = FALSE;
    ASSERT_DPC(Dpc);

    /* Check IRQL and Raise it to HIGH_LEVEL */
    KeRaiseIrql(HIGH_LEVEL, &OldIrql);
    CurrentPrcb = KeGetCurrentPrcb();

    /* Check if the DPC has more then the maximum number of CPUs */
    if (Dpc->Number >= MAXIMUM_PROCESSORS)
    {
        /* Then substract the maximum and get that PRCB. */
        Cpu = Dpc->Number - MAXIMUM_PROCESSORS;
        Prcb = KiProcessorBlock[Cpu];
    }
    else
    {
        /* Use the current one */
        Prcb = CurrentPrcb;
        Cpu = Prcb->Number;
    }

    /* ROS Sanity Check */
    ASSERT(Prcb == CurrentPrcb);

    /* Check if this is a threaded DPC and threaded DPCs are enabled */
    if ((Dpc->Type == ThreadedDpcObject) && (Prcb->ThreadDpcEnable))
    {
        /* Then use the threaded data */
        DpcData = &Prcb->DpcData[DPC_THREADED];
    }
    else
    {
        /* Otherwise, use the regular data */
        DpcData = &Prcb->DpcData[DPC_NORMAL];
    }

    /* Acquire the DPC lock */
    KiAcquireSpinLock(&DpcData->DpcLock);

    /* Get the DPC Data */
    if (!InterlockedCompareExchangePointer(&Dpc->DpcData, DpcData, NULL))
    {
        /* Now we can play with the DPC safely */
        Dpc->SystemArgument1 = SystemArgument1;
        Dpc->SystemArgument2 = SystemArgument2;
        DpcData->DpcQueueDepth++;
        DpcData->DpcCount++;
        DpcConfigured = TRUE;

        /* Check if this is a high importance DPC */
        if (Dpc->Importance == HighImportance)
        {
            /* Pre-empty other DPCs */
            InsertHeadList(&DpcData->DpcListHead, &Dpc->DpcListEntry);
        }
        else
        {
            /* Add it at the end */
            InsertTailList(&DpcData->DpcListHead, &Dpc->DpcListEntry);
        }

        /* Check if this is the DPC on the threaded list */
        if (&Prcb->DpcData[DPC_THREADED] == DpcData)
        {
            /* Make sure a threaded DPC isn't already active */
            if (!(Prcb->DpcThreadActive) && !(Prcb->DpcThreadRequested))
            {
                /* FIXME: Setup Threaded DPC */
                DPRINT1("Threaded DPC not supported\n");
                while (TRUE);
            }
        }
        else
        {
            /* Make sure a DPC isn't executing already */
            if (!(Prcb->DpcRoutineActive) && !(Prcb->DpcInterruptRequested))
            {
                /* Check if this is the same CPU */
                if (Prcb != CurrentPrcb)
                {
                    /*
                     * Check if the DPC is of high importance or above the
                     * maximum depth. If it is, then make sure that the CPU
                     * isn't idle, or that it's sleeping.
                     */
                    if (((Dpc->Importance == HighImportance) ||
                        (DpcData->DpcQueueDepth >=
                         Prcb->MaximumDpcQueueDepth)) &&
                        (!(AFFINITY_MASK(Cpu) & KiIdleSummary) ||
                         (Prcb->Sleeping)))
                    {
                        /* Set interrupt requested */
                        Prcb->DpcInterruptRequested = TRUE;

                        /* Set DPC inserted */
                        DpcInserted = TRUE;
                    }
                }
                else
                {
                    /* Check if the DPC is of anything but low importance */
                    if ((Dpc->Importance != LowImportance) ||
                        (DpcData->DpcQueueDepth >=
                         Prcb->MaximumDpcQueueDepth) ||
                        (Prcb->DpcRequestRate < Prcb->MinimumDpcRate))
                    {
                        /* Set interrupt requested */
                        Prcb->DpcInterruptRequested = TRUE;

                        /* Set DPC inserted */
                        DpcInserted = TRUE;
                    }
                }
            }
        }
    }

    /* Release the lock */
    KiReleaseSpinLock(&DpcData->DpcLock);

    /* Check if the DPC was inserted */
    if (DpcInserted)
    {
        /* Check if this was SMP */
        if (Prcb != CurrentPrcb)
        {
            /* It was, request and IPI */
            KiIpiSend(AFFINITY_MASK(Cpu), IPI_DPC);
        }
        else
        {
            /* It wasn't, request an interrupt from HAL */
            HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
        }
    }

    /* Lower IRQL */
    KeLowerIrql(OldIrql);
    return DpcConfigured;
}
Ejemplo n.º 23
0
PKDEVICE_QUEUE_ENTRY
KeRemoveDeviceQueue (
    IN PKDEVICE_QUEUE DeviceQueue
    )

/*++

Routine Description:

    This function removes an entry from the head of the specified device
    queue. If the device queue is empty, then the device is set Not-Busy
    and a NULL pointer is returned. Otherwise the next entry is removed
    from the head of the device queue and the address of device queue entry
    is returned.

    N.B. This function can only be called from DISPATCH_LEVEL.

Arguments:

    DeviceQueue - Supplies a pointer to a control object of type device queue.

Return Value:

    A NULL pointer is returned if the device queue is empty. Otherwise a
    pointer to a device queue entry is returned.

--*/

{

    PKDEVICE_QUEUE_ENTRY DeviceQueueEntry;
    PLIST_ENTRY NextEntry;

    ASSERT_DEVICE_QUEUE(DeviceQueue);
    ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);

    //
    // Lock specified device queue.
    //

    KiAcquireSpinLock(&DeviceQueue->Lock);

    ASSERT(DeviceQueue->Busy == TRUE);

    //
    // If the device queue is not empty, then remove the first entry from
    // the queue. Otherwise set the device queue not busy.
    //

    if (IsListEmpty(&DeviceQueue->DeviceListHead) == TRUE) {
        DeviceQueue->Busy = FALSE;
        DeviceQueueEntry = (PKDEVICE_QUEUE_ENTRY)NULL;
    } else {
        NextEntry = RemoveHeadList(&DeviceQueue->DeviceListHead);
        DeviceQueueEntry = CONTAINING_RECORD(NextEntry, KDEVICE_QUEUE_ENTRY,
                                             DeviceListEntry);
        DeviceQueueEntry->Inserted = FALSE;
    }

    //
    // Release device queue spin lock and return address of device queue
    // entry.
    //

    KiReleaseSpinLock(&DeviceQueue->Lock);
    return DeviceQueueEntry;
}
Ejemplo n.º 24
0
BOOLEAN
HalEnableSystemInterrupt (
    IN ULONG Vector,
    IN KIRQL Irql,
    IN KINTERRUPT_MODE InterruptMode
    )

/*++

Routine Description:

    This routine enables the specified system interrupt.

Arguments:

    Vector - Supplies the vector of the system interrupt that is enabled.

    Irql - Supplies the IRQL of the interrupting source.

    InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
        Latched.

Return Value:

    TRUE if the system interrupt was enabled

--*/

{

    KIRQL OldIrql;

    //
    // Raise IRQL to the highest level and acquire device enable spinlock.
    //

    KeRaiseIrql(HIGH_LEVEL, &OldIrql);
    KiAcquireSpinLock(&HalpSystemInterruptLock);

    //
    // If the vector number is within the range of builtin devices, then
    // enable the builtin device interrupt.
    //

    if ((Vector >= (DEVICE_VECTORS + 1)) && (Vector <= MAXIMUM_BUILTIN_VECTOR)) {
        HalpBuiltinInterruptEnable |= (1 << (Vector - DEVICE_VECTORS - 1));
        /* Start M001 */
        WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN,
                             HalpBuiltinInterruptEnable);
        /* End M001 */
    }

    //
    // If the vector number is within the range of the EISA interrupts, then
    // enable the EISA interrrupt and set the Level/Edge register.
    //

    /* Start M001 */
    /* Start S003 */
    if (Vector >= EISA_VECTORS &&
        Vector <= MAXIMUM_EISA_VECTORS &&	// S005
        Irql == INT1_LEVEL) {
        HalpEnableEisaInterrupt( Vector, InterruptMode);
    }
    /* End S003 */

    //
    // If the vector number is within the range of the PCI interrupts, then
    // disable the PCI interrrupt.
    //

    /* Start S006 */
    if (Vector == PCI_DEVICE_VECTOR && Irql == INT1_LEVEL) {
        HalpEnablePciInterrupt(Vector);
    }
    /* End S006 */
    /* End M001 */

    //
    // Release the device enable spin loc and lower IRQL to the previous level.
    //

    KiReleaseSpinLock(&HalpSystemInterruptLock);
    KeLowerIrql(OldIrql);
    return TRUE;
}
Ejemplo n.º 25
0
PKDEVICE_QUEUE_ENTRY
KeRemoveByKeyDeviceQueue (
    IN PKDEVICE_QUEUE DeviceQueue,
    IN ULONG SortKey
    )

/*++

Routine Description:

    This function removes an entry from the specified device
    queue. If the device queue is empty, then the device is set Not-Busy
    and a NULL pointer is returned. Otherwise the an entry is removed
    from the device queue and the address of device queue entry
    is returned.  The queue is search for the first entry which has a value
    greater than or equal to the SortKey.  If no such entry is found then the
    first entry of the queue is returned.

    N.B. This function can only be called from DISPATCH_LEVEL.

Arguments:

    DeviceQueue - Supplies a pointer to a control object of type device queue.

    SortKey - Supplies the sort key by which the position to remove the device
        queue entry is to be determined.

Return Value:

    A NULL pointer is returned if the device queue is empty. Otherwise a
    pointer to a device queue entry is returned.

--*/

{

    PKDEVICE_QUEUE_ENTRY DeviceQueueEntry;
    PLIST_ENTRY NextEntry;

    ASSERT_DEVICE_QUEUE(DeviceQueue);
    ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);

    //
    // Lock specified device queue.
    //

    KiAcquireSpinLock(&DeviceQueue->Lock);

    ASSERT(DeviceQueue->Busy == TRUE);

    //
    // If the device queue is not empty, then remove the first entry from
    // the queue. Otherwise set the device queue not busy.
    //

    if (IsListEmpty(&DeviceQueue->DeviceListHead) == TRUE) {
        DeviceQueue->Busy = FALSE;
        DeviceQueueEntry = (PKDEVICE_QUEUE_ENTRY)NULL;
    } else {
        NextEntry = DeviceQueue->DeviceListHead.Flink;
        while (NextEntry != &DeviceQueue->DeviceListHead) {
            DeviceQueueEntry = CONTAINING_RECORD(NextEntry, KDEVICE_QUEUE_ENTRY,
                                           DeviceListEntry);
            if (SortKey <= DeviceQueueEntry->SortKey) {
                break;
            }
            NextEntry = NextEntry->Flink;
        }

        if (NextEntry != &DeviceQueue->DeviceListHead) {
            RemoveEntryList(&DeviceQueueEntry->DeviceListEntry);

        } else {
            NextEntry = RemoveHeadList(&DeviceQueue->DeviceListHead);
            DeviceQueueEntry = CONTAINING_RECORD(NextEntry, KDEVICE_QUEUE_ENTRY,
                                             DeviceListEntry);
        }

        DeviceQueueEntry->Inserted = FALSE;
    }

    //
    // Release device queue spin lock and return address of device queue
    // entry.
    //

    KiReleaseSpinLock(&DeviceQueue->Lock);
    return DeviceQueueEntry;
}
Ejemplo n.º 26
0
NTKERNELAPI
BOOLEAN
KeRegisterBugCheckCallback (
    IN PKBUGCHECK_CALLBACK_RECORD CallbackRecord,
    IN PKBUGCHECK_CALLBACK_ROUTINE CallbackRoutine,
    IN PVOID Buffer,
    IN ULONG Length,
    IN PUCHAR Component
    )

/*++

Routine Description:

    This function registers a bug check callback record. If the system
    crashes, then the specified function will be called during bug check
    processing so it may dump additional state in the specified bug check
    buffer.

    N.B. Bug check callback routines are called in reverse order of
         registration, i.e., in LIFO order.

Arguments:

    CallbackRecord - Supplies a pointer to a callback record.

    CallbackRoutine - Supplies a pointer to the callback routine.

    Buffer - Supplies a pointer to the bug check buffer.

    Length - Supplies the length of the bug check buffer in bytes.

    Component - Supplies a pointer to a zero terminated component
        identifier.

Return Value:

    If the specified bug check callback record is successfully registered,
    then a value of TRUE is returned. Otherwise, a value of FALSE is returned.

--*/

{

    BOOLEAN Inserted;
    KIRQL OldIrql;

    //
    // Raise IRQL to HIGH_LEVEL and acquire the bug check callback list
    // spinlock.
    //

    KeRaiseIrql(HIGH_LEVEL, &OldIrql);
    KiAcquireSpinLock(&KeBugCheckCallbackLock);

    //
    // If the specified callback record is currently not registered, then
    // register the callback record.
    //

    Inserted = FALSE;
    if (CallbackRecord->State == BufferEmpty) {
        CallbackRecord->CallbackRoutine = CallbackRoutine;
        CallbackRecord->Buffer = Buffer;
        CallbackRecord->Length = Length;
        CallbackRecord->Component = Component;
        CallbackRecord->Checksum =
            ((ULONG_PTR)CallbackRoutine + (ULONG_PTR)Buffer + Length + (ULONG_PTR)Component);

        CallbackRecord->State = BufferInserted;
        InsertHeadList(&KeBugCheckCallbackListHead, &CallbackRecord->Entry);
        Inserted = TRUE;
    }

    //
    // Release the bug check callback spinlock, lower IRQL to its previous
    // value, and return whether the callback record was successfully
    // registered.
    //

    KiReleaseSpinLock(&KeBugCheckCallbackLock);
    KeLowerIrql(OldIrql);
    return Inserted;
}
Ejemplo n.º 27
0
VOID
HalDisableSystemInterrupt (
    IN ULONG Vector,
    IN KIRQL Irql
    )

/*++

Routine Description:

    This routine disables the specified system interrupt.

Arguments:

    Vector - Supplies the vector of the system interrupt that is disabled.

    Irql - Supplies the IRQL of the interrupting source.

Return Value:

    None.

--*/

{

    ULONG Irq;
    KIRQL OldIrql;

    //
    // Raise IRQL to the highest level and acquire the system interrupt
    // lock.
    //

    KeRaiseIrql(HIGH_LEVEL, &OldIrql);

    KiAcquireSpinLock(&HalpSystemInterruptLock);

    //
    // If the vector is a performance counter vector or one of the internal
    // device vectors then disable the interrupt for the 21164.
    //

    switch (Vector) {

    //
    // Performance counter 0 interrupt (internal to 21164)
    //

    case PC0_VECTOR:
    case PC0_SECONDARY_VECTOR:

        break;

    //
    // Performance counter 1 interrupt (internal to 21164)
    //

    case PC1_VECTOR:
    case PC1_SECONDARY_VECTOR:

        break;

    //
    // Performance counter 2 interrupt (internal to 21164)
    //

    case PC2_VECTOR:
    case PC2_SECONDARY_VECTOR:

        break;

    default:

        if( Irql == DEVICE_LEVEL ){

            if( HalpLynxPlatform ){

                HalpDisableLynxSioInterrupt( Vector );

            } else {

                HalpDisableSableSioInterrupt( Vector );

            }
        }

        break;

    }

    //
    // Release the system interrupt lock and restore the IRWL.
    //

    KiReleaseSpinLock(&HalpSystemInterruptLock);

    KeLowerIrql(OldIrql);

    return;
}
Ejemplo n.º 28
0
VOID
FASTCALL
KiTimedChainedDispatch2ndLvl(
    PKINTERRUPT Interrupt
    )

/*++

Routine Description:

    This function performs the same function as KiChainedDispatch2ndLvl
    except that it is written in C instead of assembly code and includes
    code for timing ISRs.

    I'd be interested in seeing some benchmarks to show if the assembly
    code is actually faster.    The Acquire/Release spinlock could be
    inlined fairly easily.

Arguments:

    Interrupt - Supplies a pointer to a control object of type interrupt.

Return Value:

    None.

--*/

{
    BOOLEAN Handled = FALSE;
    PVOID ListEnd = &Interrupt->InterruptListEntry.Flink;
    //
    //BEGINTIMING

    PKPRCB Prcb = KeGetCurrentPrcb();
    ULONGLONG StartTimeHigher;
    ULONGLONG StartTime;
    ULONGLONG TimeHigher;
    ULONGLONG ElapsedTime;

    //BEGINTIMINGend


    //
    // For each interrupt on this chain.
    //

    do {

        //
        // If the current IRQL (IRQL raised to by nature of taking this
        // interrupt) is not equal to the Synchronization IRQL required
        // for this interrupt, raise to the appropriate level.
        //

        if (Interrupt->Irql != Interrupt->SynchronizeIrql) {
            KfRaiseIrql(Interrupt->SynchronizeIrql);
        }

        //BEGINTIMING

        StartTimeHigher = Prcb->IsrTime;
        StartTime = RDTSC();

        //BEGINTIMINGend

        //
        // Acquire the interrupt lock.
        //

        KiAcquireSpinLock(Interrupt->ActualLock);

        //
        // Call the Interrupt Service Routine.
        //

        Handled |= Interrupt->ServiceRoutine(Interrupt,
                                             Interrupt->ServiceContext);

        //
        // Release the interrupt lock.
        //

        KiReleaseSpinLock(Interrupt->ActualLock);

        //ENDTIMING

        //
        // ElapsedTime is time since we started looking at this element
        // on the chain.  (ie the current interrupt object).
        //

        ElapsedTime = RDTSC() - StartTime;

        //
        // TimeHigher is the amount Prcb->IsrTime has increased since we
        // begin servicing this interrupt object, ie the amount of time
        // spent in higher level ISRs.
        //

        TimeHigher = Prcb->IsrTime - StartTimeHigher;

        //
        // Adjust ElapsedTime to time spent on this interrupt object, excluding 
        // higher level ISRs.
        //

        ElapsedTime -= TimeHigher;
        if (ElapsedTime > KiIsrTscLimit) {

            //
            // If there is a debugger attached, breakin.   Otherwise do nothing.
            // N.B. bugchecking is another possibility.
            //

            if (KdDebuggerEnabled) {
                DbgPrint("KE; ISR time limit exceeded (intobj %p)\n",
                         Interrupt);
                DbgBreakPoint();
            }
        }

        //
        // Update time spent processing interrupts.   This doesn't need 
        // to be atomic as it doesn't matter if it's a little bit lossy.
        // (Though a simple atomic add would do, it's per processor and
        // at IRQL > DISPATCH_LEVEL so it doesn't need to be locked).
        //

        Prcb->IsrTime += ElapsedTime;

        //ENDTIMINGend

        //
        // If IRQL was raised, lower to the previous level.
        //

        if (Interrupt->Irql != Interrupt->SynchronizeIrql) {
            KfLowerIrql(Interrupt->Irql);
        }

        if ((Handled != FALSE) &&
            (Interrupt->Mode == LevelSensitive)) {

            //
            // The interrupt has been handled.
            //

            return;
        }

        //
        // If this is the last entry on the chain, get out, otherwise
        // advance to the next entry.
        //

        if (Interrupt->InterruptListEntry.Flink == ListEnd) {
            ASSERT(Interrupt->Mode != LevelSensitive);

            //
            // We should only get to the end of the list if
            // (a) interrupts are on this chain are level sensitive and
            //     no ISR handled the request.   This is a system fatal
            //     condition, or,
            // (b) the chain has edge triggered interrupts in which case
            //     we must run the chain repeatedly until no ISR services
            //     the request.
            //
            // Question:  Do we actually have chained edge triggered
            //            interrupts anymore?
            //

            if (Handled == FALSE) {
                break;
            }
        }
        Interrupt = CONTAINING_RECORD(Interrupt->InterruptListEntry.Flink,
                                      KINTERRUPT,
                                      InterruptListEntry);
    } while (TRUE);
}
Ejemplo n.º 29
0
VOID
KiSyncSessionTarget(
    IN PULONG SignalDone,
    IN PKPROCESS Process,
    IN PVOID Parameter1,
    IN PVOID Parameter2
    )
/*++

 Routine Description:

    This is the target function for synchronizing the new session 
    region id.  This routine is called when the session space is removed 
    and all the processors need to be notified.

 Arguments:

    SignalDone - Supplies a pointer to a variable that is cleared when the
        requested operation has been performed.

    Process - Supplies a KPROCESS pointer which needs to be sync'ed.

 Return Value:

    None.

 Environment:

    Kernel mode.

--*/
{
#if !defined(NT_UP)

    PKTHREAD Thread;
    ULONG NewRid;
 
    //
    // Flush the entire TB on the current processor.
    //

    Thread = KeGetCurrentThread();

    //
    // check to see if the current process is the process that needs to be 
    // sync'ed
    //

    if (Process == Thread->ApcState.Process) {
        
        KiAcquireSpinLock(&KiMasterRidLock);

        //
        // disable the session region.
        //

        KiSetRegionRegister((PVOID)MM_SESSION_SPACE_DEFAULT, 
                            KiMakeValidRegionRegister(Process->SessionMapInfo->RegionId, PAGE_SHIFT));

        KiReleaseSpinLock(&KiMasterRidLock);

        //
        // flush the entire tb.
        //

        KeFlushCurrentTb();
    }

    KiIpiSignalPacketDone(SignalDone);

#endif
    return;
}
Ejemplo n.º 30
0
VOID
HalRequestIpi (
    IN ULONG Mask
    )

/*++

Routine Description:

    This routine requests an interprocessor interrupt on a set of processors.

    N.B. This routine must ensure that the interrupt is posted at the target
         processor(s) before returning.

Arguments:

    Mask - Supplies the set of processors that are sent an interprocessor
        interrupt.

Return Value:

    None.

--*/

{

#if defined(_DUO_)  // S004

    //
    // For Merge R94A/R94A'/R94D HAL
    //
    // Old version need ChipSet Bug Workaround.
    //

    ULONG OldIpiReq;
    KIRQL OldIrql;

    if (HalpUseChipSetWorkaround) {

        //
        // Request an interprocessor interrupt on each of the specified target
        // processors.
        //
        KeRaiseIrql(HIGH_LEVEL,&OldIrql);

        KiAcquireSpinLock(&HalpIpiRequestLock);

        OldIpiReq = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->IpInterruptRequest.Long);

        WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->IpInterruptRequest.Long,
                         OldIpiReq | Mask);

        READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->IpInterruptRequest.Long);

        KiReleaseSpinLock(&HalpIpiRequestLock);

        KeLowerIrql(OldIrql);
    } else {
        WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->IpInterruptRequest.Long, Mask);
    }


#endif

    return;
}