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

📄 floppy.c

📁 The sfloppy sample is a super floppy driver that resides in the directory \NtddkSrcStoragesfloppy. I
💻 C
📖 第 1 页 / 共 5 页
字号:
/*++

Copyright (C) Microsoft Corporation, 1991 - 1999

Module Name:

    floppy.c

Abstract:

    SCSI floppy class driver

Author:

    Jeff Havens (jhavens)

Environment:

    kernel mode only

Notes:

Revision History:
02/28/96    georgioc    Merged this code with code developed by compaq in
                        parallel with microsoft, for 120MB floppy support.

01/17/96    georgioc    Made code PNP aware (uses the new \storage\classpnp/scsiport)

--*/

#include "stddef.h"
#include "ntddk.h"
#include "scsi.h"
#include "classpnp.h"

#include "initguid.h"
#include "ntddstor.h"

#define MODE_DATA_SIZE      192
#define SCSI_FLOPPY_TIMEOUT  20
#define SFLOPPY_SRB_LIST_SIZE 4
//
// Define all possible drive/media combinations, given drives listed above
// and media types in ntdddisk.h.
//
// These values are used to index the DriveMediaConstants table.
//

#define NUMBER_OF_DRIVE_TYPES              7
#define DRIVE_TYPE_120M                    4    //120MB Floptical
#define DRIVE_TYPE_NONE                    NUMBER_OF_DRIVE_TYPES

//
// This array describes all media types we support.
// It should be arranged in the increasing order of density
//
// For a given drive, we list all the mediatypes that will
// work with that drive. For instance, a 120MB drive will
// take 720KB media, 1.44MB media, and 120MB media.
//
// Note that, DriveMediaConstants given below is grouped
// as drive and media combination
//
typedef enum _DRIVE_MEDIA_TYPE {
    Drive360Media160,                      // 5.25"  360k  drive;  160k   media
    Drive360Media180,                      // 5.25"  360k  drive;  180k   media
    Drive360Media320,                      // 5.25"  360k  drive;  320k   media
    Drive360Media32X,                      // 5.25"  360k  drive;  320k 1k secs
    Drive360Media360,                      // 5.25"  360k  drive;  360k   media
    Drive720Media720,                      // 3.5"   720k  drive;  720k   media
    Drive120Media160,                      // 5.25" 1.2Mb  drive;  160k   media
    Drive120Media180,                      // 5.25" 1.2Mb  drive;  180k   media
    Drive120Media320,                      // 5.25" 1.2Mb  drive;  320k   media
    Drive120Media32X,                      // 5.25" 1.2Mb  drive;  320k 1k secs
    Drive120Media360,                      // 5.25" 1.2Mb  drive;  360k   media
    Drive120Media120,                      // 5.25" 1.2Mb  drive; 1.2Mb   media
    Drive144Media720,                      // 3.5"  1.44Mb drive;  720k   media
    Drive144Media144,                      // 3.5"  1.44Mb drive; 1.44Mb  media
    Drive288Media720,                      // 3.5"  2.88Mb drive;  720k   media
    Drive288Media144,                      // 3.5"  2.88Mb drive; 1.44Mb  media
    Drive288Media288,                      // 3.5"  2.88Mb drive; 2.88Mb  media
    Drive2080Media720,                     // 3.5"  20.8Mb drive;  720k   media
    Drive2080Media144,                     // 3.5"  20.8Mb drive; 1.44Mb  media
    Drive2080Media2080,                    // 3.5"  20.8Mb drive; 20.8Mb  media
    Drive32MMedia32M,                      // 3.5"  32Mb drive; 32MB    media
    Drive120MMedia720,                     // 3.5"  120Mb drive; 720k  media
    Drive120MMedia144,                     // 3.5"  120Mb drive; 1.44Mb  media
    Drive120MMedia120M,                    // 3.5"  120Mb drive; 120Mb  media
    Drive240MMedia144M,                    // 3.5"  240Mb drive; 1.44Mb  media
    Drive240MMedia120M,                    // 3.5"  240Mb drive; 120Mb  media
    Drive240MMedia240M                     // 3.5"  240Mb drive; 240Mb  media
} DRIVE_MEDIA_TYPE;

//
// When we want to determine the media type in a drive, we will first
// guess that the media with highest possible density is in the drive,
// and keep trying lower densities until we can successfully read from
// the drive.
//
// These values are used to select a DRIVE_MEDIA_TYPE value.
//
// The following table defines ranges that apply to the DRIVE_MEDIA_TYPE
// enumerated values when trying media types for a particular drive type.
// Note that for this to work, the DRIVE_MEDIA_TYPE values must be sorted
// by ascending densities within drive types.  Also, for maximum track
// size to be determined properly, the drive types must be in ascending
// order.
//

typedef struct _DRIVE_MEDIA_LIMITS {
    DRIVE_MEDIA_TYPE HighestDriveMediaType;
    DRIVE_MEDIA_TYPE LowestDriveMediaType;
} DRIVE_MEDIA_LIMITS, *PDRIVE_MEDIA_LIMITS;

#if 0
DRIVE_MEDIA_LIMITS DriveMediaLimits[NUMBER_OF_DRIVE_TYPES] = {

    { Drive360Media360, Drive360Media160 }, // DRIVE_TYPE_0360
    { Drive120Media120, Drive120Media160 }, // DRIVE_TYPE_1200
    { Drive720Media720, Drive720Media720 }, // DRIVE_TYPE_0720
    { Drive144Media144, Drive144Media720 }, // DRIVE_TYPE_1440
    { Drive288Media288, Drive288Media720 }, // DRIVE_TYPE_2880
    { Drive2080Media2080, Drive2080Media720 }
};
#else
DRIVE_MEDIA_LIMITS DriveMediaLimits[NUMBER_OF_DRIVE_TYPES] = {

    { Drive720Media720, Drive720Media720 }, // DRIVE_TYPE_0720
    { Drive144Media144,  Drive144Media720}, // DRIVE_TYPE_1440
    { Drive288Media288,  Drive288Media720}, // DRIVE_TYPE_2880
    { Drive2080Media2080, Drive2080Media720 },
    { Drive32MMedia32M, Drive32MMedia32M }, // DRIVE_TYPE_32M
    { Drive120MMedia120M, Drive120MMedia720 }, // DRIVE_TYPE_120M
    { Drive240MMedia240M, Drive240MMedia144M } // DRIVE_TYPE_240M
};

#endif
//
// For each drive/media combination, define important constants.
//

typedef struct _DRIVE_MEDIA_CONSTANTS {
    MEDIA_TYPE MediaType;
    USHORT     BytesPerSector;
    UCHAR      SectorsPerTrack;
    USHORT     MaximumTrack;
    UCHAR      NumberOfHeads;
} DRIVE_MEDIA_CONSTANTS, *PDRIVE_MEDIA_CONSTANTS;

//
// Magic value to add to the SectorLengthCode to use it as a shift value
// to determine the sector size.
//

#define SECTORLENGTHCODE_TO_BYTESHIFT      7

//
// The following values were gleaned from many different sources, which
// often disagreed with each other.  Where numbers were in conflict, I
// chose the more conservative or most-often-selected value.
//

DRIVE_MEDIA_CONSTANTS DriveMediaConstants[] =
    {

    { F5_160_512,   0x200, 0x08, 0x27, 0x1 },
    { F5_180_512,   0x200, 0x09, 0x27, 0x1 },
    { F5_320_1024,  0x400, 0x04, 0x27, 0x2 },
    { F5_320_512,   0x200, 0x08, 0x27, 0x2 },
    { F5_360_512,   0x200, 0x09, 0x27, 0x2 },

    { F3_720_512,   0x200, 0x09, 0x4f, 0x2 },

    { F5_160_512,   0x200, 0x08, 0x27, 0x1 },
    { F5_180_512,   0x200, 0x09, 0x27, 0x1 },
    { F5_320_1024,  0x400, 0x04, 0x27, 0x2 },
    { F5_320_512,   0x200, 0x08, 0x27, 0x2 },
    { F5_360_512,   0x200, 0x09, 0x27, 0x2 },
    { F5_1Pt2_512,  0x200, 0x0f, 0x4f, 0x2 },

    { F3_720_512,   0x200, 0x09, 0x4f, 0x2 },
    { F3_1Pt44_512, 0x200, 0x12, 0x4f, 0x2 },

    { F3_720_512,   0x200, 0x09, 0x4f, 0x2 },
    { F3_1Pt44_512, 0x200, 0x12, 0x4f, 0x2 },
    { F3_2Pt88_512, 0x200, 0x24, 0x4f, 0x2 },

    { F3_720_512,   0x200, 0x09, 0x4f, 0x2 },
    { F3_1Pt44_512, 0x200, 0x12, 0x4f, 0x2 },
    { F3_20Pt8_512, 0x200, 0x1b, 0xfa, 0x6 },

    { F3_32M_512,   0x200, 0x20, 0x3ff,0x2},

    { F3_720_512,   0x200, 0x09, 0x4f, 0x2 },
    { F3_1Pt44_512, 0x200, 0x12, 0x4f, 0x2 },
    { F3_120M_512,  0x200, 0x20, 0x3c2,0x8 },

    { F3_1Pt44_512, 0x200, 0x12, 0x4f, 0x2 },
    { F3_120M_512,  0x200, 0x20, 0x3c2,0x8 },
    { F3_240M_512,  0x200, 0x38, 0x105,0x20}
};


#define NUMBER_OF_DRIVE_MEDIA_COMBINATIONS sizeof(DriveMediaConstants)/sizeof(DRIVE_MEDIA_CONSTANTS)

//
// floppy device data
//

typedef struct _DISK_DATA {
    ULONG DriveType;
    BOOLEAN IsDMF;
    // BOOLEAN EnableDMF;
    UNICODE_STRING FloppyInterfaceString;
} DISK_DATA, *PDISK_DATA;

//
// The FloppyCapacities and FloppyGeometries arrays are used by the
// USBFlopGetMediaTypes() and USBFlopFormatTracks() routines.

// The FloppyCapacities and FloppyGeometries arrays must be kept in 1:1 sync,
// i.e. each FloppyGeometries[i] must correspond to each FloppyCapacities[i].

// Also, the arrays must be kept in sorted ascending order so that they
// are returned in sorted ascending order by IOCTL_DISK_GET_MEDIA_TYPES.
//

typedef struct _FORMATTED_CAPACITY
{
    ULONG       NumberOfBlocks;

    ULONG       BlockLength;

    BOOLEAN     CanFormat;      // return for IOCTL_DISK_GET_MEDIA_TYPES ?

} FORMATTED_CAPACITY, *PFORMATTED_CAPACITY;


FORMATTED_CAPACITY FloppyCapacities[] =
{
    // Blocks  BlockLen CanFormat H   T  B/S S/T
    {0x000500, 0x0200,  TRUE}, // 2  80  512   8   640 KB  F5_640_512
    {0x0005A0, 0x0200,  TRUE}, // 2  80  512   9   720 KB  F3_720_512
    {0x000960, 0x0200,  TRUE}, // 2  80  512  15  1.20 MB  F3_1Pt2_512   (Toshiba)
    {0x0004D0, 0x0400,  TRUE}, // 2  77 1024   8  1.23 MB  F3_1Pt23_1024 (NEC)
    {0x000B40, 0x0200,  TRUE}, // 2  80  512  18  1.44 MB  F3_1Pt44_512
    {0x000D20, 0x0200, FALSE}, // 2  80  512  21  1.70 MB  DMF
    {0x010000, 0x0200,  TRUE},  // 2  1024 512  32   32 MB    F3_32M_512
    {0x03C300, 0x0200,  TRUE}, // 8 963  512  32   120 MB  F3_120M_512
    {0x0600A4, 0x0200,  TRUE}, // 13 890  512  34   200 MB  F3_200Mb_512 (HiFD)
    {0x072A00, 0x0200,  TRUE}  // 32 262  512  56   240 MB  F3_240M_512
};

DISK_GEOMETRY FloppyGeometries[] =
{
    // Cyl      MediaType       Trk/Cyl Sec/Trk Bytes/Sec
    {{80,0},    F3_640_512,     2,      8,      512},
    {{80,0},    F3_720_512,     2,      9,      512},
    {{80,0},    F3_1Pt2_512,    2,      15,     512},
    {{77,0},    F3_1Pt23_1024,  2,      8,      1024},
    {{80,0},    F3_1Pt44_512,   2,      18,     512},
    {{80,0},    F3_1Pt44_512,   2,      21,     512},   // DMF -> F3_1Pt44_512
    {{1024,0},  F3_32M_512,     2,      32,     512},
    {{963,0},   F3_120M_512,    8,      32,     512},
    {{890,0},   F3_200Mb_512,   13,     34,     512},
    {{262,0},   F3_240M_512,    32,     56,     512}
};

#define FLOPPY_CAPACITIES (sizeof(FloppyCapacities)/sizeof(FloppyCapacities[0]))

C_ASSERT((sizeof(FloppyGeometries)/sizeof(FloppyGeometries[0])) == FLOPPY_CAPACITIES);

//
// The following structures are used by USBFlopFormatTracks()
//

#pragma pack (push, 1)

typedef struct _CDB12FORMAT
{
    UCHAR   OperationCode;
    UCHAR   DefectListFormat : 3;
    UCHAR   CmpList : 1;
    UCHAR   FmtData : 1;
    UCHAR   LogicalUnitNumber : 3;
    UCHAR   TrackNumber;
    UCHAR   InterleaveMsb;
    UCHAR   InterleaveLsb;
    UCHAR   Reserved1[2];
    UCHAR   ParameterListLengthMsb;
    UCHAR   ParameterListLengthLsb;
    UCHAR   Reserved2[3];
} CDB12FORMAT, *PCDB12FORMAT;


typedef struct _DEFECT_LIST_HEADER
{
    UCHAR   Reserved1;
    UCHAR   Side : 1;
    UCHAR   Immediate : 1;
    UCHAR   Reserved2 : 2;
    UCHAR   SingleTrack : 1;
    UCHAR   DisableCert : 1;
    UCHAR   Reserved3 : 1;
    UCHAR   FormatOptionsValid : 1;
    UCHAR   DefectListLengthMsb;
    UCHAR   DefectListLengthLsb;
} DEFECT_LIST_HEADER, *PDEFECT_LIST_HEADER;

typedef struct _FORMAT_UNIT_PARAMETER_LIST
{
    DEFECT_LIST_HEADER DefectListHeader;
    FORMATTED_CAPACITY_DESCRIPTOR FormatDescriptor;
} FORMAT_UNIT_PARAMETER_LIST, *PFORMAT_UNIT_PARAMETER_LIST;

#pragma pack (pop)



NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath
    );

VOID
ScsiFlopUnload(
    IN PDRIVER_OBJECT DriverObject
    );

NTSTATUS
ScsiFlopAddDevice (
    IN PDRIVER_OBJECT DriverObject,
    IN PDEVICE_OBJECT Pdo
    );

NTSTATUS
ScsiFlopInitDevice(
    IN PDEVICE_OBJECT Fdo
    );

NTSTATUS
ScsiFlopStartDevice(
    IN PDEVICE_OBJECT Fdo
    );

NTSTATUS
ScsiFlopRemoveDevice(
    IN PDEVICE_OBJECT Fdo,
    IN UCHAR Type
    );

NTSTATUS
ScsiFlopStopDevice(
    IN PDEVICE_OBJECT Fdo,
    IN UCHAR Type
    );

BOOLEAN
FindScsiFlops(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath,
    IN PCLASS_INIT_DATA InitializationData,
    IN PDEVICE_OBJECT PortDeviceObject,
    IN ULONG PortNumber
    );



NTSTATUS
ScsiFlopReadWriteVerification(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    );

NTSTATUS
ScsiFlopDeviceControl(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    );

BOOLEAN
IsFloppyDevice(
    PDEVICE_OBJECT DeviceObject
    );

NTSTATUS
CreateFlopDeviceObject(
    IN PDRIVER_OBJECT DriverObject,
    IN PDEVICE_OBJECT PortDeviceObject,
    IN ULONG DeviceCount
    );

NTSTATUS
DetermineMediaType(
    PDEVICE_OBJECT DeviceObject
    );

ULONG
DetermineDriveType(
    PDEVICE_OBJECT DeviceObject
    );

BOOLEAN
FlCheckFormatParameters(
    IN PDEVICE_OBJECT DeviceObject,
    IN PFORMAT_PARAMETERS FormatParameters
    );

NTSTATUS
FormatMedia(
    PDEVICE_OBJECT DeviceObject,
    MEDIA_TYPE MediaType
    );

NTSTATUS
FlopticalFormatMedia(
    PDEVICE_OBJECT DeviceObject,
    PFORMAT_PARAMETERS Format
    );

VOID
ScsiFlopProcessError(
    PDEVICE_OBJECT DeviceObject,
    PSCSI_REQUEST_BLOCK Srb,
    NTSTATUS *Status,
    BOOLEAN *Retry
    );

LONG
SFlopStringCmp (
    PCHAR FirstStr,
    PCHAR SecondStr,
    ULONG Count
    );

NTSTATUS
USBFlopGetMediaTypes(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP           Irp
    );

NTSTATUS
USBFlopFormatTracks(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP           Irp
    );

#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)

#pragma alloc_text(PAGE, ScsiFlopUnload)
#pragma alloc_text(PAGE, ScsiFlopAddDevice)
#pragma alloc_text(PAGE, CreateFlopDeviceObject)
#pragma alloc_text(PAGE, ScsiFlopStartDevice)
#pragma alloc_text(PAGE, IsFloppyDevice)
#pragma alloc_text(PAGE, SFlopStringCmp)
#pragma alloc_text(PAGE, DetermineMediaType)
#pragma alloc_text(PAGE, DetermineDriveType)
#pragma alloc_text(PAGE, FlCheckFormatParameters)
#pragma alloc_text(PAGE, FormatMedia)
#pragma alloc_text(PAGE, FlopticalFormatMedia)
#pragma alloc_text(PAGE, USBFlopGetMediaTypes)
#pragma alloc_text(PAGE, USBFlopFormatTracks)

#endif


NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath
    )
/*++

Routine Description:

    This is the system initialization routine for installable drivers.
    It calls the SCSI class driver initialization routine.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -