|
|
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.