?? floppy.c
字號:
numberOfHeads = pageData->NumberOfHeads;
maximumTrack = pageData->NumberOfCylinders[1];
maximumTrack |= pageData->NumberOfCylinders[0] << 8;
sectorsPerTrack = pageData->SectorsPerTrack;
//
// Convert from number of cylinders to maximum track.
//
maximumTrack--;
//
// Search for the maximum supported media. Based on the number of heads,
// sectors per track and number of cylinders
//
for (index = 0; index < NUMBER_OF_DRIVE_MEDIA_COMBINATIONS; index++) {
//
// Walk the table forward until the drive capacity holds all of the
// data and the bytes per setor are equal
//
if (DriveMediaConstants[index].NumberOfHeads == numberOfHeads &&
DriveMediaConstants[index].MaximumTrack == maximumTrack &&
DriveMediaConstants[index].SectorsPerTrack ==sectorsPerTrack) {
ExFreePool(modeData);
//
// index is now a drive media combination. Compare this to
// the maximum drive media type in the drive media table.
//
for (length = 0; length < NUMBER_OF_DRIVE_TYPES; length++) {
if (DriveMediaLimits[length].HighestDriveMediaType == index) {
return(length);
}
}
return(DRIVE_TYPE_NONE);
}
}
// If the maximum track is greater than 8 bits then divide the
// number of tracks by 3 and multiply the number of heads by 3.
// This is a special case for the 20.8 MB floppy.
//
if (!applyFix && maximumTrack >= 0x0100) {
applyFix = TRUE;
maximumTrack++;
maximumTrack /= 3;
maximumTrack--;
numberOfHeads *= 3;
} else {
ExFreePool(modeData);
return(DRIVE_TYPE_NONE);
}
}
ExFreePool(modeData);
return(DRIVE_TYPE_NONE);
}
BOOLEAN
FlCheckFormatParameters(
IN PDEVICE_OBJECT DeviceObject,
IN PFORMAT_PARAMETERS FormatParameters
)
/*++
Routine Description:
This routine checks the supplied format parameters to make sure that
they'll work on the drive to be formatted.
Arguments:
DeviceObject - Pointer to the device object to be formated.
FormatParameters - a pointer to the caller's parameters for the FORMAT.
Return Value:
TRUE if parameters are OK.
FALSE if the parameters are bad.
--*/
{
PDRIVE_MEDIA_CONSTANTS driveMediaConstants;
DRIVE_MEDIA_TYPE driveMediaType;
ULONG index;
//
// Get the device type.
//
index = DetermineDriveType(DeviceObject);
if (index == DRIVE_TYPE_NONE) {
//
// If the determine device type failed then just use the media type
// and try the parameters.
//
driveMediaType = Drive360Media160;
while (( DriveMediaConstants[driveMediaType].MediaType !=
FormatParameters->MediaType ) &&
( driveMediaType < Drive288Media288) ) {
driveMediaType++;
}
} else {
//
// Figure out which entry in the DriveMediaConstants table to use.
//
driveMediaType =
DriveMediaLimits[index].HighestDriveMediaType;
while ( ( DriveMediaConstants[driveMediaType].MediaType !=
FormatParameters->MediaType ) &&
( driveMediaType > DriveMediaLimits[index].
LowestDriveMediaType ) ) {
driveMediaType--;
}
}
if ( DriveMediaConstants[driveMediaType].MediaType !=
FormatParameters->MediaType ) {
return FALSE;
} else {
driveMediaConstants = &DriveMediaConstants[driveMediaType];
if ( ( FormatParameters->StartHeadNumber >
(ULONG)( driveMediaConstants->NumberOfHeads - 1 ) ) ||
( FormatParameters->EndHeadNumber >
(ULONG)( driveMediaConstants->NumberOfHeads - 1 ) ) ||
( FormatParameters->StartCylinderNumber >
driveMediaConstants->MaximumTrack ) ||
( FormatParameters->EndCylinderNumber >
driveMediaConstants->MaximumTrack ) ||
( FormatParameters->EndCylinderNumber <
FormatParameters->StartCylinderNumber ) ) {
return FALSE;
} else {
return TRUE;
}
}
}
NTSTATUS
FormatMedia(
PDEVICE_OBJECT DeviceObject,
MEDIA_TYPE MediaType
)
/*++
Routine Description:
This routine formats the floppy disk. The entire floppy is formated in
one shot.
Arguments:
DeviceObject - Supplies the device object to be tested.
Irp - Supplies a pointer to the requesting Irp.
MediaType - Supplies the media type format the device for.
Return Value:
Returns a status for the operation.
--*/
{
PVOID modeData;
PSCSI_REQUEST_BLOCK srb;
PMODE_FLEXIBLE_DISK_PAGE pageData;
DRIVE_MEDIA_TYPE driveMediaType;
PDRIVE_MEDIA_CONSTANTS driveMediaConstants;
ULONG length;
NTSTATUS status;
modeData = ExAllocatePool(NonPagedPoolCacheAligned, MODE_DATA_SIZE);
if (modeData == NULL) {
return(STATUS_INSUFFICIENT_RESOURCES);
}
RtlZeroMemory(modeData, MODE_DATA_SIZE);
length = ClassModeSense(DeviceObject,
modeData,
MODE_DATA_SIZE,
MODE_PAGE_FLEXIBILE);
if (length < sizeof(MODE_PARAMETER_HEADER)) {
ExFreePool(modeData);
return(STATUS_INVALID_DEVICE_REQUEST);
}
//
// Look for the flexible disk mode page.
//
pageData = ClassFindModePage( modeData, length, MODE_PAGE_FLEXIBILE, TRUE);
//
// Make sure the page is returned and is large enough.
//
if ((pageData == NULL) ||
(pageData->PageLength + 2 <
offsetof(MODE_FLEXIBLE_DISK_PAGE, StartWritePrecom))) {
ExFreePool(modeData);
return(STATUS_INVALID_DEVICE_REQUEST);
}
//
// Look for a drive media type which matches the requested media type.
//
//
//start from Drive120MMedia120M instead of Drive2080Media2080
//
for (driveMediaType = Drive120MMedia120M;
DriveMediaConstants[driveMediaType].MediaType != MediaType;
driveMediaType--) {
if (driveMediaType == Drive360Media160) {
ExFreePool(modeData);
return(STATUS_INVALID_PARAMETER);
}
}
driveMediaConstants = &DriveMediaConstants[driveMediaType];
if ((pageData->NumberOfHeads != driveMediaConstants->NumberOfHeads) ||
(pageData->SectorsPerTrack != driveMediaConstants->SectorsPerTrack) ||
((pageData->NumberOfCylinders[0] != (UCHAR)((driveMediaConstants->MaximumTrack+1) >> 8)) &&
(pageData->NumberOfCylinders[1] != (UCHAR)driveMediaConstants->MaximumTrack+1)) ||
(pageData->BytesPerSector[0] != driveMediaConstants->BytesPerSector >> 8 )) {
//
// Update the flexible parameters page with the new parameters.
//
pageData->NumberOfHeads = driveMediaConstants->NumberOfHeads;
pageData->SectorsPerTrack = driveMediaConstants->SectorsPerTrack;
pageData->NumberOfCylinders[0] = (UCHAR)((driveMediaConstants->MaximumTrack+1) >> 8);
pageData->NumberOfCylinders[1] = (UCHAR)driveMediaConstants->MaximumTrack+1;
pageData->BytesPerSector[0] = driveMediaConstants->BytesPerSector >> 8;
//
// Clear the mode parameter header.
//
RtlZeroMemory(modeData, sizeof(MODE_PARAMETER_HEADER));
//
// Set the length equal to the length returned for the flexible page.
//
length = pageData->PageLength + 2;
//
// Copy the page after the mode parameter header.
//
RtlMoveMemory((PCHAR) modeData + sizeof(MODE_PARAMETER_HEADER),
pageData,
length
);
length += sizeof(MODE_PARAMETER_HEADER);
//
// Allocate a Srb for the format command.
//
srb = ExAllocatePool(NonPagedPool, SCSI_REQUEST_BLOCK_SIZE);
if (srb == NULL) {
ExFreePool(modeData);
return(STATUS_INSUFFICIENT_RESOURCES);
}
RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE);
srb->CdbLength = 6;
srb->Cdb[0] = SCSIOP_MODE_SELECT;
srb->Cdb[4] = (UCHAR) length;
//
// Set the PF bit.
//
srb->Cdb[1] |= 0x10;
//
// Set timeout value.
//
srb->TimeOutValue = 2;
//
// Send the mode select data.
//
status = ClassSendSrbSynchronous(DeviceObject,
srb,
modeData,
length,
TRUE
);
//
// The mode data not needed any more so free it.
//
ExFreePool(modeData);
if (!NT_SUCCESS(status)) {
ExFreePool(srb);
return(status);
}
} else {
//
// The mode data not needed any more so free it.
//
ExFreePool(modeData);
//
// Allocate a Srb for the format command.
//
srb = ExAllocatePool(NonPagedPool, SCSI_REQUEST_BLOCK_SIZE);
if (srb == NULL) {
return(STATUS_INSUFFICIENT_RESOURCES);
}
}
RtlZeroMemory(srb, SCSI_REQUEST_BLOCK_SIZE);
srb->CdbLength = 6;
srb->Cdb[0] = SCSIOP_FORMAT_UNIT;
//
// Set timeout value.
//
srb->TimeOutValue = 10 * 60;
status = ClassSendSrbSynchronous(DeviceObject,
srb,
NULL,
0,
FALSE
);
ExFreePool(srb);
return(status);
}
VOID
ScsiFlopProcessError(
PDEVICE_OBJECT DeviceObject,
PSCSI_REQUEST_BLOCK Srb,
NTSTATUS *Status,
BOOLEAN *Retry
)
/*++
Routine Description:
This routine checks the type of error. If the error indicate the floppy
controller needs to be reinitialize a command is made to do it.
Arguments:
DeviceObject - Supplies a pointer to the device object.
Srb - Supplies a pointer to the failing Srb.
Status - Status with which the IRP will be completed.
Retry - Indication of whether the request will be retried.
Return Value:
None.
--*/
{
PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
PDISK_DATA diskData = (PDISK_DATA) fdoExtension->CommonExtension.DriverData;
PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer;
PIO_STACK_LOCATION irpStack;
PIRP irp;
PSCSI_REQUEST_BLOCK srb;
LARGE_INTEGER largeInt;
PCOMPLETION_CONTEXT context;
PCDB cdb;
ULONG_PTR alignment;
ULONG majorFunction;
UNREFERENCED_PARAMETER(Status);
UNREFERENCED_PARAMETER(Retry);
largeInt.QuadPart = 1;
//
// Check the status. The initialization command only needs to be sent
// if UNIT ATTENTION or LUN NOT READY is returned.
//
if (!(Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID)) {
//
// The drive does not require reinitialization.
//
return;
}
//
// Reset the drive type.
//
diskData->DriveType = DRIVE_TYPE_NONE;
diskData->IsDMF = FALSE;
fdoExtension->DiskGeometry.MediaType = Unknown;
if (fdoExtension->AdapterDescriptor->BusType == BusTypeUsb) {
// FLPYDISK.SYS never returns a non-zero value for the ChangeCount
// on an IOCTL_DISK_CHECK_VERIFY. Some things seem to work better
// if we do the same. In particular, FatVerifyVolume() can exit between
// the IOCTL_DISK_CHECK_VERIFY and the IOCTL_DISK_GET_DRIVE_GEOMETRY
// if a non-zero ChangeCount is returned, and this appears to cause
// issues formatting unformatted media in some situations.
//
// This is something that should probably be revisited at some point.
//
fdoExtension->MediaChangeCount = 0;
if (((senseBuffer->SenseKey & 0xf) == SCSI_SENS
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -