static VOID XenPci_HighSyncCallFunction0( PRKDPC Dpc, PVOID Context, PVOID SystemArgument1, PVOID SystemArgument2) { highsync_info_t *highsync_info = Context; ULONG ActiveProcessorCount; KIRQL old_irql; UNREFERENCED_PARAMETER(Dpc); UNREFERENCED_PARAMETER(SystemArgument1); UNREFERENCED_PARAMETER(SystemArgument2); FUNCTION_ENTER(); #if (NTDDI_VERSION >= NTDDI_WINXP) ActiveProcessorCount = (ULONG)KeNumberProcessors; #else ActiveProcessorCount = (ULONG)*KeNumberProcessors; #endif InterlockedIncrement(&highsync_info->nr_procs_at_dispatch_level); if (highsync_info->sync_level > DISPATCH_LEVEL) { while (highsync_info->nr_procs_at_dispatch_level < (LONG)ActiveProcessorCount) { KeStallExecutionProcessor(1); KeMemoryBarrier(); } } _disable(); //__asm cli; KeRaiseIrql(highsync_info->sync_level, &old_irql); while (highsync_info->nr_spinning_at_sync_level < (LONG)ActiveProcessorCount - 1) { KeStallExecutionProcessor(1); KeMemoryBarrier(); } highsync_info->function0(highsync_info->context); KeLowerIrql(old_irql); _enable(); //__asm sti; highsync_info->do_spin = FALSE; KeMemoryBarrier(); /* wait for all the other processors to complete spinning, just in case it matters */ while (highsync_info->nr_spinning_at_sync_level) { KeStallExecutionProcessor(1); KeMemoryBarrier(); } InterlockedDecrement(&highsync_info->nr_procs_at_dispatch_level); /* wait until nr_procs_at_dispatch_level drops to 0 indicating that nothing else requires highsync_info */ while (highsync_info->nr_procs_at_dispatch_level) { KeStallExecutionProcessor(1); KeMemoryBarrier(); } KeSetEvent(&highsync_info->highsync_complete_event, IO_NO_INCREMENT, FALSE); FUNCTION_EXIT(); }
static VOID NTAPI BootImageFadeIn(VOID) { UCHAR PaletteBitmapBuffer[sizeof(BITMAPINFOHEADER) + sizeof(_MainPalette)]; PBITMAPINFOHEADER PaletteBitmap = (PBITMAPINFOHEADER)PaletteBitmapBuffer; LPRGBQUAD Palette = (LPRGBQUAD)(PaletteBitmapBuffer + sizeof(BITMAPINFOHEADER)); ULONG Iteration, Index, ClrUsed; /* Check if we're installed and we own it */ if ((InbvBootDriverInstalled) && (InbvDisplayState == INBV_DISPLAY_STATE_OWNED)) { /* Acquire the lock */ InbvAcquireLock(); /* * Build a bitmap containing the fade in palette. The palette entries * are then processed in a loop and set using VidBitBlt function. */ ClrUsed = sizeof(_MainPalette) / sizeof(_MainPalette[0]); RtlZeroMemory(PaletteBitmap, sizeof(BITMAPINFOHEADER)); PaletteBitmap->biSize = sizeof(BITMAPINFOHEADER); PaletteBitmap->biBitCount = 4; PaletteBitmap->biClrUsed = ClrUsed; /* * Main animation loop. */ for (Iteration = 0; Iteration <= PALETTE_FADE_STEPS; ++Iteration) { for (Index = 0; Index < ClrUsed; Index++) { Palette[Index].rgbRed = (UCHAR) (_MainPalette[Index].rgbRed * Iteration / PALETTE_FADE_STEPS); Palette[Index].rgbGreen = (UCHAR) (_MainPalette[Index].rgbGreen * Iteration / PALETTE_FADE_STEPS); Palette[Index].rgbBlue = (UCHAR) (_MainPalette[Index].rgbBlue * Iteration / PALETTE_FADE_STEPS); } VidBitBlt(PaletteBitmapBuffer, 0, 0); /* Wait for a bit. */ KeStallExecutionProcessor(PALETTE_FADE_TIME); } /* Release the lock */ InbvReleaseLock(); /* Wait for a bit. */ KeStallExecutionProcessor(PALETTE_FADE_TIME); } }
static VOID XenPci_HighSyncCallFunctionN( PRKDPC Dpc, PVOID Context, PVOID SystemArgument1, PVOID SystemArgument2) { highsync_info_t *highsync_info = Context; ULONG ActiveProcessorCount; KIRQL old_irql; UNREFERENCED_PARAMETER(Dpc); UNREFERENCED_PARAMETER(SystemArgument1); UNREFERENCED_PARAMETER(SystemArgument2); FUNCTION_ENTER(); FUNCTION_MSG("(CPU = %d)\n", KeGetCurrentProcessorNumber()); KdPrint((__DRIVER_NAME " CPU %d spinning...\n", KeGetCurrentProcessorNumber())); InterlockedIncrement(&highsync_info->nr_procs_at_dispatch_level); if (highsync_info->sync_level > DISPATCH_LEVEL) { #if (NTDDI_VERSION >= NTDDI_WINXP) ActiveProcessorCount = (ULONG)KeNumberProcessors; #else ActiveProcessorCount = (ULONG)*KeNumberProcessors; #endif while (highsync_info->nr_procs_at_dispatch_level < (LONG)ActiveProcessorCount) { KeStallExecutionProcessor(1); KeMemoryBarrier(); } } _disable(); //__asm cli; KeRaiseIrql(highsync_info->sync_level, &old_irql); InterlockedIncrement(&highsync_info->nr_spinning_at_sync_level); while(highsync_info->do_spin) { KeStallExecutionProcessor(1); KeMemoryBarrier(); } highsync_info->functionN(highsync_info->context); KeLowerIrql(old_irql); _enable(); //__asm sti; InterlockedDecrement(&highsync_info->nr_spinning_at_sync_level); InterlockedDecrement(&highsync_info->nr_procs_at_dispatch_level); FUNCTION_EXIT(); return; }
VOID SynthMidiSendFM( IN PUCHAR PortBase, IN ULONG Address, IN UCHAR Data ) { // these delays need to be 23us at least for old opl2 chips, even // though new chips can handle 1 us delays. WRITE_PORT_UCHAR(PortBase + (Address < 0x100 ? 0 : 2), (UCHAR)Address); KeStallExecutionProcessor(23); WRITE_PORT_UCHAR(PortBase + (Address < 0x100 ? 1 : 3), Data); KeStallExecutionProcessor(23); }
/* * FUNCTION: Write data to a port, waiting first for it to become ready */ BOOLEAN i8042Write( IN PPORT_DEVICE_EXTENSION DeviceExtension, IN PUCHAR addr, IN UCHAR data) { ULONG Counter; ASSERT(addr); ASSERT(DeviceExtension->ControlPort != NULL); Counter = DeviceExtension->Settings.PollingIterations; while ((KBD_IBF & READ_PORT_UCHAR(DeviceExtension->ControlPort)) && (Counter--)) { KeStallExecutionProcessor(50); } if (Counter) { WRITE_PORT_UCHAR(addr, data); INFO_(I8042PRT, "Sent 0x%x to port %p\n", data, addr); return TRUE; } return FALSE; }
void CCMIAdapter::resetController() { PAGED_CODE(); DBGPRINT(("CCMIAdapter[%p]::resetController()", this)); writeUInt32(REG_INTHLDCLR, 0); #if OUT_CHANNEL == 1 writeUInt32(REG_FUNCTRL0, ADC_CH0 | (RST_CH0 | RST_CH1)); writeUInt32(REG_FUNCTRL0, ADC_CH0 & ~(RST_CH0 | RST_CH1)); #else writeUInt32(REG_FUNCTRL0, ADC_CH1 | (RST_CH0 | RST_CH1)); writeUInt32(REG_FUNCTRL0, ADC_CH1 & ~(RST_CH0 | RST_CH1)); #endif KeStallExecutionProcessor(100L); writeUInt32(REG_FUNCTRL0, 0); writeUInt32(REG_FUNCTRL1, 0); writeUInt32(REG_CHFORMAT, 0); writeUInt32(REG_MISCCTRL, EN_DBLDAC); #if OUT_CHANNEL == 1 setUInt32Bit(REG_MISCCTRL, XCHG_DAC); #endif setUInt32Bit(REG_FUNCTRL1, BREQ); writeMixer(0, 0); return; }
VOID ShiftOutBits( IN PFDO_DATA FdoData, IN USHORT data, IN USHORT count, IN PUCHAR CSRBaseIoAddress) { USHORT x,mask; mask = 0x01 << (count - 1); x = FdoData->ReadPort((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG)); x &= ~(EEDO | EEDI); do { x &= ~EEDI; if(data & mask) x |= EEDI; FdoData->WritePort((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG), x); KeStallExecutionProcessor(100); RaiseClock(FdoData, &x, CSRBaseIoAddress); LowerClock(FdoData, &x, CSRBaseIoAddress); mask = mask >> 1; } while(mask); x &= ~EEDI; FdoData->WritePort((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG), x); }
static void vdev_sleep(void *context, unsigned int msecs) { UNREFERENCED_PARAMETER(context); /* We can't really sleep in a storage miniport so we just busy wait. */ KeStallExecutionProcessor(1000 * msecs); }
BOOLEAN CallPxe(UINT16 Service, PVOID Parameter) { PPXE pxe; PXENV_EXIT exit; pxe = GetPxeStructure(); if (!pxe) return FALSE; if (Service != PXENV_TFTP_READ) { // HACK: this delay shouldn't be necessary KeStallExecutionProcessor(100 * 1000); // 100 ms TRACE("PxeCall(0x%x, %p)\n", Service, Parameter); } exit = PxeCallApi(pxe->EntryPointSP.segment, pxe->EntryPointSP.offset, Service, Parameter); if (exit != PXENV_EXIT_SUCCESS) { ERR("PxeCall(0x%x, %p) failed with exit=%d status=0x%x\n", Service, Parameter, exit, *(PXENV_STATUS*)Parameter); return FALSE; } if (*(PXENV_STATUS*)Parameter != PXENV_STATUS_SUCCESS) { ERR("PxeCall(0x%x, %p) succeeded, but returned error status 0x%x\n", Service, Parameter, *(PXENV_STATUS*)Parameter); return FALSE; } return TRUE; }
static FORCEINLINE NTSTATUS __WaitState2( IN PCHAR BackendPath, IN OUT PXENBUS_STATE State ) { NTSTATUS Status; PCHAR Buffer; XENBUS_STATE OldState = *State; while (OldState == *State) { Status = StoreRead(NULL, BackendPath, "state", &Buffer); if (!NT_SUCCESS(Status)) goto fail; *State = (XENBUS_STATE)strtoul(Buffer, NULL, 10); AustereFree(Buffer); if (*State == OldState) KeStallExecutionProcessor(100000); } LogTrace("BACKEND_STATE -> %s\n", __XenbusStateName(*State)); return STATUS_SUCCESS; fail: return Status; }
BOOLEAN SynthPresent(PUCHAR base, PUCHAR inbase, volatile BOOLEAN *Fired) /*++ Routine Description: Detect the presence or absence of a 3812 (adlib-compatible) synthesizer at the given i/o address by starting the timer and looking for an overflow. Can be used to detect left and right synthesizers separately. Arguments: base - base output address inbase - base input address Return Value: TRUE if a synthesizer is present at that address --*/ { #define inport(port) READ_PORT_UCHAR((PUCHAR)(port)) UCHAR t1, t2; if (Fired) { *Fired = FALSE; } // check if the chip is present SynthMidiSendFM(base, 4, 0x60); // mask T1 & T2 SynthMidiSendFM(base, 4, 0x80); // reset IRQ t1 = inport(inbase); // read status register SynthMidiSendFM(base, 2, 0xff); // set timer - 1 latch SynthMidiSendFM(base, 4, 0x21); // unmask & start T1 // this timer should go off in 80 us. It sometimes // takes more than 100us, but will always have expired within // 200 us if it is ever going to. KeStallExecutionProcessor(200); if (Fired && *Fired) { return TRUE; } t2 = inport(inbase); // read status register SynthMidiSendFM(base, 4, 0x60); SynthMidiSendFM(base, 4, 0x80); if (!((t1 & 0xE0) == 0) || !((t2 & 0xE0) == 0xC0)) { return(FALSE); } return TRUE; #undef inport }
VOID LowerClock( IN PFDO_DATA FdoData, IN OUT USHORT *x, IN PUCHAR CSRBaseIoAddress) { *x = *x & ~EESK; FdoData->WritePort((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG), *x); KeStallExecutionProcessor(100); }
BOOLEAN mpuWrite( PSOUND_HARDWARE pHw, UCHAR value ) /*++ Routine Description: Write a command or data to the MPU Arguments: pHw - Pointer to the device extension data value - the value to be written Return Value: TRUE if written correctly , FALSE otherwise --*/ { ULONG uCount; ASSERT(pHw->Key == HARDWARE_KEY); uCount = 100; while (uCount--) { int InnerCount; HwEnter(pHw); // // Inner count loop protects against dynamic deadlock with // midi. // for (InnerCount = 0; InnerCount < 10; InnerCount++) { if (!(INPORT(pHw, MPU_STATUS_PORT) & 0x40)) { // is it ok to send data (bit 6 clear)? - drude OUTPORT(pHw, MPU_DATA_PORT, value); break; } KeStallExecutionProcessor(1); // 1 us } HwLeave(pHw); if (InnerCount < 10) { return TRUE; } } dprintf1(("mpuWrite:Failed to write %x to mpu", (ULONG)value)); return FALSE; }
VOID i8042Flush( IN PPORT_DEVICE_EXTENSION DeviceExtension) { UCHAR Ignore; /* Flush output buffer */ while (NT_SUCCESS(i8042ReadData(DeviceExtension, KBD_OBF /* | MOU_OBF*/, &Ignore))) { KeStallExecutionProcessor(50); TRACE_(I8042PRT, "Output data flushed\n"); } /* Flush input buffer */ while (NT_SUCCESS(i8042ReadData(DeviceExtension, KBD_IBF, &Ignore))) { KeStallExecutionProcessor(50); TRACE_(I8042PRT, "Input data flushed\n"); } }
static void ChipSelOn(void) { ConsoleLedState = *CpuAuxControl & CONSOLE_LED; *CpuAuxControl &= ~CPU_TO_SER; *CpuAuxControl &= ~SERCLK; *CpuAuxControl &= ~NVRAM_PRE; KeStallExecutionProcessor(1); *CpuAuxControl |= CONSOLE_CS; *CpuAuxControl |= SERCLK; }
static BOOLEAN SpiSendSynchronousSrb( IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, IN PSCSI_REQUEST_BLOCK Srb) { BOOLEAN ret; ASSERT(!(Srb->SrbFlags & SRB_FLAGS_IS_ACTIVE)); /* HACK: handle lack of interrupts */ while (!(DeviceExtension->InterruptFlags & SCSI_PORT_NEXT_REQUEST_READY)) { KeStallExecutionProcessor(100 * 1000); DeviceExtension->HwInterrupt(DeviceExtension->MiniPortDeviceExtension); } DeviceExtension->InterruptFlags &= ~SCSI_PORT_NEXT_REQUEST_READY; Srb->SrbFlags |= SRB_FLAGS_IS_ACTIVE; if (!DeviceExtension->HwStartIo( DeviceExtension->MiniPortDeviceExtension, Srb)) { ExFreePool(Srb); return FALSE; } /* HACK: handle lack of interrupts */ while (Srb->SrbFlags & SRB_FLAGS_IS_ACTIVE) { KeStallExecutionProcessor(100 * 1000); DeviceExtension->HwInterrupt(DeviceExtension->MiniPortDeviceExtension); } ret = SRB_STATUS(Srb->SrbStatus) == SRB_STATUS_SUCCESS; ExFreePool(Srb); return ret; }
static NTSTATUS i8042BasicDetect( IN PPORT_DEVICE_EXTENSION DeviceExtension) { NTSTATUS Status; ULONG ResendIterations; UCHAR Value = 0; /* Don't enable keyboard and mouse interrupts, disable keyboard/mouse */ i8042Flush(DeviceExtension); if (!i8042ChangeMode(DeviceExtension, CCB_KBD_INT_ENAB | CCB_MOUSE_INT_ENAB, CCB_KBD_DISAB | CCB_MOUSE_DISAB)) return STATUS_IO_DEVICE_ERROR; i8042Flush(DeviceExtension); /* Issue a CTRL_SELF_TEST command to check if this is really an i8042 controller */ ResendIterations = DeviceExtension->Settings.ResendIterations + 1; while (ResendIterations--) { if (!i8042Write(DeviceExtension, DeviceExtension->ControlPort, CTRL_SELF_TEST)) { WARN_(I8042PRT, "Writing CTRL_SELF_TEST command failed\n"); return STATUS_IO_TIMEOUT; } Status = i8042ReadDataWait(DeviceExtension, &Value); if (!NT_SUCCESS(Status)) { WARN_(I8042PRT, "Failed to read CTRL_SELF_TEST response, status 0x%08lx\n", Status); return Status; } if (Value == KBD_SELF_TEST_OK) { INFO_(I8042PRT, "CTRL_SELF_TEST completed successfully!\n"); break; } else if (Value == KBD_RESEND) { TRACE_(I8042PRT, "Resending...\n", Value); KeStallExecutionProcessor(50); } else { WARN_(I8042PRT, "Got 0x%02x instead of 0x55\n", Value); return STATUS_IO_DEVICE_ERROR; } } return STATUS_SUCCESS; }
static int NvramHold(void) { int Error, Timeout = NVDELAY_LIMIT; ChipSelOn(); while (!(*CpuAuxControl & SER_TO_CPU) && Timeout--) KeStallExecutionProcessor(NVDELAY_TIME); Error = (*CpuAuxControl & SER_TO_CPU) ? ESUCCESS : EIO; ChipSelOff(); return Error; }
VOID VIOSerialSendCtrlMsg( IN WDFDEVICE Device, IN ULONG id, IN USHORT event, IN USHORT value ) { struct VirtIOBufferDescriptor sg; struct virtqueue *vq; UINT len; PPORTS_DEVICE pContext = GetPortsDevice(Device); VIRTIO_CONSOLE_CONTROL cpkt; int cnt = 0; if (!pContext->isHostMultiport) { return; } vq = pContext->c_ovq; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> %s vq = %p\n", __FUNCTION__, vq); cpkt.id = id; cpkt.event = event; cpkt.value = value; sg.physAddr = MmGetPhysicalAddress(&cpkt); sg.ulSize = sizeof(cpkt); WdfSpinLockAcquire(pContext->CVqLock); if(0 <= vq->vq_ops->add_buf(vq, &sg, 1, 0, &cpkt, NULL, 0)) { vq->vq_ops->kick(vq); while(!vq->vq_ops->get_buf(vq, &len)) { KeStallExecutionProcessor(50); if(++cnt > RETRY_THRESHOLD) { TraceEvents(TRACE_LEVEL_FATAL, DBG_PNP, "<-> %s retries = %d\n", __FUNCTION__, cnt); break; } } } WdfSpinLockRelease(pContext->CVqLock); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- %s cnt = %d\n", __FUNCTION__, cnt); }
USHORT GetEEpromSize( IN PFDO_DATA FdoData, IN PUCHAR CSRBaseIoAddress) { USHORT x, data; USHORT size = 1; // select EEPROM, reset bits, set EECS x = FdoData->ReadPort((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG)); x &= ~(EEDI | EEDO | EESK); x |= EECS; FdoData->WritePort((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG), x); // write the read opcode ShiftOutBits(FdoData, EEPROM_READ_OPCODE, 3, CSRBaseIoAddress); // experiment to discover the size of the eeprom. request register zero // and wait for the eeprom to tell us it has accepted the entire address. x = FdoData->ReadPort((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG)); do { size *= 2; // each bit of address doubles eeprom size x |= EEDO; // set bit to detect "dummy zero" x &= ~EEDI; // address consists of all zeros FdoData->WritePort((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG), x); KeStallExecutionProcessor(100); RaiseClock(FdoData, &x, CSRBaseIoAddress); LowerClock(FdoData, &x, CSRBaseIoAddress); // check for "dummy zero" x = FdoData->ReadPort((PUSHORT)(CSRBaseIoAddress + CSR_EEPROM_CONTROL_REG)); if (size > EEPROM_MAX_SIZE) { size = 0; break; } } while (x & EEDO); // Now read the data (16 bits) in from the selected EEPROM word data = ShiftInBits(FdoData, CSRBaseIoAddress); EEpromCleanup(FdoData, CSRBaseIoAddress); return size; }
BOOLEAN mpuDumpBufferNoLock( PSOUND_HARDWARE pHw ) /*++ Routine Description: Dumps the contents of the hardware buffer and discard it. Assume the hardware is already locked! Arguments: pHw - pointer to the device extension data Return Value: TRUE if we succeed. --*/ { int Count = 0; int i; // dump the current hardware midi input while(Count < 2048) // we should have no more than this { for(i = 1000; i > 0; i--) { if (!(INPORT(pHw, MPU_STATUS_PORT) & 0x80)) { // do we have data waiting (bit 7 clear)? INPORT(pHw, MPU_DATA_PORT); // read and just discard the byte Count++; break; } KeStallExecutionProcessor(1); } // if we waited this long, we don't have anymore data to dump if(i == 0) break; } dprintf1(("Hardware buffer dump byte count %x", (ULONG)Count)); return TRUE; // always }
BOOLEAN mpuWriteNoLock( PSOUND_HARDWARE pHw, UCHAR value ) /*++ Routine Description: Write a command or data to the MPU. The call assumes the caller has acquired the spin lock Arguments: pHw - Pointer to the device extension data value - the value to be written Return Value: TRUE if written correctly , FALSE otherwise --*/ { int uCount; ASSERT(pHw->Key == HARDWARE_KEY); uCount = 1000; while (uCount--) { if (!(INPORT(pHw, MPU_STATUS_PORT) & 0x40)) { // is it ok to send data (bit 6 clear)? - drude OUTPORT(pHw, MPU_DATA_PORT, value); break; } KeStallExecutionProcessor(1); // 1 us } if (uCount >= 0) { return TRUE; } dprintf1(("mpuWriteNoLock:Failed to write %x to mpu", (ULONG)value)); return FALSE; }
static NTSTATUS NTAPI Send_Byte(PCONTROLLER_INFO ControllerInfo, UCHAR Byte) /* * FUNCTION: Send a byte from the host to the controller's FIFO * ARGUMENTS: * ControllerInfo: Info structure for the controller we're writing to * Offset: Offset over the controller's base address that we're writing to * Byte: Byte to write to the bus * RETURNS: * STATUS_SUCCESS if the byte was written successfully * STATUS_UNSUCCESSFUL if not * NOTES: * - Function designed after flowchart in intel datasheet * - 250us max delay. Note that this is exactly 5 times longer * than Microsoft recommends stalling the processor * - PAGED_CODE, because we spin for more than the Microsoft-recommended * maximum. * - This function is necessary because sometimes the FIFO reacts slowly * and isn't yet ready to read or write the next byte */ { int i; PAGED_CODE(); for(i = 0; i < 5; i++) { if(ReadyForWrite(ControllerInfo)) break; KeStallExecutionProcessor(50); } if (i < 5) { WRITE_PORT_UCHAR(ControllerInfo->BaseAddress + FIFO, Byte); return STATUS_SUCCESS; } else { INFO_(FLOPPY, "Send_Byte: timed out trying to write\n"); HwDumpRegisters(ControllerInfo); return STATUS_UNSUCCESSFUL; } }
//======================================================================================== // Function: SB_SMBusPollDone // Purpose: This routine wait transmit done. // Return Value: // STATUS_IO_DEVICE_ERROR - Wait done timeout // STATUS_UNSUCCESSFUL - Transmit error // STATUS_PENDING - Continue // STATUS_SUCCESS - Transmit done //======================================================================================== static NTSTATUS SB_SMBusPollDone(PTwoWireTransfer pTW) { int WaitDoneCount = 0; do { KeStallExecutionProcessor(30); SB_ReadSMBusPort(SMBSTS_ADDR); } while((regSB.SMBSTS.bit.HOSTBUSY != 0) && (WaitDoneCount++ < SB_MAX_TIMEOUT)); if (WaitDoneCount >= SB_MAX_TIMEOUT) { pTW->errCode = SUSI_STATUS_TIMEOUT; return STATUS_IO_DEVICE_ERROR; } return SB_SMBusCheckAfterTransmit(pTW); }
static NTSTATUS NTAPI Get_Byte(PCONTROLLER_INFO ControllerInfo, PUCHAR Byte) /* * FUNCTION: Read a byte from the controller to the host * ARGUMENTS: * ControllerInfo: Info structure for the controller we're reading from * Offset: Offset over the controller's base address that we're reading from * Byte: Byte to read from the bus * RETURNS: * STATUS_SUCCESS if the byte was read successfully * STATUS_UNSUCCESSFUL if not * NOTES: * - Function designed after flowchart in intel datasheet * - 250us max delay. Note that this is exactly 5 times longer * than Microsoft recommends stalling the processor * - Remember that we can be interrupted here, so this might * take much more wall clock time than 250us * - PAGED_CODE because we spin for longer than Microsoft recommends */ { int i; PAGED_CODE(); for(i = 0; i < 5; i++) { if(ReadyForRead(ControllerInfo)) break; KeStallExecutionProcessor(50); } if (i < 5) { *Byte = READ_PORT_UCHAR(ControllerInfo->BaseAddress + FIFO); return STATUS_SUCCESS; } else { INFO_(FLOPPY, "Get_Byte: timed out trying to write\n"); HwDumpRegisters(ControllerInfo); return STATUS_UNSUCCESSFUL; } }
// Locks all other processors and returns exclusivity pointer. This function // should never be called before the last exclusivity is released. _Use_decl_annotations_ EXTERN_C void *ExclGainExclusivity() { NT_ASSERT(InterlockedAdd(&g_ExclpNumberOfLockedProcessors, 0) == 0); _InterlockedAnd(&g_ExclpReleaseAllProcessors, 0); const auto numberOfProcessors = KeQueryActiveProcessorCount(nullptr); // Allocates DPCs for all processors. auto context = reinterpret_cast<ExclusivityContext *>(ExAllocatePoolWithTag( NonPagedPoolNx, sizeof(void *) + (numberOfProcessors * sizeof(KDPC)), EXCLP_POOL_TAG)); if (!context) { return nullptr; } // Execute a lock DPC for all processors but this. context->OldIrql = KeRaiseIrqlToDpcLevel(); const auto currentCpu = KeGetCurrentProcessorNumber(); for (auto i = 0ul; i < numberOfProcessors; i++) { if (i == currentCpu) { continue; } // Queue a lock DPC. KeInitializeDpc(&context->Dpcs[i], ExclpRaiseIrqlAndWaitDpc, nullptr); KeSetTargetProcessorDpc(&context->Dpcs[i], static_cast<CCHAR>(i)); KeInsertQueueDpc(&context->Dpcs[i], nullptr, nullptr); } // Wait until all other processors were halted. const auto needToBeLocked = numberOfProcessors - 1; while (_InterlockedCompareExchange(&g_ExclpNumberOfLockedProcessors, needToBeLocked, needToBeLocked) != static_cast<LONG>(needToBeLocked)) { KeStallExecutionProcessor(10); } return context; }
//======================================================================================== // Function: SB_SMBusWaitFree // Purpose: This routine check flag to wait bus free. // Return Value: // STATUS_IO_DEVICE_ERROR - Bus busy // STATUS_SUCCESS //======================================================================================== static NTSTATUS SB_SMBusWaitFree(void) { int WaitBusCount = 0; SB_ReadSMBusPort(SMBSTS_ADDR); while (regSB.SMBSTS.bit.HOSTBUSY && ((WaitBusCount++) < SB_MAX_TIMEOUT)) { KeStallExecutionProcessor(20); SB_ReadSMBusPort(SMBSTS_ADDR); } if (WaitBusCount >= SB_MAX_TIMEOUT) { DebugPrint(DBG_SMB | DBG_KERNEL, "[SMBus][SB] Wait bus free timeout\n"); regSB.SMBSTS.reg = 0xFF; SB_WriteSMBusPort(SMBSTS_ADDR); return STATUS_IO_DEVICE_ERROR; } return SUSI_STATUS_SUCCESS; }
_Use_decl_annotations_ EXTERN_C void ExclReleaseExclusivity( void *Exclusivity) { if (!Exclusivity) { return; } // Tell other processors they can be unlocked with changing the value. _InterlockedIncrement(&g_ExclpReleaseAllProcessors); // Wait until all other processors were unlocked. while (_InterlockedCompareExchange(&g_ExclpNumberOfLockedProcessors, 0, 0)) { KeStallExecutionProcessor(10); } auto context = static_cast<ExclusivityContext *>(Exclusivity); KeLowerIrql(context->OldIrql); ExFreePoolWithTag(Exclusivity, EXCLP_POOL_TAG); }
/* * FUNCTION: Read data from data port */ NTSTATUS i8042ReadDataWait( IN PPORT_DEVICE_EXTENSION DeviceExtension, OUT PUCHAR Data) { ULONG Counter; NTSTATUS Status; Counter = DeviceExtension->Settings.PollingIterations; while (Counter--) { Status = i8042ReadKeyboardData(DeviceExtension, Data); if (NT_SUCCESS(Status)) return Status; KeStallExecutionProcessor(50); } /* Timed out */ return STATUS_IO_TIMEOUT; }
/*++ Routine Description: Detect the presence or absence of a 3812 (adlib-compatible) synthesizer at the given i/o address by starting the timer and looking for an overflow. Can be used to detect left and right synthesizers separately. Arguments: base - base output address inbase - base input address Return Value: TRUE if a synthesizer is present at that address --*/ BOOL SoundSynthPresent(PUCHAR base, PUCHAR inbase) { #define inport(port) READ_PORT_UCHAR((PUCHAR)(port)) UCHAR t1, t2; DbgPrintf3(("SoundSynthPresent() - Entry")); // check if the chip is present SoundMidiSendFM(base, 4, 0x60); // mask T1 & T2 SoundMidiSendFM(base, 4, 0x80); // reset IRQ t1 = inport(inbase); // read status register SoundMidiSendFM(base, 2, 0xff); // set timer - 1 latch SoundMidiSendFM(base, 4, 0x21); // unmask & start T1 // this timer should go off in 80 us. It sometimes // takes more than 100us, but will always have expired within // 200 us if it is ever going to. KeStallExecutionProcessor(200); t2 = inport(inbase); // read status register SoundMidiSendFM(base, 4, 0x60); SoundMidiSendFM(base, 4, 0x80); if (!((t1 & 0xE0) == 0) || !((t2 & 0xE0) == 0xC0)) { return(FALSE); } return TRUE; #undef inport }