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

📄 flo_data.h

📁 The flpydisk sample is a floppy driver that resides in the directory \NtddkSrcStorageFdcFlpydsk. It
💻 H
📖 第 1 页 / 共 2 页
字号:
/*++

Copyright (C) Microsoft Corporation, 1991 - 1999

Module Name:

    flo_data.h

Abstract:

    This file includes data and hardware declarations for the NEC PD765
    (aka AT, ISA, and ix86) and Intel 82077 (aka MIPS) floppy driver for
    NT.

Author:


Environment:

    Kernel mode only.

Notes:


--*/


#if DBG
//
// For checked kernels, define a macro to print out informational
// messages.
//
// FloppyDebug is normally 0.  At compile-time or at run-time, it can be
// set to some bit patter for increasingly detailed messages.
//
// Big, nasty errors are noted with DBGP.  Errors that might be
// recoverable are handled by the WARN bit.  More information on
// unusual but possibly normal happenings are handled by the INFO bit.
// And finally, boring details such as routines entered and register
// dumps are handled by the SHOW bit.
//
#define FLOPDBGP              ((ULONG)0x00000001)
#define FLOPWARN              ((ULONG)0x00000002)
#define FLOPINFO              ((ULONG)0x00000004)
#define FLOPSHOW              ((ULONG)0x00000008)
#define FLOPIRPPATH           ((ULONG)0x00000010)
#define FLOPFORMAT            ((ULONG)0x00000020)
#define FLOPSTATUS            ((ULONG)0x00000040)
#define FLOPPNP               ((ULONG)0x00000080)
extern ULONG FloppyDebugLevel;
#define FloppyDump(LEVEL,STRING) \
        do { \
            if (FloppyDebugLevel & (LEVEL)) { \
                DbgPrint STRING; \
            } \
        } while (0)
#else
#define FloppyDump(LEVEL,STRING) do {NOTHING;} while (0)
#endif

//
//  Define macros for driver paging
//
#define FloppyPageEntireDriver()            \
{                                           \
    ExAcquireFastMutex(PagingMutex);        \
    if (--PagingReferenceCount == 0) {      \
        MmPageEntireDriver(DriverEntry);    \
    }                                       \
    ExReleaseFastMutex(PagingMutex);        \
}

#define FloppyResetDriverPaging()           \
{                                           \
    ExAcquireFastMutex(PagingMutex);        \
    if (++PagingReferenceCount == 1) {      \
        MmResetDriverPaging(DriverEntry);   \
    }                                       \
    ExReleaseFastMutex(PagingMutex);        \
}




//
// If we don't get enough map registers to handle the maximum track size,
// we will allocate a contiguous buffer and do I/O to/from that.
//
// On MIPS, we should always have enough map registers.  On the ix86 we
// might not, and when we allocate the contiguous buffer we have to make
// sure that it's in the first 16Mb of RAM to make sure the DMA chip can
// address it.
//

#define MAXIMUM_DMA_ADDRESS                0xFFFFFF

//
// The byte in the boot sector that specifies the type of media, and
// the values that it can assume.  We can often tell what type of media
// is in the drive by seeing which controller parameters allow us to read
// the diskette, but some different densities are readable with the same
// parameters so we use this byte to decide the media type.
//

typedef struct _BOOT_SECTOR_INFO {
    UCHAR   JumpByte[1];
    UCHAR   Ignore1[2];
    UCHAR   OemData[8];
    UCHAR   BytesPerSector[2];
    UCHAR   Ignore2[6];
    UCHAR   NumberOfSectors[2];
    UCHAR   MediaByte[1];
    UCHAR   Ignore3[2];
    UCHAR   SectorsPerTrack[2];
    UCHAR   NumberOfHeads[2];
} BOOT_SECTOR_INFO, *PBOOT_SECTOR_INFO;


//
// Retry counts -
//
// When attempting I/O, we may run into many different errors.  The
// hardware retries things 8 times invisibly.  If the hardware reports
// any type of error, we will recalibrate and retry the operation
// up to RECALIBRATE_RETRY_COUNT times.  When this expires, we check to
// see if there's an overrun - if so, the DMA is probably being hogged
// by a higher priority device, so we repeat the earlier loop up to
// OVERRUN_RETRY_COUNT times.
//
// Any packet that is about to be returned with an error caused by an
// unexpected hardware error or state will be restarted from the very
// beginning after resetting the hardware HARDWARE_RESET_RETRY_COUNT
// times.
//

#define RECALIBRATE_RETRY_COUNT            3
#define OVERRUN_RETRY_COUNT                1
#define HARDWARE_RESET_RETRY_COUNT         2

//
// The I/O system calls our timer routine once every second.  If the timer
// counter is -1, the timer is "off" and the timer routine will just return.
// By setting the counter to 3, the timer routine will decrement the
// counter every second, so the timer will expire in 2 to 3 seconds.  At
// that time the drive motor will be turned off.
//

#define TIMER_CANCEL                       -1
#define TIMER_EXPIRED                      0
#define FDC_TIMEOUT                        4


//
// Define drive types.  Numbers are read from CMOS, translated to these
// numbers, and then used as an index into the DRIVE_MEDIA_LIMITS table.
//

#define DRIVE_TYPE_0360                    0
#define DRIVE_TYPE_1200                    1
#define DRIVE_TYPE_0720                    2
#define DRIVE_TYPE_1440                    3
#define DRIVE_TYPE_2880                    4
#define DRIVE_TYPE_1200_E                  5  // NEC98: 5.25" 1.2Mb  externel drive

#define NUMBER_OF_DRIVE_TYPES              5
#define NUMBER_OF_DRIVE_TYPES_NEC98        6
#define DRIVE_TYPE_NONE                    NUMBER_OF_DRIVE_TYPES
#define DRIVE_TYPE_INVALID                 DRIVE_TYPE_NONE + 1

#define BOOT_SECTOR_SIZE      (IsNEC_98 ? 1024 : 512)

//
// Media types are defined in ntdddisk.h, but we'll add one type here.
// This keeps us from wasting time trying to determine the media type
// over and over when, for example, a fresh floppy is about to be
// formatted.
//

#define Undetermined                       -1

//
// 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_MEDIA_COMBINATIONS_             17
#define _NUMBER_OF_DRIVE_MEDIA_COMBINATIONS_NEC98_       21

#define NUMBER_OF_DRIVE_MEDIA_COMBINATIONS \
        (ULONG)(IsNEC_98 ? _NUMBER_OF_DRIVE_MEDIA_COMBINATIONS_NEC98_ : _NUMBER_OF_DRIVE_MEDIA_COMBINATIONS_)

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
} DRIVE_MEDIA_TYPE;

//
// for NEC98
//
typedef enum _DRIVE_MEDIA_TYPE_NEC98 {
    Drive360Media160Nec98,                 // 5.25"  360k  drive;  160k   media
    Drive360Media180Nec98,                 // 5.25"  360k  drive;  180k   media
    Drive360Media320Nec98,                 // 5.25"  360k  drive;  320k   media
    Drive360Media32XNec98,                 // 5.25"  360k  drive;  320k 1k secs
    Drive360Media360Nec98,                 // 5.25"  360k  drive;  360k   media

    Drive120Media160Nec98,                 //  5.25" 1.2Mb drive;  160k   media
    Drive120Media180Nec98,                 //  5.25" 1.2Mb drive;  180k   media
    Drive120Media320Nec98,                 //  5.25" 1.2Mb drive;  320k   media
    Drive120Media32XNec98,                 //  5.25" 1.2Mb drive;  320k 1k secs
    Drive120Media360Nec98,                 //  5.25" 1.2Mb drive;  360k   media
    Drive120Media640Nec98,                 //  5.25" 1.2Mb drive;  640k   media
    Drive120Media720Nec98,                 //  5.25" 1.2Mb drive;  720k   media
    Drive120Media120Nec98,                 //  5.25" 1.2Mb drive; 1.2Mb   media
    Drive120Media123Nec98,                 //  5.25" 1.2Mb drive;1.25Mb   media

    Drive144Media640Nec98,                 //  3.5"  1.44Mb drive;  640k   media
    Drive144Media720Nec98,                 //  3.5"  1.44Mb drive;  720k   media
    Drive144Media120Nec98,                 //  3.5"  1.44Mb drive; 1.2Mb   media
    Drive144Media123Nec98,                 //  3.5"  1.44Mb drive; 1.25Mb   media
    Drive144Media144Nec98,                 //  3.5"  1.44Mb drive; 1.44Mb  media

    Drive12EMedia120Nec98,                 //  5.25" 1.2Mb externel drive; 1.2Mb   media
    Drive12EMedia123Nec98,                 //  5.25" 1.2Mb externel drive; 1.25Mb   media
} DRIVE_MEDIA_TYPE_NEC98;

//
// 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;

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
};

//
// for NEC98
//
typedef struct _DRIVE_MEDIA_LIMITS_NEC98 {
    DRIVE_MEDIA_TYPE_NEC98 HighestDriveMediaType;
    DRIVE_MEDIA_TYPE_NEC98 LowestDriveMediaType;
} DRIVE_MEDIA_LIMITS_NEC98, *PDRIVE_MEDIA_LIMITS_NEC98;

DRIVE_MEDIA_LIMITS_NEC98 _DriveMediaLimits_NEC98[NUMBER_OF_DRIVE_TYPES_NEC98] = {

    { Drive360Media360Nec98, Drive360Media160Nec98 }, // DRIVE_TYPE_0360
    { Drive120Media123Nec98, Drive120Media160Nec98 }, // DRIVE_TYPE_1200
    { Drive120Media720Nec98, Drive120Media160Nec98 }, // DRIVE_TYPE_0720
    { Drive144Media144Nec98, Drive144Media640Nec98 }, // DRIVE_TYPE_1440
    { Drive144Media144Nec98, Drive144Media640Nec98 }, // DRIVE_TYPE_2880 - dummy, never be used.
    { Drive12EMedia123Nec98, Drive12EMedia120Nec98 }  // DRIVE_TYPE_1200_E
};

PDRIVE_MEDIA_LIMITS DriveMediaLimits;

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

typedef struct _DRIVE_MEDIA_CONSTANTS {
    MEDIA_TYPE MediaType;
    UCHAR      StepRateHeadUnloadTime;
    UCHAR      HeadLoadTime;
    UCHAR      MotorOffTime;
    UCHAR      SectorLengthCode;
    USHORT     BytesPerSector;
    UCHAR      SectorsPerTrack;
    UCHAR      ReadWriteGapLength;
    UCHAR      FormatGapLength;
    UCHAR      FormatFillCharacter;
    UCHAR      HeadSettleTime;
    USHORT     MotorSettleTimeRead;
    USHORT     MotorSettleTimeWrite;
    UCHAR      MaximumTrack;
    UCHAR      CylinderShift;
    UCHAR      DataTransferRate;
    UCHAR      NumberOfHeads;
    UCHAR      DataLength;
    UCHAR      MediaByte;
    UCHAR      SkewDelta;
} 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[_NUMBER_OF_DRIVE_MEDIA_COMBINATIONS_] =
{
    { F5_160_512,   0xdf, 0x2, 0x25, 0x2, 0x200, 0x08, 0x2a, 0x50, 0xf6, 0xf, 1000, 1000, 0x27, 0, 0x2, 0x1, 0xff, 0xfe, 0 },
    { F5_180_512,   0xdf, 0x2, 0x25, 0x2, 0x200, 0x09, 0x2a, 0x50, 0xf6, 0xf, 1000, 1000, 0x27, 0, 0x2, 0x1, 0xff, 0xfc, 0 },
    { F5_320_512,   0xdf, 0x2, 0x25, 0x2, 0x200, 0x08, 0x2a, 0x50, 0xf6, 0xf, 1000, 1000, 0x27, 0, 0x2, 0x2, 0xff, 0xff, 0 },
    { F5_320_1024,  0xdf, 0x2, 0x25, 0x3, 0x400, 0x04, 0x80, 0xf0, 0xf6, 0xf, 1000, 1000, 0x27, 0, 0x2, 0x2, 0xff, 0xff, 0 },
    { F5_360_512,   0xdf, 0x2, 0x25, 0x2, 0x200, 0x09, 0x2a, 0x50, 0xf6, 0xf,  250, 1000, 0x27, 0, 0x2, 0x2, 0xff, 0xfd, 0 },
    { F3_720_512,   0xdf, 0x2, 0x25, 0x2, 0x200, 0x09, 0x2a, 0x50, 0xf6, 0xf,  500, 1000, 0x4f, 0, 0x2, 0x2, 0xff, 0xf9, 2 },
    { F5_160_512,   0xdf, 0x2, 0x25, 0x2, 0x200, 0x08, 0x2a, 0x50, 0xf6, 0xf, 1000, 1000, 0x27, 1, 0x1, 0x1, 0xff, 0xfe, 0 },
    { F5_180_512,   0xdf, 0x2, 0x25, 0x2, 0x200, 0x09, 0x2a, 0x50, 0xf6, 0xf, 1000, 1000, 0x27, 1, 0x1, 0x1, 0xff, 0xfc, 0 },
    { F5_320_512,   0xdf, 0x2, 0x25, 0x2, 0x200, 0x08, 0x2a, 0x50, 0xf6, 0xf, 1000, 1000, 0x27, 1, 0x1, 0x2, 0xff, 0xff, 0 },
    { F5_320_1024,  0xdf, 0x2, 0x25, 0x3, 0x400, 0x04, 0x80, 0xf0, 0xf6, 0xf, 1000, 1000, 0x27, 1, 0x1, 0x2, 0xff, 0xff, 0 },
    { F5_360_512,   0xdf, 0x2, 0x25, 0x2, 0x200, 0x09, 0x2a, 0x50, 0xf6, 0xf,  625, 1000, 0x27, 1, 0x1, 0x2, 0xff, 0xfd, 0 },
    { F5_1Pt2_512,  0xdf, 0x2, 0x25, 0x2, 0x200, 0x0f, 0x1b, 0x54, 0xf6, 0xf,  625, 1000, 0x4f, 0, 0x0, 0x2, 0xff, 0xf9, 0 },
    { F3_720_512,   0xdf, 0x2, 0x25, 0x2, 0x200, 0x09, 0x2a, 0x50, 0xf6, 0xf,  500, 1000, 0x4f, 0, 0x2, 0x2, 0xff, 0xf9, 2 },
    { F3_1Pt44_512, 0xaf, 0x2, 0x25, 0x2, 0x200, 0x12, 0x1b, 0x65, 0xf6, 0xf,  500, 1000, 0x4f, 0, 0x0, 0x2, 0xff, 0xf0, 3 },
    { F3_720_512,   0xe1, 0x2, 0x25, 0x2, 0x200, 0x09, 0x2a, 0x50, 0xf6, 0xf,  500, 1000, 0x4f, 0, 0x2, 0x2, 0xff, 0xf9, 2 },
    { F3_1Pt44_512, 0xd1, 0x2, 0x25, 0x2, 0x200, 0x12, 0x1b, 0x65, 0xf6, 0xf,  500, 1000, 0x4f, 0, 0x0, 0x2, 0xff, 0xf0, 3 },
    { F3_2Pt88_512, 0xa1, 0x2, 0x25, 0x2, 0x200, 0x24, 0x38, 0x53, 0xf6, 0xf,  500, 1000, 0x4f, 0, 0x3, 0x2, 0xff, 0xf0, 6 }
};

//
// for NEC98
//
DRIVE_MEDIA_CONSTANTS _DriveMediaConstants_NEC98[_NUMBER_OF_DRIVE_MEDIA_COMBINATIONS_NEC98_] =
{
    //
    // 5.25" 360k drive
    //
    { F5_160_512,   0xdf, 0x2, 0x25, 0x2, 0x200, 0x08, 0x2a, 0x50, 0xf6, 0xf, 1000, 1000, 0x27, 0, 0x2, 0x1, 0xff, 0xfe, 0 },
    { F5_180_512,   0xdf, 0x2, 0x25, 0x2, 0x200, 0x09, 0x2a, 0x50, 0xf6, 0xf, 1000, 1000, 0x27, 0, 0x2, 0x1, 0xff, 0xfc, 0 },
    { F5_320_512,   0xdf, 0x2, 0x25, 0x2, 0x200, 0x08, 0x2a, 0x50, 0xf6, 0xf, 1000, 1000, 0x27, 0, 0x2, 0x2, 0xff, 0xff, 0 },
    { F5_320_1024,  0xdf, 0x2, 0x25, 0x3, 0x400, 0x04, 0x80, 0xf0, 0xf6, 0xf, 1000, 1000, 0x27, 0, 0x2, 0x2, 0xff, 0xff, 0 },
    { F5_360_512,   0xdf, 0x2, 0x25, 0x2, 0x200, 0x09, 0x2a, 0x50, 0xf6, 0xf, 250, 1000, 0x27, 0, 0x2, 0x2, 0xff, 0xfd, 0 },

    //
    // 5.25" 1.2Mb drive
    //
    { F5_160_512,   0xdf, 0x16, 0x25, 0x2, 0x200, 0x08, 0x2a, 0x50, 0xe5, 0xf, 1000, 1000, 0x27, 1, 0x2, 0x1, 0xff, 0xfe, 0 },
    { F5_180_512,   0xdf, 0x16, 0x25, 0x2, 0x200, 0x09, 0x2a, 0x50, 0xe5, 0xf, 1000, 1000, 0x27, 1, 0x2, 0x1, 0xff, 0xfc, 0 },
    { F5_320_512,   0xdf, 0x16, 0x25, 0x2, 0x200, 0x08, 0x2a, 0x50, 0xe5, 0xf, 1000, 1000, 0x27, 1, 0x2, 0x2, 0xff, 0xff, 0 },
    { F5_320_1024,  0xdf, 0x16, 0x25, 0x3, 0x400, 0x04, 0x80, 0xf0, 0xe5, 0xf, 1000, 1000, 0x27, 1, 0x2, 0x2, 0xff, 0xff, 0 },
    { F5_360_512,   0xdf, 0x16, 0x25, 0x2, 0x200, 0x09, 0x2a, 0x50, 0xe5, 0xf, 1000, 1000, 0x27, 1, 0x2, 0x2, 0xff, 0xfd, 0 },
    { F5_640_512,   0xdf, 0x16, 0x25, 0x2, 0x200, 0x08, 0x2a, 0x50, 0xe5, 0xf, 1000, 1000, 0x4f, 0, 0x0, 0x2, 0xff, 0xfb, 0 },
    { F5_720_512,   0xdf, 0x16, 0x25, 0x2, 0x200, 0x09, 0x2a, 0x50, 0xe5, 0xf, 1000, 1000, 0x4f, 0, 0x0, 0x2, 0xff, 0xf9, 2 },
    { F5_1Pt2_512,  0xcf, 0x24, 0x25, 0x2, 0x200, 0x0f, 0x1b, 0x54, 0xe5, 0xf, 1000, 1000, 0x4f, 0, 0x0, 0x2, 0xff, 0xf9, 0 },
    { F5_1Pt23_1024,0xcf, 0x24, 0x25, 0x3, 0x400, 0x08, 0x35, 0x74, 0xe5, 0xf, 1000, 1000, 0x4c, 0, 0x0, 0x2, 0xff, 0xfe, 0 },

    //
    // 3.5"  1.44Mb drive
    //
    { F3_640_512,   0xdf, 0x16, 0x25, 0x2, 0x200, 0x08, 0x2a, 0x50, 0xe5, 0xf, 1000, 1000, 0x4f, 0, 0x0, 0x2, 0xff, 0xfb, 0 },
    { F3_720_512,   0xdf, 0x16, 0x25, 0x2, 0x200, 0x09, 0x2a, 0x50, 0xe5, 0xf, 1000, 1000, 0x4f, 0, 0x0, 0x2, 0xff, 0xf9, 2 },
    { F3_1Pt2_512,  0xcf, 0x24, 0x25, 0x2, 0x200, 0x0f, 0x1b, 0x54, 0xe5, 0xf, 1000, 1000, 0x4f, 0, 0x0, 0x2, 0xff, 0xf9, 0 },
    { F3_1Pt23_1024,0xcf, 0x24, 0x25, 0x3, 0x400, 0x08, 0x35, 0x74, 0xe5, 0xf, 1000, 1000, 0x4c, 0, 0x0, 0x2, 0xff, 0xfe, 0 },
    { F3_1Pt44_512, 0xdf, 0x24, 0x25, 0x2, 0x200, 0x12, 0x1b, 0x6c, 0xe5, 0xf, 1000, 1000, 0x4f, 0, 0x0, 0x2, 0xff, 0xf0, 3 },

    //
    // 5.25" 1.2Mb externel drive
    //
    { F5_1Pt2_512,  0xbf, 0x32, 0x25, 0x2, 0x200, 0x0f, 0x1b, 0x54, 0xe5, 0xf, 1000, 1000, 0x4f, 0, 0x0, 0x2, 0xff, 0xf9, 0 },
    { F5_1Pt23_1024,0xbf, 0x32, 0x25, 0x3, 0x400, 0x08, 0x35, 0x74, 0xe5, 0xf, 1000, 1000, 0x4c, 0, 0x0, 0x2, 0xff, 0xfe, 0 },

};

PDRIVE_MEDIA_CONSTANTS DriveMediaConstants;



//
// Parameter fields passed to the CONFIGURE command.
//
#define COMMND_CONFIGURE_IMPLIED_SEEKS     0x40
#define COMMND_CONFIGURE_FIFO_THRESHOLD    0x0F
#define COMMND_CONFIGURE_DISABLE_FIFO      0x20
#define COMMND_CONFIGURE_DISABLE_POLLING   0x10

//
// Write Enable bit for PERPENDICULAR MODE command.
//
#define COMMND_PERPENDICULAR_MODE_OW       0x80

//
// Bits in the DRIVE_CONTROL register.
//
#define DRVCTL_RESET                       0x00

⌨️ 快捷键说明

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