mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
231 lines
7.4 KiB
231 lines
7.4 KiB
/*++
|
|
|
|
Copyright (C) Microsoft Corporation, 1996 - 1996
|
|
|
|
Module Name:
|
|
|
|
hardware.c
|
|
|
|
Abstract:
|
|
|
|
Hardware I/O.
|
|
|
|
--*/
|
|
|
|
#include "common.h"
|
|
|
|
VOID
|
|
HwCancelRoutine(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
{
|
|
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
|
|
Irp->IoStatus.Status = STATUS_CANCELLED;
|
|
Irp->Tail.Overlay.AuxiliaryBuffer = NULL;
|
|
IoReleaseCancelSpinLock(Irp->CancelIrql);
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
|
|
BOOLEAN
|
|
HwDeviceIsr(
|
|
IN PKINTERRUPT Interrupt,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
)
|
|
{
|
|
PDEVICE_INSTANCE DeviceInstance;
|
|
|
|
DeviceInstance = (PDEVICE_INSTANCE)DeviceObject->DeviceExtension;
|
|
if (READ_STATUS_PORT(DeviceInstance) & MPU401_DSR)
|
|
return FALSE;
|
|
if (IoRequestDpc(DeviceObject, NULL, NULL))
|
|
InterlockedIncrement(&DeviceInstance->DpcCount);
|
|
return TRUE;
|
|
}
|
|
|
|
static
|
|
VOID
|
|
CompletePendingIrp(
|
|
IN PIRP Irp,
|
|
IN OUT PKIRQL IrqlOld
|
|
)
|
|
{
|
|
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
|
|
IoSetCancelRoutine(Irp, NULL);
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
Irp->Tail.Overlay.AuxiliaryBuffer = NULL;
|
|
IoReleaseCancelSpinLock(*IrqlOld);
|
|
IoCompleteRequest(Irp, IO_SOUND_INCREMENT);
|
|
IoAcquireCancelSpinLock(IrqlOld);
|
|
}
|
|
|
|
VOID
|
|
HwDeferredRead(
|
|
IN PKDPC Dpc,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN ULONGLONG SystemTime
|
|
)
|
|
{
|
|
PDEVICE_INSTANCE DeviceInstance;
|
|
PPIN_INSTANCE PinInstance;
|
|
BOOLEAN FifoEmpty;
|
|
|
|
FifoEmpty = FALSE;
|
|
DeviceInstance = (PDEVICE_INSTANCE)DeviceObject->DeviceExtension;
|
|
PinInstance = (PPIN_INSTANCE)DeviceInstance->PinFileObjects[ID_MUSICCAPTURE_PIN]->FsContext;
|
|
if (PinInstance && (PinInstance->State == KSSTATE_RUN)) {
|
|
ULONG TimeStamp;
|
|
PLIST_ENTRY IrpListEntry;
|
|
KIRQL IrqlOld;
|
|
|
|
TimeStamp = (ULONG)((KeQueryPerformanceCounter(NULL).QuadPart - PinInstance->TimeBase) * 1000 / PinInstance->Frequency);
|
|
IoAcquireCancelSpinLock(&IrqlOld);
|
|
for (IrpListEntry = PinInstance->IoQueue.Flink; IrpListEntry != &PinInstance->IoQueue; IrpListEntry = PinInstance->IoQueue.Flink) {
|
|
PIO_STACK_LOCATION IrpStack;
|
|
PIRP Irp;
|
|
PCHAR ReadParam;
|
|
PCHAR Buffer;
|
|
ULONG ReadSize;
|
|
PKSSTREAM_HEADER StreamHdr;
|
|
|
|
Irp = (PIRP)CONTAINING_RECORD(IrpListEntry->Flink, IRP, Tail.Overlay.ListEntry);
|
|
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
|
ReadParam = MmGetSystemAddressForMdl(Irp->MdlAddress);
|
|
StreamHdr = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
|
|
Buffer = ReadParam + StreamHdr->DataSize;
|
|
if (!StreamHdr->DataSize || (StreamHdr->PresentationTime.Time / 10000 + *(PULONG)Irp->Tail.Overlay.AuxiliaryBuffer != TimeStamp)) {
|
|
PCHAR NextChunk;
|
|
|
|
NextChunk = (PCHAR)(((ULONG)Buffer + FILE_LONG_ALIGNMENT) & ~FILE_LONG_ALIGNMENT);
|
|
if (!StreamHdr->DataSize) {
|
|
StreamHdr->PresentationTime.Time = TimeStamp * 10000;
|
|
*(PULONG)NextChunk = 0;
|
|
} else if ((ULONG)(NextChunk + 2 * sizeof(ULONG) - ReadParam) >= IrpStack->Parameters.DeviceIoControl.InputBufferLength) {
|
|
CompletePendingIrp(Irp, &IrqlOld);
|
|
continue;
|
|
} else
|
|
*(PULONG)NextChunk = (ULONG)(TimeStamp - StreamHdr->PresentationTime.Time / 10000);
|
|
*((PULONG)NextChunk + 1) = 0;
|
|
Irp->Tail.Overlay.AuxiliaryBuffer = NextChunk;
|
|
NextChunk += (2 * sizeof(ULONG));
|
|
PinInstance->ByteIo += NextChunk - Buffer;
|
|
Buffer = NextChunk;
|
|
}
|
|
ReadSize = 0;
|
|
do {
|
|
*Buffer++ = READ_DATA_PORT(DeviceInstance);
|
|
ReadSize++;
|
|
if (READ_STATUS_PORT(DeviceInstance) & MPU401_DSR) {
|
|
FifoEmpty = TRUE;
|
|
break;
|
|
}
|
|
} while ((ULONG)(Buffer - ReadParam) < IrpStack->Parameters.DeviceIoControl.InputBufferLength);
|
|
*((PULONG)Irp->Tail.Overlay.AuxiliaryBuffer + 1) += ReadSize;
|
|
PinInstance->ByteIo += ReadSize;
|
|
StreamHdr->DataSize = Buffer - ReadParam;
|
|
if ((ULONG)(Buffer - ReadParam) == IrpStack->Parameters.DeviceIoControl.InputBufferLength)
|
|
CompletePendingIrp(Irp, &IrqlOld);
|
|
if (FifoEmpty)
|
|
break;
|
|
}
|
|
IoReleaseCancelSpinLock(IrqlOld);
|
|
PinGenerateEvent(PinInstance, &KSEVENTSETID_Connection, KSEVENT_CONNECTION_POSITIONUPDATE);
|
|
}
|
|
if (!FifoEmpty) {
|
|
KIRQL IrqlOld;
|
|
|
|
IoAcquireCancelSpinLock(&IrqlOld);
|
|
do
|
|
READ_DATA_PORT(DeviceInstance);
|
|
while (!(READ_STATUS_PORT(DeviceInstance) & MPU401_DSR));
|
|
IoReleaseCancelSpinLock(IrqlOld);
|
|
}
|
|
InterlockedDecrement(&DeviceInstance->DpcCount);
|
|
}
|
|
|
|
VOID
|
|
HwDeferredWrite(
|
|
IN PKDPC Dpc,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN ULONGLONG SystemTime
|
|
)
|
|
{
|
|
PDEVICE_INSTANCE DeviceInstance;
|
|
PPIN_INSTANCE PinInstance;
|
|
|
|
DeviceInstance = (PDEVICE_INSTANCE)DeviceObject->DeviceExtension;
|
|
PinInstance = (PPIN_INSTANCE)DeviceInstance->PinFileObjects[ID_MUSICCAPTURE_PIN]->FsContext;
|
|
if (PinInstance->State == KSSTATE_RUN) {
|
|
ULONG TimeStamp;
|
|
PLIST_ENTRY IrpListEntry;
|
|
KIRQL IrqlOld;
|
|
|
|
TimeStamp = (ULONG)((KeQueryPerformanceCounter(NULL).QuadPart - PinInstance->TimeBase) * 1000 / PinInstance->Frequency);
|
|
IoAcquireCancelSpinLock(&IrqlOld);
|
|
for (IrpListEntry = PinInstance->IoQueue.Flink; IrpListEntry != &PinInstance->IoQueue; IrpListEntry = PinInstance->IoQueue.Flink) {
|
|
PIRP Irp;
|
|
PCHAR ReadParam;
|
|
PKSSTREAM_HEADER StreamHdr;
|
|
ULONG Continue;
|
|
|
|
Irp = (PIRP)CONTAINING_RECORD(IrpListEntry->Flink, IRP, Tail.Overlay.ListEntry);
|
|
StreamHdr = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
|
|
ReadParam = MmGetSystemAddressForMdl(Irp->MdlAddress);
|
|
Continue = TRUE;
|
|
for (;;) {
|
|
PCHAR Buffer;
|
|
ULONG WriteSize;
|
|
ULONG WrittenSize;
|
|
|
|
if (StreamHdr->PresentationTime.Time / 10000 + *(PULONG)Irp->Tail.Overlay.AuxiliaryBuffer > TimeStamp) {
|
|
LARGE_INTEGER liTime;
|
|
|
|
liTime.QuadPart = -(LONG)(StreamHdr->PresentationTime.Time / 10000 + *(PULONG)Irp->Tail.Overlay.AuxiliaryBuffer - TimeStamp);
|
|
if (!PinInstance->QueueTimer.Header.Inserted && !KeSetTimerEx(&PinInstance->QueueTimer, liTime, 0, &PinInstance->QueueDpc))
|
|
InterlockedIncrement(&PinInstance->TimerCount);
|
|
Continue = FALSE;
|
|
break;
|
|
}
|
|
WriteSize = *(((PULONG)Irp->Tail.Overlay.AuxiliaryBuffer) + 1);
|
|
WrittenSize = Irp->IoStatus.Information;
|
|
WriteSize -= (WrittenSize - (Irp->Tail.Overlay.AuxiliaryBuffer - ReadParam));
|
|
if (WriteSize > StreamHdr->DataSize - WrittenSize)
|
|
WriteSize = StreamHdr->DataSize - WrittenSize;
|
|
for (; WriteSize; WriteSize--) {
|
|
for (Continue = MPU_TIMEOUT; Continue && (READ_STATUS_PORT(DeviceInstance) & MPU401_DRR); Continue--)
|
|
KeStallExecutionProcessor(1);
|
|
if (!Continue)
|
|
break;
|
|
WRITE_DATA_PORT(DeviceInstance, ReadParam[WrittenSize++]);
|
|
}
|
|
if (!WriteSize || (WrittenSize - Irp->IoStatus.Information)) {
|
|
if (Irp->IoStatus.Information == Irp->Tail.Overlay.AuxiliaryBuffer - ReadParam + 2 * sizeof(ULONG))
|
|
PinInstance->ByteIo += 2 * sizeof(ULONG);
|
|
PinInstance->ByteIo += (WrittenSize - Irp->IoStatus.Information);
|
|
if (!WriteSize) {
|
|
PCHAR NextChunk;
|
|
|
|
NextChunk = (PCHAR)(((ULONG)Irp->Tail.Overlay.AuxiliaryBuffer + FILE_LONG_ALIGNMENT) & ~FILE_LONG_ALIGNMENT);
|
|
Irp->IoStatus.Information = NextChunk - ReadParam + 2 * sizeof(ULONG);
|
|
if (Irp->IoStatus.Information >= StreamHdr->DataSize) {
|
|
Irp->IoStatus.Information = StreamHdr->DataSize;
|
|
CompletePendingIrp(Irp, &IrqlOld);
|
|
break;
|
|
}
|
|
PinInstance->ByteIo += (NextChunk - Irp->Tail.Overlay.AuxiliaryBuffer);
|
|
Irp->Tail.Overlay.AuxiliaryBuffer = NextChunk;
|
|
} else {
|
|
Irp->IoStatus.Information = WrittenSize;
|
|
if (!Continue)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!Continue)
|
|
break;
|
|
}
|
|
IoReleaseCancelSpinLock(IrqlOld);
|
|
PinGenerateEvent(PinInstance, &KSEVENTSETID_Connection, KSEVENT_CONNECTION_POSITIONUPDATE);
|
|
}
|
|
InterlockedDecrement(&PinInstance->TimerCount);
|
|
}
|