?? floppy.c
字號:
/*++
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 + -