示例#1
0
OsStatus_t
ApicPerformIPI(
    _In_ UUId_t CoreId,
    _In_ int    Assert)
{
	uint32_t    IpiHigh = APIC_DESTINATION(CoreId); // We use physical addressing for IPI/SIPI
	uint32_t    IpiLow  = 0;
    IntStatus_t InterruptStatus;
    OsStatus_t  Status;

    // Determine assert or deassert
    if (Assert) {
        IpiLow = APIC_DELIVERY_MODE(APIC_MODE_INIT) | APIC_LEVEL_ASSERT | APIC_DESTINATION_PHYSICAL;
    }
    else {
        IpiLow = APIC_DELIVERY_MODE(APIC_MODE_INIT) | APIC_TRIGGER_LEVEL | APIC_DESTINATION_PHYSICAL;
    }
    
	// Wait for ICR to clear
    InterruptStatus = InterruptDisable();
	Status          = ApicWaitForIdle();
    if (Status == OsSuccess) {        
        // Always write upper first, irq is sent when low is written
        ApicWriteLocal(APIC_ICR_HIGH, IpiHigh);
        ApicWriteLocal(APIC_ICR_LOW,  IpiLow);
        Status = ApicWaitForIdle(); 
    }
    InterruptRestoreState(InterruptStatus);
    return Status;
}
示例#2
0
OsStatus_t
ApicPerformSIPI(
    _In_ UUId_t    CoreId,
    _In_ uintptr_t Address)
{
	uint32_t    IpiLow  = APIC_DELIVERY_MODE(APIC_MODE_SIPI) | APIC_LEVEL_ASSERT | APIC_DESTINATION_PHYSICAL;
	uint32_t    IpiHigh = APIC_DESTINATION(CoreId); // We use physical addressing for IPI/SIPI
    uint8_t     Vector  = 0;
    IntStatus_t InterruptStatus;
    OsStatus_t  Status;
    
    // Sanitize address given
    assert((Address % 0x1000) == 0);
    Vector = Address / 0x1000;
    assert(Vector <= 0xF);
    IpiLow |= Vector;

	// Wait for ICR to clear
    InterruptStatus = InterruptDisable();
	Status          = ApicWaitForIdle();
    if (Status == OsSuccess) {        
        // Always write upper first, irq is sent when low is written
        ApicWriteLocal(APIC_ICR_HIGH, IpiHigh);
        ApicWriteLocal(APIC_ICR_LOW,  IpiLow);
        Status = ApicWaitForIdle();
    }
    InterruptRestoreState(InterruptStatus);
    return Status;
}
示例#3
0
OsStatus_t
ApicSendInterrupt(
    _In_ InterruptTarget_t  Type,
    _In_ UUId_t             Specific,
    _In_ uint32_t           Vector)
{
	uint32_t    IpiLow  = 0;
	uint32_t    IpiHigh = 0;
    UUId_t      CoreId  = ArchGetProcessorCoreId();
    IntStatus_t InterruptStatus;
    OsStatus_t  Status;

    if (!ApicIsInitialized()) {
        return OsSuccess;
    }
    
    if (Type == InterruptSpecific && Specific == CoreId) {
        Type = InterruptSelf;
    }

    // Handle target types
    if (Type == InterruptSpecific) {
	    IpiHigh = APIC_DESTINATION(Specific);
    }
    else if (Type == InterruptSelf) {
        IpiLow |= (1 << 18);
    }
    else if (Type == InterruptAll) {
        IpiLow |= (1 << 19);
    }
    else {
        IpiLow |= (1 << 19) | (1 << 18);
    }

	// Physical Destination (Bit 11 = 0)
	// Fixed Delivery
	// Assert (Bit 14 = 1)
    // Edge (Bit 15 = 0)
	IpiLow |= APIC_VECTOR(Vector) | APIC_LEVEL_ASSERT | APIC_DESTINATION_PHYSICAL;

    // Are we sending to ourself? Handle this a bit differently, if the ICR is already
    // busy we don't want to clear it as we already a send pending, just queue up interrupt
    InterruptStatus = InterruptDisable();
	Status          = ApicWaitForIdle();
    if (Status == OsSuccess) {
        ApicWriteLocal(APIC_ICR_HIGH, IpiHigh);
        ApicWriteLocal(APIC_ICR_LOW,  IpiLow);
        Status = ApicWaitForIdle();
    }
    InterruptRestoreState(InterruptStatus);
    return Status;
}
示例#4
0
文件: Pit.c 项目: Fluray/MollenOS
/* Entry point of a module */
MODULES_API void ModuleInit(void *Data)
{
	/* We need these */
	MCoreDevice_t *Device = NULL;
	MCoreTimerDevice_t *Timer = NULL;
	PitTimer_t *Pit = NULL;

	/* We want a frequncy of 1000 hz */
	uint32_t Divisor = (1193181 / 1000);
	IntStatus_t IntrState;

	/* Unused */
	_CRT_UNUSED(Data);

	/* Allocate */
	Device = (MCoreDevice_t*)kmalloc(sizeof(MCoreDevice_t));
	Pit = (PitTimer_t*)kmalloc(sizeof(PitTimer_t));
	Timer = (MCoreTimerDevice_t*)kmalloc(sizeof(MCoreTimerDevice_t));

	/* Disable IRQ's for this duration */
	IntrState = InterruptDisable();
	Pit->PitCounter = 0;
	Pit->Divisor = Divisor;

	/* Setup Timer */
	Timer->TimerData = Pit;
	Timer->Sleep = PitSleep;
	Timer->Stall = PitStall;
	Timer->GetTicks = PitGetClocks;

	/* Install Irq */
	InterruptInstallISA(X86_PIT_IRQ, INTERRUPT_PIT, PitIrqHandler, Timer);

	/* Before enabling, register us */
	Pit->DeviceId = DmCreateDevice("PIT Timer", DeviceTimer, Timer);

	/* We use counter 0, select counter 0 and configure it */
	outb(X86_PIT_REGISTER_COMMAND,
		X86_PIT_COMMAND_SQUAREWAVEGEN |
		X86_PIT_COMMAND_RL_DATA |
		X86_PIT_COMMAND_COUNTER_0);

	/* Set divisor */
	outb(X86_PIT_REGISTER_COUNTER0, (uint8_t)(Divisor & 0xFF));
	outb(X86_PIT_REGISTER_COUNTER0, (uint8_t)((Divisor >> 8) & 0xFF));

	/* Done, reenable interrupts */
	InterruptRestoreState(IntrState);
}
示例#5
0
void
ApicSynchronizeArbIds(void)
{
    // Variables
    IntStatus_t InterruptStatus;
    OsStatus_t Status;

	// Not needed on AMD and not supported on P4 
	// So we need a check here in place to do it @todo
    InterruptStatus = InterruptDisable();
	Status          = ApicWaitForIdle();
    assert(Status != OsError);

	ApicWriteLocal(APIC_ICR_HIGH,   0);
	ApicWriteLocal(APIC_ICR_LOW,    APIC_ICR_SH_ALL | APIC_TRIGGER_LEVEL | APIC_DELIVERY_MODE(APIC_MODE_INIT));
	
    Status = ApicWaitForIdle();
    assert(Status != OsError);
    InterruptRestoreState(InterruptStatus);
}