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
514 Create floppy control instance on controller.
516 @param This Pointer of EFI_DRIVER_BINDING_PROTOCOL
517 @param Controller driver controller handle
518 @param RemainingDevicePath Children's device path
520 @retval whether success to create floppy control instance.
524 FdcControllerDriverStart (
525 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
526 IN EFI_HANDLE Controller
,
527 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
531 Stop this driver on ControllerHandle. Support stoping any child handles
532 created by this driver.
534 @param This Protocol instance pointer.
535 @param Controller Handle of device to stop driver on
536 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
537 children is zero stop the entire bus driver.
538 @param ChildHandleBuffer List of Child Handles to Stop.
540 @retval EFI_SUCCESS This driver is removed ControllerHandle
541 @retval other This driver was not removed from this device
546 FdcControllerDriverStop (
547 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
548 IN EFI_HANDLE Controller
,
549 IN UINTN NumberOfChildren
,
550 IN EFI_HANDLE
*ChildHandleBuffer
554 // EFI Block I/O Protocol Functions
557 Reset the Floppy Logic Drive, call the FddReset function
559 @param This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface
560 @param ExtendedVerification BOOLEAN: Indicate that the driver may perform a more
561 exhaustive verification operation of the device during
562 reset, now this par is ignored in this driver
563 @retval EFI_SUCCESS: The Floppy Logic Drive is reset
564 @retval EFI_DEVICE_ERROR: The Floppy Logic Drive is not functioning correctly
571 IN EFI_BLOCK_IO_PROTOCOL
*This
,
572 IN BOOLEAN ExtendedVerification
576 Flush block via fdd controller
578 @param This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface
585 IN EFI_BLOCK_IO_PROTOCOL
*This
589 Read the requested number of blocks from the device
591 @param This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface
592 @param MediaId UINT32: The media id that the read request is for
593 @param LBA EFI_LBA: The starting logic block address to read from on the device
594 @param BufferSize UINTN: The size of the Buffer in bytes
595 @param Buffer VOID *: A pointer to the destination buffer for the data
597 @retval EFI_SUCCESS: The data was read correctly from the device
598 @retval EFI_DEVICE_ERROR:The device reported an error while attempting to perform
600 @retval EFI_NO_MEDIA: There is no media in the device
601 @retval EFI_MEDIA_CHANGED: The MediaId is not for the current media
602 @retval EFI_BAD_BUFFER_SIZE: The BufferSize parameter is not a multiple of the
603 intrinsic block size of the device
604 @retval EFI_INVALID_PARAMETER:The read request contains LBAs that are not valid,
605 or the buffer is not on proper alignment
611 IN EFI_BLOCK_IO_PROTOCOL
*This
,
619 Write a specified number of blocks to the device
621 @param This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface
622 @param MediaId UINT32: The media id that the write request is for
623 @param LBA EFI_LBA: The starting logic block address to be written
624 @param BufferSize UINTN: The size in bytes in Buffer
625 @param Buffer VOID *: A pointer to the source buffer for the data
627 @retval EFI_SUCCESS: The data were written correctly to the device
628 @retval EFI_WRITE_PROTECTED: The device can not be written to
629 @retval EFI_NO_MEDIA: There is no media in the device
630 @retval EFI_MEDIA_CHANGED: The MediaId is not for the current media
631 @retval EFI_DEVICE_ERROR: The device reported an error while attempting to perform
633 @retval EFI_BAD_BUFFER_SIZE: The BufferSize parameter is not a multiple of the
634 intrinsic block size of the device
635 @retval EFI_INVALID_PARAMETER:The write request contains LBAs that are not valid,
636 or the buffer is not on proper alignment
641 IN EFI_BLOCK_IO_PROTOCOL
*This
,
649 // Prototypes of internal functions
653 Detect the floppy drive is presented or not
655 @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
656 @retval EFI_SUCCESS Drive is presented
657 @retval EFI_NOT_FOUND Drive is not presented
662 IN FDC_BLK_IO_DEV
*FdcDev
667 Do recalibrate and see the drive is presented or not
668 Set the media parameters
670 @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
671 @return the drive is presented or not
676 IN FDC_BLK_IO_DEV
*FdcDev
681 Reset the Floppy Logic Drive
683 @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
685 @retval EFI_SUCCESS: The Floppy Logic Drive is reset
686 @retval EFI_DEVICE_ERROR: The Floppy Logic Drive is not functioning correctly and
692 IN FDC_BLK_IO_DEV
*FdcDev
697 Turn the drive's motor on
698 The drive's motor must be on before any command can be executed
700 @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
702 @retval EFI_SUCCESS: Turn the drive's motor on successfully
703 @retval EFI_DEVICE_ERROR: The drive is busy, so can not turn motor on
704 @retval EFI_INVALID_PARAMETER: Fail to Set timer(Cancel timer)
709 IN FDC_BLK_IO_DEV
*FdcDev
714 Set a Timer and when Timer goes off, turn the motor off
717 @param FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
719 @retval EFI_SUCCESS: Set the Timer successfully
720 @retval EFI_INVALID_PARAMETER: Fail to Set the timer
725 IN FDC_BLK_IO_DEV
*FdcDev
729 Detect the disk in the drive is changed or not
732 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
734 @retval EFI_SUCCESS: No disk media change
735 @retval EFI_DEVICE_ERROR: Fail to do the recalibrate or seek operation
736 @retval EFI_NO_MEDIA: No disk in the drive
737 @retval EFI_MEDIA_CHANGED: There is a new disk in the drive
741 IN FDC_BLK_IO_DEV
*FdcDev
745 Do the Specify command, this command sets DMA operation
746 and the initial values for each of the three internal
747 times: HUT, SRT and HLT
749 @param FdcDev Pointer to instance of FDC_BLK_IO_DEV
751 @retval EFI_SUCCESS: Execute the Specify command successfully
752 @retval EFI_DEVICE_ERROR: Fail to execute the command
757 IN FDC_BLK_IO_DEV
*FdcDev
761 Set the head of floppy drive to track 0
763 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
764 @retval EFI_SUCCESS: Execute the Recalibrate operation successfully
765 @retval EFI_DEVICE_ERROR: Fail to execute the Recalibrate operation
770 IN FDC_BLK_IO_DEV
*FdcDev
774 Set the head of floppy drive to the new cylinder
776 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
777 @param Lba EFI_LBA : The logic block address want to seek
779 @retval EFI_SUCCESS: Execute the Seek operation successfully
780 @retval EFI_DEVICE_ERROR: Fail to execute the Seek operation
785 IN FDC_BLK_IO_DEV
*FdcDev
,
790 Do the Sense Interrupt Status command, this command
791 resets the interrupt signal
793 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
794 @param StatusRegister0 UINT8 *: Be used to save Status Register 0 read from FDC
795 @param PresentCylinderNumber UINT8 *: Be used to save present cylinder number
798 @retval EFI_SUCCESS: Execute the Sense Interrupt Status command successfully
799 @retval EFI_DEVICE_ERROR: Fail to execute the command
804 IN FDC_BLK_IO_DEV
*FdcDev
,
805 IN OUT UINT8
*StatusRegister0
,
806 IN OUT UINT8
*PresentCylinderNumber
810 Do the Sense Drive Status command
812 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
813 @param Lba EFI_LBA : Logic block address
815 @retval EFI_SUCCESS: Execute the Sense Drive Status command successfully
816 @retval EFI_DEVICE_ERROR: Fail to execute the command
817 @retval EFI_WRITE_PROTECTED:The disk is write protected
822 IN FDC_BLK_IO_DEV
*FdcDev
,
827 Update the disk media properties and if necessary
828 reinstall Block I/O interface
830 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
832 @retval EFI_SUCCESS: Do the operation successfully
833 @retval EFI_DEVICE_ERROR: Fail to the operation
838 IN FDC_BLK_IO_DEV
*FdcDev
842 Set the data rate and so on
844 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
846 @retval EFI_SUCCESS success to set the data rate
850 IN FDC_BLK_IO_DEV
*FdcDev
854 Read or Write a number of blocks in the same cylinder
856 @param FdcDev A pointer to Data Structure FDC_BLK_IO_DEV
857 @param HostAddress device address
858 @param Lba The starting logic block address to read from on the device
859 @param NumberOfBlocks The number of block wanted to be read or write
860 @param Read Operation type: read or write
862 @retval EFI_SUCCESS Success operate
866 ReadWriteDataSector (
867 IN FDC_BLK_IO_DEV
*FdcDev
,
868 IN VOID
*HostAddress
,
870 IN UINTN NumberOfBlocks
,
875 Fill in FDD command's parameter
877 @param FdcDev Pointer to instance of FDC_BLK_IO_DEV
878 @param Lba The starting logic block address to read from on the device
879 @param Command FDD command
884 IN FDC_BLK_IO_DEV
*FdcDev
,
886 IN FDD_COMMAND_PACKET1
*Command
890 Read result byte from Data Register of FDC
892 @param FdcDev Pointer to instance of FDC_BLK_IO_DEV
893 @param Pointer UINT8 *: Be used to save result byte read from FDC
896 @retval EFI_SUCCESS: Read result byte from FDC successfully
897 @retval EFI_DEVICE_ERROR: The FDC is not ready to be read
902 IN FDC_BLK_IO_DEV
*FdcDev
,
907 Write command byte to Data Register of FDC
909 @param FdcDev Pointer to instance of FDC_BLK_IO_DEV
910 @param Pointer Be used to save command byte written to FDC
912 @retval EFI_SUCCESS: Write command byte to FDC successfully
913 @retval EFI_DEVICE_ERROR: The FDC is not ready to be written
918 IN FDC_BLK_IO_DEV
*FdcDev
,
923 Detect the specified floppy logic drive is busy or
924 not within a period of time
926 @param FdcDev Indicate it is drive A or drive B
927 @param TimeoutInSeconds the time period for waiting
929 @retval EFI_SUCCESS: The drive and command are not busy
930 @retval EFI_TIMEOUT: The drive or command is still busy after a period time that
931 set by TimeoutInSeconds
936 IN FDC_BLK_IO_DEV
*FdcDev
,
937 IN UINTN TimeoutInSeconds
942 Routine Description: Determine whether FDC is ready to write or read
944 @param FdcDev Pointer to instance of FDC_BLK_IO_DEV
945 @param Dio BOOLEAN: Indicate the FDC is waiting to write or read
946 @param TimeoutInSeconds UINTN: The time period for waiting
948 @retval EFI_SUCCESS: FDC is ready to write or read
949 @retval EFI_NOT_READY: FDC is not ready within the specified time period
954 IN FDC_BLK_IO_DEV
*FdcDev
,
956 IN UINTN TimeoutInSeconds
960 Set FDC control structure's attribute according to
963 @param Result Point to result structure
964 @param FdcDev FDC control structure
966 @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value
967 @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value
968 @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value
969 @retval EFI_SUCCESS - GC_TODO: Add description for return value
974 IN FDD_RESULT_PACKET
*Result
,
975 IN OUT FDC_BLK_IO_DEV
*FdcDev
979 Check the drive status information
981 @param StatusRegister3 the value of Status Register 3
983 @retval EFI_SUCCESS The disk is not write protected
984 @retval EFI_WRITE_PROTECTED: The disk is write protected
989 IN UINT8 StatusRegister3
993 Calculate the number of block in the same cylinder
996 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
997 @param LBA EFI_LBA: The starting logic block address
998 @param NumberOfBlocks UINTN: The number of blocks
1000 @return The number of blocks in the same cylinder which the starting
1001 logic block address is LBA
1005 GetTransferBlockCount (
1006 IN FDC_BLK_IO_DEV
*FdcDev
,
1008 IN UINTN NumberOfBlocks
1012 When the Timer(2s) off, turn the drive's motor off
1014 @param Event EFI_EVENT: Event(the timer) whose notification function is being
1016 @param Context VOID *: Pointer to the notification function's context
1027 Read I/O port for FDC
1029 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
1030 @param Offset The offset address of port
1035 IN FDC_BLK_IO_DEV
*FdcDev
,
1040 Write I/O port for FDC
1042 @param FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
1043 @param Offset The offset address of port
1044 @param Data Value written to port
1049 IN FDC_BLK_IO_DEV
*FdcDev
,
1055 Read or Write a number of blocks to floppy device
1057 @param This Pointer to instance of EFI_BLOCK_IO_PROTOCOL
1058 @param MediaId The media id of read/write request
1059 @param LBA The starting logic block address to read from on the device
1060 @param BufferSize The size of the Buffer in bytes
1061 @param Operation - GC_TODO: add argument description
1062 @param Buffer - GC_TODO: add argument description
1064 @retval EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
1065 @retval EFI_SUCCESS - GC_TODO: Add description for return value
1066 @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1067 @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1068 @retval EFI_NO_MEDIA - GC_TODO: Add description for return value
1069 @retval EFI_MEDIA_CHANGED - GC_TODO: Add description for return value
1070 @retval EFI_WRITE_PROTECTED - GC_TODO: Add description for return value
1071 @retval EFI_BAD_BUFFER_SIZE - GC_TODO: Add description for return value
1072 @retval EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
1073 @retval EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
1074 @retval EFI_SUCCESS - GC_TODO: Add description for return value
1075 @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1076 @retval EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1077 @retval EFI_SUCCESS - GC_TODO: Add description for return value
1081 FddReadWriteBlocks (
1082 IN EFI_BLOCK_IO_PROTOCOL
*This
,
1085 IN UINTN BufferSize
,
1086 IN BOOLEAN Operation
,
1091 Common interface for free cache
1093 @param FdcDev Pointer of FDC_BLK_IO_DEV instance
1098 IN FDC_BLK_IO_DEV
*FdcDev