📄 floppy.c
字号:
scsiAddress.TargetId,
scsiAddress.Lun);
RtlInitUnicodeString(&arcUnicodeString, arcNameBuffer);
//
// Create device object for this device.
//
swprintf(ntNameBuffer,L"\\Device\\Floppy%d",fdoExtension->DeviceNumber);
//
// Create local copy of unicode string
//
RtlInitUnicodeString(&ntUnicodeString,ntNameBuffer);
IoAssignArcName(&arcUnicodeString, &ntUnicodeString);
//
// Create the multi() arc name -- Create the "fake"
// name of multi(0)disk(0)fdisk(#) to handle the case where the
// SCSI floppy is the only floppy in the system. If this fails
// it doesn't matter because the previous scsi() based ArcName
// will work. This name is necessary for installation.
//
swprintf(arcNameBuffer, L"\\ArcName\\multi(%d)disk(%d)fdisk(%d)",
0,
0,
fdoExtension->DeviceNumber);
RtlInitUnicodeString(&arcUnicodeString, arcNameBuffer);
IoAssignArcName(&arcUnicodeString, &ntUnicodeString);
//
// Set our interface state.
//
{
PDISK_DATA diskData = commonExtension->DriverData;
if(diskData->FloppyInterfaceString.Buffer != NULL) {
status = IoSetDeviceInterfaceState(
&(diskData->FloppyInterfaceString),
TRUE);
#if DBG
if(!NT_SUCCESS(status)) {
DebugPrint((1, "ScsiFlopStartDevice: Unable to set device "
"interface state to TRUE for fdo %#p "
"[%#08lx]\n",
Fdo, status));
}
#endif
}
}
return STATUS_SUCCESS;
}
NTSTATUS
ScsiFlopReadWriteVerification(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Arguments:
Return Value:
NT Status
--*/
{
PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS status = STATUS_SUCCESS;
//
// Make sure that the number of bytes to transfer is a multiple of the sector size
//
if ((irpSp->Parameters.Read.Length & (fdoExtension->DiskGeometry.BytesPerSector - 1)) != 0)
{
status = STATUS_INVALID_PARAMETER;
}
Irp->IoStatus.Status = status;
return status;
}
NTSTATUS
ScsiFlopDeviceControl(
PDEVICE_OBJECT DeviceObject,
PIRP Irp
)
/*++
Routine Description:
Arguments:
Return Value:
Status is returned.
--*/
{
KIRQL currentIrql;
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
PSCSI_REQUEST_BLOCK srb;
PCDB cdb;
NTSTATUS status;
PDISK_GEOMETRY outputBuffer;
ULONG outputBufferLength;
ULONG i;
DRIVE_MEDIA_TYPE lowestDriveMediaType;
DRIVE_MEDIA_TYPE highestDriveMediaType;
PFORMAT_PARAMETERS formatParameters;
PMODE_PARAMETER_HEADER modeData;
ULONG length;
//
// Initialize the information field
//
Irp->IoStatus.Information = 0;
srb = ExAllocatePool(NonPagedPool, SCSI_REQUEST_BLOCK_SIZE);
if (srb == NULL) {
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
if (IoIsErrorUserInduced(STATUS_INSUFFICIENT_RESOURCES)) {
IoSetHardErrorOrVerifyDevice(Irp, DeviceObject);
}
KeRaiseIrql(DISPATCH_LEVEL, ¤tIrql);
ClassReleaseRemoveLock(DeviceObject, Irp);
ClassCompleteRequest(DeviceObject, Irp, 0);
KeLowerIrql(currentIrql);
return(STATUS_INSUFFICIENT_RESOURCES);
}
//
// Write zeros to Srb.
//
RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE);
cdb = (PCDB)srb->Cdb;
switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
case IOCTL_DISK_VERIFY: {
PVERIFY_INFORMATION verifyInfo = Irp->AssociatedIrp.SystemBuffer;
LARGE_INTEGER byteOffset;
ULONG sectorOffset;
USHORT sectorCount;
//
// Validate buffer length.
//
if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
sizeof(VERIFY_INFORMATION)) {
status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
//
// Perform a bounds check on the sector range
//
if ((verifyInfo->StartingOffset.QuadPart > fdoExtension->CommonExtension.PartitionLength.QuadPart) ||
(verifyInfo->StartingOffset.QuadPart < 0))
{
status = STATUS_NONEXISTENT_SECTOR;
break;
}
else
{
ULONGLONG bytesRemaining = fdoExtension->CommonExtension.PartitionLength.QuadPart - verifyInfo->StartingOffset.QuadPart;
if ((ULONGLONG)verifyInfo->Length > bytesRemaining)
{
status = STATUS_NONEXISTENT_SECTOR;
break;
}
}
//
// Verify sectors
//
srb->CdbLength = 10;
cdb->CDB10.OperationCode = SCSIOP_VERIFY;
//
// Add disk offset to starting sector.
//
byteOffset.QuadPart = fdoExtension->CommonExtension.StartingOffset.QuadPart +
verifyInfo->StartingOffset.QuadPart;
//
// Convert byte offset to sector offset.
//
sectorOffset = (ULONG)(byteOffset.QuadPart >> fdoExtension->SectorShift);
//
// Convert ULONG byte count to USHORT sector count.
//
sectorCount = (USHORT)(verifyInfo->Length >> fdoExtension->SectorShift);
//
// Move little endian values into CDB in big endian format.
//
cdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)§orOffset)->Byte3;
cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)§orOffset)->Byte2;
cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)§orOffset)->Byte1;
cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)§orOffset)->Byte0;
cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)§orCount)->Byte1;
cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)§orCount)->Byte0;
//
// The verify command is used by the NT FORMAT utility and
// requests are sent down for 5% of the volume size. The
// request timeout value is calculated based on the number of
// sectors verified.
//
srb->TimeOutValue = ((sectorCount + 0x7F) >> 7) *
fdoExtension->TimeOutValue;
status = ClassSendSrbAsynchronous(DeviceObject,
srb,
Irp,
NULL,
0,
FALSE);
return(status);
}
case IOCTL_DISK_GET_PARTITION_INFO: {
if (fdoExtension->AdapterDescriptor->BusType == BusTypeUsb) {
status = USBFlopGetMediaTypes(DeviceObject, NULL);
// Don't need to propagate any error if one occurs
//
status = STATUS_SUCCESS;
} else {
status = DetermineMediaType(DeviceObject);
}
if (!NT_SUCCESS(status)) {
// so will propogate error
NOTHING;
} else if (fdoExtension->DiskGeometry.MediaType == F3_120M_512) {
//so that the format code will not try to partition it.
status = STATUS_INVALID_DEVICE_REQUEST;
} else {
//
// Free the Srb, since it is not needed.
//
ExFreePool(srb);
//
// Pass the request to the common device control routine.
//
return(ClassDeviceControl(DeviceObject, Irp));
}
break;
}
case IOCTL_DISK_GET_DRIVE_GEOMETRY: {
DebugPrint((3,"ScsiDeviceIoControl: Get drive geometry\n"));
if (fdoExtension->AdapterDescriptor->BusType == BusTypeUsb)
{
status = USBFlopGetMediaTypes(DeviceObject,
Irp);
break;
}
//
// If there's not enough room to write the
// data, then fail the request.
//
if ( irpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof( DISK_GEOMETRY ) ) {
status = STATUS_INVALID_PARAMETER;
break;
}
status = DetermineMediaType(DeviceObject);
if (!NT_SUCCESS(status)) {
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = status;
} else {
//
// Copy drive geometry information from device extension.
//
RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer,
&(fdoExtension->DiskGeometry),
sizeof(DISK_GEOMETRY));
Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);
status = STATUS_SUCCESS;
}
break;
}
case IOCTL_DISK_GET_MEDIA_TYPES: {
if (fdoExtension->AdapterDescriptor->BusType == BusTypeUsb)
{
status = USBFlopGetMediaTypes(DeviceObject,
Irp);
break;
}
i = DetermineDriveType(DeviceObject);
if (i == DRIVE_TYPE_NONE) {
status = STATUS_UNRECOGNIZED_MEDIA;
break;
}
lowestDriveMediaType = DriveMediaLimits[i].LowestDriveMediaType;
highestDriveMediaType = DriveMediaLimits[i].HighestDriveMediaType;
outputBufferLength =
irpStack->Parameters.DeviceIoControl.OutputBufferLength;
//
// Make sure that the input buffer has enough room to return
// at least one descriptions of a supported media type.
//
if ( outputBufferLength < ( sizeof( DISK_GEOMETRY ) ) ) {
status = STATUS_BUFFER_TOO_SMALL;
break;
}
//
// Assume success, although we might modify it to a buffer
// overflow warning below (if the buffer isn't big enough
// to hold ALL of the media descriptions).
//
status = STATUS_SUCCESS;
if (outputBufferLength < ( sizeof( DISK_GEOMETRY ) *
( highestDriveMediaType - lowestDriveMediaType + 1 ) ) ) {
//
// The buffer is too small for all of the descriptions;
// calculate what CAN fit in the buffer.
//
status = STATUS_BUFFER_OVERFLOW;
highestDriveMediaType = (DRIVE_MEDIA_TYPE)( ( lowestDriveMediaType - 1 ) +
( outputBufferLength /
sizeof( DISK_GEOMETRY ) ) );
}
outputBuffer = (PDISK_GEOMETRY) Irp->AssociatedIrp.SystemBuffer;
for (i = (UCHAR)lowestDriveMediaType;i <= (UCHAR)highestDriveMediaType;i++ ) {
outputBuffer->MediaType = DriveMediaConstants[i].MediaType;
outputBuffer->Cylinders.LowPart =
DriveMediaConstants[i].MaximumTrack + 1;
outputBuffer->Cylinders.HighPart = 0;
outputBuffer->TracksPerCylinder =
DriveMediaConstants[i].NumberOfHeads;
outputBuffer->SectorsPerTrack =
DriveMediaConstants[i].SectorsPerTrack;
outputBuffer->BytesPerSector =
DriveMediaConstants[i].BytesPerSector;
outputBuffer++;
Irp->IoStatus.Information += sizeof( DISK_GEOMETRY );
}
break;
}
case IOCTL_DISK_FORMAT_TRACKS: {
if (fdoExtension->AdapterDescriptor->BusType == BusTypeUsb)
{
status = USBFlopFormatTracks(DeviceObject,
Irp);
break;
}
//
// Make sure that we got all the necessary format parameters.
//
if ( irpStack->Parameters.DeviceIoControl.InputBufferLength <sizeof( FORMAT_PARAMETERS ) ) {
status = STATUS_INVALID_PARAMETER;
break;
}
formatParameters = (PFORMAT_PARAMETERS) Irp->AssociatedIrp.SystemBuffer;
//
// Make sure the parameters we got are reasonable.
//
if ( !FlCheckFormatParameters(DeviceObject, formatParameters)) {
status = STATUS_INVALID_PARAMETER;
break;
}
//
// If this request is for a 20.8 MB floppy then call a special
// floppy format routine.
//
if (formatParameters->MediaType == F3_20Pt8_512) {
status = FlopticalFormatMedia(DeviceObject,
formatParameters
);
break;
}
//
// All the work is done in the pass. If this is not the first pass,
// then complete the request and return;
//
if (formatParameters->StartCylinderNumber != 0 || formatParameters->StartHeadNumber != 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -