mirror of https://github.com/lianthony/NT4.0
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.
374 lines
8.6 KiB
374 lines
8.6 KiB
/*++
|
|
|
|
Copyright (c) 1996 Hewlett-Packard Corporation
|
|
|
|
Module Name:
|
|
|
|
ioctl.c
|
|
|
|
Abstract:
|
|
|
|
This driver enables secondary floppy controllers to be accessable
|
|
to qic117.sys, floppy.sys and other floppy disk based devices.
|
|
This file contains code for device control and unload driver.
|
|
|
|
Author:
|
|
|
|
Kurt Godwin (v-kurtg) 26-Mar-1996.
|
|
|
|
Environment:
|
|
|
|
Kernel mode only.
|
|
|
|
Notes:
|
|
|
|
Revision History:
|
|
$Log:$
|
|
|
|
--*/
|
|
|
|
|
|
//
|
|
// Include files.
|
|
//
|
|
|
|
#include <ntddk.h> // various NT definitions
|
|
#include <ntiologc.h>
|
|
#include <flpyenbl.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "genflpy.h"
|
|
#include "ioctl.h"
|
|
|
|
int GenFlpyDebugLevel;
|
|
|
|
|
|
NTSTATUS
|
|
GenFlpyCreateClose(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by the I/O system when the GenFlpy is opened or
|
|
closed.
|
|
|
|
No action is performed other than completing the request successfully.
|
|
|
|
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:
|
|
|
|
STATUS_INVALID_PARAMETER if parameters are invalid,
|
|
STATUS_SUCCESS otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
GenFlpyDeviceControl(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by the I/O system to perform a device I/O
|
|
control function.
|
|
|
|
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:
|
|
|
|
STATUS_SUCCESS if recognized I/O control code,
|
|
STATUS_INVALID_DEVICE_REQUEST otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
PGENFLPY_EXTENSION cardExtension;
|
|
PIO_STACK_LOCATION irpSp;
|
|
NTSTATUS ntStatus;
|
|
void *pParms;
|
|
|
|
//
|
|
// Set up necessary object and extension pointers.
|
|
//
|
|
|
|
cardExtension = DeviceObject->DeviceExtension;
|
|
irpSp = IoGetCurrentIrpStackLocation( Irp );
|
|
|
|
//
|
|
// Assume failure.
|
|
//
|
|
|
|
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
|
|
//
|
|
// Determine which I/O control code was specified.
|
|
//
|
|
|
|
GenFlpyDump(
|
|
FCXXDIAG1,
|
|
("GENFLPY: Enabler IOCTL called: %x\n",irpSp->Parameters.DeviceIoControl.IoControlCode));
|
|
|
|
pParms = irpSp->Parameters.DeviceIoControl.Type3InputBuffer;
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
switch ( irpSp->Parameters.DeviceIoControl.IoControlCode )
|
|
{
|
|
case IOCTL_AQUIRE_FDC:
|
|
//
|
|
// If we have conflicts, wait for all of the events for these
|
|
// conflicts. When we have them all, we have control of the
|
|
// irq and dma for these devices.
|
|
//
|
|
// NOTE: it is assumed that all devices (except the native FDC)
|
|
// are in a tri-stated state. Therefore, all we need worry about
|
|
// is our controller and the native controller.
|
|
//
|
|
if (cardExtension->adapterConflicts) {
|
|
|
|
Irp->IoStatus.Status = KeWaitForMultipleObjects(
|
|
cardExtension->adapterConflicts, //
|
|
&cardExtension->adapterConflictArray[0], //
|
|
WaitAll,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE, //
|
|
(PLARGE_INTEGER)pParms, // controller wait was specified in input buffer
|
|
NULL);
|
|
|
|
}
|
|
if (NT_SUCCESS(Irp->IoStatus.Status)) {
|
|
//
|
|
// At this point, we have complete control of the
|
|
// adapter.
|
|
//
|
|
// For now, we don't need to do any more than disable the
|
|
// main FDC (if needed)
|
|
//
|
|
if (cardExtension->sharingNativeFDC)
|
|
WRITE_PORT_UCHAR(cardExtension->NativeFdcDor, 4);
|
|
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case IOCTL_RELEASE_FDC:
|
|
//
|
|
// If we have aquired any conflict events, clear them now
|
|
//
|
|
if (cardExtension->adapterConflicts) {
|
|
int i;
|
|
UCHAR dor;
|
|
|
|
for (i=0;i<cardExtension->adapterConflicts;++i)
|
|
(void) KeSetEvent(
|
|
cardExtension->adapterConflictArray[i],
|
|
(KPRIORITY) 0,
|
|
FALSE );
|
|
|
|
// Tri-state the DMA and IRQ lines
|
|
dor = READ_PORT_UCHAR(cardExtension->deviceBase+2);
|
|
WRITE_PORT_UCHAR(cardExtension->deviceBase+2,(UCHAR)(dor & ~0x08));
|
|
}
|
|
break;
|
|
|
|
case IOCTL_GET_FDC_INFO:
|
|
{
|
|
//
|
|
// Fill in the information structure with the proper stuff
|
|
//
|
|
PFDC_INFORMATION info = pParms;
|
|
|
|
info->SpeedsAvailable = FDC_SPEED_250KB | FDC_SPEED_300KB |
|
|
FDC_SPEED_500KB | FDC_SPEED_1MB |
|
|
FDC_SPEED_2MB;
|
|
|
|
info->DmaWidthsSupported = FDC_8_BIT_DMA;
|
|
info->ClockRatesSupported = FDC_CLOCK_48MHZ;
|
|
info->FloppyControllerType = FDC_TYPE_82078_64;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case IOCTL_SET_FDC_MODE:
|
|
//
|
|
// For now, we don't need to do any thing here.
|
|
//
|
|
break;
|
|
|
|
case IOCTL_ADD_CONTENDER:
|
|
Irp->IoStatus.Status = GenFlpyGetFDCEvent(
|
|
&cardExtension->adapterConflictArray[cardExtension->adapterConflicts],
|
|
*(PULONG)pParms);
|
|
|
|
if ( NT_SUCCESS( Irp->IoStatus.Status ) ) {
|
|
++cardExtension->adapterConflicts;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
//
|
|
// The specified I/O control code is unrecognized by this driver.
|
|
// The I/O status field in the IRP has already been set so just
|
|
// terminate the switch.
|
|
//
|
|
|
|
GenFlpyDump(
|
|
FCXXDIAG1,
|
|
("GENFLPY: ERROR: unrecognized IOCTL %x\n",
|
|
irpSp->Parameters.DeviceIoControl.IoControlCode));
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Finish the I/O operation by simply completing the packet and returning
|
|
// the same status as in the packet itself.
|
|
//
|
|
|
|
ntStatus = Irp->IoStatus.Status;
|
|
|
|
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
VOID
|
|
GenFlpyUnloadDriver(
|
|
IN PDRIVER_OBJECT DriverObject
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called by the I/O system to unload the driver.
|
|
|
|
Any resources previously allocated must be freed.
|
|
|
|
Arguments:
|
|
|
|
DriverObject - a pointer to the object that represents our driver.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
--*/
|
|
|
|
{
|
|
PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject;
|
|
|
|
GenFlpyDump(
|
|
FCXXDIAG1,
|
|
("GENFLPY: Unloading driver\n")
|
|
);
|
|
|
|
if ( deviceObject != NULL )
|
|
{
|
|
PGENFLPY_EXTENSION cardExtension = deviceObject->DeviceExtension;
|
|
|
|
if (cardExtension != NULL)
|
|
{
|
|
// if (cardExtension->UnicodeWin32Name.Buffer != NULL)
|
|
// {
|
|
//IoDeleteSymbolicLink( &cardExtension->UnicodeWin32Name );
|
|
|
|
// ExFreePool( cardExtension->UnicodeWin32Name.Buffer );
|
|
// }
|
|
// if (cardExtension->UnicodeDeviceName.Buffer != NULL)
|
|
// {
|
|
//IoDeleteSymbolicLink( &cardExtension->UnicodeWin32Name );
|
|
|
|
// ExFreePool( cardExtension->UnicodeDeviceName.Buffer );
|
|
// }
|
|
}
|
|
IoDeleteDevice( deviceObject );
|
|
}
|
|
}
|
|
|
|
NTSTATUS
|
|
GenFlpyGetFDCEvent(
|
|
IN PKEVENT *ppevent,
|
|
IN int controller_number
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
Creates a syncronization event for the floppy controller
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
|
|
{
|
|
PKEVENT event;
|
|
STRING sFdcEvent;
|
|
UNICODE_STRING usFdcEvent;
|
|
char FdcEvent[sizeof(FDC_EVENT)+10];
|
|
NTSTATUS nt_status;
|
|
HANDLE event_handle;
|
|
|
|
sprintf(FdcEvent, FDC_EVENT, controller_number );
|
|
|
|
GenFlpyDump(
|
|
FCXXDIAG1,
|
|
("GENFLPY: creating synchronization event %s\n",FdcEvent)
|
|
);
|
|
|
|
|
|
RtlInitString( &sFdcEvent, FdcEvent );
|
|
|
|
nt_status = RtlAnsiStringToUnicodeString(&usFdcEvent,&sFdcEvent,TRUE );
|
|
|
|
if (NT_SUCCESS(nt_status)) {
|
|
event = IoCreateSynchronizationEvent(
|
|
&usFdcEvent,
|
|
&event_handle);
|
|
|
|
if ( event == NULL ) {
|
|
GenFlpyDump(
|
|
FCXXERRORS,
|
|
("GENFLPY: error creating synchronization event %s\n",FdcEvent)
|
|
);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
RtlFreeUnicodeString( &usFdcEvent );
|
|
}
|
|
|
|
|
|
*ppevent = event;
|
|
|
|
return nt_status;
|
|
}
|