📄 floppy.c
字号:
ASSERT(disketteExtension->FloppyThread != NULL);
KeWaitForSingleObject( disketteExtension->FloppyThread,
Executive,
KernelMode,
FALSE,
NULL );
//
// Very unlikely, but it did happen once. So make
// sure FloppyThread is not NULL.
//
if (disketteExtension->FloppyThread != NULL) {
ObDereferenceObject( disketteExtension->FloppyThread );
}
disketteExtension->FloppyThread = NULL;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoSkipCurrentIrpStackLocation( Irp );
ntStatus = IoCallDriver( disketteExtension->TargetObject, Irp );
} else {
//
// We failed to either start the thread or get a pointer to the
// thread object. Either way veto the Query.
//
ntStatus = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
}
break;
case IRP_MN_CANCEL_STOP_DEVICE:
case IRP_MN_CANCEL_REMOVE_DEVICE:
if ( irpSp->MinorFunction == IRP_MN_CANCEL_STOP_DEVICE ) {
FloppyDump( FLOPPNP,("FloppyPnp: IRP_MN_CANCEL_STOP_DEVICE - Irp: %p\n", Irp) );
} else {
FloppyDump( FLOPPNP,("FloppyPnp: IRP_MN_CANCEL_REMOVE_DEVICE - Irp: %p\n", Irp) );
}
if ( !disketteExtension->IsStarted ) {
//
// Nothing to do, just pass the irp down:
// no need to start the device
//
// Set Status to SUCCESS before passing the irp down
//
Irp->IoStatus.Status = STATUS_SUCCESS;
IoSkipCurrentIrpStackLocation (Irp);
ntStatus = IoCallDriver( disketteExtension->TargetObject, Irp );
} else {
KEVENT doneEvent;
//
// Set the status to STATUS_SUCCESS
//
Irp->IoStatus.Status = STATUS_SUCCESS;
//
// We need to wait for the lower drivers to do their job.
//
IoCopyCurrentIrpStackLocationToNext (Irp);
//
// Clear the event: it will be set in the completion
// routine.
//
KeInitializeEvent( &doneEvent,
SynchronizationEvent,
FALSE);
IoSetCompletionRoutine( Irp,
FloppyPnpComplete,
&doneEvent,
TRUE, TRUE, TRUE );
ntStatus = IoCallDriver( disketteExtension->TargetObject, Irp );
if ( ntStatus == STATUS_PENDING ) {
KeWaitForSingleObject( &doneEvent,
Executive,
KernelMode,
FALSE,
NULL );
ntStatus = Irp->IoStatus.Status;
}
ExAcquireFastMutex(&(disketteExtension->HoldNewReqMutex));
disketteExtension->HoldNewRequests = FALSE;
ExReleaseFastMutex(&(disketteExtension->HoldNewReqMutex));
//
// Process the queued requests
//
FloppyProcessQueuedRequests( disketteExtension );
//
// We must now complete the IRP, since we stopped it in the
// completetion routine with MORE_PROCESSING_REQUIRED.
//
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
}
break;
case IRP_MN_STOP_DEVICE:
FloppyDump( FLOPPNP,("FloppyPnp: IRP_MN_STOP_DEVICE - Irp: %p\n", Irp) );
disketteExtension->IsStarted = FALSE;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoSkipCurrentIrpStackLocation( Irp );
ntStatus = IoCallDriver( disketteExtension->TargetObject, Irp );
break;
case IRP_MN_REMOVE_DEVICE:
FloppyDump( FLOPPNP,("FloppyPnp: IRP_MN_REMOVE_DEVICE - Irp: %p\n", Irp) );
//
// We need to mark the fact that we don't hold requests first, since
// we asserted earlier that we are holding requests only if
// we're not removed.
//
ExAcquireFastMutex(&(disketteExtension->HoldNewReqMutex));
disketteExtension->HoldNewRequests = FALSE;
ExReleaseFastMutex(&(disketteExtension->HoldNewReqMutex));
disketteExtension->IsStarted = FALSE;
disketteExtension->IsRemoved = TRUE;
//
// Here we either have completed all the requests in a personal
// queue when IRP_MN_QUERY_REMOVE was received, or will have to
// fail all of them if this is a surprise removal.
// Note that fdoData->IsRemoved is TRUE, so pSD_ProcessQueuedRequests
// will simply flush the queue, completing each IRP with
// STATUS_DELETE_PENDING
//
FloppyProcessQueuedRequests( disketteExtension );
//
// Forward this Irp to the underlying PDO
//
IoSkipCurrentIrpStackLocation( Irp );
Irp->IoStatus.Status = STATUS_SUCCESS;
ntStatus = IoCallDriver( disketteExtension->TargetObject, Irp );
//
// Send notification that we are going away.
//
if ( disketteExtension->InterfaceString.Buffer != NULL ) {
IoSetDeviceInterfaceState( &disketteExtension->InterfaceString,
FALSE);
RtlFreeUnicodeString( &disketteExtension->InterfaceString );
RtlInitUnicodeString( &disketteExtension->InterfaceString, NULL );
}
RtlFreeUnicodeString( &disketteExtension->DeviceName );
RtlInitUnicodeString( &disketteExtension->DeviceName, NULL );
if ( disketteExtension->ArcName.Length != 0 ) {
IoDeassignArcName( &disketteExtension->ArcName );
RtlFreeUnicodeString( &disketteExtension->ArcName );
RtlInitUnicodeString( &disketteExtension->ArcName, NULL );
}
//
// Detatch from the undelying device.
//
IoDetachDevice( disketteExtension->TargetObject );
//
// And delete the device.
//
IoDeleteDevice( DeviceObject );
IoGetConfigurationInformation()->FloppyCount--;
break;
default:
FloppyDump( FLOPPNP, ("FloppyPnp: Unsupported PNP Request %x - Irp: %p\n",irpSp->MinorFunction, Irp) );
IoSkipCurrentIrpStackLocation( Irp );
ntStatus = IoCallDriver( disketteExtension->TargetObject, Irp );
}
//
// Page out the driver if it is not busy elsewhere.
//
FloppyPageEntireDriver();
return ntStatus;
}
NTSTATUS
FloppyStartDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
NTSTATUS ntStatus;
NTSTATUS pnpStatus;
KEVENT doneEvent;
FDC_INFO fdcInfo;
CONFIGURATION_TYPE Dc = DiskController;
CONFIGURATION_TYPE Fp = FloppyDiskPeripheral;
PDISKETTE_EXTENSION disketteExtension = (PDISKETTE_EXTENSION)DeviceObject->DeviceExtension;
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
FloppyDump( FLOPSHOW,("FloppyStartDevice: Irp: %p\n", Irp) );
FloppyDump( FLOPSHOW, (" AllocatedResources = %08x\n",irpSp->Parameters.StartDevice.AllocatedResources));
FloppyDump( FLOPSHOW, (" AllocatedResourcesTranslated = %08x\n",irpSp->Parameters.StartDevice.AllocatedResourcesTranslated));
//
// First we must pass this Irp on to the PDO.
//
KeInitializeEvent( &doneEvent, NotificationEvent, FALSE );
IoCopyCurrentIrpStackLocationToNext( Irp );
IoSetCompletionRoutine( Irp,
FloppyPnpComplete,
&doneEvent,
TRUE, TRUE, TRUE );
ntStatus = IoCallDriver( disketteExtension->TargetObject, Irp );
if ( ntStatus == STATUS_PENDING ) {
ntStatus = KeWaitForSingleObject( &doneEvent,
Executive,
KernelMode,
FALSE,
NULL );
ASSERT( ntStatus == STATUS_SUCCESS );
ntStatus = Irp->IoStatus.Status;
}
fdcInfo.BufferCount = 0;
fdcInfo.BufferSize = 0;
ntStatus = FlFdcDeviceIo( disketteExtension->TargetObject,
IOCTL_DISK_INTERNAL_GET_FDC_INFO,
&fdcInfo );
if ( NT_SUCCESS(ntStatus) ) {
disketteExtension->MaxTransferSize = fdcInfo.MaxTransferSize;
if ( (fdcInfo.AcpiBios) &&
(fdcInfo.AcpiFdiSupported) ) {
ntStatus = FlAcpiConfigureFloppy( disketteExtension, &fdcInfo );
if ( disketteExtension->DriveType == DRIVE_TYPE_2880 ) {
disketteExtension->PerpendicularMode |= 1 << fdcInfo.PeripheralNumber;
}
} else {
INTERFACE_TYPE InterfaceType;
if ( disketteExtension->DriveType == DRIVE_TYPE_2880 ) {
disketteExtension->PerpendicularMode |= 1 << fdcInfo.PeripheralNumber;
}
//
// Query the registry till we find the correct interface type,
// since we do not know what type of interface we are on.
//
for ( InterfaceType = 0;
InterfaceType < MaximumInterfaceType;
InterfaceType++ ) {
fdcInfo.BusType = InterfaceType;
ntStatus = IoQueryDeviceDescription( &fdcInfo.BusType,
&fdcInfo.BusNumber,
&Dc,
&fdcInfo.ControllerNumber,
&Fp,
&fdcInfo.PeripheralNumber,
FlConfigCallBack,
disketteExtension );
if (NT_SUCCESS(ntStatus)) {
//
// We found the interface we are on.
//
FloppyDump(FLOPSHOW,
("Interface Type is %x\n", InterfaceType));
break;
}
}
}
if ( NT_SUCCESS(ntStatus) ) {
if (IsNEC_98) {
disketteExtension->DeviceUnit = (UCHAR)fdcInfo.UnitNumber;
disketteExtension->DriveOnValue = (UCHAR)fdcInfo.UnitNumber;
} else { // (IsNEC_98)
disketteExtension->DeviceUnit = (UCHAR)fdcInfo.PeripheralNumber;
disketteExtension->DriveOnValue =
(UCHAR)(fdcInfo.PeripheralNumber | ( DRVCTL_DRIVE_0 << fdcInfo.PeripheralNumber ));
} // (IsNEC_98)
pnpStatus = IoRegisterDeviceInterface( disketteExtension->UnderlyingPDO,
(LPGUID)&MOUNTDEV_MOUNTED_DEVICE_GUID,
NULL,
&disketteExtension->InterfaceString );
if ( NT_SUCCESS(pnpStatus) ) {
pnpStatus = IoSetDeviceInterfaceState( &disketteExtension->InterfaceString,
TRUE );
}
disketteExtension->IsStarted = TRUE;
ExAcquireFastMutex(&(disketteExtension->HoldNewReqMutex));
disketteExtension->HoldNewRequests = FALSE;
ExReleaseFastMutex(&(disketteExtension->HoldNewReqMutex));
FloppyProcessQueuedRequests( disketteExtension );
}
}
Irp->IoStatus.Status = ntStatus;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return ntStatus;
}
NTSTATUS
FloppyPnpComplete (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
Routine Description:
A completion routine for use when calling the lower device objects to
which our bus (FDO) is attached.
--*/
{
KeSetEvent ((PKEVENT) Context, 1, FALSE);
// No special priority
// No Wait
return STATUS_MORE_PROCESSING_REQUIRED; // Keep this IRP
}
NTSTATUS
FloppyPower(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Arguments:
DeviceObject - a pointer to the object that represents the device
that I/O is to be done on.
Irp - a pointer to the I/O Request Packet for this request.
Return Value:
--*/
{
PDISKETTE_EXTENSION disketteExtension;
NTSTATUS ntStatus = Irp->IoStatus.Status;
PIO_STACK_LOCATION irpSp;
POWER_STATE_TY
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -