Source code of Windows XP (NT5)
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

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