ReactOS 0.4.15-dev-7788-g1ad9096
hardware.c
Go to the documentation of this file.
1/*
2 * ReactOS Floppy Driver
3 * Copyright (C) 2004, Vizzini (vizzini@plasmic.com)
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * PROJECT: ReactOS Floppy Driver
20 * FILE: hardware.c
21 * PURPOSE: FDC Hardware control routines
22 * PROGRAMMER: Vizzini (vizzini@plasmic.com)
23 * REVISIONS:
24 * 15-Feb-2004 vizzini - Created
25 * NOTES:
26 * - Many of these functions are based directly on information from the
27 * Intel datasheet for their enhanced floppy controller. Send_Byte and
28 * Get_Byte are direct C implementations of their flowcharts, and the
29 * read/write routine and others are loose adaptations of their charts.
30 * - These routines are generally designed to be small, atomic operations. They
31 * do not wait for interrupts, deal with DMA, or do any other Windows-
32 * specific things, unless they have to.
33 * - If you compare this to Microsoft samples or to the old ReactOS driver,
34 * or even to the linux driver, you will notice a big difference: we use
35 * a system thread to drain the queue. This is because it's illegal to block
36 * in a dispatch routine, unless you're a top-level driver (which we absolutely
37 * are not). One big reason is that we may be called at raised IRQL, at which
38 * it's illegal to block. The floppy controller is a *dumb* piece of hardware,
39 * too - it is slow and difficult to deal with. The solution is to do all
40 * of the blocking and servicing of the controller in a dedicated worker
41 * thread.
42 * - Some information taken from Intel 82077AA data sheet (order #290166-007)
43 *
44 * TODO: ATM the constants defined in hardware.h *might* be shifted to line up
45 * with the bit position in the register, or they *might not*. This should
46 * all be converted to standardize on absolute values or shifts.
47 * I prefer bit fields, but they break endianness.
48 */
49
50#include "precomp.h"
51
52#include <debug.h>
53
54/*
55 * Hardware Support Routines
56 */
57
58static BOOLEAN NTAPI
60/*
61 * FUNCTION: Determine of the controller is ready to accept a byte on the FIFO
62 * ARGUMENTS:
63 * ControllerInfo: Info structure for the FDC we're testing
64 * RETURNS:
65 * TRUE if the controller can accept a byte right now
66 * FALSE otherwise
67 * NOTES:
68 * - it is necessary to check both that the FIFO is set to "outbound"
69 * and that the "ready for i/o" bit is set.
70 */
71{
73
74 if(Status & MSR_IO_DIRECTION) /* 0 for out */
75 return FALSE;
76
78 return FALSE;
79
80 return TRUE;
81}
82
83
84static BOOLEAN NTAPI
86/*
87 * FUNCTION: Determine of the controller is ready to read a byte on the FIFO
88 * ARGUMENTS:
89 * ControllerInfo: Info structure for the FDC we're testing
90 * RETURNS:
91 * TRUE if the controller can read a byte right now
92 * FALSE otherwise
93 * NOTES:
94 * - it is necessary to check both that the FIFO is set to "inbound"
95 * and that the "ready for i/o" bit is set.
96 */
97{
99
100 if(!(Status & MSR_IO_DIRECTION)) /* Read = 1 */
101 return FALSE;
102
104 return FALSE;
105
106 return TRUE;
107}
108
109
110static NTSTATUS NTAPI
112/*
113 * FUNCTION: Send a byte from the host to the controller's FIFO
114 * ARGUMENTS:
115 * ControllerInfo: Info structure for the controller we're writing to
116 * Offset: Offset over the controller's base address that we're writing to
117 * Byte: Byte to write to the bus
118 * RETURNS:
119 * STATUS_SUCCESS if the byte was written successfully
120 * STATUS_UNSUCCESSFUL if not
121 * NOTES:
122 * - Function designed after flowchart in intel datasheet
123 * - 250us max delay. Note that this is exactly 5 times longer
124 * than Microsoft recommends stalling the processor
125 * - PAGED_CODE, because we spin for more than the Microsoft-recommended
126 * maximum.
127 * - This function is necessary because sometimes the FIFO reacts slowly
128 * and isn't yet ready to read or write the next byte
129 */
130{
131 int i;
132
133 PAGED_CODE();
134
135 for(i = 0; i < 5; i++)
136 {
137 if(ReadyForWrite(ControllerInfo))
138 break;
139
141 }
142
143 if (i < 5)
144 {
145 WRITE_PORT_UCHAR(ControllerInfo->BaseAddress + FIFO, Byte);
146 return STATUS_SUCCESS;
147 }
148 else
149 {
150 INFO_(FLOPPY, "Send_Byte: timed out trying to write\n");
151 HwDumpRegisters(ControllerInfo);
152 return STATUS_UNSUCCESSFUL;
153 }
154}
155
156
157static NTSTATUS NTAPI
159/*
160 * FUNCTION: Read a byte from the controller to the host
161 * ARGUMENTS:
162 * ControllerInfo: Info structure for the controller we're reading from
163 * Offset: Offset over the controller's base address that we're reading from
164 * Byte: Byte to read from the bus
165 * RETURNS:
166 * STATUS_SUCCESS if the byte was read successfully
167 * STATUS_UNSUCCESSFUL if not
168 * NOTES:
169 * - Function designed after flowchart in intel datasheet
170 * - 250us max delay. Note that this is exactly 5 times longer
171 * than Microsoft recommends stalling the processor
172 * - Remember that we can be interrupted here, so this might
173 * take much more wall clock time than 250us
174 * - PAGED_CODE because we spin for longer than Microsoft recommends
175 */
176{
177 int i;
178
179 PAGED_CODE();
180
181 for(i = 0; i < 5; i++)
182 {
183 if(ReadyForRead(ControllerInfo))
184 break;
185
187 }
188
189 if (i < 5)
190 {
191 *Byte = READ_PORT_UCHAR(ControllerInfo->BaseAddress + FIFO);
192 return STATUS_SUCCESS;
193 }
194 else
195 {
196 INFO_(FLOPPY, "Get_Byte: timed out trying to write\n");
197 HwDumpRegisters(ControllerInfo);
198 return STATUS_UNSUCCESSFUL;
199 }
200}
201
202
204HwSetDataRate(PCONTROLLER_INFO ControllerInfo, UCHAR DataRate)
205/*
206 * FUNCTION: Set the data rte on a controller
207 * ARGUMENTS:
208 * ControllerInfo: Controller whose rate is being set
209 * DataRate: Data rate code to set the controller to
210 * RETURNS:
211 * STATUS_SUCCESS
212 */
213{
214 TRACE_(FLOPPY, "HwSetDataRate called; writing rate code 0x%x to offset 0x%x\n", DataRate, DATA_RATE_SELECT_REGISTER);
215
216 WRITE_PORT_UCHAR(ControllerInfo->BaseAddress + DATA_RATE_SELECT_REGISTER, DataRate);
217
218 return STATUS_SUCCESS;
219}
220
221
224/*
225 * FUNCTION: Turn off all motors
226 * ARGUMENTS:
227 * DriveInfo: drive to turn off
228 * RETURNS:
229 * STATUS_SUCCESS if the motor is successfully turned off
230 * NOTES:
231 * - Don't call this routine directly unless you've thought about it
232 * and read the source to StartMotor() and StopMotor().
233 * - Called at DISPATCH_LEVEL
234 */
235{
236 TRACE_(FLOPPY, "HwTurnOffMotor: writing byte 0x%x to offset 0x%x\n", DOR_FDC_ENABLE|DOR_DMA_IO_INTERFACE_ENABLE, DIGITAL_OUTPUT_REGISTER);
237
239
240 return STATUS_SUCCESS;
241}
242
243
246/*
247 * FUNCTION: Turn on the motor on the selected drive
248 * ARGUMENTS:
249 * DriveInfo: drive to turn on
250 * RETURNS:
251 * STATUS_SUCCESS if the motor is successfully turned on
252 * STATUS_UNSUCCESSFUL otherwise
253 * NOTES:
254 * - Doesn't interrupt
255 * - Currently cannot fail
256 */
257{
258 PCONTROLLER_INFO ControllerInfo = DriveInfo->ControllerInfo;
259 UCHAR Unit = DriveInfo->UnitNumber;
261
262 PAGED_CODE();
263
264 /* turn on motor */
265 Buffer = Unit;
266
269
270 if(Unit == 0)
272 else if (Unit == 1)
274 else if (Unit == 2)
276 else if (Unit == 3)
278
279 TRACE_(FLOPPY, "HwTurnOnMotor: writing byte 0x%x to offset 0x%x\n", Buffer, DIGITAL_OUTPUT_REGISTER);
281
282 return STATUS_SUCCESS;
283}
284
285
288/*
289 * FUNCTION: Start a sense status command
290 * ARGUMENTS:
291 * DriveInfo: Drive to inquire about
292 * RETURNS:
293 * STATUS_SUCCESS if the command is successfully queued to the controller
294 * STATUS_UNSUCCESSFUL if not
295 * NOTES:
296 * - Generates an interrupt
297 * - hard-wired to head 0
298 */
299{
300 UCHAR Buffer[2];
301 int i;
302
303 PAGED_CODE();
304
305 TRACE_(FLOPPY, "HwSenseDriveStatus called\n");
306
308 Buffer[1] = DriveInfo->UnitNumber; /* hard-wired to head 0 for now */
309
310 for(i = 0; i < 2; i++)
311 if(Send_Byte(DriveInfo->ControllerInfo, Buffer[i]) != STATUS_SUCCESS)
312 {
313 WARN_(FLOPPY, "HwSenseDriveStatus: failed to write FIFO\n");
314 return STATUS_UNSUCCESSFUL;
315 }
316
317 return STATUS_SUCCESS;
318}
319
320
324 UCHAR Unit,
325 UCHAR Cylinder,
326 UCHAR Head,
327 UCHAR Sector,
328 UCHAR BytesPerSector,
329 UCHAR EndOfTrack,
330 UCHAR Gap3Length,
332/*
333 * FUNCTION: Read or write data to the drive
334 * ARGUMENTS:
335 * ControllerInfo: controller to target the read/write request to
336 * Read: TRUE if the device should be read; FALSE if written
337 * Unit: Drive number to target
338 * Cylinder: cylinder to start the read on
339 * Head: head to start the read on
340 * Sector: sector to start the read on (1-based!)
341 * BytesPerSector: sector size constant (hardware.h)
342 * EndOfTrack: Marks the last sector number to read/write on the track
343 * Gap3Length: Gap length for the operation
344 * DataLength: Bytes to read, *unless* BytesPerSector is specified
345 * RETURNS:
346 * STATUS_SUCCESS if the operation was successfully queued to the controller
347 * STATUS_UNSUCCESSFUL otherwise
348 * NOTES:
349 * - Generates an interrupt
350 */
351{
352 UCHAR Buffer[9];
353 int i;
354
355 PAGED_CODE();
356
357 /* Shouldn't be using DataLength in this driver */
358 ASSERT(DataLength == 0xff);
359
360 /* Build the command to send */
361 if(Read)
363 else
365
367
368 Buffer[1] = (Head << COMMAND_HEAD_NUMBER_SHIFT) | Unit;
369 Buffer[2] = Cylinder;
370 Buffer[3] = Head;
371 Buffer[4] = Sector;
372 Buffer[5] = BytesPerSector;
373 Buffer[6] = EndOfTrack;
374 Buffer[7] = Gap3Length;
375 Buffer[8] = DataLength;
376
377 /* Send the command */
378 for(i = 0; i < 9; i++)
379 {
380 INFO_(FLOPPY, "HwReadWriteData: Sending a command byte to the FIFO: 0x%x\n", Buffer[i]);
381
382 if(Send_Byte(ControllerInfo, Buffer[i]) != STATUS_SUCCESS)
383 {
384 WARN_(FLOPPY, "HwReadWriteData: Unable to write to the FIFO\n");
385 return STATUS_UNSUCCESSFUL;
386 }
387 }
388
389 return STATUS_SUCCESS;
390}
391
392
395/*
396 * FUNCTION: Get the result of a recalibrate command
397 * ARGUMENTS:
398 * ControllerInfo: controller to query
399 * RETURNS:
400 * STATUS_SUCCESS if the recalibratewas a success
401 * STATUS_UNSUCCESSFUL otherwise
402 * NOTES:
403 * - This function tests the error conditions itself, and boils the
404 * whole thing down to a single SUCCESS or FAILURE result
405 * - Called post-interrupt; does not interrupt
406 * TODO
407 * - perhaps handle more status
408 */
409{
410 UCHAR Buffer[2];
411 int i;
412
413 PAGED_CODE();
414
416 {
417 WARN_(FLOPPY, "HwRecalibrateResult: Unable to write the controller\n");
418 return STATUS_UNSUCCESSFUL;
419 }
420
421 for(i = 0; i < 2; i++)
422 if(Get_Byte(ControllerInfo, &Buffer[i]) != STATUS_SUCCESS)
423 {
424 WARN_(FLOPPY, "HwRecalibrateResult: unable to read FIFO\n");
425 return STATUS_UNSUCCESSFUL;
426 }
427
428 /* Validate that it did what we told it to */
429 INFO_(FLOPPY, "HwRecalibrateResult results: ST0: 0x%x PCN: 0x%x\n", Buffer[0], Buffer[1]);
430
431 /*
432 * Buffer[0] = ST0
433 * Buffer[1] = PCN
434 */
435
436 /* Is the PCN 0? */
437 if(Buffer[1] != 0)
438 {
439 WARN_(FLOPPY, "HwRecalibrateResult: PCN not 0\n");
440 return STATUS_UNSUCCESSFUL;
441 }
442
443 /* test seek complete */
445 {
446 WARN_(FLOPPY, "HwRecalibrateResult: Failed to complete the seek\n");
447 return STATUS_UNSUCCESSFUL;
448 }
449
450 /* Is the equipment check flag set? Could be no disk in drive... */
452 {
453 WARN_(FLOPPY, "HwRecalibrateResult: Seeked to track 0 successfully, but EC is set; returning failure\n");
454 return STATUS_UNSUCCESSFUL;
455 }
456
457 return STATUS_SUCCESS;
458}
459
460
463/*
464 * FUNCTION: Get the result of a read or write from the controller
465 * ARGUMENTS:
466 * ControllerInfo: controller to query
467 * RETURNS:
468 * STATUS_SUCCESS if the read/write was a success
469 * STATUS_UNSUCCESSFUL otherwise
470 * NOTES:
471 * - This function tests the error conditions itself, and boils the
472 * whole thing down to a single SUCCESS or FAILURE result
473 * - Called post-interrupt; does not interrupt
474 * TODO:
475 * - perhaps handle more status
476 */
477{
478 UCHAR Buffer[7];
479 int i;
480
481 PAGED_CODE();
482
483 for(i = 0; i < 7; i++)
484 if(Get_Byte(ControllerInfo, &Buffer[i]) != STATUS_SUCCESS)
485 {
486 WARN_(FLOPPY, "HwReadWriteResult: unable to read fifo\n");
487 return STATUS_UNSUCCESSFUL;
488 }
489
490 /* Validate that it did what we told it to */
491 INFO_(FLOPPY, "HwReadWriteResult results: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", Buffer[0], Buffer[1], Buffer[2], Buffer[3],
492 Buffer[4], Buffer[5], Buffer[6]);
493
494 /* Last command successful? */
496 return STATUS_UNSUCCESSFUL;
497
498 return STATUS_SUCCESS;
499}
500
501
504/*
505 * FUNCTION: Start a recalibration of a drive
506 * ARGUMENTS:
507 * DriveInfo: Drive to recalibrate
508 * RETURNS:
509 * STATUS_SUCCESS if the command was successfully queued to the controller
510 * STATUS_UNSUCCESSFUL otherwise
511 * NOTES:
512 * - Generates an interrupt
513 */
514{
515 PCONTROLLER_INFO ControllerInfo = DriveInfo->ControllerInfo;
516 UCHAR Unit = DriveInfo->UnitNumber;
517 UCHAR Buffer[2];
518 int i;
519
520 TRACE_(FLOPPY, "HwRecalibrate called\n");
521
522 PAGED_CODE();
523
525 Buffer[1] = Unit;
526
527 for(i = 0; i < 2; i++)
528 if(Send_Byte(ControllerInfo, Buffer[i]) != STATUS_SUCCESS)
529 {
530 WARN_(FLOPPY, "HwRecalibrate: unable to write FIFO\n");
531 return STATUS_UNSUCCESSFUL;
532 }
533
534 return STATUS_SUCCESS;
535}
536
537
540/*
541 * FUNCTION: Send a sense interrupt status command to a controller
542 * ARGUMENTS:
543 * ControllerInfo: controller to queue the command to
544 * RETURNS:
545 * STATUS_SUCCESS if the command is queued successfully
546 * STATUS_UNSUCCESSFUL if not
547 */
548{
549 UCHAR Buffer[2];
550 int i;
551
552 PAGED_CODE();
553
555 {
556 WARN_(FLOPPY, "HwSenseInterruptStatus: failed to write controller\n");
557 return STATUS_UNSUCCESSFUL;
558 }
559
560 for(i = 0; i < 2; i++)
561 {
562 if(Get_Byte(ControllerInfo, &Buffer[i]) != STATUS_SUCCESS)
563 {
564 WARN_(FLOPPY, "HwSenseInterruptStatus: failed to read controller\n");
565 return STATUS_UNSUCCESSFUL;
566 }
567 }
568
569 INFO_(FLOPPY, "HwSenseInterruptStatus returned 0x%x 0x%x\n", Buffer[0], Buffer[1]);
570
571 return STATUS_SUCCESS;
572}
573
574
576HwReadId(PDRIVE_INFO DriveInfo, UCHAR Head)
577/*
578 * FUNCTION: Issue a read id command to the drive
579 * ARGUMENTS:
580 * DriveInfo: Drive to read id from
581 * Head: Head to read the ID from
582 * RETURNS:
583 * STATUS_SUCCESS if the command is queued
584 * STATUS_UNSUCCESSFUL otherwise
585 * NOTES:
586 * - Generates an interrupt
587 */
588{
589 UCHAR Buffer[2];
590 int i;
591
592 TRACE_(FLOPPY, "HwReadId called\n");
593
594 PAGED_CODE();
595
597 Buffer[1] = (Head << COMMAND_HEAD_NUMBER_SHIFT) | DriveInfo->UnitNumber;
598
599 for(i = 0; i < 2; i++)
600 if(Send_Byte(DriveInfo->ControllerInfo, Buffer[i]) != STATUS_SUCCESS)
601 {
602 WARN_(FLOPPY, "HwReadId: unable to send bytes to fifo\n");
603 return STATUS_UNSUCCESSFUL;
604 }
605
606 return STATUS_SUCCESS;
607}
608
609
612 UCHAR Unit,
613 UCHAR Head,
614 UCHAR BytesPerSector,
616 UCHAR Gap3Length,
617 UCHAR FillerPattern)
618/*
619 * FUNCTION: Format a track
620 * ARGUMENTS:
621 * ControllerInfo: controller to target with the request
622 * Unit: drive to format on
623 * Head: head to format on
624 * BytesPerSector: constant from hardware.h to select density
625 * SectorsPerTrack: sectors per track
626 * Gap3Length: gap length to use during format
627 * FillerPattern: pattern to write into the data portion of sectors
628 * RETURNS:
629 * STATUS_SUCCESS if the command is successfully queued
630 * STATUS_UNSUCCESSFUL otherwise
631 */
632{
633 UCHAR Buffer[6];
634 int i;
635
636 TRACE_(FLOPPY, "HwFormatTrack called\n");
637
638 PAGED_CODE();
639
641 Buffer[1] = (Head << COMMAND_HEAD_NUMBER_SHIFT) | Unit;
642 Buffer[2] = BytesPerSector;
644 Buffer[4] = Gap3Length;
645 Buffer[5] = FillerPattern;
646
647 for(i = 0; i < 6; i++)
648 if(Send_Byte(ControllerInfo, Buffer[i]) != STATUS_SUCCESS)
649 {
650 WARN_(FLOPPY, "HwFormatTrack: unable to send bytes to floppy\n");
651 return STATUS_UNSUCCESSFUL;
652 }
653
654 return STATUS_SUCCESS;
655}
656
657
659HwSeek(PDRIVE_INFO DriveInfo, UCHAR Cylinder)
660/*
661 * FUNCTION: Seek the heads to a particular cylinder
662 * ARGUMENTS:
663 * DriveInfo: Drive to seek
664 * Cylinder: cylinder to move to
665 * RETURNS:
666 * STATUS_SUCCESS if the command is successfully sent
667 * STATUS_UNSUCCESSFUL otherwise
668 * NOTES:
669 * - Generates an interrupt
670 */
671{
672 LARGE_INTEGER Delay;
673 UCHAR Buffer[3];
674 int i;
675
676 TRACE_(FLOPPY, "HwSeek called for cyl 0x%x\n", Cylinder);
677
678 PAGED_CODE();
679
680 Buffer[0] = COMMAND_SEEK;
681 Buffer[1] = DriveInfo->UnitNumber;
682 Buffer[2] = Cylinder;
683
684 for(i = 0; i < 3; i++)
685 if(Send_Byte(DriveInfo->ControllerInfo, Buffer[i]) != STATUS_SUCCESS)
686 {
687 WARN_(FLOPPY, "HwSeek: failed to write fifo\n");
688 return STATUS_UNSUCCESSFUL;
689 }
690
691 /* Wait for the head to settle */
692 Delay.QuadPart = 10 * 1000;
693 Delay.QuadPart *= -1;
694 Delay.QuadPart *= DriveInfo->FloppyDeviceData.HeadSettleTime;
695
697
698 return STATUS_SUCCESS;
699}
700
701
704 BOOLEAN EIS,
705 BOOLEAN EFIFO,
706 BOOLEAN POLL,
707 UCHAR FIFOTHR,
708 UCHAR PRETRK)
709/*
710 * FUNCTION: Sends configuration to the drive
711 * ARGUMENTS:
712 * ControllerInfo: controller to target with the request
713 * EIS: Enable implied seek
714 * EFIFO: Enable advanced fifo
715 * POLL: Enable polling
716 * FIFOTHR: fifo threshold
717 * PRETRK: precomp (see intel datasheet)
718 * RETURNS:
719 * STATUS_SUCCESS if the command is successfully sent
720 * STATUS_UNSUCCESSFUL otherwise
721 * NOTES:
722 * - No interrupt
723 */
724{
725 UCHAR Buffer[4];
726 int i;
727
728 TRACE_(FLOPPY, "HwConfigure called\n");
729
730 PAGED_CODE();
731
733 Buffer[1] = 0;
734 Buffer[2] = (EIS * CONFIGURE_EIS) + (EFIFO * CONFIGURE_EFIFO) + (POLL * CONFIGURE_POLL) + (FIFOTHR);
735 Buffer[3] = PRETRK;
736
737 for(i = 0; i < 4; i++)
738 if(Send_Byte(ControllerInfo, Buffer[i]) != STATUS_SUCCESS)
739 {
740 WARN_(FLOPPY, "HwConfigure: failed to write the fifo\n");
741 return STATUS_UNSUCCESSFUL;
742 }
743
744 return STATUS_SUCCESS;
745}
746
747
750/*
751 * FUNCTION: Gets the version of the controller
752 * ARGUMENTS:
753 * ControllerInfo: controller to target with the request
754 * ConfigValue: Configuration value to send to the drive (see header)
755 * RETURNS:
756 * Version number returned by the command, or
757 * 0 on failure
758 * NOTE:
759 * - This command doesn't interrupt, so we go right to reading after
760 * we issue the command
761 */
762{
764
765 PAGED_CODE();
766
767 if(Send_Byte(ControllerInfo, COMMAND_VERSION) != STATUS_SUCCESS)
768 {
769 WARN_(FLOPPY, "HwGetVersion: unable to write fifo\n");
770 return STATUS_UNSUCCESSFUL;
771 }
772
773 if(Get_Byte(ControllerInfo, &Buffer) != STATUS_SUCCESS)
774 {
775 WARN_(FLOPPY, "HwGetVersion: unable to write fifo\n");
776 return STATUS_UNSUCCESSFUL;
777 }
778
779 INFO_(FLOPPY, "HwGetVersion returning version 0x%x\n", Buffer);
780
781 return Buffer;
782}
783
785HwDiskChanged(PDRIVE_INFO DriveInfo, PBOOLEAN DiskChanged)
786/*
787 * FUNCTION: Detect whether the hardware has sensed a disk change
788 * ARGUMENTS:
789 * DriveInfo: pointer to the drive that we are to check
790 * DiskChanged: boolean that is set with whether or not the controller thinks there has been a disk change
791 * RETURNS:
792 * STATUS_SUCCESS if the drive is successfully queried
793 * NOTES:
794 * - Does not interrupt.
795 * - Guessing a bit at the Model30 stuff
796 */
797{
799 PCONTROLLER_INFO ControllerInfo = (PCONTROLLER_INFO) DriveInfo->ControllerInfo;
800
802
803 TRACE_(FLOPPY, "HwDiskChanged: read 0x%x from DIR\n", Buffer);
804
805 if(ControllerInfo->Model30)
806 {
808 {
809 INFO_(FLOPPY, "HdDiskChanged - Model30 - returning TRUE\n");
810 *DiskChanged = TRUE;
811 }
812 else
813 {
814 INFO_(FLOPPY, "HdDiskChanged - Model30 - returning FALSE\n");
815 *DiskChanged = FALSE;
816 }
817 }
818 else
819 {
821 {
822 INFO_(FLOPPY, "HdDiskChanged - PS2 - returning TRUE\n");
823 *DiskChanged = TRUE;
824 }
825 else
826 {
827 INFO_(FLOPPY, "HdDiskChanged - PS2 - returning FALSE\n");
828 *DiskChanged = FALSE;
829 }
830 }
831
832 return STATUS_SUCCESS;
833}
834
837/*
838 * FUNCTION: Get the result of a sense drive status command
839 * ARGUMENTS:
840 * ControllerInfo: controller to query
841 * Status: Status from the drive sense command
842 * RETURNS:
843 * STATUS_SUCCESS if we can successfully read the status
844 * STATUS_UNSUCCESSFUL otherwise
845 * NOTES:
846 * - Called post-interrupt; does not interrupt
847 */
848{
849 PAGED_CODE();
850
851 if(Get_Byte(ControllerInfo, Status) != STATUS_SUCCESS)
852 {
853 WARN_(FLOPPY, "HwSenseDriveStatus: unable to read fifo\n");
854 return STATUS_UNSUCCESSFUL;
855 }
856
857 TRACE_(FLOPPY, "HwSenseDriveStatusResult: ST3: 0x%x\n", *Status);
858
859 return STATUS_SUCCESS;
860}
861
862
865 PUCHAR CurCylinder,
866 PUCHAR CurHead)
867/*
868 * FUNCTION: Get the result of a read id command
869 * ARGUMENTS:
870 * ControllerInfo: controller to query
871 * CurCylinder: Returns the cylinder that we're at
872 * CurHead: Returns the head that we're at
873 * RETURNS:
874 * STATUS_SUCCESS if the read id was a success
875 * STATUS_UNSUCCESSFUL otherwise
876 * NOTES:
877 * - This function tests the error conditions itself, and boils the
878 * whole thing down to a single SUCCESS or FAILURE result
879 * - Called post-interrupt; does not interrupt
880 * TODO
881 * - perhaps handle more status
882 */
883{
884 UCHAR Buffer[7] = {0,0,0,0,0,0,0};
885 int i;
886
887 PAGED_CODE();
888
889 for(i = 0; i < 7; i++)
890 if(Get_Byte(ControllerInfo, &Buffer[i]) != STATUS_SUCCESS)
891 {
892 WARN_(FLOPPY, "ReadIdResult(): can't read from the controller\n");
893 return STATUS_UNSUCCESSFUL;
894 }
895
896 /* Validate that it did what we told it to */
897 INFO_(FLOPPY, "ReadId results: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", Buffer[0], Buffer[1], Buffer[2], Buffer[3],
898 Buffer[4], Buffer[5], Buffer[6]);
899
900 /* Last command successful? */
902 {
903 WARN_(FLOPPY, "ReadId didn't return last command success\n");
904 return STATUS_UNSUCCESSFUL;
905 }
906
907 /* ID mark found? */
909 {
910 WARN_(FLOPPY, "ReadId didn't find an address mark\n");
911 return STATUS_UNSUCCESSFUL;
912 }
913
914 if(CurCylinder)
915 *CurCylinder = Buffer[3];
916
917 if(CurHead)
918 *CurHead = Buffer[4];
919
920 return STATUS_SUCCESS;
921}
922
923
926 UCHAR HeadLoadTime,
927 UCHAR HeadUnloadTime,
928 UCHAR StepRateTime,
929 BOOLEAN NonDma)
930/*
931 * FUNCTION: Set up timing and DMA mode for the controller
932 * ARGUMENTS:
933 * ControllerInfo: Controller to set up
934 * HeadLoadTime: Head load time (see data sheet for details)
935 * HeadUnloadTime: Head unload time
936 * StepRateTime: Step rate time
937 * NonDma: TRUE to disable DMA mode
938 * RETURNS:
939 * STATUS_SUCCESS if the controller is successfully programmed
940 * STATUS_UNSUCCESSFUL if not
941 * NOTES:
942 * - Does not interrupt
943 *
944 * TODO: Figure out timings
945 */
946{
947 UCHAR Buffer[3];
948 int i;
949
951 /*
952 Buffer[1] = (StepRateTime << 4) + HeadUnloadTime;
953 Buffer[2] = (HeadLoadTime << 1) + (NonDma ? 1 : 0);
954 */
955 Buffer[1] = 0xdf;
956 Buffer[2] = 0x2;
957
958 //INFO_(FLOPPY, "HwSpecify: sending 0x%x 0x%x 0x%x to FIFO\n", Buffer[0], Buffer[1], Buffer[2]);
959 WARN_(FLOPPY, "HWSPECIFY: FIXME - sending 0x3 0xd1 0x2 to FIFO\n");
960
961 for(i = 0; i < 3; i++)
962 if(Send_Byte(ControllerInfo, Buffer[i]) != STATUS_SUCCESS)
963 {
964 WARN_(FLOPPY, "HwSpecify: unable to write to controller\n");
965 return STATUS_UNSUCCESSFUL;
966 }
967
968 return STATUS_SUCCESS;
969}
970
971
974/*
975 * FUNCTION: Reset the controller
976 * ARGUMENTS:
977 * ControllerInfo: controller to reset
978 * RETURNS:
979 * STATUS_SUCCESS in all cases
980 * NOTES:
981 * - Generates an interrupt that must be serviced four times (one per drive)
982 */
983{
984 TRACE_(FLOPPY, "HwReset called\n");
985
986 /* Write the reset bit in the DRSR */
988
989 /* Check for the reset bit in the DOR and set it if necessary (see Intel doc) */
991 {
992 HwDumpRegisters(ControllerInfo);
993 INFO_(FLOPPY, "HwReset: Setting Enable bit\n");
995 HwDumpRegisters(ControllerInfo);
996
998 {
999 WARN_(FLOPPY, "HwReset: failed to set the DOR enable bit!\n");
1000 HwDumpRegisters(ControllerInfo);
1001 return STATUS_UNSUCCESSFUL;
1002 }
1003 }
1004
1005 return STATUS_SUCCESS;
1006}
1007
1008
1011/*
1012 * FUNCTION: Power down a controller
1013 * ARGUMENTS:
1014 * ControllerInfo: Controller to power down
1015 * RETURNS:
1016 * STATUS_SUCCESS
1017 * NOTES:
1018 * - Wake up with a hardware reset
1019 */
1020{
1021 TRACE_(FLOPPY, "HwPowerOff called on controller 0x%p\n", ControllerInfo);
1022
1024
1025 return STATUS_SUCCESS;
1026}
1027
1028VOID NTAPI
1030/*
1031 * FUNCTION: Dump all readable registers from the floppy controller
1032 * ARGUMENTS:
1033 * ControllerInfo: Controller to dump registers from
1034 */
1035{
1036 UNREFERENCED_PARAMETER(ControllerInfo);
1037
1038 INFO_(FLOPPY, "STATUS:\n");
1039 INFO_(FLOPPY, "STATUS_REGISTER_A = 0x%x\n", READ_PORT_UCHAR(ControllerInfo->BaseAddress + STATUS_REGISTER_A));
1040 INFO_(FLOPPY, "STATUS_REGISTER_B = 0x%x\n", READ_PORT_UCHAR(ControllerInfo->BaseAddress + STATUS_REGISTER_B));
1041 INFO_(FLOPPY, "DIGITAL_OUTPUT_REGISTER = 0x%x\n", READ_PORT_UCHAR(ControllerInfo->BaseAddress + DIGITAL_OUTPUT_REGISTER));
1042 INFO_(FLOPPY, "MAIN_STATUS_REGISTER =0x%x\n", READ_PORT_UCHAR(ControllerInfo->BaseAddress + MAIN_STATUS_REGISTER));
1043 INFO_(FLOPPY, "DIGITAL_INPUT_REGISTER = 0x%x\n", READ_PORT_UCHAR(ControllerInfo->BaseAddress + DIGITAL_INPUT_REGISTER));
1044}
#define PAGED_CODE()
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI KeStallExecutionProcessor(IN ULONG MicroSeconds)
Definition: ntoskrnl.c:81
_In_ ULONG _In_opt_ WDFREQUEST _In_opt_ PVOID _In_ size_t _In_ PVOID _In_ size_t _Out_ size_t * DataLength
Definition: cdrom.h:1444
Definition: bufpool.h:45
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define TRACE_(x)
Definition: compat.h:76
unsigned char Byte
Definition: zlib.h:37
struct _CONTROLLER_INFO * PCONTROLLER_INFO
NTSTATUS NTAPI HwReadWriteResult(PCONTROLLER_INFO ControllerInfo)
Definition: hardware.c:462
NTSTATUS NTAPI HwFormatTrack(PCONTROLLER_INFO ControllerInfo, UCHAR Unit, UCHAR Head, UCHAR BytesPerSector, UCHAR SectorsPerTrack, UCHAR Gap3Length, UCHAR FillerPattern)
Definition: hardware.c:611
NTSTATUS NTAPI HwRecalibrateResult(PCONTROLLER_INFO ControllerInfo)
Definition: hardware.c:394
NTSTATUS NTAPI HwTurnOnMotor(PDRIVE_INFO DriveInfo)
Definition: hardware.c:245
NTSTATUS NTAPI HwConfigure(PCONTROLLER_INFO ControllerInfo, BOOLEAN EIS, BOOLEAN EFIFO, BOOLEAN POLL, UCHAR FIFOTHR, UCHAR PRETRK)
Definition: hardware.c:703
NTSTATUS NTAPI HwGetVersion(PCONTROLLER_INFO ControllerInfo)
Definition: hardware.c:749
VOID NTAPI HwDumpRegisters(PCONTROLLER_INFO ControllerInfo)
Definition: hardware.c:1029
static BOOLEAN NTAPI ReadyForRead(PCONTROLLER_INFO ControllerInfo)
Definition: hardware.c:85
NTSTATUS NTAPI HwSeek(PDRIVE_INFO DriveInfo, UCHAR Cylinder)
Definition: hardware.c:659
NTSTATUS NTAPI HwSetDataRate(PCONTROLLER_INFO ControllerInfo, UCHAR DataRate)
Definition: hardware.c:204
NTSTATUS NTAPI HwReset(PCONTROLLER_INFO ControllerInfo)
Definition: hardware.c:973
NTSTATUS NTAPI HwRecalibrate(PDRIVE_INFO DriveInfo)
Definition: hardware.c:503
static BOOLEAN NTAPI ReadyForWrite(PCONTROLLER_INFO ControllerInfo)
Definition: hardware.c:59
NTSTATUS NTAPI HwSpecify(PCONTROLLER_INFO ControllerInfo, UCHAR HeadLoadTime, UCHAR HeadUnloadTime, UCHAR StepRateTime, BOOLEAN NonDma)
Definition: hardware.c:925
NTSTATUS NTAPI HwReadId(PDRIVE_INFO DriveInfo, UCHAR Head)
Definition: hardware.c:576
NTSTATUS NTAPI HwReadWriteData(PCONTROLLER_INFO ControllerInfo, BOOLEAN Read, UCHAR Unit, UCHAR Cylinder, UCHAR Head, UCHAR Sector, UCHAR BytesPerSector, UCHAR EndOfTrack, UCHAR Gap3Length, UCHAR DataLength)
Definition: hardware.c:322
NTSTATUS NTAPI HwSenseInterruptStatus(PCONTROLLER_INFO ControllerInfo)
Definition: hardware.c:539
NTSTATUS NTAPI HwSenseDriveStatusResult(PCONTROLLER_INFO ControllerInfo, PUCHAR Status)
Definition: hardware.c:836
NTSTATUS NTAPI HwDiskChanged(PDRIVE_INFO DriveInfo, PBOOLEAN DiskChanged)
Definition: hardware.c:785
static NTSTATUS NTAPI Send_Byte(PCONTROLLER_INFO ControllerInfo, UCHAR Byte)
Definition: hardware.c:111
NTSTATUS NTAPI HwTurnOffMotor(PCONTROLLER_INFO ControllerInfo)
Definition: hardware.c:223
NTSTATUS NTAPI HwPowerOff(PCONTROLLER_INFO ControllerInfo)
Definition: hardware.c:1010
NTSTATUS NTAPI HwSenseDriveStatus(PDRIVE_INFO DriveInfo)
Definition: hardware.c:287
static NTSTATUS NTAPI Get_Byte(PCONTROLLER_INFO ControllerInfo, PUCHAR Byte)
Definition: hardware.c:158
NTSTATUS NTAPI HwReadIdResult(PCONTROLLER_INFO ControllerInfo, PUCHAR CurCylinder, PUCHAR CurHead)
Definition: hardware.c:864
#define DIGITAL_INPUT_REGISTER
Definition: hardware.h:51
#define COMMAND_RECALIBRATE
Definition: hardware.h:193
#define DOR_FLOPPY_MOTOR_ON_A
Definition: hardware.h:77
#define READ_DATA_MT
Definition: hardware.h:212
#define DOR_FLOPPY_MOTOR_ON_D
Definition: hardware.h:80
#define DOR_FLOPPY_MOTOR_ON_C
Definition: hardware.h:79
#define COMMAND_SENSE_INTERRUPT_STATUS
Definition: hardware.h:194
#define DOR_FLOPPY_MOTOR_ON_B
Definition: hardware.h:78
#define SR0_LCS_SUCCESS
Definition: hardware.h:133
#define STATUS_REGISTER_B
Definition: hardware.h:44
#define COMMAND_VERSION
Definition: hardware.h:200
#define DRSR_SW_RESET
Definition: hardware.h:103
#define COMMAND_READ_ID
Definition: hardware.h:196
#define CONFIGURE_POLL
Definition: hardware.h:247
#define DOR_FDC_ENABLE
Definition: hardware.h:74
#define DOR_RESET
Definition: hardware.h:75
#define DRSR_POWER_DOWN
Definition: hardware.h:102
#define DOR_DMA_IO_INTERFACE_ENABLE
Definition: hardware.h:76
#define STATUS_REGISTER_A
Definition: hardware.h:43
#define COMMAND_FORMAT_TRACK
Definition: hardware.h:198
#define CONFIGURE_EIS
Definition: hardware.h:249
#define SR0_EQUIPMENT_CHECK
Definition: hardware.h:116
#define CONFIGURE_EFIFO
Definition: hardware.h:248
#define SR0_LAST_COMMAND_STATUS
Definition: hardware.h:118
#define DATA_RATE_SELECT_REGISTER
Definition: hardware.h:48
#define READ_DATA_MFM
Definition: hardware.h:211
#define COMMAND_SPECIFY
Definition: hardware.h:189
#define COMMAND_SEEK
Definition: hardware.h:199
#define DIR_DISKETTE_CHANGE
Definition: hardware.h:176
#define MSR_IO_DIRECTION
Definition: hardware.h:95
#define MSR_DATA_REG_READY_FOR_IO
Definition: hardware.h:96
#define READ_ID_MFM
Definition: hardware.h:215
#define SR0_SEEK_COMPLETE
Definition: hardware.h:117
#define DIGITAL_OUTPUT_REGISTER
Definition: hardware.h:45
#define COMMAND_WRITE_DATA
Definition: hardware.h:191
#define COMMAND_HEAD_NUMBER_SHIFT
Definition: hardware.h:236
#define COMMAND_READ_DATA
Definition: hardware.h:192
#define SR1_CANNOT_FIND_ID_ADDRESS
Definition: hardware.h:139
#define MAIN_STATUS_REGISTER
Definition: hardware.h:47
#define COMMAND_SENSE_DRIVE_STATUS
Definition: hardware.h:190
#define FIFO
Definition: hardware.h:49
#define COMMAND_CONFIGURE
Definition: hardware.h:202
#define KeDelayExecutionThread(mode, foo, t)
Definition: env_spec_w32.h:484
Unit
Definition: gdiplusenums.h:26
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define ASSERT(a)
Definition: mode.c:44
#define KernelMode
Definition: asm.h:34
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define READ_PORT_UCHAR(p)
Definition: pc98vid.h:22
#define WRITE_PORT_UCHAR(p, d)
Definition: pc98vid.h:21
#define INFO_(ch,...)
Definition: debug.h:159
#define WARN_(ch,...)
Definition: debug.h:157
#define STATUS_SUCCESS
Definition: shellext.h:65
_In_ BOOLEAN Read
Definition: strmini.h:479
BOOLEAN Model30
Definition: floppy.h:82
PUCHAR BaseAddress
Definition: fdc.h:49
struct _CONTROLLER_INFO * ControllerInfo
Definition: fdc.h:23
CM_FLOPPY_DEVICE_DATA FloppyDeviceData
Definition: fdc.h:27
UCHAR UnitNumber
Definition: fdc.h:24
unsigned char * PBOOLEAN
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
unsigned char * PUCHAR
Definition: typedefs.h:53
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
LONGLONG QuadPart
Definition: typedefs.h:114
_In_ ULONG _In_ ULONG SectorsPerTrack
Definition: iofuncs.h:2071
unsigned char UCHAR
Definition: xmlstorage.h:181