|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1991 - 1993 Microsoft Corporation ! 4: ! 5: Module Name: ! 6: ! 7: flo_data.h ! 8: ! 9: Abstract: ! 10: ! 11: This file includes data and hardware declarations for the NEC PD765 ! 12: (aka AT, ISA, and ix86) and Intel 82077 (aka MIPS) floppy driver for ! 13: NT. ! 14: ! 15: Author: ! 16: ! 17: ! 18: Environment: ! 19: ! 20: Kernel mode only. ! 21: ! 22: Notes: ! 23: ! 24: ! 25: --*/ ! 26: ! 27: ! 28: #if DBG ! 29: // ! 30: // For checked kernels, define a macro to print out informational ! 31: // messages. ! 32: // ! 33: // FloppyDebug is normally 0. At compile-time or at run-time, it can be ! 34: // set to some bit patter for increasingly detailed messages. ! 35: // ! 36: // Big, nasty errors are noted with DBGP. Errors that might be ! 37: // recoverable are handled by the WARN bit. More information on ! 38: // unusual but possibly normal happenings are handled by the INFO bit. ! 39: // And finally, boring details such as routines entered and register ! 40: // dumps are handled by the SHOW bit. ! 41: // ! 42: #define FLOPDBGP ((ULONG)0x00000001) ! 43: #define FLOPWARN ((ULONG)0x00000002) ! 44: #define FLOPINFO ((ULONG)0x00000004) ! 45: #define FLOPSHOW ((ULONG)0x00000008) ! 46: #define FLOPIRPPATH ((ULONG)0x00000010) ! 47: #define FLOPFORMAT ((ULONG)0x00000020) ! 48: extern ULONG FloppyDebugLevel; ! 49: #define FloppyDump(LEVEL,STRING) \ ! 50: do { \ ! 51: if (FloppyDebugLevel & LEVEL) { \ ! 52: DbgPrint STRING; \ ! 53: } \ ! 54: } while (0) ! 55: #else ! 56: #define FloppyDump(LEVEL,STRING) do {NOTHING;} while (0) ! 57: #endif ! 58: ! 59: ! 60: // ! 61: // For device name manipulation, we allocate a buffer since there is no ! 62: // preset limit on name size. The system hands us a prefix, and we ! 63: // allocate the buffer to be the size of that prefix plus the delta defined ! 64: // below. This size gives us room for ! 65: // PREFIX + <disk number> ! 66: // with up to five digits for the disk number. ! 67: // ! 68: ! 69: #define DEVICE_NAME_DELTA 5 ! 70: ! 71: // ! 72: // Partitions need to be linked to ARC names, in case we're booting off ! 73: // the partition. The system hands us a prefix, and we allocate the ! 74: // buffer to be the size of that prefix plus the delta defined below. ! 75: // This size gives us room for ! 76: // PREFIX + disk(<#>)fdisk(<#>) ! 77: // with up to five digits per number. ! 78: // ! 79: ! 80: #define ARC_NAME_DELTA 23 ! 81: ! 82: // ! 83: // Macros to access the controller. Note that the *_PORT_UCHAR macros ! 84: // work on all machines, whether the I/O ports are separate or in ! 85: // memory space. ! 86: // ! 87: ! 88: #define READ_CONTROLLER( Address ) \ ! 89: READ_PORT_UCHAR( ( PUCHAR )Address ) ! 90: ! 91: #define WRITE_CONTROLLER( Address, Value ) \ ! 92: WRITE_PORT_UCHAR( ( PUCHAR )Address, ( UCHAR )Value ) ! 93: ! 94: ! 95: // ! 96: // If we don't get enough map registers to handle the maximum track size, ! 97: // we will allocate a contiguous buffer and do I/O to/from that. ! 98: // ! 99: // On MIPS, we should always have enough map registers. On the ix86 we ! 100: // might not, and when we allocate the contiguous buffer we have to make ! 101: // sure that it's in the first 16Mb of RAM to make sure the DMA chip can ! 102: // address it. ! 103: // ! 104: ! 105: #define MAXIMUM_DMA_ADDRESS 0xFFFFFF ! 106: ! 107: // ! 108: // The byte in the boot sector that specifies the type of media, and ! 109: // the values that it can assume. We can often tell what type of media ! 110: // is in the drive by seeing which controller parameters allow us to read ! 111: // the diskette, but some different densities are readable with the same ! 112: // parameters so we use this byte to decide the media type. ! 113: // ! 114: ! 115: #define MEDIA_DESCRIPTOR_OFFSET 0x15 ! 116: #define MEDIA_DESCRIPTOR_SECTORS_PER_TRACK 0x18 ! 117: #define MEDIA_DESCRIPTOR_NUM_OF_HEADS 0x1A ! 118: ! 119: #define MEDIA_DESCRIPTOR_160K 0xFE ! 120: #define MEDIA_DESCRIPTOR_180K 0xFC ! 121: #define MEDIA_DESCRIPTOR_320K 0xFF ! 122: #define MEDIA_DESCRIPTOR_360K 0xFD ! 123: #define MEDIA_DESCRIPTOR_720K_OR_1220K 0xF9 ! 124: #define MEDIA_DESCRIPTOR_1440K_OR_2880K 0xF0 ! 125: ! 126: // ! 127: // Retry counts - ! 128: // ! 129: // When moving a byte to/from the FIFO, we sit in a tight loop for a while ! 130: // waiting for the controller to become ready. The number of times through ! 131: // the loop is controlled by FIFO_TIGHTLOOP_RETRY_COUNT. When that count ! 132: // expires, we'll wait in 10ms increments. FIFO_DELAY_RETRY_COUNT controls ! 133: // how many times we wait. ! 134: // ! 135: // The ISR_SENSE_RETRY_COUNT is the maximum number of 1 microsecond ! 136: // stalls that the ISR will do waiting for the controller to accept ! 137: // a SENSE INTERRUPT command. We do this because there is a hardware ! 138: // quirk in at least the NCR 8 processor machine where it can take ! 139: // up to 50 microseconds to accept the command. ! 140: // ! 141: // When attempting I/O, we may run into many different errors. The ! 142: // hardware retries things 8 times invisibly. If the hardware reports ! 143: // any type of error, we will recalibrate and retry the operation ! 144: // up to RECALIBRATE_RETRY_COUNT times. When this expires, we check to ! 145: // see if there's an overrun - if so, the DMA is probably being hogged ! 146: // by a higher priority device, so we repeat the earlier loop up to ! 147: // OVERRUN_RETRY_COUNT times. ! 148: // ! 149: // Any packet that is about to be returned with an error caused by an ! 150: // unexpected hardware error or state will be restarted from the very ! 151: // beginning after resetting the hardware HARDWARE_RESET_RETRY_COUNT ! 152: // times. ! 153: // ! 154: ! 155: #define FIFO_TIGHTLOOP_RETRY_COUNT 500 ! 156: #define FIFO_ISR_TIGHTLOOP_RETRY_COUNT 25 ! 157: #define ISR_SENSE_RETRY_COUNT 50 ! 158: #define FIFO_DELAY_RETRY_COUNT 5 ! 159: #define RECALIBRATE_RETRY_COUNT 3 ! 160: #define OVERRUN_RETRY_COUNT 3 ! 161: #define HARDWARE_RESET_RETRY_COUNT 2 ! 162: #define FLOPPY_RESET_ISR_THRESHOLD 20 ! 163: ! 164: // ! 165: // The I/O system calls our timer routine once every second. If the timer ! 166: // counter is -1, the timer is "off" and the timer routine will just return. ! 167: // By setting the counter to 3, the timer routine will decrement the ! 168: // counter every second, so the timer will expire in 2 to 3 seconds. At ! 169: // that time the drive motor will be turned off. ! 170: // ! 171: ! 172: #define TIMER_CANCEL -1 ! 173: #define TIMER_EXPIRED 0 ! 174: #define TIMER_START 3 ! 175: ! 176: ! 177: // ! 178: // Define drive types. Numbers are read from CMOS, translated to these ! 179: // numbers, and then used as an index into the DRIVE_MEDIA_LIMITS table. ! 180: // ! 181: ! 182: #define DRIVE_TYPE_0360 0 ! 183: #define DRIVE_TYPE_1200 1 ! 184: #define DRIVE_TYPE_0720 2 ! 185: #define DRIVE_TYPE_1440 3 ! 186: #define DRIVE_TYPE_2880 4 ! 187: ! 188: #define NUMBER_OF_DRIVE_TYPES 5 ! 189: #define DRIVE_TYPE_NONE NUMBER_OF_DRIVE_TYPES ! 190: #define DRIVE_TYPE_INVALID DRIVE_TYPE_NONE + 1 ! 191: ! 192: // ! 193: // Media types are defined in ntdddisk.h, but we'll add one type here. ! 194: // This keeps us from wasting time trying to determine the media type ! 195: // over and over when, for example, a fresh floppy is about to be ! 196: // formatted. ! 197: // ! 198: ! 199: #define Undetermined -1 ! 200: ! 201: // ! 202: // Define all possible drive/media combinations, given drives listed above ! 203: // and media types in ntdddisk.h. ! 204: // ! 205: // These values are used to index the DriveMediaConstants table. ! 206: // ! 207: ! 208: #define NUMBER_OF_DRIVE_MEDIA_COMBINATIONS 17 ! 209: ! 210: typedef enum _DRIVE_MEDIA_TYPE { ! 211: Drive360Media160, // 5.25" 360k drive; 160k media ! 212: Drive360Media180, // 5.25" 360k drive; 180k media ! 213: Drive360Media320, // 5.25" 360k drive; 320k media ! 214: Drive360Media32X, // 5.25" 360k drive; 320k 1k secs ! 215: Drive360Media360, // 5.25" 360k drive; 360k media ! 216: Drive720Media720, // 3.5" 720k drive; 720k media ! 217: Drive120Media160, // 5.25" 1.2Mb drive; 160k media ! 218: Drive120Media180, // 5.25" 1.2Mb drive; 180k media ! 219: Drive120Media320, // 5.25" 1.2Mb drive; 320k media ! 220: Drive120Media32X, // 5.25" 1.2Mb drive; 320k 1k secs ! 221: Drive120Media360, // 5.25" 1.2Mb drive; 360k media ! 222: Drive120Media120, // 5.25" 1.2Mb drive; 1.2Mb media ! 223: Drive144Media720, // 3.5" 1.44Mb drive; 720k media ! 224: Drive144Media144, // 3.5" 1.44Mb drive; 1.44Mb media ! 225: Drive288Media720, // 3.5" 2.88Mb drive; 720k media ! 226: Drive288Media144, // 3.5" 2.88Mb drive; 1.44Mb media ! 227: Drive288Media288 // 3.5" 2.88Mb drive; 2.88Mb media ! 228: } DRIVE_MEDIA_TYPE; ! 229: ! 230: // ! 231: // When we want to determine the media type in a drive, we will first ! 232: // guess that the media with highest possible density is in the drive, ! 233: // and keep trying lower densities until we can successfully read from ! 234: // the drive. ! 235: // ! 236: // These values are used to select a DRIVE_MEDIA_TYPE value. ! 237: // ! 238: // The following table defines ranges that apply to the DRIVE_MEDIA_TYPE ! 239: // enumerated values when trying media types for a particular drive type. ! 240: // Note that for this to work, the DRIVE_MEDIA_TYPE values must be sorted ! 241: // by ascending densities within drive types. Also, for maximum track ! 242: // size to be determined properly, the drive types must be in ascending ! 243: // order. ! 244: // ! 245: ! 246: typedef struct _DRIVE_MEDIA_LIMITS { ! 247: DRIVE_MEDIA_TYPE HighestDriveMediaType; ! 248: DRIVE_MEDIA_TYPE LowestDriveMediaType; ! 249: } DRIVE_MEDIA_LIMITS, *PDRIVE_MEDIA_LIMITS; ! 250: ! 251: DRIVE_MEDIA_LIMITS DriveMediaLimits[NUMBER_OF_DRIVE_TYPES] = { ! 252: ! 253: { Drive360Media360, Drive360Media160 }, // DRIVE_TYPE_0360 ! 254: { Drive120Media120, Drive120Media160 }, // DRIVE_TYPE_1200 ! 255: { Drive720Media720, Drive720Media720 }, // DRIVE_TYPE_0720 ! 256: { Drive144Media144, Drive144Media720 }, // DRIVE_TYPE_1440 ! 257: { Drive288Media288, Drive288Media720 } // DRIVE_TYPE_2880 ! 258: }; ! 259: ! 260: // ! 261: // For each drive/media combination, define important constants. ! 262: // ! 263: ! 264: typedef struct _DRIVE_MEDIA_CONSTANTS { ! 265: MEDIA_TYPE MediaType; ! 266: UCHAR StepRateHeadUnloadTime; ! 267: UCHAR HeadLoadTime; ! 268: UCHAR MotorOffTime; ! 269: UCHAR SectorLengthCode; ! 270: USHORT BytesPerSector; ! 271: UCHAR SectorsPerTrack; ! 272: UCHAR ReadWriteGapLength; ! 273: UCHAR FormatGapLength; ! 274: UCHAR FormatFillCharacter; ! 275: UCHAR HeadSettleTime; ! 276: USHORT MotorSettleTimeRead; ! 277: USHORT MotorSettleTimeWrite; ! 278: UCHAR MaximumTrack; ! 279: UCHAR CylinderShift; ! 280: UCHAR DataTransferRate; ! 281: UCHAR NumberOfHeads; ! 282: UCHAR DataLength; ! 283: } DRIVE_MEDIA_CONSTANTS, *PDRIVE_MEDIA_CONSTANTS; ! 284: ! 285: // ! 286: // Magic value to add to the SectorLengthCode to use it as a shift value ! 287: // to determine the sector size. ! 288: // ! 289: ! 290: #define SECTORLENGTHCODE_TO_BYTESHIFT 7 ! 291: ! 292: // ! 293: // The following values were gleaned from many different sources, which ! 294: // often disagreed with each other. Where numbers were in conflict, I ! 295: // chose the more conservative or most-often-selected value. ! 296: // ! 297: ! 298: DRIVE_MEDIA_CONSTANTS DriveMediaConstants[NUMBER_OF_DRIVE_MEDIA_COMBINATIONS] = ! 299: { ! 300: ! 301: { F5_160_512, 0xdf, 0x2, 0x25, 0x2, 0x200, 0x08, 0x2a, 0x50, 0xf6, 0xf, ! 302: 1000, 1000, 0x27, 0, 0x2, 0x1, 0xff }, ! 303: { F5_180_512, 0xdf, 0x2, 0x25, 0x2, 0x200, 0x09, 0x2a, 0x50, 0xf6, 0xf, ! 304: 1000, 1000, 0x27, 0, 0x2, 0x1, 0xff }, ! 305: { F5_320_512, 0xdf, 0x2, 0x25, 0x2, 0x200, 0x08, 0x2a, 0x50, 0xf6, 0xf, ! 306: 1000, 1000, 0x27, 0, 0x2, 0x2, 0xff }, ! 307: { F5_320_1024, 0xdf, 0x2, 0x25, 0x3, 0x400, 0x04, 0x80, 0xf0, 0xf6, 0xf, ! 308: 1000, 1000, 0x27, 0, 0x2, 0x2, 0xff }, ! 309: { F5_360_512, 0xdf, 0x2, 0x25, 0x2, 0x200, 0x09, 0x2a, 0x50, 0xf6, 0xf, ! 310: 250, 1000, 0x27, 0, 0x2, 0x2, 0xff }, ! 311: ! 312: { F3_720_512, 0xdf, 0x2, 0x25, 0x2, 0x200, 0x09, 0x2a, 0x50, 0xf6, 0xf, ! 313: 500, 1000, 0x4f, 0, 0x2, 0x2, 0xff }, ! 314: ! 315: { F5_160_512, 0xdf, 0x2, 0x25, 0x2, 0x200, 0x08, 0x2a, 0x50, 0xf6, 0xf, ! 316: 1000, 1000, 0x27, 1, 0x1, 0x1, 0xff }, ! 317: { F5_180_512, 0xdf, 0x2, 0x25, 0x2, 0x200, 0x09, 0x2a, 0x50, 0xf6, 0xf, ! 318: 1000, 1000, 0x27, 1, 0x1, 0x1, 0xff }, ! 319: { F5_320_512, 0xdf, 0x2, 0x25, 0x2, 0x200, 0x08, 0x2a, 0x50, 0xf6, 0xf, ! 320: 1000, 1000, 0x27, 1, 0x1, 0x2, 0xff }, ! 321: { F5_320_1024, 0xdf, 0x2, 0x25, 0x3, 0x400, 0x04, 0x80, 0xf0, 0xf6, 0xf, ! 322: 1000, 1000, 0x27, 1, 0x1, 0x2, 0xff }, ! 323: { F5_360_512, 0xdf, 0x2, 0x25, 0x2, 0x200, 0x09, 0x2a, 0x50, 0xf6, 0xf, ! 324: 625, 1000, 0x27, 1, 0x1, 0x2, 0xff }, ! 325: { F5_1Pt2_512, 0xdf, 0x2, 0x25, 0x2, 0x200, 0x0f, 0x1b, 0x54, 0xf6, 0xf, ! 326: 625, 1000, 0x4f, 0, 0x0, 0x2, 0xff }, ! 327: ! 328: { F3_720_512, 0xdf, 0x2, 0x25, 0x2, 0x200, 0x09, 0x2a, 0x50, 0xf6, 0xf, ! 329: 500, 1000, 0x4f, 0, 0x2, 0x2, 0xff }, ! 330: { F3_1Pt44_512, 0xaf, 0x2, 0x25, 0x2, 0x200, 0x12, 0x1b, 0x6c, 0xf6, 0xf, ! 331: 500, 1000, 0x4f, 0, 0x0, 0x2, 0xff }, ! 332: ! 333: { F3_720_512, 0xe1, 0x2, 0x25, 0x2, 0x200, 0x09, 0x2a, 0x50, 0xf6, 0xf, ! 334: 500, 1000, 0x4f, 0, 0x2, 0x2, 0xff }, ! 335: { F3_1Pt44_512, 0xd1, 0x2, 0x25, 0x2, 0x200, 0x12, 0x1b, 0x65, 0xf6, 0xf, ! 336: 500, 1000, 0x4f, 0, 0x0, 0x2, 0xff }, ! 337: { F3_2Pt88_512, 0xa1, 0x2, 0x25, 0x2, 0x200, 0x24, 0x38, 0x53, 0xf6, 0xf, ! 338: 500, 1000, 0x4f, 0, 0x3, 0x2, 0xff } ! 339: }; ! 340: ! 341: ! 342: // ! 343: // Boot Configuration Information ! 344: // ! 345: ! 346: // ! 347: // Define the maximum number of controllers and floppies per controller ! 348: // that this driver will support. ! 349: // ! 350: // The number of floppies per controller is fixed at 4, since the ! 351: // controllers don't have enough bits to select more than that (and ! 352: // actually, many controllers will only support 2). The number of ! 353: // controllers per machine is arbitrary; 3 should be more than enough. ! 354: // ! 355: ! 356: #define MAXIMUM_CONTROLLERS_PER_MACHINE 3 ! 357: #define MAXIMUM_DISKETTES_PER_CONTROLLER 4 ! 358: ! 359: // ! 360: // Floppy register structure. The base address of the controller is ! 361: // passed in by configuration management. Note that this is the 82077 ! 362: // structure, which is a superset of the PD765 structure. Not all of ! 363: // the registers are used. ! 364: // ! 365: ! 366: typedef struct _CONTROLLER { ! 367: UCHAR StatusA; ! 368: UCHAR StatusB; ! 369: UCHAR DriveControl; ! 370: UCHAR Reserved1; ! 371: UCHAR Status; ! 372: UCHAR Fifo; ! 373: UCHAR Reserved2; ! 374: union { ! 375: UCHAR DataRate; ! 376: UCHAR DiskChange; ! 377: } DRDC; ! 378: } CONTROLLER, *PCONTROLLER; ! 379: ! 380: // ! 381: // This structure holds all of the configuration data. It is filled in ! 382: // by FlGetConfigurationInformation(), which gets the information from ! 383: // the configuration manager or the hardware architecture layer (HAL). ! 384: // ! 385: ! 386: typedef struct _CONFIG_CONTROLLER_DATA { ! 387: PHYSICAL_ADDRESS OriginalBaseAddress; ! 388: ULONG ResourcePortType; ! 389: PCONTROLLER ControllerBaseAddress; ! 390: PADAPTER_OBJECT AdapterObject; ! 391: ULONG SpanOfControllerAddress; ! 392: ULONG NumberOfMapRegisters; ! 393: ULONG BusNumber; ! 394: ULONG OriginalIrql; ! 395: ULONG OriginalVector; ! 396: ULONG OriginalDmaChannel; ! 397: LONG ActualControllerNumber; ! 398: INTERFACE_TYPE InterfaceType; ! 399: KINTERRUPT_MODE InterruptMode; ! 400: KAFFINITY ProcessorMask; ! 401: KIRQL ControllerIrql; ! 402: BOOLEAN SaveFloatState; ! 403: BOOLEAN SharableVector; ! 404: BOOLEAN MappedAddress; ! 405: BOOLEAN OkToUseThisController; ! 406: ULONG ControllerVector; ! 407: UCHAR NumberOfDrives; ! 408: UCHAR DriveType[MAXIMUM_DISKETTES_PER_CONTROLLER]; ! 409: DRIVE_MEDIA_CONSTANTS BiosDriveMediaConstants[MAXIMUM_DISKETTES_PER_CONTROLLER]; ! 410: } CONFIG_CONTROLLER_DATA,*PCONFIG_CONTROLLER_DATA; ! 411: ! 412: typedef struct _CONFIG_DATA { ! 413: PULONG FloppyCount; ! 414: PUCHAR NtNamePrefix; ! 415: UCHAR NumberOfControllers; ! 416: CONFIG_CONTROLLER_DATA Controller[MAXIMUM_CONTROLLERS_PER_MACHINE]; ! 417: } CONFIG_DATA; ! 418: ! 419: typedef CONFIG_DATA *PCONFIG_DATA; ! 420: ! 421: ! 422: // ! 423: // Floppy commands. Optional bits allowed. ! 424: // ! 425: ! 426: #define COMMND_READ_DATA 0x06 // Multi-Track, MFM, Skip ! 427: #define COMMND_READ_DELETED_DATA 0x0C // Multi-Track, MFM, Skip ! 428: #define COMMND_READ_TRACK 0x02 // MFM ! 429: #define COMMND_WRITE_DATA 0x05 // Multi-Track, MFM ! 430: #define COMMND_WRITE_DELETED_DATA 0x09 // Multi-Track, MFM ! 431: #define COMMND_READ_ID 0x0A // MFM ! 432: #define COMMND_FORMAT_TRACK 0x0D // MFM ! 433: #define COMMND_RECALIBRATE 0x07 ! 434: #define COMMND_SENSE_INTERRUPT 0x08 ! 435: #define COMMND_SPECIFY 0x03 ! 436: #define COMMND_SENSE_DRIVE 0x04 ! 437: #define COMMND_SEEK 0x0F ! 438: #define COMMND_PERPENDICULAR_MODE 0x12 ! 439: #define COMMND_CONFIGURE 0x13 ! 440: ! 441: // ! 442: // Optional bits used with the commands. ! 443: // ! 444: ! 445: #define COMMND_MULTI_TRACK 0x80 ! 446: #define COMMND_MFM 0x40 ! 447: #define COMMND_SKIP 0x20 ! 448: ! 449: // ! 450: // Parameter fields passed to the CONFIGURE command. ! 451: // ! 452: ! 453: #define COMMND_CONFIGURE_IMPLIED_SEEKS 0x40 ! 454: #define COMMND_CONFIGURE_FIFO_THRESHOLD 0x0F ! 455: #define COMMND_CONFIGURE_DISABLE_FIFO 0x20 ! 456: #define COMMND_CONFIGURE_DISABLE_POLLING 0x10 ! 457: ! 458: // ! 459: // Write Enable bit for PERPENDICULAR MODE command. ! 460: // ! 461: ! 462: #define COMMND_PERPENDICULAR_MODE_OW 0x80 ! 463: ! 464: // ! 465: // The command table is used by FlIssueCommand() to determine how many ! 466: // bytes to get and receive, and whether or not to wait for an interrupt. ! 467: // Some commands have extra bits; COMMAND_MASK takes these off. ! 468: // FirstResultByte indicates whether the command has a result stage ! 469: // or not; if so, it's 1 because the ISR read the 1st byte, and ! 470: // NumberOfResultBytes is 1 less than expected. If not, it's 0 and ! 471: // NumberOfResultBytes is 2, since the ISR will have issued a SENSE ! 472: // INTERRUPT STATUS command. ! 473: // ! 474: ! 475: #define COMMAND_MASK 0x1f ! 476: ! 477: typedef struct _COMMAND_TABLE { ! 478: UCHAR NumberOfParameters; ! 479: UCHAR FirstResultByte; ! 480: UCHAR NumberOfResultBytes; ! 481: BOOLEAN InterruptExpected; ! 482: BOOLEAN AlwaysImplemented; ! 483: } COMMAND_TABLE; ! 484: ! 485: COMMAND_TABLE CommandTable[] = { ! 486: ! 487: { 0, 0, 0, FALSE, FALSE }, // 00 not implemented ! 488: { 0, 0, 0, FALSE, FALSE }, // 01 not implemented ! 489: { 8, 1, 7, TRUE, TRUE }, // 02 read track ! 490: { 2, 0, 0, FALSE, TRUE }, // 03 specify ! 491: { 1, 0, 1, FALSE, TRUE }, // 04 sense drive status ! 492: { 8, 1, 7, TRUE, TRUE }, // 05 write ! 493: { 8, 1, 7, TRUE, TRUE }, // 06 read ! 494: { 1, 0, 2, TRUE, TRUE }, // 07 recalibrate ! 495: { 0, 0, 2, FALSE, TRUE }, // 08 sense interrupt status ! 496: { 0, 0, 0, FALSE, FALSE }, // 09 not implemented ! 497: { 1, 1, 7, TRUE, TRUE }, // 0a read id ! 498: { 0, 0, 0, FALSE, FALSE }, // 0b not implemented ! 499: { 0, 0, 0, FALSE, FALSE }, // 0c not implemented ! 500: { 5, 1, 7, TRUE, TRUE }, // 0d format track ! 501: { 0, 0, 10, FALSE, FALSE }, // 0e dump registers ! 502: { 2, 0, 2, TRUE, TRUE }, // 0f seek ! 503: { 0, 0, 1, FALSE, FALSE }, // 10 version ! 504: { 0, 0, 0, FALSE, FALSE }, // 11 not implemented ! 505: { 1, 0, 0, FALSE, FALSE }, // 12 perpendicular mode ! 506: { 3, 0, 0, FALSE, FALSE }, // 13 configure ! 507: { 0, 0, 0, FALSE, FALSE }, // 14 not implemented ! 508: { 0, 0, 0, FALSE, FALSE }, // 15 not implemented ! 509: { 8, 1, 7, TRUE, FALSE } // 16 verify ! 510: }; ! 511: ! 512: // ! 513: // Bits in the DRIVE_CONTROL register. ! 514: // ! 515: ! 516: #define DRVCTL_RESET 0x00 ! 517: #define DRVCTL_ENABLE_CONTROLLER 0x04 ! 518: #define DRVCTL_ENABLE_DMA_AND_INTERRUPTS 0x08 ! 519: #define DRVCTL_DRIVE_0 0x10 ! 520: #define DRVCTL_DRIVE_1 0x21 ! 521: #define DRVCTL_DRIVE_2 0x42 ! 522: #define DRVCTL_DRIVE_3 0x83 ! 523: #define DRVCTL_DRIVE_MASK 0x03 ! 524: #define DRVCTL_MOTOR_MASK 0xf0 ! 525: ! 526: // ! 527: // Bits in the STATUS register. ! 528: // ! 529: ! 530: #define STATUS_DRIVE_0_BUSY 0x01 ! 531: #define STATUS_DRIVE_1_BUSY 0x02 ! 532: #define STATUS_DRIVE_2_BUSY 0x04 ! 533: #define STATUS_DRIVE_3_BUSY 0x08 ! 534: #define STATUS_CONTROLLER_BUSY 0x10 ! 535: #define STATUS_DMA_UNUSED 0x20 ! 536: #define STATUS_DIRECTION_READ 0x40 ! 537: #define STATUS_DATA_REQUEST 0x80 ! 538: ! 539: #define STATUS_IO_READY_MASK 0xc0 ! 540: #define STATUS_READ_READY 0xc0 ! 541: #define STATUS_WRITE_READY 0x80 ! 542: ! 543: // ! 544: // Bits in the DATA_RATE register. ! 545: // ! 546: ! 547: #define DATART_0125 0x03 ! 548: #define DATART_0250 0x02 ! 549: #define DATART_0300 0x01 ! 550: #define DATART_0500 0x00 ! 551: #define DATART_1000 0x03 ! 552: #define DATART_RESERVED 0xfc ! 553: ! 554: // ! 555: // Bits in the DISK_CHANGE register. ! 556: // ! 557: ! 558: #define DSKCHG_RESERVED 0x7f ! 559: #define DSKCHG_DISKETTE_REMOVED 0x80 ! 560: ! 561: // ! 562: // Bits in status register 0. ! 563: // ! 564: ! 565: #define STREG0_DRIVE_0 0x00 ! 566: #define STREG0_DRIVE_1 0x01 ! 567: #define STREG0_DRIVE_2 0x02 ! 568: #define STREG0_DRIVE_3 0x03 ! 569: #define STREG0_HEAD 0x04 ! 570: #define STREG0_DRIVE_NOT_READY 0x08 ! 571: #define STREG0_DRIVE_FAULT 0x10 ! 572: #define STREG0_SEEK_COMPLETE 0x20 ! 573: #define STREG0_END_NORMAL 0x00 ! 574: #define STREG0_END_ERROR 0x40 ! 575: #define STREG0_END_INVALID_COMMAND 0x80 ! 576: #define STREG0_END_DRIVE_NOT_READY 0xC0 ! 577: #define STREG0_END_MASK 0xC0 ! 578: ! 579: // ! 580: // Bits in status register 1. ! 581: // ! 582: ! 583: #define STREG1_ID_NOT_FOUND 0x01 ! 584: #define STREG1_WRITE_PROTECTED 0x02 ! 585: #define STREG1_SECTOR_NOT_FOUND 0x04 ! 586: #define STREG1_RESERVED1 0x08 ! 587: #define STREG1_DATA_OVERRUN 0x10 ! 588: #define STREG1_CRC_ERROR 0x20 ! 589: #define STREG1_RESERVED2 0x40 ! 590: #define STREG1_END_OF_DISKETTE 0x80 ! 591: ! 592: // ! 593: // Bits in status register 2. ! 594: // ! 595: ! 596: #define STREG2_SUCCESS 0x00 ! 597: #define STREG2_DATA_NOT_FOUND 0x01 ! 598: #define STREG2_BAD_CYLINDER 0x02 ! 599: #define STREG2_SCAN_FAIL 0x04 ! 600: #define STREG2_SCAN_EQUAL 0x08 ! 601: #define STREG2_WRONG_CYLINDER 0x10 ! 602: #define STREG2_CRC_ERROR 0x20 ! 603: #define STREG2_DELETED_DATA 0x40 ! 604: #define STREG2_RESERVED 0x80 ! 605: ! 606: // ! 607: // Bits in status register 3. ! 608: // ! 609: ! 610: #define STREG3_DRIVE_0 0x00 ! 611: #define STREG3_DRIVE_1 0x01 ! 612: #define STREG3_DRIVE_2 0x02 ! 613: #define STREG3_DRIVE_3 0x03 ! 614: #define STREG3_HEAD 0x04 ! 615: #define STREG3_TWO_SIDED 0x08 ! 616: #define STREG3_TRACK_0 0x10 ! 617: #define STREG3_DRIVE_READY 0x20 ! 618: #define STREG3_WRITE_PROTECTED 0x40 ! 619: #define STREG3_DRIVE_FAULT 0x80 ! 620: ! 621: ! 622: // ! 623: // Runtime device structures ! 624: // ! 625: ! 626: // ! 627: // There is one CONTROLLER_DATA allocated per controller (generally one ! 628: // per machine). It holds all information common to all the drives ! 629: // attached to the controller. ! 630: // ! 631: ! 632: typedef struct _CONTROLLER_DATA { ! 633: UCHAR FifoBuffer[10]; ! 634: LARGE_INTEGER InterruptDelay; ! 635: LARGE_INTEGER Minimum10msDelay; ! 636: LIST_ENTRY ListEntry; ! 637: KEVENT InterruptEvent; ! 638: KEVENT AllocateAdapterChannelEvent; ! 639: KDPC LogErrorDpc; ! 640: KSEMAPHORE RequestSemaphore; ! 641: KSPIN_LOCK TimerSpinLock; ! 642: KSPIN_LOCK ListSpinLock; ! 643: PKINTERRUPT InterruptObject; ! 644: PVOID MapRegisterBase; ! 645: PUCHAR IoBuffer; ! 646: PMDL IoBufferMdl; ! 647: PADAPTER_OBJECT AdapterObject; ! 648: PDEVICE_OBJECT CurrentDeviceObject; ! 649: PDRIVER_OBJECT DriverObject; ! 650: PCONTROLLER ControllerAddress; ! 651: PVOID LastDisketteExtension; ! 652: HANDLE ControllerEventHandle; ! 653: PKEVENT ControllerEvent; ! 654: ULONG IoBufferSize; ! 655: ULONG SpanOfControllerAddress; ! 656: ULONG NumberOfMapRegisters; ! 657: ULONG IsrReentered; ! 658: LONG MotorTimer; ! 659: DRIVE_MEDIA_TYPE LastDriveMediaType; ! 660: UCHAR NumberOfDrives; ! 661: UCHAR DriveControlImage; ! 662: UCHAR HardwareFailCount; ! 663: BOOLEAN HardwareFailed; ! 664: BOOLEAN CommandHasResultPhase; ! 665: BOOLEAN ControllerConfigurable; ! 666: BOOLEAN CreatedArtificialDrive; ! 667: BOOLEAN UnloadingDriver; ! 668: BOOLEAN MappedControllerAddress; ! 669: BOOLEAN CurrentInterrupt; ! 670: UCHAR PerpendicularDrives; ! 671: } CONTROLLER_DATA; ! 672: ! 673: typedef CONTROLLER_DATA *PCONTROLLER_DATA; ! 674: ! 675: // ! 676: // There is one DISKETTE_EXTENSION attached to the device object of each ! 677: // floppy drive. Only data directly related to that drive (and the media ! 678: // in it) is stored here; common data is in CONTROLLER_DATA. So the ! 679: // DISKETTE_EXTENSION has a pointer to the CONTROLLER_DATA. ! 680: // ! 681: ! 682: typedef struct _DISKETTE_EXTENSION { ! 683: PDEVICE_OBJECT DeviceObject; ! 684: PCONTROLLER_DATA ControllerData; ! 685: UCHAR DriveType; ! 686: ULONG BytesPerSector; ! 687: ULONG ByteCapacity; ! 688: MEDIA_TYPE MediaType; ! 689: DRIVE_MEDIA_TYPE DriveMediaType; ! 690: UCHAR DeviceUnit; ! 691: UCHAR DriveOnValue; ! 692: BOOLEAN ArtificialVerifyRequired; ! 693: DRIVE_MEDIA_CONSTANTS BiosDriveMediaConstants; ! 694: DRIVE_MEDIA_CONSTANTS DriveMediaConstants; ! 695: } DISKETTE_EXTENSION; ! 696: ! 697: typedef DISKETTE_EXTENSION *PDISKETTE_EXTENSION; ! 698: ! 699: ! 700: // ! 701: // Prototypes of external routines. ! 702: // ! 703: ! 704: LONG ! 705: sprintf( ! 706: CHAR *, ! 707: const CHAR *, ! 708: ... ! 709: ); ! 710: ! 711: // ! 712: // Prototypes of driver routines. ! 713: // ! 714: ! 715: NTSTATUS ! 716: DriverEntry( ! 717: IN PDRIVER_OBJECT DriverObject, ! 718: IN PUNICODE_STRING RegistryPath ! 719: ); ! 720: ! 721: NTSTATUS ! 722: FlConfigCallBack( ! 723: IN PVOID Context, ! 724: IN PUNICODE_STRING PathName, ! 725: IN INTERFACE_TYPE BusType, ! 726: IN ULONG BusNumber, ! 727: IN PKEY_VALUE_FULL_INFORMATION *BusInformation, ! 728: IN CONFIGURATION_TYPE ControllerType, ! 729: IN ULONG ControllerNumber, ! 730: IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation, ! 731: IN CONFIGURATION_TYPE PeripheralType, ! 732: IN ULONG PeripheralNumber, ! 733: IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation ! 734: ); ! 735: ! 736: BOOLEAN ! 737: FlReportResources( ! 738: IN PDRIVER_OBJECT DriverObject, ! 739: IN PCONFIG_DATA ConfigData, ! 740: IN UCHAR ControllerNumber ! 741: ); ! 742: ! 743: NTSTATUS ! 744: FlGetConfigurationInformation( ! 745: OUT PCONFIG_DATA *ConfigData ! 746: ); ! 747: ! 748: NTSTATUS ! 749: FlInitializeController( ! 750: IN PCONFIG_DATA ConfigData, ! 751: IN UCHAR ControllerNumber, ! 752: IN PDRIVER_OBJECT DriverObject ! 753: ); ! 754: ! 755: NTSTATUS ! 756: FlInitializeControllerHardware( ! 757: IN PCONTROLLER_DATA ControllerData, ! 758: IN PDEVICE_OBJECT DeviceObject ! 759: ); ! 760: ! 761: NTSTATUS ! 762: FlInitializeDrive( ! 763: IN PCONFIG_DATA ConfigData, ! 764: IN PCONTROLLER_DATA ControllerData, ! 765: IN UCHAR ControllerNum, ! 766: IN UCHAR DisketteNum, ! 767: IN UCHAR DisketteUnit, ! 768: IN PDRIVER_OBJECT DriverObject ! 769: ); ! 770: ! 771: NTSTATUS ! 772: FloppyDispatchCreateClose( ! 773: IN PDEVICE_OBJECT DeviceObject, ! 774: IN PIRP Irp ! 775: ); ! 776: ! 777: NTSTATUS ! 778: FloppyDispatchDeviceControl( ! 779: IN PDEVICE_OBJECT DeviceObject, ! 780: IN PIRP Irp ! 781: ); ! 782: ! 783: NTSTATUS ! 784: FloppyDispatchReadWrite( ! 785: IN PDEVICE_OBJECT DeviceObject, ! 786: IN PIRP Irp ! 787: ); ! 788: ! 789: BOOLEAN ! 790: FloppyInterruptService( ! 791: IN PKINTERRUPT Interrupt, ! 792: IN PVOID Context ! 793: ); ! 794: ! 795: VOID ! 796: FloppyDeferredProcedure( ! 797: IN PKDPC Dpc, ! 798: IN PVOID DeferredContext, ! 799: IN PVOID SystemArgument1, ! 800: IN PVOID SystemArgument2 ! 801: ); ! 802: ! 803: VOID ! 804: FloppyUnloadDriver( ! 805: IN PDRIVER_OBJECT DriverObject ! 806: ); ! 807: ! 808: VOID ! 809: FloppyMotorOffDpc( ! 810: IN PDEVICE_OBJECT DeviceObject, ! 811: IN PVOID Context ! 812: ); ! 813: ! 814: NTSTATUS ! 815: FlRecalibrateDrive( ! 816: IN PDISKETTE_EXTENSION DisketteExtension ! 817: ); ! 818: ! 819: NTSTATUS ! 820: FlDatarateSpecifyConfigure( ! 821: IN PDISKETTE_EXTENSION DisketteExtension ! 822: ); ! 823: ! 824: NTSTATUS ! 825: FlStartDrive( ! 826: IN OUT PDISKETTE_EXTENSION DisketteExtension, ! 827: IN BOOLEAN WriteOperation, ! 828: IN BOOLEAN SetUpMedia, ! 829: IN BOOLEAN IgnoreChange ! 830: ); ! 831: ! 832: VOID ! 833: FlFinishOperation( ! 834: IN OUT PIRP Irp, ! 835: IN PDISKETTE_EXTENSION DisketteExtension ! 836: ); ! 837: ! 838: NTSTATUS ! 839: FlDetermineMediaType( ! 840: IN OUT PDISKETTE_EXTENSION DisketteExtension ! 841: ); ! 842: ! 843: VOID ! 844: FloppyThread( ! 845: IN PVOID Context ! 846: ); ! 847: ! 848: IO_ALLOCATION_ACTION ! 849: FloppyAllocateAdapterChannel( ! 850: IN PDEVICE_OBJECT DeviceObject, ! 851: IN PIRP Irp, ! 852: IN PVOID MapRegisterBase, ! 853: IN PVOID Context ! 854: ); ! 855: ! 856: NTSTATUS ! 857: FlReadWrite( ! 858: IN OUT PDISKETTE_EXTENSION DisketteExtension, ! 859: IN OUT PIRP Irp ! 860: ); ! 861: ! 862: NTSTATUS ! 863: FlFormat( ! 864: IN PDISKETTE_EXTENSION DisketteExtension, ! 865: IN PIRP Irp ! 866: ); ! 867: ! 868: NTSTATUS ! 869: FlSendByte( ! 870: IN UCHAR ByteToSend, ! 871: IN PCONTROLLER_DATA ControllerData ! 872: ); ! 873: ! 874: NTSTATUS ! 875: FlGetByte( ! 876: OUT PUCHAR ByteToGet, ! 877: IN PCONTROLLER_DATA ControllerData ! 878: ); ! 879: ! 880: NTSTATUS ! 881: FlIssueCommand( ! 882: IN UCHAR Command, ! 883: IN OUT PDISKETTE_EXTENSION DisketteExtension ! 884: ); ! 885: ! 886: BOOLEAN ! 887: FlCheckFormatParameters( ! 888: IN PDISKETTE_EXTENSION DisketteExtension, ! 889: IN PFORMAT_PARAMETERS Fp ! 890: ); ! 891: ! 892: PCONTROLLER ! 893: FlGetControllerBase( ! 894: IN INTERFACE_TYPE BusType, ! 895: IN ULONG BusNumber, ! 896: PHYSICAL_ADDRESS IoAddress, ! 897: ULONG NumberOfBytes, ! 898: BOOLEAN InIoSpace, ! 899: PBOOLEAN MappedAddress ! 900: ); ! 901: ! 902: VOID ! 903: FlLogErrorDpc( ! 904: IN PKDPC Dpc, ! 905: IN PVOID DeferredContext, ! 906: IN PVOID SystemContext1, ! 907: IN PVOID SystemContext2 ! 908: );
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.