⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 floppy.c

📁 The sfloppy sample is a super floppy driver that resides in the directory \NtddkSrcStoragesfloppy. I
💻 C
📖 第 1 页 / 共 5 页
字号:
             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, &currentIrql);
        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)&sectorOffset)->Byte3;
       cdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&sectorOffset)->Byte2;
       cdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&sectorOffset)->Byte1;
       cdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&sectorOffset)->Byte0;

       cdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&sectorCount)->Byte1;
       cdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&sectorCount)->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 + -