示例#1
0
文件: mailbox.c 项目: MHesham/bsp
/*++

Routine Description:

    Write to mail box in a serialize manner

Arguments:

    DeviceContextPtr - Pointer to device context

    Channel - Mailbox Channel

    Value - Value to be written

    Request - Optional WDF request object associated with this mailbox 
        transaction

Return Value:

    NTSTATUS

--*/
_Use_decl_annotations_
NTSTATUS RpiqMailboxWrite (
    DEVICE_CONTEXT* DeviceContextPtr,
    ULONG Channel,
    ULONG Value,
    WDFREQUEST Request
    )
{
    NTSTATUS status;
    ULONG count = 0, reg;
    LARGE_INTEGER timeOut = { 0 };

    PAGED_CODE();
    
    WdfWaitLockAcquire(DeviceContextPtr->WriteLock, NULL);

    timeOut.QuadPart = WDF_REL_TIMEOUT_IN_MS(1);

    reg = READ_REGISTER_NOFENCE_ULONG(&DeviceContextPtr->Mailbox->Status);

    // Poll until mailbox is available. It doesn't seem like
    // the mailbox is full often so polling is sufficient for now
    // rather than enable mailbox empty interrupt
    while (reg & MAILBOX_STATUS_FULL) {
        if (count > MAX_POLL) {
            RPIQ_LOG_ERROR(
                "Exit Fail Status 0x%08x", 
                DeviceContextPtr->Mailbox->Status);
            status = STATUS_IO_TIMEOUT;
            goto End;
        }

        KeDelayExecutionThread(KernelMode, FALSE, &timeOut);
        reg = READ_REGISTER_NOFENCE_ULONG(&DeviceContextPtr->Mailbox->Status);
        ++count;
    }

    if (Request) {
        status = WdfRequestForwardToIoQueue(
            Request,
            DeviceContextPtr->ChannelQueue[Channel]);
        if (!NT_SUCCESS(status)) {
            RPIQ_LOG_ERROR(
                "WdfRequestForwardToIoQueue failed ( %!STATUS!)",
                status);
            goto End;
        }
    }

    WRITE_REGISTER_NOFENCE_ULONG(
        &DeviceContextPtr->Mailbox->Write, 
        (Value & ~MAILBOX_CHANNEL_MASK) | Channel);

    status = STATUS_SUCCESS;

End:
    WdfWaitLockRelease(DeviceContextPtr->WriteLock);

    return status;
}
_Use_decl_annotations_
void VC4_DEBUG::DumpPixelValveRegisters (VC4PIXELVALVE_REGISTERS* RegistersPtr)
{
    PAGED_CODE();
    ROS_ASSERT_MAX_IRQL(PASSIVE_LEVEL);

    // Read the registers into a local copy and use the debugger
    // to interpret the bitfields
    struct {
        VC4PIXELVALVE_CONTROL Control;
        VC4PIXELVALVE_VCONTROL VControl;
        ULONG VSyncD;
        VC4PIXELVALVE_HORZA HorzA;
        VC4PIXELVALVE_HORZB HorzB;
        VC4PIXELVALVE_VERTA VertA;
        VC4PIXELVALVE_VERTB VertB;
        ULONG VertAEven;
        ULONG VertBEven;
        VC4PIXELVALVE_INTERRUPT IntEn;
        VC4PIXELVALVE_INTERRUPT IntStat;
        ULONG Status;
        ULONG HactAct;
    } registers;

    registers.Control.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->Control);
    registers.VControl.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->VControl);
    registers.VSyncD = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->VSyncD);
    registers.HorzA.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->HorzA);
    registers.HorzB.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->HorzB);
    registers.VertA.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->VertA);
    registers.VertB.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->VertB);
    registers.VertAEven = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->VertAEven);
    registers.VertBEven = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->VertBEven);
    registers.IntEn.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->IntEn);
    registers.IntStat.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->IntStat);
    registers.Status = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->Status);
    registers.HactAct = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->HactAct);
}
_Use_decl_annotations_
void VC4_DEBUG::DumpHvsRegisters (VC4HVS_REGISTERS* RegistersPtr)
{
    PAGED_CODE();
    ROS_ASSERT_MAX_IRQL(PASSIVE_LEVEL);

    // Read the registers into a local copy and use the debugger
    // to interpret the bitfields
    struct {
        VC4HVS_DISPCTRL DISPCTRL;
        VC4HVS_DISPSTAT DISPSTAT;
        ULONG DISPID;
        VC4HVS_DISPECTRL DISPECTRL;
        VC4HVS_DISPPROF DISPPROF;
        VC4HVS_DISPDITHER DISPDITHER;
        VC4HVS_DISPEOLN DISPEOLN;
        VC4HVS_DISPLIST DISPLIST0;
        VC4HVS_DISPLIST DISPLIST1;
        VC4HVS_DISPLIST DISPLIST2;
        VC4HVS_DISPLSTAT DISPLSTAT;
        VC4HVS_DISPLACT DISPLACT0;
        VC4HVS_DISPLACT DISPLACT1;
        VC4HVS_DISPLACT DISPLACT2;
        VC4HVS_DISPFIFOCTRL DISPCTRL0;
        VC4HVS_DISPBKGND DISPBKGND0;
        VC4HVS_DISPFIFOSTAT DISPSTAT0;
        VC4HVS_DISPFIFOBASE DISPBASE0;
        VC4HVS_DISPFIFOCTRL DISPCTRL1;
        VC4HVS_DISPBKGND DISPBKGND1;
        VC4HVS_DISPFIFOSTAT DISPSTAT1;
        VC4HVS_DISPFIFOBASE DISPBASE1;
        VC4HVS_DISPFIFOCTRL DISPCTRL2;
        VC4HVS_DISPBKGND DISPBKGND2;
        VC4HVS_DISPFIFOSTAT DISPSTAT2;
        VC4HVS_DISPFIFOBASE DISPBASE2;
        VC4HVS_DISPALPHA2 DISPALPHA2;
        VC4HVS_GAMADDR GAMADDR;
    } registers;

    registers.DISPCTRL.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->DISPCTRL);
    registers.DISPSTAT.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->DISPSTAT);
    registers.DISPID = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->DISPID);
    registers.DISPECTRL.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->DISPECTRL);
    registers.DISPPROF.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->DISPPROF);
    registers.DISPDITHER.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->DISPDITHER);
    registers.DISPEOLN.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->DISPEOLN);
    registers.DISPLIST0.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->DISPLIST0);
    registers.DISPLIST1.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->DISPLIST1);
    registers.DISPLIST2.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->DISPLIST2);
    registers.DISPLSTAT.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->DISPLSTAT);
    registers.DISPLACT0.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->DISPLACT0);
    registers.DISPLACT1.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->DISPLACT1);
    registers.DISPLACT2.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->DISPLACT2);
    registers.DISPCTRL0.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->DISPCTRL0);
    registers.DISPBKGND0.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->DISPBKGND0);
    registers.DISPSTAT0.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->DISPSTAT0);
    registers.DISPBASE0.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->DISPBASE0);
    registers.DISPCTRL1.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->DISPCTRL1);
    registers.DISPBKGND1.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->DISPBKGND1);
    registers.DISPSTAT1.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->DISPSTAT1);
    registers.DISPBASE1.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->DISPBASE1);
    registers.DISPCTRL2.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->DISPCTRL2);
    registers.DISPBKGND2.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->DISPBKGND2);
    registers.DISPSTAT2.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->DISPSTAT2);
    registers.DISPBASE2.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->DISPBASE2);
    registers.DISPALPHA2.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->DISPALPHA2);
    registers.GAMADDR.AsUlong = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->GAMADDR);

    // Read context memory into local variable
    ULONG* contextMem = new (PagedPool, ROS_ALLOC_TAG::TEMP) ULONG[0x1000];
    for (ULONG i = 0; i < ARRAYSIZE(RegistersPtr->DLISTMEM); ++i) {
        contextMem[i] = READ_REGISTER_NOFENCE_ULONG(&RegistersPtr->DLISTMEM[i]);
    }
    auto freeContextMem = ROS_FINALLY::Do([&] {
        PAGED_CODE();
        delete[] contextMem;
    });

    auto entryPtr = reinterpret_cast<const VC4HVS_DLIST_ENTRY_UNITY*>(
        &contextMem[registers.DISPLACT1.LACT]);
    UNREFERENCED_PARAMETER(entryPtr);
}