2 Include file for ISA Floppy Driver
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #define _ISA_FLOPPY_H_
14 #include <Protocol/BlockIo.h>
15 #include <Protocol/IsaIo.h>
16 #include <Protocol/DevicePath.h>
17 #include <Guid/StatusCodeDataTypeId.h>
19 #include <Library/TimerLib.h>
20 #include <Library/DebugLib.h>
21 #include <Library/UefiDriverEntryPoint.h>
22 #include <Library/BaseLib.h>
23 #include <Library/UefiLib.h>
24 #include <Library/BaseMemoryLib.h>
25 #include <Library/MemoryAllocationLib.h>
26 #include <Library/UefiBootServicesTableLib.h>
27 #include <Library/ReportStatusCodeLib.h>
28 #include <Library/PcdLib.h>
30 extern EFI_DRIVER_BINDING_PROTOCOL gFdcControllerDriver
;
32 #define STALL_1_SECOND 1000000
33 #define STALL_1_MSECOND 1000
41 // Internal Data Structures
43 #define FDC_BLK_IO_DEV_SIGNATURE SIGNATURE_32 ('F', 'B', 'I', 'O')
44 #define FLOPPY_CONTROLLER_CONTEXT_SIGNATURE SIGNATURE_32 ('F', 'D', 'C', 'C')
55 BOOLEAN FddResetPerformed
;
56 EFI_STATUS FddResetStatus
;
57 BOOLEAN NeedRecalibrate
;
60 } FLOPPY_CONTROLLER_CONTEXT
;
65 EFI_BLOCK_IO_PROTOCOL BlkIo
;
66 EFI_BLOCK_IO_MEDIA BlkMedia
;
68 EFI_ISA_IO_PROTOCOL
*IsaIo
;
73 UINT8 PresentCylinderNumber
;
77 EFI_UNICODE_STRING_TABLE
*ControllerNameTable
;
78 FLOPPY_CONTROLLER_CONTEXT
*ControllerState
;
80 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
83 #include "ComponentName.h"
85 #define FDD_BLK_IO_FROM_THIS(a) CR (a, FDC_BLK_IO_DEV, BlkIo, FDC_BLK_IO_DEV_SIGNATURE)
86 #define FLOPPY_CONTROLLER_FROM_LIST_ENTRY(a) \
88 FLOPPY_CONTROLLER_CONTEXT, \
90 FLOPPY_CONTROLLER_CONTEXT_SIGNATURE \
93 #define DISK_1440K_EOT 0x12
94 #define DISK_1440K_GPL 0x1b
95 #define DISK_1440K_DTL 0xff
96 #define DISK_1440K_NUMBER 0x02
97 #define DISK_1440K_MAXTRACKNUM 0x4f
98 #define DISK_1440K_BYTEPERSECTOR 512
110 } FDD_COMMAND_PACKET1
;
115 } FDD_COMMAND_PACKET2
;
154 // Digital Output Register address offset
156 #define FDC_REGISTER_DOR 2
159 // Main Status Register address offset
161 #define FDC_REGISTER_MSR 4
164 // Data Register address offset
166 #define FDC_REGISTER_DTR 5
169 // Configuration Control Register(data rate select) address offset
171 #define FDC_REGISTER_CCR 7
174 // Digital Input Register(diskchange) address offset
176 #define FDC_REGISTER_DIR 7
180 // FDC Register Bit Definitions
183 // Digital Out Register(WO)
186 // Select Drive: 0=A 1=B
188 #define SELECT_DRV BIT0
193 #define RESET_FDC BIT2
198 #define INT_DMA_ENABLE BIT3
201 // Turn On Drive A Motor
203 #define DRVA_MOTOR_ON BIT4
206 // Turn On Drive B Motor
208 #define DRVB_MOTOR_ON BIT5
211 // Main Status Register(RO)
239 // Request For Master
244 // Configuration Control Register(WO)
249 #define CCR_DRC (BIT0 | BIT1)
252 // Digital Input Register(RO)
259 // #define CCR_DCL BIT7 // Diskette change
263 #define DRC_500KBS 0x0
268 #define DRC_300KBS 0x01
273 #define DRC_250KBS 0x02
278 #define READ_DATA_CMD 0x06
279 #define WRITE_DATA_CMD 0x05
280 #define WRITE_DEL_DATA_CMD 0x09
281 #define READ_DEL_DATA_CMD 0x0C
282 #define READ_TRACK_CMD 0x02
283 #define READ_ID_CMD 0x0A
284 #define FORMAT_TRACK_CMD 0x0D
285 #define SCAN_EQU_CMD 0x11
286 #define SCAN_LOW_EQU_CMD 0x19
287 #define SCAN_HIGH_EQU_CMD 0x1D
288 #define SEEK_CMD 0x0F
289 #define RECALIBRATE_CMD 0x07
290 #define SENSE_INT_STATUS_CMD 0x08
291 #define SPECIFY_CMD 0x03
292 #define SENSE_DRV_STATUS_CMD 0x04
295 // CMD_MT: Multi_Track Selector
296 // when set , this flag selects the multi-track operating mode.
297 // In this mode, the FDC treats a complete cylinder under head0 and 1
303 // CMD_MFM: MFM/FM Mode Selector
304 // A one selects the double density(MFM) mode
305 // A zero selects single density (FM) mode
311 // When set to 1, sectors containing a deleted data address mark will
312 // automatically be skipped during the execution of Read Data.
313 // When set to 0, the sector is read or written the same as the read and
319 // FDC Status Register Bit Definitions
327 #define STS0_IC (BIT7 | BIT6)
330 // Seek End: the FDC completed a seek or recalibrate command
340 // Not Ready(unused), this bit is always 0
345 // Head Address: the current head address
350 // STS0_US1 & STS0_US0: Drive Select(the current selected drive)
355 #define STS0_US1 BIT1
360 #define STS0_US0 BIT0
374 // Data Error: The FDC detected a CRC error in either the ID field or
375 // data field of a sector
380 // Overrun/Underrun: Becomes set if FDC does not receive CPU or DMA service
381 // within the required time interval
399 // Missing Address Mark
409 // Data Error in Data Field: The FDC detected a CRC error in the data field
414 // Wrong Cylinder: The track address from sector ID field is different from
415 // the track address maintained inside FDC
425 // Missing Address Mark in Data Field
445 // STS3_US1 & STS3_US0 : Drive Select
447 #define STS3_US1 BIT1
448 #define STS3_US0 BIT0
451 // Status Register 0 Interrupt Code Description
454 // Normal Termination of Command
459 // Abnormal Termination of Command
469 // Abnormal Termination caused by Polling
474 // EFI Driver Binding Protocol Functions
478 Test controller is a floppy disk drive device
480 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
481 @param[in] Controller The handle of the controller to test.
482 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path.
484 @retval EFI_SUCCESS The device is supported by this driver.
485 @retval EFI_ALREADY_STARTED The device is already being managed by this driver.
486 @retval EFI_ACCESS_DENIED The device is already being managed by a different driver
487 or an application that requires exclusive access.
491 FdcControllerDriverSupported (
492 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
493 IN EFI_HANDLE Controller
,
494 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
498 Start this driver on Controller.
500 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
501 @param[in] ControllerHandle The handle of the controller to start. This handle
502 must support a protocol interface that supplies
503 an I/O abstraction to the driver.
504 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path.
505 This parameter is ignored by device drivers, and is optional for bus drivers.
507 @retval EFI_SUCCESS The device was started.
508 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.
509 Currently not implemented.
510 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
511 @retval Others The driver failded to start the device.
515 FdcControllerDriverStart (
516 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
517 IN EFI_HANDLE Controller
,
518 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
522 Stop this driver on ControllerHandle.
524 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
525 @param[in] ControllerHandle A handle to the device being stopped. The handle must
526 support a bus specific I/O protocol for the driver
527 to use to stop the device.
528 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
529 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
530 if NumberOfChildren is 0.
532 @retval EFI_SUCCESS The device was stopped.
533 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
537 FdcControllerDriverStop (
538 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
539 IN EFI_HANDLE Controller
,
540 IN UINTN NumberOfChildren
,
541 IN EFI_HANDLE
*ChildHandleBuffer
545 // EFI Block I/O Protocol Functions
549 Reset the Floppy Logic Drive, call the FddReset function.
551 @param This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface
552 @param ExtendedVerification BOOLEAN: Indicate that the driver may perform a more
553 exhaustive verification operation of the device during
554 reset, now this par is ignored in this driver
555 @retval EFI_SUCCESS: The Floppy Logic Drive is reset
556 @retval EFI_DEVICE_ERROR: The Floppy Logic Drive is not functioning correctly
563 IN EFI_BLOCK_IO_PROTOCOL
*This
,
564 IN BOOLEAN ExtendedVerification
568 Flush block via fdd controller.
570 @param This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface
577 IN EFI_BLOCK_IO_PROTOCOL
*This
581 Read the requested number of blocks from the device.
583 @param This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface
584 @param MediaId UINT32: The media id that the read request is for
585 @param Lba EFI_LBA: The starting logic block address to read from on the device
586 @param BufferSize UINTN: The size of the Buffer in bytes
587 @param Buffer VOID *: A pointer to the destination buffer for the data
589 @retval EFI_SUCCESS: The data was read correctly from the device
590 @retval EFI_DEVICE_ERROR:The device reported an error while attempting to perform
592 @retval EFI_NO_MEDIA: There is no media in the device
593 @retval EFI_MEDIA_CHANGED: The MediaId is not for the current media
594 @retval EFI_BAD_BUFFER_SIZE: The BufferSize parameter is not a multiple of the
595 intrinsic block size of the device
596 @retval EFI_INVALID_PARAMETER:The read request contains LBAs that are not valid,
597 or the buffer is not on proper alignment
603 IN EFI_BLOCK_IO_PROTOCOL
*This
,
611 Write a specified number of blocks to the device.
613 @param This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface
614 @param MediaId UINT32: The media id that the write request is for
615 @param Lba EFI_LBA: The starting logic block address to be written
616 @param BufferSize UINTN: The size in bytes in Buffer
617 @param Buffer VOID *: A pointer to the source buffer for the data
619 @retval EFI_SUCCESS: The data were written correctly to the device
620 @retval EFI_WRITE_PROTECTED: The device can not be written to
621 @retval EFI_NO_MEDIA: There is no media in the device
622 @retval EFI_MEDIA_CHANGED: The MediaId is not for the current media
623 @retval EFI_DEVICE_ERROR: The device reported an error while attempting to perform
625 @retval EFI_BAD_BUFFER_SIZE: The BufferSize parameter is not a multiple of the
626 intrinsic block size of the device
627 @retval EFI_INVALID_PARAMETER:The write request contains LBAs that are not valid,
628 or the buffer is not on proper alignment
633 IN EFI_BLOCK_IO_PROTOCOL
*This
,
641 // Prototypes of internal functions
645 Detect the floppy drive is presented or not.
647 @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
648 @retval EFI_SUCCESS Drive is presented
649 @retval EFI_NOT_FOUND Drive is not presented
654 IN FDC_BLK_IO_DEV
*FdcDev
659 Do recalibrate and see the drive is presented or not.
660 Set the media parameters.
662 @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
663 @return the drive is presented or not
668 IN FDC_BLK_IO_DEV
*FdcDev
673 Reset the Floppy Logic Drive.
675 @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
677 @retval EFI_SUCCESS: The Floppy Logic Drive is reset
678 @retval EFI_DEVICE_ERROR: The Floppy Logic Drive is not functioning correctly and
684 IN FDC_BLK_IO_DEV
*FdcDev
689 Turn the drive's motor on.
690 The drive's motor must be on before any command can be executed.
692 @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
694 @retval EFI_SUCCESS: Turn the drive's motor on successfully
695 @retval EFI_DEVICE_ERROR: The drive is busy, so can not turn motor on
696 @retval EFI_INVALID_PARAMETER: Fail to Set timer(Cancel timer)
701 IN FDC_BLK_IO_DEV
*FdcDev
706 Set a Timer and when Timer goes off, turn the motor off.
709 @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
711 @retval EFI_SUCCESS: Set the Timer successfully
712 @retval EFI_INVALID_PARAMETER: Fail to Set the timer
717 IN FDC_BLK_IO_DEV
*FdcDev
721 Detect the disk in the drive is changed or not.
724 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
726 @retval EFI_SUCCESS: No disk media change
727 @retval EFI_DEVICE_ERROR: Fail to do the recalibrate or seek operation
728 @retval EFI_NO_MEDIA: No disk in the drive
729 @retval EFI_MEDIA_CHANGED: There is a new disk in the drive
733 IN FDC_BLK_IO_DEV
*FdcDev
737 Do the Specify command, this command sets DMA operation
738 and the initial values for each of the three internal
739 times: HUT, SRT and HLT.
741 @param FdcDev Pointer to instance of FDC_BLK_IO_DEV
743 @retval EFI_SUCCESS: Execute the Specify command successfully
744 @retval EFI_DEVICE_ERROR: Fail to execute the command
749 IN FDC_BLK_IO_DEV
*FdcDev
753 Set the head of floppy drive to track 0.
755 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
756 @retval EFI_SUCCESS: Execute the Recalibrate operation successfully
757 @retval EFI_DEVICE_ERROR: Fail to execute the Recalibrate operation
762 IN FDC_BLK_IO_DEV
*FdcDev
766 Set the head of floppy drive to the new cylinder.
768 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
769 @param Lba EFI_LBA : The logic block address want to seek
771 @retval EFI_SUCCESS: Execute the Seek operation successfully
772 @retval EFI_DEVICE_ERROR: Fail to execute the Seek operation
777 IN FDC_BLK_IO_DEV
*FdcDev
,
782 Do the Sense Interrupt Status command, this command resets the interrupt signal.
784 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
785 @param StatusRegister0 UINT8 *: Be used to save Status Register 0 read from FDC
786 @param PresentCylinderNumber UINT8 *: Be used to save present cylinder number
789 @retval EFI_SUCCESS: Execute the Sense Interrupt Status command successfully
790 @retval EFI_DEVICE_ERROR: Fail to execute the command
795 IN FDC_BLK_IO_DEV
*FdcDev
,
796 IN OUT UINT8
*StatusRegister0
,
797 IN OUT UINT8
*PresentCylinderNumber
801 Do the Sense Drive Status command.
803 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
804 @param Lba EFI_LBA : Logic block address
806 @retval EFI_SUCCESS: Execute the Sense Drive Status command successfully
807 @retval EFI_DEVICE_ERROR: Fail to execute the command
808 @retval EFI_WRITE_PROTECTED:The disk is write protected
813 IN FDC_BLK_IO_DEV
*FdcDev
,
818 Update the disk media properties and if necessary reinstall Block I/O interface.
820 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
822 @retval EFI_SUCCESS: Do the operation successfully
823 @retval EFI_DEVICE_ERROR: Fail to the operation
828 IN FDC_BLK_IO_DEV
*FdcDev
832 Set the data rate and so on.
834 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
836 @retval EFI_SUCCESS success to set the data rate
840 IN FDC_BLK_IO_DEV
*FdcDev
844 Read or Write a number of blocks in the same cylinder.
846 @param FdcDev A pointer to Data Structure FDC_BLK_IO_DEV
847 @param HostAddress device address
848 @param Lba The starting logic block address to read from on the device
849 @param NumberOfBlocks The number of block wanted to be read or write
850 @param Read Operation type: read or write
852 @retval EFI_SUCCESS Success operate
856 ReadWriteDataSector (
857 IN FDC_BLK_IO_DEV
*FdcDev
,
858 IN VOID
*HostAddress
,
860 IN UINTN NumberOfBlocks
,
865 Fill in FDD command's parameter.
867 @param FdcDev Pointer to instance of FDC_BLK_IO_DEV
868 @param Lba The starting logic block address to read from on the device
869 @param Command FDD command
874 IN FDC_BLK_IO_DEV
*FdcDev
,
876 IN FDD_COMMAND_PACKET1
*Command
880 Read result byte from Data Register of FDC.
882 @param FdcDev Pointer to instance of FDC_BLK_IO_DEV
883 @param Pointer Buffer to store the byte read from FDC
885 @retval EFI_SUCCESS Read result byte from FDC successfully
886 @retval EFI_DEVICE_ERROR The FDC is not ready to be read
891 IN FDC_BLK_IO_DEV
*FdcDev
,
896 Write command byte to Data Register of FDC.
898 @param FdcDev Pointer to instance of FDC_BLK_IO_DEV
899 @param Pointer Be used to save command byte written to FDC
901 @retval EFI_SUCCESS: Write command byte to FDC successfully
902 @retval EFI_DEVICE_ERROR: The FDC is not ready to be written
907 IN FDC_BLK_IO_DEV
*FdcDev
,
912 Detect the specified floppy logic drive is busy or not within a period of time.
914 @param FdcDev Indicate it is drive A or drive B
915 @param Timeout The time period for waiting
917 @retval EFI_SUCCESS: The drive and command are not busy
918 @retval EFI_TIMEOUT: The drive or command is still busy after a period time that
924 IN FDC_BLK_IO_DEV
*FdcDev
,
929 Determine whether FDC is ready to write or read.
931 @param FdcDev Pointer to instance of FDC_BLK_IO_DEV
932 @param Dio BOOLEAN: Indicate the FDC is waiting to write or read
933 @param Timeout The time period for waiting
935 @retval EFI_SUCCESS: FDC is ready to write or read
936 @retval EFI_NOT_READY: FDC is not ready within the specified time period
941 IN FDC_BLK_IO_DEV
*FdcDev
,
947 Set FDC control structure's attribute according to result.
949 @param Result Point to result structure
950 @param FdcDev FDC control structure
952 @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value
953 @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value
954 @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value
955 @retval EFI_SUCCESS - GC_TODO: Add description for return value
960 IN FDD_RESULT_PACKET
*Result
,
961 IN OUT FDC_BLK_IO_DEV
*FdcDev
965 Check the drive status information.
967 @param StatusRegister3 the value of Status Register 3
969 @retval EFI_SUCCESS The disk is not write protected
970 @retval EFI_WRITE_PROTECTED: The disk is write protected
975 IN UINT8 StatusRegister3
979 Calculate the number of block in the same cylinder according to Lba.
981 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
982 @param Lba EFI_LBA: The starting logic block address
983 @param NumberOfBlocks UINTN: The number of blocks
985 @return The number of blocks in the same cylinder which the starting
986 logic block address is Lba
990 GetTransferBlockCount (
991 IN FDC_BLK_IO_DEV
*FdcDev
,
993 IN UINTN NumberOfBlocks
997 When the Timer(2s) off, turn the drive's motor off.
999 @param Event EFI_EVENT: Event(the timer) whose notification function is being
1001 @param Context VOID *: Pointer to the notification function's context
1012 Read I/O port for FDC.
1014 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
1015 @param Offset The offset address of port
1020 IN FDC_BLK_IO_DEV
*FdcDev
,
1025 Write I/O port for FDC.
1027 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
1028 @param Offset The offset address of port
1029 @param Data Value written to port
1034 IN FDC_BLK_IO_DEV
*FdcDev
,
1040 Read or Write a number of blocks to floppy device.
1042 @param This Pointer to instance of EFI_BLOCK_IO_PROTOCOL
1043 @param MediaId The media id of read/write request
1044 @param Lba The starting logic block address to read from on the device
1045 @param BufferSize The size of the Buffer in bytes
1046 @param Operation - GC_TODO: add argument description
1047 @param Buffer - GC_TODO: add argument description
1049 @retval EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
1050 @retval EFI_SUCCESS - GC_TODO: Add description for return value
1051 @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1052 @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1053 @retval EFI_NO_MEDIA - GC_TODO: Add description for return value
1054 @retval EFI_MEDIA_CHANGED - GC_TODO: Add description for return value
1055 @retval EFI_WRITE_PROTECTED - GC_TODO: Add description for return value
1056 @retval EFI_BAD_BUFFER_SIZE - GC_TODO: Add description for return value
1057 @retval EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
1058 @retval EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
1059 @retval EFI_SUCCESS - GC_TODO: Add description for return value
1060 @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1061 @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1062 @retval EFI_SUCCESS - GC_TODO: Add description for return value
1066 FddReadWriteBlocks (
1067 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1070 IN UINTN BufferSize
,
1071 IN BOOLEAN Operation
,
1076 Common interface for free cache.
1078 @param FdcDev Pointer of FDC_BLK_IO_DEV instance
1083 IN FDC_BLK_IO_DEV
*FdcDev