/*++ 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); }