2 Include for ISA Floppy Driver
3 Define the data structure and so on
5 Copyright (c) 2006 - 2007, Intel Corporation.<BR>
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 #include <FrameworkPei.h>
22 #include <Protocol/BlockIo.h>
23 #include <Protocol/IsaIo.h>
24 #include <Protocol/DevicePath.h>
26 #include <Library/TimerLib.h>
27 #include <Library/DebugLib.h>
28 #include <Library/UefiDriverEntryPoint.h>
29 #include <Library/BaseLib.h>
30 #include <Library/UefiLib.h>
31 #include <Library/BaseMemoryLib.h>
32 #include <Library/MemoryAllocationLib.h>
33 #include <Library/UefiBootServicesTableLib.h>
34 #include <Library/ReportStatusCodeLib.h>
36 // Driver Binding Externs
38 extern EFI_DRIVER_BINDING_PROTOCOL gFdcControllerDriver
;
39 extern EFI_COMPONENT_NAME_PROTOCOL gIsaFloppyComponentName
;
40 extern EFI_COMPONENT_NAME2_PROTOCOL gIsaFloppyComponentName2
;
45 #define STALL_1_SECOND 1000000
46 #define STALL_1_MSECOND 1000
54 // Internal Data Structures
56 #define FDC_BLK_IO_DEV_SIGNATURE EFI_SIGNATURE_32 ('F', 'B', 'I', 'O')
57 #define FLOPPY_CONTROLLER_CONTEXT_SIGNATURE EFI_SIGNATURE_32 ('F', 'D', 'C', 'C')
68 BOOLEAN FddResetPerformed
;
69 EFI_STATUS FddResetStatus
;
70 BOOLEAN NeedRecalibrate
;
73 } FLOPPY_CONTROLLER_CONTEXT
;
78 EFI_BLOCK_IO_PROTOCOL BlkIo
;
79 EFI_BLOCK_IO_MEDIA BlkMedia
;
81 EFI_ISA_IO_PROTOCOL
*IsaIo
;
86 UINT8 PresentCylinderNumber
;
90 EFI_UNICODE_STRING_TABLE
*ControllerNameTable
;
91 FLOPPY_CONTROLLER_CONTEXT
*ControllerState
;
93 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
96 #include "ComponentName.h"
98 #define FDD_BLK_IO_FROM_THIS(a) CR (a, FDC_BLK_IO_DEV, BlkIo, FDC_BLK_IO_DEV_SIGNATURE)
99 #define FLOPPY_CONTROLLER_FROM_LIST_ENTRY(a) \
101 FLOPPY_CONTROLLER_CONTEXT, \
103 FLOPPY_CONTROLLER_CONTEXT_SIGNATURE \
106 #define DISK_1440K_EOT 0x12
107 #define DISK_1440K_GPL 0x1b
108 #define DISK_1440K_DTL 0xff
109 #define DISK_1440K_NUMBER 0x02
110 #define DISK_1440K_MAXTRACKNUM 0x4f
111 #define DISK_1440K_BYTEPERSECTOR 512
123 } FDD_COMMAND_PACKET1
;
128 } FDD_COMMAND_PACKET2
;
167 // 0x3F2 Digital Output Register
169 #define FDC_REGISTER_DOR 2
172 // 0x3F4 Main Status Register
174 #define FDC_REGISTER_MSR 4
177 // 0x3F5 Data Register
179 #define FDC_REGISTER_DTR 5
182 // 0x3F7 Configuration Control Register(data rate select)
184 #define FDC_REGISTER_CCR 7
187 // 0x3F7 Digital Input Register(diskchange)
189 #define FDC_REGISTER_DIR 7
194 // FDC Register Bit Definitions
197 // Digital Out Register(WO)
200 // Select Drive: 0=A 1=B
202 #define SELECT_DRV BIT0
207 #define RESET_FDC BIT2
212 #define INT_DMA_ENABLE BIT3
215 // Turn On Drive A Motor
217 #define DRVA_MOTOR_ON BIT4
220 // Turn On Drive B Motor
222 #define DRVB_MOTOR_ON BIT5
225 // Main Status Register(RO)
253 // Request For Master
258 // Configuration Control Register(WO)
263 #define CCR_DRC (BIT0 | BIT1)
266 // Digital Input Register(RO)
273 // #define CCR_DCL BIT7 // Diskette change
277 #define DRC_500KBS 0x0
282 #define DRC_300KBS 0x01
287 #define DRC_250KBS 0x02
292 #define READ_DATA_CMD 0x06
293 #define WRITE_DATA_CMD 0x05
294 #define WRITE_DEL_DATA_CMD 0x09
295 #define READ_DEL_DATA_CMD 0x0C
296 #define READ_TRACK_CMD 0x02
297 #define READ_ID_CMD 0x0A
298 #define FORMAT_TRACK_CMD 0x0D
299 #define SCAN_EQU_CMD 0x11
300 #define SCAN_LOW_EQU_CMD 0x19
301 #define SCAN_HIGH_EQU_CMD 0x1D
302 #define SEEK_CMD 0x0F
303 #define RECALIBRATE_CMD 0x07
304 #define SENSE_INT_STATUS_CMD 0x08
305 #define SPECIFY_CMD 0x03
306 #define SENSE_DRV_STATUS_CMD 0x04
309 // CMD_MT: Multi_Track Selector
310 // when set , this flag selects the multi-track operating mode.
311 // In this mode, the FDC treats a complete cylinder under head0 and 1
317 // CMD_MFM: MFM/FM Mode Selector
318 // A one selects the double density(MFM) mode
319 // A zero selects single density (FM) mode
325 // When set to 1, sectors containing a deleted data address mark will
326 // automatically be skipped during the execution of Read Data.
327 // When set to 0, the sector is read or written the same as the read and
333 // FDC Status Register Bit Definitions
341 #define STS0_IC (BIT7 | BIT6)
344 // Seek End: the FDC completed a seek or recalibrate command
354 // Not Ready(unused), this bit is always 0
359 // Head Address: the current head address
364 // STS0_US1 & STS0_US0: Drive Select(the current selected drive)
369 #define STS0_US1 BIT1
374 #define STS0_US0 BIT0
388 // Data Error: The FDC detected a CRC error in either the ID field or
389 // data field of a sector
394 // Overrun/Underrun: Becomes set if FDC does not receive CPU or DMA service
395 // within the required time interval
413 // Missing Address Mark
423 // Data Error in Data Field: The FDC detected a CRC error in the data field
428 // Wrong Cylinder: The track address from sector ID field is different from
429 // the track address maintained inside FDC
439 // Missing Address Mark in Data Field
459 // STS3_US1 & STS3_US0 : Drive Select
461 #define STS3_US1 BIT1
462 #define STS3_US0 BIT0
465 // Status Register 0 Interrupt Code Description
468 // Normal Termination of Command
473 // Abnormal Termination of Command
483 // Abnormal Termination caused by Polling
490 extern EFI_DRIVER_BINDING_PROTOCOL gFdcControllerDriver
;
493 // EFI Driver Binding Protocol Functions
496 Test controller is a Floppy Disk Controller
498 @param This Pointer of EFI_DRIVER_BINDING_PROTOCOL
499 @param Controller driver's controller
500 @param RemainingDevicePath children device path
502 @retval EFI_UNSUPPORTED controller is not floppy disk
503 @retval EFI_SUCCESS controller is floppy disk
507 FdcControllerDriverSupported (
508 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
509 IN EFI_HANDLE Controller
,
510 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
515 Create floppy control instance on controller.
517 @param This Pointer of EFI_DRIVER_BINDING_PROTOCOL
518 @param Controller driver controller handle
519 @param RemainingDevicePath Children's device path
521 @retval whether success to create floppy control instance.
525 FdcControllerDriverStart (
526 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
527 IN EFI_HANDLE Controller
,
528 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
533 Stop this driver on ControllerHandle. Support stoping any child handles
534 created by this driver.
536 @param This Protocol instance pointer.
537 @param Controller Handle of device to stop driver on
538 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
539 children is zero stop the entire bus driver.
540 @param ChildHandleBuffer List of Child Handles to Stop.
542 @retval EFI_SUCCESS This driver is removed ControllerHandle
543 @retval other This driver was not removed from this device
548 FdcControllerDriverStop (
549 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
550 IN EFI_HANDLE Controller
,
551 IN UINTN NumberOfChildren
,
552 IN EFI_HANDLE
*ChildHandleBuffer
557 // EFI Block I/O Protocol Functions
560 Reset the Floppy Logic Drive, call the FddReset function
562 @param This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface
563 @param ExtendedVerification BOOLEAN: Indicate that the driver may perform a more
564 exhaustive verification operation of the device during
565 reset, now this par is ignored in this driver
566 @retval EFI_SUCCESS: The Floppy Logic Drive is reset
567 @retval EFI_DEVICE_ERROR: The Floppy Logic Drive is not functioning correctly
574 IN EFI_BLOCK_IO_PROTOCOL
*This
,
575 IN BOOLEAN ExtendedVerification
580 Flush block via fdd controller
582 @param This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface
589 IN EFI_BLOCK_IO_PROTOCOL
*This
594 Read the requested number of blocks from the device
596 @param This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface
597 @param MediaId UINT32: The media id that the read request is for
598 @param LBA EFI_LBA: The starting logic block address to read from on the device
599 @param BufferSize UINTN: The size of the Buffer in bytes
600 @param Buffer VOID *: A pointer to the destination buffer for the data
602 @retval EFI_SUCCESS: The data was read correctly from the device
603 @retval EFI_DEVICE_ERROR:The device reported an error while attempting to perform
605 @retval EFI_NO_MEDIA: There is no media in the device
606 @retval EFI_MEDIA_CHANGED: The MediaId is not for the current media
607 @retval EFI_BAD_BUFFER_SIZE: The BufferSize parameter is not a multiple of the
608 intrinsic block size of the device
609 @retval EFI_INVALID_PARAMETER:The read request contains LBAs that are not valid,
610 or the buffer is not on proper alignment
616 IN EFI_BLOCK_IO_PROTOCOL
*This
,
625 Write a specified number of blocks to the device
627 @param This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface
628 @param MediaId UINT32: The media id that the write request is for
629 @param LBA EFI_LBA: The starting logic block address to be written
630 @param BufferSize UINTN: The size in bytes in Buffer
631 @param Buffer VOID *: A pointer to the source buffer for the data
633 @retval EFI_SUCCESS: The data were written correctly to the device
634 @retval EFI_WRITE_PROTECTED: The device can not be written to
635 @retval EFI_NO_MEDIA: There is no media in the device
636 @retval EFI_MEDIA_CHANGED: The MediaId is not for the current media
637 @retval EFI_DEVICE_ERROR: The device reported an error while attempting to perform
639 @retval EFI_BAD_BUFFER_SIZE: The BufferSize parameter is not a multiple of the
640 intrinsic block size of the device
641 @retval EFI_INVALID_PARAMETER:The write request contains LBAs that are not valid,
642 or the buffer is not on proper alignment
647 IN EFI_BLOCK_IO_PROTOCOL
*This
,
656 // Prototypes of internal functions
660 Detect the floppy drive is presented or not
662 @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
663 @retval EFI_SUCCESS Drive is presented
664 @retval EFI_NOT_FOUND Drive is not presented
669 IN FDC_BLK_IO_DEV
*FdcDev
675 Do recalibrate and see the drive is presented or not
676 Set the media parameters
678 @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
679 @return the drive is presented or not
684 IN FDC_BLK_IO_DEV
*FdcDev
690 Reset the Floppy Logic Drive
692 @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
694 @retval EFI_SUCCESS: The Floppy Logic Drive is reset
695 @retval EFI_DEVICE_ERROR: The Floppy Logic Drive is not functioning correctly and
701 IN FDC_BLK_IO_DEV
*FdcDev
707 Turn the drive's motor on
708 The drive's motor must be on before any command can be executed
710 @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
712 @retval EFI_SUCCESS: Turn the drive's motor on successfully
713 @retval EFI_DEVICE_ERROR: The drive is busy, so can not turn motor on
714 @retval EFI_INVALID_PARAMETER: Fail to Set timer(Cancel timer)
719 IN FDC_BLK_IO_DEV
*FdcDev
725 Set a Timer and when Timer goes off, turn the motor off
728 @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
730 @retval EFI_SUCCESS: Set the Timer successfully
731 @retval EFI_INVALID_PARAMETER: Fail to Set the timer
736 IN FDC_BLK_IO_DEV
*FdcDev
741 Detect the disk in the drive is changed or not
744 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
746 @retval EFI_SUCCESS: No disk media change
747 @retval EFI_DEVICE_ERROR: Fail to do the recalibrate or seek operation
748 @retval EFI_NO_MEDIA: No disk in the drive
749 @retval EFI_MEDIA_CHANGED: There is a new disk in the drive
753 IN FDC_BLK_IO_DEV
*FdcDev
758 Do the Specify command, this command sets DMA operation
759 and the initial values for each of the three internal
760 times: HUT, SRT and HLT
762 @param FdcDev Pointer to instance of FDC_BLK_IO_DEV
764 @retval EFI_SUCCESS: Execute the Specify command successfully
765 @retval EFI_DEVICE_ERROR: Fail to execute the command
770 IN FDC_BLK_IO_DEV
*FdcDev
775 Set the head of floppy drive to track 0
777 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
778 @retval EFI_SUCCESS: Execute the Recalibrate operation successfully
779 @retval EFI_DEVICE_ERROR: Fail to execute the Recalibrate operation
784 IN FDC_BLK_IO_DEV
*FdcDev
789 Set the head of floppy drive to the new cylinder
791 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
792 @param Lba EFI_LBA : The logic block address want to seek
794 @retval EFI_SUCCESS: Execute the Seek operation successfully
795 @retval EFI_DEVICE_ERROR: Fail to execute the Seek operation
800 IN FDC_BLK_IO_DEV
*FdcDev
,
806 Do the Sense Interrupt Status command, this command
807 resets the interrupt signal
809 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
810 @param StatusRegister0 UINT8 *: Be used to save Status Register 0 read from FDC
811 @param PresentCylinderNumber UINT8 *: Be used to save present cylinder number
814 @retval EFI_SUCCESS: Execute the Sense Interrupt Status command successfully
815 @retval EFI_DEVICE_ERROR: Fail to execute the command
820 IN FDC_BLK_IO_DEV
*FdcDev
,
821 IN OUT UINT8
*StatusRegister0
,
822 IN OUT UINT8
*PresentCylinderNumber
827 Do the Sense Drive Status command
829 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
830 @param Lba EFI_LBA : Logic block address
832 @retval EFI_SUCCESS: Execute the Sense Drive Status command successfully
833 @retval EFI_DEVICE_ERROR: Fail to execute the command
834 @retval EFI_WRITE_PROTECTED:The disk is write protected
839 IN FDC_BLK_IO_DEV
*FdcDev
,
845 Update the disk media properties and if necessary
846 reinstall Block I/O interface
848 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
850 @retval EFI_SUCCESS: Do the operation successfully
851 @retval EFI_DEVICE_ERROR: Fail to the operation
856 IN FDC_BLK_IO_DEV
*FdcDev
861 Set the data rate and so on
863 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
865 @retval EFI_SUCCESS success to set the data rate
869 IN FDC_BLK_IO_DEV
*FdcDev
874 Read or Write a number of blocks in the same cylinder
876 @param FdcDev A pointer to Data Structure FDC_BLK_IO_DEV
877 @param HostAddress device address
878 @param Lba The starting logic block address to read from on the device
879 @param NumberOfBlocks The number of block wanted to be read or write
880 @param Read Operation type: read or write
882 @retval EFI_SUCCESS Success operate
886 ReadWriteDataSector (
887 IN FDC_BLK_IO_DEV
*FdcDev
,
888 IN VOID
*HostAddress
,
890 IN UINTN NumberOfBlocks
,
896 Fill in FDD command's parameter
898 @param FdcDev Pointer to instance of FDC_BLK_IO_DEV
899 @param Lba The starting logic block address to read from on the device
900 @param Command FDD command
905 IN FDC_BLK_IO_DEV
*FdcDev
,
907 IN FDD_COMMAND_PACKET1
*Command
912 Read result byte from Data Register of FDC
914 @param FdcDev Pointer to instance of FDC_BLK_IO_DEV
915 @param Pointer UINT8 *: Be used to save result byte read from FDC
918 @retval EFI_SUCCESS: Read result byte from FDC successfully
919 @retval EFI_DEVICE_ERROR: The FDC is not ready to be read
924 IN FDC_BLK_IO_DEV
*FdcDev
,
930 Write command byte to Data Register of FDC
932 @param FdcDev Pointer to instance of FDC_BLK_IO_DEV
933 @param Pointer Be used to save command byte written to FDC
935 @retval EFI_SUCCESS: Write command byte to FDC successfully
936 @retval EFI_DEVICE_ERROR: The FDC is not ready to be written
941 IN FDC_BLK_IO_DEV
*FdcDev
,
947 Detect the specified floppy logic drive is busy or
948 not within a period of time
950 @param FdcDev Indicate it is drive A or drive B
951 @param TimeoutInSeconds the time period for waiting
953 @retval EFI_SUCCESS: The drive and command are not busy
954 @retval EFI_TIMEOUT: The drive or command is still busy after a period time that
955 set by TimeoutInSeconds
960 IN FDC_BLK_IO_DEV
*FdcDev
,
961 IN UINTN TimeoutInSeconds
967 Routine Description: Determine whether FDC is ready to write or read
969 @param FdcDev Pointer to instance of FDC_BLK_IO_DEV
970 @param Dio BOOLEAN: Indicate the FDC is waiting to write or read
971 @param TimeoutInSeconds UINTN: The time period for waiting
973 @retval EFI_SUCCESS: FDC is ready to write or read
974 @retval EFI_NOT_READY: FDC is not ready within the specified time period
979 IN FDC_BLK_IO_DEV
*FdcDev
,
981 IN UINTN TimeoutInSeconds
986 Set FDC control structure's attribute according to
989 @param Result Point to result structure
990 @param FdcDev FDC control structure
992 @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value
993 @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value
994 @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value
995 @retval EFI_SUCCESS - GC_TODO: Add description for return value
1000 IN FDD_RESULT_PACKET
*Result
,
1001 IN OUT FDC_BLK_IO_DEV
*FdcDev
1006 Check the drive status information
1008 @param StatusRegister3 the value of Status Register 3
1010 @retval EFI_SUCCESS The disk is not write protected
1011 @retval EFI_WRITE_PROTECTED: The disk is write protected
1016 IN UINT8 StatusRegister3
1021 Calculate the number of block in the same cylinder
1024 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
1025 @param LBA EFI_LBA: The starting logic block address
1026 @param NumberOfBlocks UINTN: The number of blocks
1028 @return The number of blocks in the same cylinder which the starting
1029 logic block address is LBA
1033 GetTransferBlockCount (
1034 IN FDC_BLK_IO_DEV
*FdcDev
,
1036 IN UINTN NumberOfBlocks
1041 When the Timer(2s) off, turn the drive's motor off
1043 @param Event EFI_EVENT: Event(the timer) whose notification function is being
1045 @param Context VOID *: Pointer to the notification function's context
1057 Read I/O port for FDC
1059 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
1060 @param Offset The offset address of port
1065 IN FDC_BLK_IO_DEV
*FdcDev
,
1071 Write I/O port for FDC
1073 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
1074 @param Offset The offset address of port
1075 @param Data Value written to port
1080 IN FDC_BLK_IO_DEV
*FdcDev
,
1087 Read or Write a number of blocks to floppy device
1089 @param This Pointer to instance of EFI_BLOCK_IO_PROTOCOL
1090 @param MediaId The media id of read/write request
1091 @param LBA The starting logic block address to read from on the device
1092 @param BufferSize The size of the Buffer in bytes
1093 @param Operation - GC_TODO: add argument description
1094 @param Buffer - GC_TODO: add argument description
1096 @retval EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
1097 @retval EFI_SUCCESS - GC_TODO: Add description for return value
1098 @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1099 @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1100 @retval EFI_NO_MEDIA - GC_TODO: Add description for return value
1101 @retval EFI_MEDIA_CHANGED - GC_TODO: Add description for return value
1102 @retval EFI_WRITE_PROTECTED - GC_TODO: Add description for return value
1103 @retval EFI_BAD_BUFFER_SIZE - GC_TODO: Add description for return value
1104 @retval EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
1105 @retval EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
1106 @retval EFI_SUCCESS - GC_TODO: Add description for return value
1107 @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1108 @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1109 @retval EFI_SUCCESS - GC_TODO: Add description for return value
1113 FddReadWriteBlocks (
1114 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1117 IN UINTN BufferSize
,
1118 IN BOOLEAN Operation
,
1124 Common interface for free cache
1126 @param FdcDev Pointer of FDC_BLK_IO_DEV instance
1131 IN FDC_BLK_IO_DEV
*FdcDev