summaryrefslogtreecommitdiff
path: root/Bus
diff options
context:
space:
mode:
authoryshang1 <yshang1@6f19259b-4bc3-4df7-8a09-765794883524>2007-07-10 09:04:15 +0000
committeryshang1 <yshang1@6f19259b-4bc3-4df7-8a09-765794883524>2007-07-10 09:04:15 +0000
commit3d075fb46209472234081b55dfbbe5dbfaf504c8 (patch)
treec785a4215344e5e72305946e0d0b314a2224a713 /Bus
parentf8f8c6f2e1b9b3a12c98b42a10084e55ddb3547b (diff)
downloadedk2-3d075fb46209472234081b55dfbbe5dbfaf504c8.zip
edk2-3d075fb46209472234081b55dfbbe5dbfaf504c8.tar.gz
edk2-3d075fb46209472234081b55dfbbe5dbfaf504c8.tar.bz2
Import IsaFloppy Dxe and Pei in IntelFrameworkModulePkg.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2/IntelFrameworkModulePkg@3168 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'Bus')
-rw-r--r--Bus/Isa/IsaFloppy/Dxe/ComponentName.c239
-rw-r--r--Bus/Isa/IsaFloppy/Dxe/ComponentName.h111
-rw-r--r--Bus/Isa/IsaFloppy/Dxe/EntryPoint.c55
-rw-r--r--Bus/Isa/IsaFloppy/Dxe/IsaFloppy.c451
-rw-r--r--Bus/Isa/IsaFloppy/Dxe/IsaFloppy.h1321
-rw-r--r--Bus/Isa/IsaFloppy/Dxe/IsaFloppy.inf109
-rw-r--r--Bus/Isa/IsaFloppy/Dxe/IsaFloppy.msa105
-rw-r--r--Bus/Isa/IsaFloppy/Dxe/IsaFloppyBlock.c458
-rw-r--r--Bus/Isa/IsaFloppy/Dxe/IsaFloppyCtrl.c1551
-rw-r--r--Bus/Isa/IsaFloppy/Pei/Fdc.h215
-rw-r--r--Bus/Isa/IsaFloppy/Pei/FloppyPeim.c1785
-rw-r--r--Bus/Isa/IsaFloppy/Pei/FloppyPeim.dxs34
-rw-r--r--Bus/Isa/IsaFloppy/Pei/FloppyPeim.h254
-rw-r--r--Bus/Isa/IsaFloppy/Pei/FloppyPeim.inf103
-rw-r--r--Bus/Isa/IsaFloppy/Pei/FloppyPeim.msa72
15 files changed, 6863 insertions, 0 deletions
diff --git a/Bus/Isa/IsaFloppy/Dxe/ComponentName.c b/Bus/Isa/IsaFloppy/Dxe/ComponentName.c
new file mode 100644
index 0000000..cffb930
--- /dev/null
+++ b/Bus/Isa/IsaFloppy/Dxe/ComponentName.c
@@ -0,0 +1,239 @@
+/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved. <BR>
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ ComponentName.c
+
+Abstract:
+
+--*/
+
+#include "IsaFloppy.h"
+
+//
+// EFI Component Name Protocol
+//
+EFI_COMPONENT_NAME_PROTOCOL gIsaFloppyComponentName = {
+ IsaFloppyComponentNameGetDriverName,
+ IsaFloppyComponentNameGetControllerName,
+ "eng"
+};
+
+STATIC EFI_UNICODE_STRING_TABLE mIsaFloppyDriverNameTable[] = {
+ {
+ "eng",
+ L"ISA Floppy Driver"
+ },
+ {
+ NULL,
+ NULL
+ }
+};
+
+EFI_STATUS
+EFIAPI
+IsaFloppyComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+/*++
+
+ Routine Description:
+
+ Retrieves a Unicode string that is the user readable name of the EFI Driver.
+
+ Arguments:
+
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ Language - A pointer to a three character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ DriverName - A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ Returns:
+
+ EFI_SUCCESS - The Unicode string for the Driver specified by This
+ and the language specified by Language was returned
+ in DriverName.
+ EFI_INVALID_PARAMETER - Language is NULL.
+ EFI_INVALID_PARAMETER - DriverName is NULL.
+ EFI_UNSUPPORTED - The driver specified by This does not support the
+ language specified by Language.
+
+--*/
+{
+ return LookupUnicodeString (
+ Language,
+ gIsaFloppyComponentName.SupportedLanguages,
+ mIsaFloppyDriverNameTable,
+ DriverName
+ );
+}
+
+EFI_STATUS
+EFIAPI
+IsaFloppyComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+/*++
+
+ Routine Description:
+
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI Driver.
+
+ Arguments:
+
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ ControllerHandle - The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ ChildHandle - The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device drivers. It will also be NULL
+ for a bus drivers that wish to retrieve the name of the
+ bus controller. It will not be NULL for a bus driver
+ that wishes to retrieve the name of a child controller.
+ Language - A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ ControllerName - A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language
+ specified by Language from the point of view of the
+ driver specified by This.
+
+ Returns:
+
+ EFI_SUCCESS - The Unicode string for the user readable name in the
+ language specified by Language for the driver
+ specified by This was returned in DriverName.
+ EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+ EFI_INVALID_PARAMETER - Language is NULL.
+ EFI_INVALID_PARAMETER - ControllerName is NULL.
+ EFI_UNSUPPORTED - The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+ EFI_UNSUPPORTED - The driver specified by This does not support the
+ language specified by Language.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;
+ FDC_BLK_IO_DEV *FdcDev;
+ EFI_ISA_IO_PROTOCOL *IsaIoProtocol;
+
+ //
+ // This is a device driver, so ChildHandle must be NULL.
+ //
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Check Controller's handle
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiIsaIoProtocolGuid,
+ (VOID **) &IsaIoProtocol,
+ gFdcControllerDriver.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (!EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiIsaIoProtocolGuid,
+ gFdcControllerDriver.DriverBindingHandle,
+ ControllerHandle
+ );
+
+ return EFI_UNSUPPORTED;
+ }
+
+ if (Status != EFI_ALREADY_STARTED) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Get the Block I/O Protocol on Controller
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlkIo,
+ gFdcControllerDriver.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Get the Floppy Disk Controller's Device structure
+ //
+ FdcDev = FDD_BLK_IO_FROM_THIS (BlkIo);
+
+ return LookupUnicodeString (
+ Language,
+ gIsaFloppyComponentName.SupportedLanguages,
+ FdcDev->ControllerNameTable,
+ ControllerName
+ );
+}
+
+VOID
+AddName (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+ Routine Description:
+
+ Add the component name for the floppy device
+
+ Arguments:
+
+ FdcDev - A pointer to the FDC_BLK_IO_DEV instance.
+
+ Returns:
+
+ None
+
+--*/
+{
+ CHAR16 FloppyDriveName[FLOPPY_DRIVE_NAME_ASCII_LEN + 1];
+
+ StrCpy (FloppyDriveName, FLOPPY_DRIVE_NAME);
+ FloppyDriveName[FLOPPY_DRIVE_NAME_ASCII_LEN - 1] = (CHAR16) (L'0' + FdcDev->Disk);
+ AddUnicodeString (
+ "eng",
+ gIsaFloppyComponentName.SupportedLanguages,
+ &FdcDev->ControllerNameTable,
+ FloppyDriveName
+ );
+}
diff --git a/Bus/Isa/IsaFloppy/Dxe/ComponentName.h b/Bus/Isa/IsaFloppy/Dxe/ComponentName.h
new file mode 100644
index 0000000..be4fdb5
--- /dev/null
+++ b/Bus/Isa/IsaFloppy/Dxe/ComponentName.h
@@ -0,0 +1,111 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation. All rights reserved.
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+Module Name:
+
+ ComponentName.h
+
+Abstract:
+
+Revision History:
+
+--*/
+
+#ifndef _ISA_FLOPPY_COMPONENT_NAME_H
+#define _ISA_FLOPPY_COMPONENT_NAME_H
+
+#define FLOPPY_DRIVE_NAME L"ISA Floppy Drive # "
+#define FLOPPY_DRIVE_NAME_ASCII_LEN (sizeof ("ISA Floppy Drive # ") - 1)
+#define ADD_FLOPPY_NAME(x) AddName ((x))
+
+extern EFI_COMPONENT_NAME_PROTOCOL gIsaFloppyComponentName;
+
+//
+// EFI Component Name Functions
+//
+EFI_STATUS
+EFIAPI
+IsaFloppyComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ Language - GC_TODO: add argument description
+ DriverName - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+IsaFloppyComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ ControllerHandle - GC_TODO: add argument description
+ ChildHandle - GC_TODO: add argument description
+ Language - GC_TODO: add argument description
+ ControllerName - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+VOID
+AddName (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcDev - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/Bus/Isa/IsaFloppy/Dxe/EntryPoint.c b/Bus/Isa/IsaFloppy/Dxe/EntryPoint.c
new file mode 100644
index 0000000..451d4cb
--- /dev/null
+++ b/Bus/Isa/IsaFloppy/Dxe/EntryPoint.c
@@ -0,0 +1,55 @@
+/**@file
+ Entry Point Source file.
+
+ This file contains the user entry point
+
+ Copyright (c) 2006 - 2007, Intel Corporation.
+ All rights reserved.
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.
+**/
+
+
+#include "IsaFloppy.h"
+
+/**
+ The user Entry Point for module IsaFloppy. The user code starts with this function.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeIsaFloppy(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Install driver model protocol(s).
+ //
+ Status = EfiLibInstallAllDriverProtocols (
+ ImageHandle,
+ SystemTable,
+ &gFdcControllerDriver,
+ ImageHandle,
+ &gIsaFloppyComponentName,
+ NULL,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+
+ return Status;
+}
diff --git a/Bus/Isa/IsaFloppy/Dxe/IsaFloppy.c b/Bus/Isa/IsaFloppy/Dxe/IsaFloppy.c
new file mode 100644
index 0000000..483e750
--- /dev/null
+++ b/Bus/Isa/IsaFloppy/Dxe/IsaFloppy.c
@@ -0,0 +1,451 @@
+/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved. <BR>
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+Module Name:
+
+ IsaFloppy.c
+
+Abstract:
+
+ ISA Floppy Driver
+ 1. Support two types diskette drive
+ 1.44M drive and 2.88M drive (and now only support 1.44M)
+ 2. Support two diskette drives
+ 3. Use DMA channel 2 to transfer data
+ 4. Do not use interrupt
+ 5. Support diskette change line signal and write protect
+
+ conforming to EFI driver model
+
+Revision History:
+
+--*/
+
+#include "IsaFloppy.h"
+
+LIST_ENTRY gControllerHead = INITIALIZE_LIST_HEAD_VARIABLE(gControllerHead);
+
+//
+// ISA Floppy Driver Binding Protocol
+//
+EFI_DRIVER_BINDING_PROTOCOL gFdcControllerDriver = {
+ FdcControllerDriverSupported,
+ FdcControllerDriverStart,
+ FdcControllerDriverStop,
+ 0xa,
+ NULL,
+ NULL
+};
+
+EFI_STATUS
+EFIAPI
+FdcControllerDriverSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+Routine Description:
+
+ ControllerDriver Protocol Method
+
+Arguments:
+
+Returns:
+
+--*/
+// GC_TODO: This - add argument and description to function comment
+// GC_TODO: Controller - add argument and description to function comment
+// GC_TODO: RemainingDevicePath - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ EFI_ISA_IO_PROTOCOL *IsaIo;
+
+ //
+ // Open the ISA I/O Protocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiIsaIoProtocolGuid,
+ (VOID **) &IsaIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Use the ISA I/O Protocol to see if Controller is a Floppy Disk Controller
+ //
+ Status = EFI_SUCCESS;
+ if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x604)) {
+ Status = EFI_UNSUPPORTED;
+ }
+ //
+ // Close the ISA I/O Protocol
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiIsaIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+FdcControllerDriverStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+// GC_TODO: This - add argument and description to function comment
+// GC_TODO: Controller - add argument and description to function comment
+// GC_TODO: RemainingDevicePath - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ FDC_BLK_IO_DEV *FdcDev;
+ EFI_ISA_IO_PROTOCOL *IsaIo;
+ UINTN Index;
+ LIST_ENTRY *List;
+ BOOLEAN Found;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+
+ FdcDev = NULL;
+ IsaIo = NULL;
+
+ //
+ // Open the device path protocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Report enable progress code
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_ENABLE,
+ ParentDevicePath
+ );
+
+ //
+ // Open the ISA I/O Protocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiIsaIoProtocolGuid,
+ (VOID **) &IsaIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ //
+ // Allocate the Floppy Disk Controller's Device structure
+ //
+ FdcDev = AllocateZeroPool (sizeof (FDC_BLK_IO_DEV));
+ if (FdcDev == NULL) {
+ goto Done;
+ }
+ //
+ // Initialize the Floppy Disk Controller's Device structure
+ //
+ FdcDev->Signature = FDC_BLK_IO_DEV_SIGNATURE;
+ FdcDev->Handle = Controller;
+ FdcDev->IsaIo = IsaIo;
+ FdcDev->Disk = (EFI_FDC_DISK) IsaIo->ResourceList->Device.UID;
+ FdcDev->Cache = NULL;
+ FdcDev->Event = NULL;
+ FdcDev->ControllerState = NULL;
+ FdcDev->DevicePath = ParentDevicePath;
+
+ ADD_FLOPPY_NAME (FdcDev);
+
+ //
+ // Look up the base address of the Floppy Disk Controller
+ //
+ for (Index = 0; FdcDev->IsaIo->ResourceList->ResourceItem[Index].Type != EfiIsaAcpiResourceEndOfList; Index++) {
+ if (FdcDev->IsaIo->ResourceList->ResourceItem[Index].Type == EfiIsaAcpiResourceIo) {
+ FdcDev->BaseAddress = (UINT16) FdcDev->IsaIo->ResourceList->ResourceItem[Index].StartRange;
+ }
+ }
+ //
+ // Maintain the list of controller list
+ //
+ Found = FALSE;
+ List = gControllerHead.ForwardLink;
+ while (List != &gControllerHead) {
+ FdcDev->ControllerState = FLOPPY_CONTROLLER_FROM_LIST_ENTRY (List);
+ if (FdcDev->BaseAddress == FdcDev->ControllerState->BaseAddress) {
+ Found = TRUE;
+ break;
+ }
+
+ List = List->ForwardLink;
+ }
+
+ if (!Found) {
+ //
+ // The Controller is new
+ //
+ FdcDev->ControllerState = AllocatePool (sizeof (FLOPPY_CONTROLLER_CONTEXT));
+ if (FdcDev->ControllerState == NULL) {
+ goto Done;
+ }
+
+ FdcDev->ControllerState->Signature = FLOPPY_CONTROLLER_CONTEXT_SIGNATURE;
+ FdcDev->ControllerState->FddResetPerformed = FALSE;
+ FdcDev->ControllerState->NeedRecalibrate = FALSE;
+ FdcDev->ControllerState->BaseAddress = FdcDev->BaseAddress;
+ FdcDev->ControllerState->NumberOfDrive = 0;
+
+ InsertTailList (&gControllerHead, &FdcDev->ControllerState->Link);
+ }
+ //
+ // Create a timer event for each Floppd Disk Controller.
+ // This timer event is used to control the motor on and off
+ //
+ Status = gBS->CreateEvent (
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ FddTimerProc,
+ FdcDev,
+ &FdcDev->Event
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ //
+ // Reset the Floppy Disk Controller
+ //
+ if (!FdcDev->ControllerState->FddResetPerformed) {
+ FdcDev->ControllerState->FddResetPerformed = TRUE;
+ FdcDev->ControllerState->FddResetStatus = FddReset (FdcDev);
+ }
+
+ if (EFI_ERROR (FdcDev->ControllerState->FddResetStatus)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_PRESENCE_DETECT,
+ ParentDevicePath
+ );
+
+ //
+ // Discover the Floppy Drive
+ //
+ Status = DiscoverFddDevice (FdcDev);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+ //
+ // Install protocol interfaces for the serial device.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Controller,
+ &gEfiBlockIoProtocolGuid,
+ &FdcDev->BlkIo,
+ NULL
+ );
+
+ FdcDev->ControllerState->NumberOfDrive++;
+
+Done:
+ if (EFI_ERROR (Status)) {
+
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_CONTROLLER_ERROR,
+ ParentDevicePath
+ );
+
+ //
+ // Close the device path protocol
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ //
+ // Close the ISA I/O Protocol
+ //
+ if (IsaIo != NULL) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiIsaIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+ //
+ // If a Floppy Disk Controller Device structure was allocated, then free it
+ //
+ if (FdcDev != NULL) {
+ if (FdcDev->Event != NULL) {
+ //
+ // Close the event for turning the motor off
+ //
+ gBS->CloseEvent (FdcDev->Event);
+ }
+
+ FreeUnicodeStringTable (FdcDev->ControllerNameTable);
+ gBS->FreePool (FdcDev);
+ }
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+FdcControllerDriverStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+/*++
+
+ Routine Description:
+
+ Arguments:
+
+ Returns:
+
+--*/
+// GC_TODO: This - add argument and description to function comment
+// GC_TODO: Controller - add argument and description to function comment
+// GC_TODO: NumberOfChildren - add argument and description to function comment
+// GC_TODO: ChildHandleBuffer - add argument and description to function comment
+// GC_TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;
+ FDC_BLK_IO_DEV *FdcDev;
+
+ //
+ // Get the Block I/O Protocol on Controller
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlkIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Get the Floppy Disk Controller's Device structure
+ //
+ FdcDev = FDD_BLK_IO_FROM_THIS (BlkIo);
+
+ //
+ // Report disable progress code
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_DISABLE,
+ FdcDev->DevicePath
+ );
+
+ //
+ // Turn the motor off on the Floppy Disk Controller
+ //
+ FddTimerProc (FdcDev->Event, FdcDev);
+
+ //
+ // Uninstall the Block I/O Protocol
+ //
+ Status = gBS->UninstallProtocolInterface (
+ Controller,
+ &gEfiBlockIoProtocolGuid,
+ &FdcDev->BlkIo
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Close the device path protocol
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ //
+ // Close the ISA I/O Protocol
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiIsaIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ //
+ // Free the controller list if needed
+ //
+ FdcDev->ControllerState->NumberOfDrive--;
+
+ //
+ // Close the event for turning the motor off
+ //
+ gBS->CloseEvent (FdcDev->Event);
+
+ //
+ // Free the cache if one was allocated
+ //
+ FdcFreeCache (FdcDev);
+
+ //
+ // Free the Floppy Disk Controller's Device structure
+ //
+ FreeUnicodeStringTable (FdcDev->ControllerNameTable);
+ gBS->FreePool (FdcDev);
+
+ return EFI_SUCCESS;
+}
diff --git a/Bus/Isa/IsaFloppy/Dxe/IsaFloppy.h b/Bus/Isa/IsaFloppy/Dxe/IsaFloppy.h
new file mode 100644
index 0000000..c2bf78d
--- /dev/null
+++ b/Bus/Isa/IsaFloppy/Dxe/IsaFloppy.h
@@ -0,0 +1,1321 @@
+/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+Module Name:
+
+ IsaFloppy.h
+
+Abstract:
+
+ Include for ISA Floppy Driver
+ Define the data structure and so on
+
+Revision History:
+
+--*/
+
+#ifndef _ISA_FLOPPY_H
+#define _ISA_FLOPPY_H
+
+#include <PiDxe.h>
+#include <FrameworkPei.h>
+//
+// The protocols, PPI and GUID defintions for this module
+//
+#include <Protocol/BlockIo.h>
+#include <Protocol/IsaIo.h>
+#include <Protocol/DevicePath.h>
+//
+// The Library classes this module consumes
+//
+#include <Library/TimerLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/ReportStatusCodeLib.h>
+//
+// Driver Binding Externs
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gFdcControllerDriver;
+extern EFI_COMPONENT_NAME_PROTOCOL gIsaFloppyComponentName;
+
+//
+// define some value
+//
+#define STALL_1_SECOND 1000000
+#define STALL_1_MSECOND 1000
+
+#define DATA_IN 1
+#define DATA_OUT 0
+#define READ 0
+#define WRITE 1
+
+//
+// Internal Data Structures
+//
+#define FDC_BLK_IO_DEV_SIGNATURE EFI_SIGNATURE_32 ('F', 'B', 'I', 'O')
+#define FLOPPY_CONTROLLER_CONTEXT_SIGNATURE EFI_SIGNATURE_32 ('F', 'D', 'C', 'C')
+
+typedef enum {
+ FDC_DISK0 = 0,
+ FDC_DISK1 = 1,
+ FDC_MAX_DISK= 2
+} EFI_FDC_DISK;
+
+typedef struct {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+ BOOLEAN FddResetPerformed;
+ EFI_STATUS FddResetStatus;
+ BOOLEAN NeedRecalibrate;
+ UINT8 NumberOfDrive;
+ UINT16 BaseAddress;
+} FLOPPY_CONTROLLER_CONTEXT;
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ EFI_BLOCK_IO_PROTOCOL BlkIo;
+ EFI_BLOCK_IO_MEDIA BlkMedia;
+
+ EFI_ISA_IO_PROTOCOL *IsaIo;
+
+ UINT16 BaseAddress;
+
+ EFI_FDC_DISK Disk;
+ UINT8 PresentCylinderNumber;
+ UINT8 *Cache;
+
+ EFI_EVENT Event;
+ EFI_UNICODE_STRING_TABLE *ControllerNameTable;
+ FLOPPY_CONTROLLER_CONTEXT *ControllerState;
+
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+} FDC_BLK_IO_DEV;
+
+#include "ComponentName.h"
+
+#define FDD_BLK_IO_FROM_THIS(a) CR (a, FDC_BLK_IO_DEV, BlkIo, FDC_BLK_IO_DEV_SIGNATURE)
+#define FLOPPY_CONTROLLER_FROM_LIST_ENTRY(a) \
+ CR (a, \
+ FLOPPY_CONTROLLER_CONTEXT, \
+ Link, \
+ FLOPPY_CONTROLLER_CONTEXT_SIGNATURE \
+ )
+
+#define DISK_1440K_EOT 0x12
+#define DISK_1440K_GPL 0x1b
+#define DISK_1440K_DTL 0xff
+#define DISK_1440K_NUMBER 0x02
+#define DISK_1440K_MAXTRACKNUM 0x4f
+#define DISK_1440K_BYTEPERSECTOR 512
+
+typedef struct {
+ UINT8 CommandCode;
+ UINT8 DiskHeadSel;
+ UINT8 Cylinder;
+ UINT8 Head;
+ UINT8 Sector;
+ UINT8 Number;
+ UINT8 EndOfTrack;
+ UINT8 GapLength;
+ UINT8 DataLength;
+} FDD_COMMAND_PACKET1;
+
+typedef struct {
+ UINT8 CommandCode;
+ UINT8 DiskHeadSel;
+} FDD_COMMAND_PACKET2;
+
+typedef struct {
+ UINT8 CommandCode;
+ UINT8 SrtHut;
+ UINT8 HltNd;
+} FDD_SPECIFY_CMD;
+
+typedef struct {
+ UINT8 CommandCode;
+ UINT8 DiskHeadSel;
+ UINT8 NewCylinder;
+} FDD_SEEK_CMD;
+
+typedef struct {
+ UINT8 CommandCode;
+ UINT8 DiskHeadSel;
+ UINT8 Cylinder;
+ UINT8 Head;
+ UINT8 Sector;
+ UINT8 EndOfTrack;
+ UINT8 GapLength;
+ UINT8 ScanTestPause;
+} FDD_SCAN_CMD;
+
+typedef struct {
+ UINT8 Status0;
+ UINT8 Status1;
+ UINT8 Status2;
+ UINT8 C;
+ UINT8 H;
+ UINT8 S;
+ UINT8 Number;
+} FDD_RESULT_PACKET;
+
+//
+// FDC Registers
+//
+//
+// 0x3F2 Digital Output Register
+//
+#define FDC_REGISTER_DOR 2
+
+//
+// 0x3F4 Main Status Register
+//
+#define FDC_REGISTER_MSR 4
+
+//
+// 0x3F5 Data Register
+//
+#define FDC_REGISTER_DTR 5
+
+//
+// 0x3F7 Configuration Control Register(data rate select)
+//
+#define FDC_REGISTER_CCR 7
+
+//
+// 0x3F7 Digital Input Register(diskchange)
+//
+#define FDC_REGISTER_DIR 7
+
+
+
+//
+// FDC Register Bit Definitions
+//
+//
+// Digital Out Register(WO)
+//
+//
+// Select Drive: 0=A 1=B
+//
+#define SELECT_DRV BIT0
+
+//
+// Reset FDC
+//
+#define RESET_FDC BIT2
+
+//
+// Enable Int & DMA
+//
+#define INT_DMA_ENABLE BIT3
+
+//
+// Turn On Drive A Motor
+//
+#define DRVA_MOTOR_ON BIT4
+
+//
+// Turn On Drive B Motor
+//
+#define DRVB_MOTOR_ON BIT5
+
+//
+// Main Status Register(RO)
+//
+//
+// Drive A Busy
+//
+#define MSR_DAB BIT0
+
+//
+// Drive B Busy
+//
+#define MSR_DBB BIT1
+
+//
+// FDC Busy
+//
+#define MSR_CB BIT4
+
+//
+// Non-DMA Mode
+//
+#define MSR_NDM BIT5
+
+//
+// Data Input/Output
+//
+#define MSR_DIO BIT6
+
+//
+// Request For Master
+//
+#define MSR_RQM BIT7
+
+//
+// Configuration Control Register(WO)
+//
+//
+// Data Rate select
+//
+#define CCR_DRC (BIT0 | BIT1)
+
+//
+// Digital Input Register(RO)
+//
+//
+// Disk change line
+//
+#define DIR_DCL BIT7
+//
+// #define CCR_DCL BIT7 // Diskette change
+//
+// 500K
+//
+#define DRC_500KBS 0x0
+
+//
+// 300K
+//
+#define DRC_300KBS 0x01
+
+//
+// 250K
+//
+#define DRC_250KBS 0x02
+
+//
+// FDC Command Code
+//
+#define READ_DATA_CMD 0x06
+#define WRITE_DATA_CMD 0x05
+#define WRITE_DEL_DATA_CMD 0x09
+#define READ_DEL_DATA_CMD 0x0C
+#define READ_TRACK_CMD 0x02
+#define READ_ID_CMD 0x0A
+#define FORMAT_TRACK_CMD 0x0D
+#define SCAN_EQU_CMD 0x11
+#define SCAN_LOW_EQU_CMD 0x19
+#define SCAN_HIGH_EQU_CMD 0x1D
+#define SEEK_CMD 0x0F
+#define RECALIBRATE_CMD 0x07
+#define SENSE_INT_STATUS_CMD 0x08
+#define SPECIFY_CMD 0x03
+#define SENSE_DRV_STATUS_CMD 0x04
+
+//
+// CMD_MT: Multi_Track Selector
+// when set , this flag selects the multi-track operating mode.
+// In this mode, the FDC treats a complete cylinder under head0 and 1
+// as a single track
+//
+#define CMD_MT BIT7
+
+//
+// CMD_MFM: MFM/FM Mode Selector
+// A one selects the double density(MFM) mode
+// A zero selects single density (FM) mode
+//
+#define CMD_MFM BIT6
+
+//
+// CMD_SK: Skip Flag
+// When set to 1, sectors containing a deleted data address mark will
+// automatically be skipped during the execution of Read Data.
+// When set to 0, the sector is read or written the same as the read and
+// write commands.
+//
+#define CMD_SK BIT5
+
+//
+// FDC Status Register Bit Definitions
+//
+//
+// Status Register 0
+//
+//
+// Interrupt Code
+//
+#define STS0_IC (BIT7 | BIT6)
+
+//
+// Seek End: the FDC completed a seek or recalibrate command
+//
+#define STS0_SE BIT5
+
+//
+// Equipment Check
+//
+#define STS0_EC BIT4
+
+//
+// Not Ready(unused), this bit is always 0
+//
+#define STS0_NR BIT3
+
+//
+// Head Address: the current head address
+//
+#define STS0_HA BIT2
+
+//
+// STS0_US1 & STS0_US0: Drive Select(the current selected drive)
+//
+//
+// Unit Select1
+//
+#define STS0_US1 BIT1
+
+//
+// Unit Select0
+//
+#define STS0_US0 BIT0
+
+//
+// Status Register 1
+//
+//
+// End of Cylinder
+//
+#define STS1_EN BIT7
+
+//
+// BIT6 is unused
+//
+//
+// Data Error: The FDC detected a CRC error in either the ID field or
+// data field of a sector
+//
+#define STS1_DE BIT5
+
+//
+// Overrun/Underrun: Becomes set if FDC does not receive CPU or DMA service
+// within the required time interval
+//
+#define STS1_OR BIT4
+
+//
+// BIT3 is unused
+//
+//
+// No data
+//
+#define STS1_ND BIT2
+
+//
+// Not Writable
+//
+#define STS1_NW BIT1
+
+//
+// Missing Address Mark
+//
+#define STS1_MA BIT0
+
+//
+// Control Mark
+//
+#define STS2_CM BIT6
+
+//
+// Data Error in Data Field: The FDC detected a CRC error in the data field
+//
+#define STS2_DD BIT5
+
+//
+// Wrong Cylinder: The track address from sector ID field is different from
+// the track address maintained inside FDC
+//
+#define STS2_WC BIT4
+
+//
+// Bad Cylinder
+//
+#define STS2_BC BIT1
+
+//
+// Missing Address Mark in Data Field
+//
+#define STS2_MD BIT0
+
+//
+// Write Protected
+//
+#define STS3_WP BIT6
+
+//
+// Track 0
+//
+#define STS3_T0 BIT4
+
+//
+// Head Address
+//
+#define STS3_HD BIT2
+
+//
+// STS3_US1 & STS3_US0 : Drive Select
+//
+#define STS3_US1 BIT1
+#define STS3_US0 BIT0
+
+//
+// Status Register 0 Interrupt Code Description
+//
+//
+// Normal Termination of Command
+//
+#define IC_NT 0x0
+
+//
+// Abnormal Termination of Command
+//
+#define IC_AT 0x40
+
+//
+// Invalid Command
+//
+#define IC_IC 0x80
+
+//
+// Abnormal Termination caused by Polling
+//
+#define IC_ATRC 0xC0
+
+//
+// Global Variables
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gFdcControllerDriver;
+
+//
+// EFI Driver Binding Protocol Functions
+//
+EFI_STATUS
+EFIAPI
+FdcControllerDriverSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ Controller - GC_TODO: add argument description
+ RemainingDevicePath - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+FdcControllerDriverStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ Controller - GC_TODO: add argument description
+ RemainingDevicePath - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+FdcControllerDriverStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ Controller - GC_TODO: add argument description
+ NumberOfChildren - GC_TODO: add argument description
+ ChildHandleBuffer - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+//
+// EFI Block I/O Protocol Functions
+//
+EFI_STATUS
+EFIAPI
+FdcReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ ExtendedVerification - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+FddFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+FddReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ MediaId - GC_TODO: add argument description
+ LBA - GC_TODO: add argument description
+ BufferSize - GC_TODO: add argument description
+ Buffer - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+FddWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ MediaId - GC_TODO: add argument description
+ LBA - GC_TODO: add argument description
+ BufferSize - GC_TODO: add argument description
+ Buffer - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+//
+// Prototypes of internal functions
+//
+EFI_STATUS
+DiscoverFddDevice (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcDev - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+FddIdentify (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcDev - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+FddReset (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcDev - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+MotorOn (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcDev - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+MotorOff (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcDev - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+DisketChanged (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcDev - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+Specify (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcDev - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+Recalibrate (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcDev - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+Seek (
+ IN FDC_BLK_IO_DEV *FdcDev,
+ IN EFI_LBA Lba
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcDev - GC_TODO: add argument description
+ Lba - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+SenseIntStatus (
+ IN FDC_BLK_IO_DEV *FdcDev,
+ IN OUT UINT8 *StatusRegister0,
+ IN OUT UINT8 *PresentCylinderNumber
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcDev - GC_TODO: add argument description
+ StatusRegister0 - GC_TODO: add argument description
+ PresentCylinderNumber - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+SenseDrvStatus (
+ IN FDC_BLK_IO_DEV *FdcDev,
+ IN EFI_LBA Lba
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcDev - GC_TODO: add argument description
+ Lba - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+DetectMedia (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcDev - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+Setup (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcDev - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+ReadWriteDataSector (
+ IN FDC_BLK_IO_DEV *FdcDev,
+ IN VOID *HostAddress,
+ IN EFI_LBA Lba,
+ IN UINTN NumberOfBlocks,
+ IN BOOLEAN Read
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcDev - GC_TODO: add argument description
+ HostAddress - GC_TODO: add argument description
+ Lba - GC_TODO: add argument description
+ NumberOfBlocks - GC_TODO: add argument description
+ Read - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+VOID
+FillPara (
+ IN FDC_BLK_IO_DEV *FdcDev,
+ IN EFI_LBA Lba,
+ IN FDD_COMMAND_PACKET1 *Command
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcDev - GC_TODO: add argument description
+ Lba - GC_TODO: add argument description
+ Command - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+DataInByte (
+ IN FDC_BLK_IO_DEV *FdcDev,
+ IN UINT8 *Pointer
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcDev - GC_TODO: add argument description
+ Pointer - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+DataOutByte (
+ IN FDC_BLK_IO_DEV *FdcDev,
+ IN UINT8 *Pointer
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcDev - GC_TODO: add argument description
+ Pointer - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+FddWaitForBSYClear (
+ IN FDC_BLK_IO_DEV *FdcDev,
+ IN UINTN TimeoutInSeconds
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcDev - GC_TODO: add argument description
+ TimeoutInSeconds - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+FddDRQReady (
+ IN FDC_BLK_IO_DEV *FdcDev,
+ IN BOOLEAN Dio,
+ IN UINTN TimeoutInSeconds
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcDev - GC_TODO: add argument description
+ Dio - GC_TODO: add argument description
+ TimeoutInSeconds - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+CheckResult (
+ IN FDD_RESULT_PACKET *Result,
+ IN OUT FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Result - GC_TODO: add argument description
+ FdcDev - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+CheckStatus3 (
+ IN UINT8 StatusRegister3
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ StatusRegister3 - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+UINTN
+GetTransferBlockCount (
+ IN FDC_BLK_IO_DEV *FdcDev,
+ IN EFI_LBA LBA,
+ IN UINTN NumberOfBlocks
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcDev - GC_TODO: add argument description
+ LBA - GC_TODO: add argument description
+ NumberOfBlocks - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+VOID
+EFIAPI
+FddTimerProc (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Event - GC_TODO: add argument description
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+UINT8
+FdcReadPort (
+ IN FDC_BLK_IO_DEV *FdcDev,
+ IN UINT32 Offset
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcDev - GC_TODO: add argument description
+ Offset - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+VOID
+FdcWritePort (
+ IN FDC_BLK_IO_DEV *FdcDev,
+ IN UINT32 Offset,
+ IN UINT8 Data
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcDev - GC_TODO: add argument description
+ Offset - GC_TODO: add argument description
+ Data - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+FddReadWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ IN BOOLEAN Operation,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ MediaId - GC_TODO: add argument description
+ LBA - GC_TODO: add argument description
+ BufferSize - GC_TODO: add argument description
+ Operation - GC_TODO: add argument description
+ Buffer - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+VOID
+FdcFreeCache (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcDev - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/Bus/Isa/IsaFloppy/Dxe/IsaFloppy.inf b/Bus/Isa/IsaFloppy/Dxe/IsaFloppy.inf
new file mode 100644
index 0000000..906cc96
--- /dev/null
+++ b/Bus/Isa/IsaFloppy/Dxe/IsaFloppy.inf
@@ -0,0 +1,109 @@
+#/** @file
+# Component description file for IsaFloppy module.
+#
+# ISA Floppy Driver
+# 1. Support two types diskette drive
+# 1.44M drive and 2.88M drive (and now only support 1.44M)
+# 2. Support two diskette drives
+# 3. Use DMA channel 2 to transfer data
+# 4. Do not use interrupt
+# 5. Support diskette change line signal and write protect
+#
+# Conforming to EFI driver model
+# Copyright (c) 2006 - 2007, Intel Corporation.
+#
+# All rights reserved.
+# This software and associated documentation (if any) is furnished
+# under a license and may only be used or copied in accordance
+# with the terms of the license. Except as permitted by such
+# license, no part of this software or documentation may be
+# reproduced, stored in a retrieval system, or transmitted in any
+# form or by any means without the express written consent of
+# Intel Corporation.
+#
+#
+#**/
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = IsaFloppy
+ FILE_GUID = 0abd8284-6da3-4616-971a-83a5148067ba
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+
+ ENTRY_POINT = InitializeIsaFloppy
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+# DRIVER_BINDING = gFdcControllerDriver
+# COMPONENT_NAME = gIsaFloppyComponentName
+# Create Event Guid C Name: Event Type: EVENT_TYPE_PERIODIC_TIMER
+#
+#
+
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+
+[Sources.common]
+ ComponentName.c
+ ComponentName.h
+ IsaFloppyCtrl.c
+ IsaFloppyBlock.c
+ IsaFloppy.c
+ IsaFloppy.h
+ EntryPoint.c
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+# this module.
+#
+################################################################################
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+
+################################################################################
+#
+# Library Class Section - list of Library Classes that are required for
+# this module.
+#
+################################################################################
+
+[LibraryClasses]
+ ReportStatusCodeLib
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ BaseMemoryLib
+ UefiLib
+ BaseLib
+ UefiDriverEntryPoint
+ DebugLib
+ TimerLib
+
+
+################################################################################
+#
+# Protocol C Name Section - list of Protocol and Protocol Notify C Names
+# that this module uses or produces.
+#
+################################################################################
+
+[Protocols]
+ gEfiIsaIoProtocolGuid # PROTOCOL TO_START
+ gEfiBlockIoProtocolGuid # PROTOCOL BY_START
+ gEfiDevicePathProtocolGuid # PROTOCOL TO_START
+
diff --git a/Bus/Isa/IsaFloppy/Dxe/IsaFloppy.msa b/Bus/Isa/IsaFloppy/Dxe/IsaFloppy.msa
new file mode 100644
index 0000000..7e9fb24
--- /dev/null
+++ b/Bus/Isa/IsaFloppy/Dxe/IsaFloppy.msa
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ModuleSurfaceArea xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd" xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <MsaHeader>
+ <ModuleName>IsaFloppy</ModuleName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <GuidValue>0abd8284-6da3-4616-971a-83a5148067ba</GuidValue>
+ <Version>1.0</Version>
+ <Abstract>Component description file for IsaFloppy module.</Abstract>
+ <Description>ISA Floppy Driver
+ 1. Support two types diskette drive
+ 1.44M drive and 2.88M drive (and now only support 1.44M)
+ 2. Support two diskette drives
+ 3. Use DMA channel 2 to transfer data
+ 4. Do not use interrupt
+ 5. Support diskette change line signal and write protect
+
+ Conforming to EFI driver model</Description>
+ <Copyright>Copyright (c) 2006 - 2007, Intel Corporation.</Copyright>
+ <License>All rights reserved.
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.</License>
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
+ </MsaHeader>
+ <ModuleDefinitions>
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
+ <BinaryModule>false</BinaryModule>
+ <OutputFileBasename>IsaFloppy</OutputFileBasename>
+ </ModuleDefinitions>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>TimerLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DebugLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiDriverModelLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiDriverEntryPoint</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseMemoryLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>MemoryAllocationLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiBootServicesTableLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>ReportStatusCodeLib</Keyword>
+ </LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>IsaFloppy.h</Filename>
+ <Filename>IsaFloppy.c</Filename>
+ <Filename>IsaFloppyBlock.c</Filename>
+ <Filename>IsaFloppyCtrl.c</Filename>
+ <Filename>ComponentName.h</Filename>
+ <Filename>ComponentName.c</Filename>
+ </SourceFiles>
+ <PackageDependencies>
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
+ <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
+ </PackageDependencies>
+ <Protocols>
+ <Protocol Usage="TO_START">
+ <ProtocolCName>gEfiDevicePathProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="BY_START">
+ <ProtocolCName>gEfiBlockIoProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="TO_START">
+ <ProtocolCName>gEfiIsaIoProtocolGuid</ProtocolCName>
+ </Protocol>
+ </Protocols>
+ <Events>
+ <CreateEvents>
+ <EventTypes Usage="ALWAYS_CONSUMED">
+ <EventType>EVENT_TYPE_PERIODIC_TIMER</EventType>
+ <HelpText>Timer event for each Floppd Disk Controller to control the motor on and off.</HelpText>
+ </EventTypes>
+ </CreateEvents>
+ </Events>
+ <Externs>
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
+ <Extern>
+ <DriverBinding>gFdcControllerDriver</DriverBinding>
+ <ComponentName>gIsaFloppyComponentName</ComponentName>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea> \ No newline at end of file
diff --git a/Bus/Isa/IsaFloppy/Dxe/IsaFloppyBlock.c b/Bus/Isa/IsaFloppy/Dxe/IsaFloppyBlock.c
new file mode 100644
index 0000000..7d6f59f
--- /dev/null
+++ b/Bus/Isa/IsaFloppy/Dxe/IsaFloppyBlock.c
@@ -0,0 +1,458 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation. All rights reserved. <BR>
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+Module Name:
+
+ IsaFloppyBlock.c
+
+Abstract:
+
+ ISA Floppy Driver
+ 1. Support two types diskette drive
+ 1.44M drive and 2.88M drive (and now only support 1.44M)
+ 2. Support two diskette drives
+ 3. Use DMA channel 2 to transfer data
+ 4. Do not use interrupt
+ 5. Support diskette change line signal and write protect
+
+ Implement the Block IO interface
+
+Revision History:
+
+--*/
+
+#include "IsaFloppy.h"
+
+EFI_STATUS
+EFIAPI
+FdcReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+/*++
+
+ Routine Description: Reset the Floppy Logic Drive, call the FddReset function
+ Parameters:
+ This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface
+ ExtendedVerification BOOLEAN: Indicate that the driver may perform a more
+ exhaustive verification operation of the device during
+ reset, now this par is ignored in this driver
+ Returns:
+ EFI_SUCCESS: The Floppy Logic Drive is reset
+ EFI_DEVICE_ERROR: The Floppy Logic Drive is not functioning correctly
+ and can not be reset
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: This - add argument and description to function comment
+// GC_TODO: ExtendedVerification - add argument and description to function comment
+{
+ FDC_BLK_IO_DEV *FdcDev;
+
+ //
+ // Reset the Floppy Disk Controller
+ //
+ FdcDev = FDD_BLK_IO_FROM_THIS (This);
+
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_P_PC_RESET | EFI_PERIPHERAL_REMOVABLE_MEDIA,
+ FdcDev->DevicePath
+ );
+
+ return FddReset (FdcDev);
+}
+
+EFI_STATUS
+EFIAPI
+FddFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ )
+/*++
+
+ Routine Description:
+ Parameters:
+ This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface
+ Returns:
+ EFI_SUCCESS:
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: This - add argument and description to function comment
+{
+ //
+ // Not supported yet
+ //
+ return EFI_SUCCESS;
+}
+
+STATIC
+VOID
+FddReportStatus (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN Read
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ Read - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ FDC_BLK_IO_DEV *FdcDev;
+
+ FdcDev = FDD_BLK_IO_FROM_THIS (This);
+
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_ERROR_CODE,
+ ((Read) ? EFI_P_EC_INPUT_ERROR : EFI_P_EC_OUTPUT_ERROR) | EFI_PERIPHERAL_REMOVABLE_MEDIA,
+ FdcDev->DevicePath
+ );
+}
+
+EFI_STATUS
+EFIAPI
+FddReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+ Routine Description: Read the requested number of blocks from the device
+ Parameters:
+ This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface
+ MediaId UINT32: The media id that the read request is for
+ LBA EFI_LBA: The starting logic block address to read from on the device
+ BufferSize UINTN: The size of the Buffer in bytes
+ Buffer VOID *: A pointer to the destination buffer for the data
+ Returns:
+ EFI_SUCCESS: The data was read correctly from the device
+ EFI_DEVICE_ERROR:The device reported an error while attempting to perform
+ the read operation
+ EFI_NO_MEDIA: There is no media in the device
+ EFI_MEDIA_CHANGED: The MediaId is not for the current media
+ EFI_BAD_BUFFER_SIZE: The BufferSize parameter is not a multiple of the
+ intrinsic block size of the device
+ EFI_INVALID_PARAMETER:The read request contains LBAs that are not valid,
+ or the buffer is not on proper alignment
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: This - add argument and description to function comment
+// GC_TODO: MediaId - add argument and description to function comment
+// GC_TODO: LBA - add argument and description to function comment
+// GC_TODO: BufferSize - add argument and description to function comment
+// GC_TODO: Buffer - add argument and description to function comment
+{
+ EFI_STATUS Status;
+
+ Status = FddReadWriteBlocks (This, MediaId, LBA, BufferSize, READ, Buffer);
+
+ if (EFI_ERROR (Status)) {
+ FddReportStatus (This, TRUE);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+FddWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+/*++
+
+ Routine Description: Write a specified number of blocks to the device
+ Parameters:
+ This EFI_BLOCK_IO *: A pointer to the Block I/O protocol interface
+ MediaId UINT32: The media id that the write request is for
+ LBA EFI_LBA: The starting logic block address to be written
+ BufferSize UINTN: The size in bytes in Buffer
+ Buffer VOID *: A pointer to the source buffer for the data
+ Returns :
+ EFI_SUCCESS: The data were written correctly to the device
+ EFI_WRITE_PROTECTED: The device can not be written to
+ EFI_NO_MEDIA: There is no media in the device
+ EFI_MEDIA_CHANGED: The MediaId is not for the current media
+ EFI_DEVICE_ERROR: The device reported an error while attempting to perform
+ the write operation
+ EFI_BAD_BUFFER_SIZE: The BufferSize parameter is not a multiple of the
+ intrinsic block size of the device
+ EFI_INVALID_PARAMETER:The write request contains LBAs that are not valid,
+ or the buffer is not on proper alignment
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: function comment is missing 'Returns:'
+// GC_TODO: This - add argument and description to function comment
+// GC_TODO: MediaId - add argument and description to function comment
+// GC_TODO: LBA - add argument and description to function comment
+// GC_TODO: BufferSize - add argument and description to function comment
+// GC_TODO: Buffer - add argument and description to function comment
+{
+ EFI_STATUS Status;
+
+ Status = FddReadWriteBlocks (This, MediaId, LBA, BufferSize, WRITE, Buffer);
+
+ if (EFI_ERROR (Status)) {
+ FddReportStatus (This, FALSE);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+FddReadWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ IN BOOLEAN Operation,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ MediaId - GC_TODO: add argument description
+ LBA - GC_TODO: add argument description
+ BufferSize - GC_TODO: add argument description
+ Operation - GC_TODO: add argument description
+ Buffer - GC_TODO: add argument description
+
+Returns:
+
+ EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
+ EFI_SUCCESS - GC_TODO: Add description for return value
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_NO_MEDIA - GC_TODO: Add description for return value
+ EFI_MEDIA_CHANGED - GC_TODO: Add description for return value
+ EFI_WRITE_PROTECTED - GC_TODO: Add description for return value
+ EFI_BAD_BUFFER_SIZE - GC_TODO: Add description for return value
+ EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
+ EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
+ EFI_SUCCESS - GC_TODO: Add description for return value
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_SUCCESS - GC_TODO: Add description for return value
+
+--*/
+{
+ EFI_BLOCK_IO_MEDIA *Media;
+ FDC_BLK_IO_DEV *FdcDev;
+ UINTN BlockSize;
+ UINTN NumberOfBlocks;
+ UINTN BlockCount;
+ EFI_STATUS Status;
+ //
+ // EFI_STATUS CacheStatus;
+ //
+ EFI_LBA LBA0;
+ UINT8 *Pointer;
+
+ //
+ // Get the intrinsic block size
+ //
+ Media = This->Media;
+ BlockSize = Media->BlockSize;
+ FdcDev = FDD_BLK_IO_FROM_THIS (This);
+
+ if (Operation == WRITE) {
+ if (LBA == 0) {
+ FdcFreeCache (FdcDev);
+ }
+ }
+ //
+ // Check the Parameter is valid
+ //
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+ //
+ // Set the drive motor on
+ //
+ Status = MotorOn (FdcDev);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Check to see if media can be detected
+ //
+ Status = DetectMedia (FdcDev);
+ if (EFI_ERROR (Status)) {
+ MotorOff (FdcDev);
+ FdcFreeCache (FdcDev);
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Check to see if media is present
+ //
+ if (!(Media->MediaPresent)) {
+ MotorOff (FdcDev);
+ FdcFreeCache (FdcDev);
+
+ /*
+ if (FdcDev->Cache) {
+ gBS->FreePool (FdcDev->Cache);
+ FdcDev->Cache = NULL;
+ }
+*/
+ return EFI_NO_MEDIA;
+ }
+ //
+ // Check to see if media has been changed
+ //
+ if (MediaId != Media->MediaId) {
+ MotorOff (FdcDev);
+ FdcFreeCache (FdcDev);
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (Operation == WRITE) {
+ if (Media->ReadOnly) {
+ MotorOff (FdcDev);
+ return EFI_WRITE_PROTECTED;
+ }
+ }
+ //
+ // Check the parameters for this read/write operation
+ //
+ if (BufferSize % BlockSize != 0) {
+ MotorOff (FdcDev);
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ if (LBA > Media->LastBlock) {
+ MotorOff (FdcDev);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (((BufferSize / BlockSize) + LBA - 1) > Media->LastBlock) {
+ MotorOff (FdcDev);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Operation == READ) {
+ //
+ // See if the data that is being read is already in the cache
+ //
+ if (FdcDev->Cache) {
+ if (LBA == 0 && BufferSize == BlockSize) {
+ MotorOff (FdcDev);
+ CopyMem ((UINT8 *) Buffer, (UINT8 *) FdcDev->Cache, BlockSize);
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ //
+ // Set up Floppy Disk Controller
+ //
+ Status = Setup (FdcDev);
+ if (EFI_ERROR (Status)) {
+ MotorOff (FdcDev);
+ return EFI_DEVICE_ERROR;
+ }
+
+ NumberOfBlocks = BufferSize / BlockSize;
+ LBA0 = LBA;
+ Pointer = Buffer;
+
+ //
+ // read blocks in the same cylinder.
+ // in a cylinder , there are 18 * 2 = 36 blocks
+ //
+ BlockCount = GetTransferBlockCount (FdcDev, LBA, NumberOfBlocks);
+ while ((BlockCount != 0) && !EFI_ERROR (Status)) {
+ Status = ReadWriteDataSector (FdcDev, Buffer, LBA, BlockCount, Operation);
+ if (EFI_ERROR (Status)) {
+ MotorOff (FdcDev);
+ FddReset (FdcDev);
+ return EFI_DEVICE_ERROR;
+ }
+
+ LBA += BlockCount;
+ NumberOfBlocks -= BlockCount;
+ Buffer = (VOID *) ((UINTN) Buffer + BlockCount * BlockSize);
+ BlockCount = GetTransferBlockCount (FdcDev, LBA, NumberOfBlocks);
+ }
+
+ Buffer = Pointer;
+
+ //
+ // Turn the motor off
+ //
+ MotorOff (FdcDev);
+
+ if (Operation == READ) {
+ //
+ // Cache the data read
+ //
+ if (LBA0 == 0 && !FdcDev->Cache) {
+ FdcDev->Cache = AllocateCopyPool (BlockSize, Buffer);
+ }
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+VOID
+FdcFreeCache (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcDev - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ if (FdcDev->Cache) {
+ gBS->FreePool (FdcDev->Cache);
+ FdcDev->Cache = NULL;
+ }
+}
diff --git a/Bus/Isa/IsaFloppy/Dxe/IsaFloppyCtrl.c b/Bus/Isa/IsaFloppy/Dxe/IsaFloppyCtrl.c
new file mode 100644
index 0000000..21e7d4a
--- /dev/null
+++ b/Bus/Isa/IsaFloppy/Dxe/IsaFloppyCtrl.c
@@ -0,0 +1,1551 @@
+/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved. <BR>
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+Module Name:
+
+ IsaFloppyCtrl.c
+
+Abstract:
+
+ ISA Floppy Driver
+ 1. Support two types diskette drive
+ 1.44M drive and 2.88M drive (and now only support 1.44M)
+ 2. Support two diskette drives
+ 3. Use DMA channel 2 to transfer data
+ 4. Do not use interrupt
+ 5. Support diskette change line signal and write protect
+
+ The internal function for the floppy driver
+
+Revision History:
+
+--*/
+
+#include "IsaFloppy.h"
+
+EFI_STATUS
+DiscoverFddDevice (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+ Routine Description: Detect the floppy drive is presented or not
+ Parameters:
+ FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
+ Returns:
+ EFI_SUCCESS Drive is presented
+ EFI_NOT_FOUND Drive is not presented
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+{
+ EFI_STATUS Status;
+
+ FdcDev->BlkIo.Media = &FdcDev->BlkMedia;
+
+ //
+ // Call FddIndentify subroutine
+ //
+ Status = FddIdentify (FdcDev);
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ FdcDev->BlkIo.Reset = FdcReset;
+ FdcDev->BlkIo.FlushBlocks = FddFlushBlocks;
+ FdcDev->BlkIo.ReadBlocks = FddReadBlocks;
+ FdcDev->BlkIo.WriteBlocks = FddWriteBlocks;
+ FdcDev->BlkMedia.LogicalPartition = FALSE;
+ FdcDev->BlkMedia.WriteCaching = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FddIdentify (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+ Routine Description: Do recalibrate and see the drive is presented or not
+ Set the media parameters
+ Parameters:
+ FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
+ Returns:
+ EFI_SUCCESS:
+ EFI_DEVICE_ERROR:
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+{
+ EFI_STATUS Status;
+
+ //
+ // Set Floppy Disk Controller's motor on
+ //
+ Status = MotorOn (FdcDev);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = Recalibrate (FdcDev);
+
+ if (EFI_ERROR (Status)) {
+ MotorOff (FdcDev);
+ FdcDev->ControllerState->NeedRecalibrate = TRUE;
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Set Media Parameter
+ //
+ FdcDev->BlkIo.Media->RemovableMedia = TRUE;
+ FdcDev->BlkIo.Media->MediaPresent = TRUE;
+ //
+ // investigate
+ //
+ FdcDev->BlkIo.Media->MediaId = 0;
+
+ //
+ // Check Media
+ //
+ Status = DisketChanged (FdcDev);
+ switch (Status) {
+ case EFI_NO_MEDIA:
+ FdcDev->BlkIo.Media->MediaPresent = FALSE;
+ break;
+
+ case EFI_MEDIA_CHANGED:
+ case EFI_SUCCESS:
+ break;
+
+ default:
+ MotorOff (FdcDev);
+ return Status;
+ }
+ //
+ // Check Disk Write Protected
+ //
+ Status = SenseDrvStatus (FdcDev, 0);
+ switch (Status) {
+ case EFI_WRITE_PROTECTED:
+ FdcDev->BlkIo.Media->ReadOnly = TRUE;
+ break;
+
+ case EFI_SUCCESS:
+ FdcDev->BlkIo.Media->ReadOnly = FALSE;
+ break;
+
+ default:
+ return EFI_DEVICE_ERROR;
+ break;
+ }
+
+ MotorOff (FdcDev);
+
+ //
+ // Set Media Default Type
+ //
+ FdcDev->BlkIo.Media->BlockSize = DISK_1440K_BYTEPERSECTOR;
+ FdcDev->BlkIo.Media->LastBlock = DISK_1440K_EOT * 2 * (DISK_1440K_MAXTRACKNUM + 1) - 1;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FddReset (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+ Routine Description: Reset the Floppy Logic Drive
+ Parameters:
+ FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
+ Returns:
+ EFI_SUCCESS: The Floppy Logic Drive is reset
+ EFI_DEVICE_ERROR: The Floppy Logic Drive is not functioning correctly and
+ can not be reset
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+{
+ UINT8 data;
+ UINT8 StatusRegister0;
+ UINT8 PresentCylinderNumber;
+ UINTN Index;
+
+ //
+ // Report reset progress code
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_RESET,
+ FdcDev->DevicePath
+ );
+
+ //
+ // Reset specified Floppy Logic Drive according to FdcDev -> Disk
+ // Set Digital Output Register(DOR) to do reset work
+ // bit0 & bit1 of DOR : Drive Select
+ // bit2 : Reset bit
+ // bit3 : DMA and Int bit
+ // Reset : a "0" written to bit2 resets the FDC, this reset will remain
+ // active until
+ // a "1" is written to this bit.
+ // Reset step 1:
+ // use bit0 & bit1 to select the logic drive
+ // write "0" to bit2
+ //
+ data = 0x0;
+ data = (UINT8) (data | (SELECT_DRV & FdcDev->Disk));
+ FdcWritePort (FdcDev, FDC_REGISTER_DOR, data);
+
+ //
+ // wait some time,at least 120us
+ //
+ MicroSecondDelay (500);
+
+ //
+ // Reset step 2:
+ // write "1" to bit2
+ // write "1" to bit3 : enable DMA
+ //
+ data |= 0x0C;
+ FdcWritePort (FdcDev, FDC_REGISTER_DOR, data);
+
+ //
+ // Experience value
+ //
+ MicroSecondDelay (2000);
+
+ //
+ // wait specified floppy logic drive is not busy
+ //
+ if (EFI_ERROR (FddWaitForBSYClear (FdcDev, 1))) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Set the Transfer Data Rate
+ //
+ FdcWritePort (FdcDev, FDC_REGISTER_CCR, 0x0);
+
+ //
+ // Experience value
+ //
+ MicroSecondDelay (100);
+
+ //
+ // Issue Sense interrupt command for each drive (total 4 drives)
+ //
+ for (Index = 0; Index < 4; Index++) {
+ if (EFI_ERROR (SenseIntStatus (FdcDev, &StatusRegister0, &PresentCylinderNumber))) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ //
+ // issue Specify command
+ //
+ if (EFI_ERROR (Specify (FdcDev))) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+MotorOn (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+ Routine Description: Turn the drive's motor on
+ The drive's motor must be on before any command can be executed
+ Parameters:
+ FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
+ Returns:
+ EFI_SUCCESS: Turn the drive's motor on successfully
+ EFI_DEVICE_ERROR: The drive is busy, so can not turn motor on
+ EFI_INVALID_PARAMETER: Fail to Set timer(Cancel timer)
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ UINT8 data;
+
+ //
+ // Control of the floppy drive motors is a big pain. If motor is off, you have
+ // to turn it on first. But you can not leave the motor on all the time, since
+ // that would wear out the disk. On the other hand, if you turn the motor off
+ // after each operation, the system performance will be awful. The compromise
+ // used in this driver is to leave the motor on for 2 seconds after
+ // each operation. If a new operation is started in that interval(2s),
+ // the motor need not be turned on again. If no new operation is started,
+ // a timer goes off and the motor is turned off
+ //
+ //
+ // Cancel the timer
+ //
+ Status = gBS->SetTimer (FdcDev->Event, TimerCancel, 0);
+
+ if (EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Get the motor status
+ //
+ data = FdcReadPort (FdcDev, FDC_REGISTER_DOR);
+
+ if (((FdcDev->Disk == FDC_DISK0) && ((data & 0x10) == 0x10)) ||
+ ((FdcDev->Disk == FDC_DISK1) && ((data & 0x21) == 0x21))
+ ) {
+ return EFI_SUCCESS;
+ }
+ //
+ // The drive's motor is off, so need turn it on
+ // first look at command and drive are busy or not
+ //
+ if (EFI_ERROR (FddWaitForBSYClear (FdcDev, 1))) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // for drive A: 1CH, drive B: 2DH
+ //
+ data = 0x0C;
+ data = (UINT8) (data | (SELECT_DRV & FdcDev->Disk));
+ if (FdcDev->Disk == FDC_DISK0) {
+ //
+ // drive A
+ //
+ data |= DRVA_MOTOR_ON;
+ } else {
+ //
+ // drive B
+ //
+ data |= DRVB_MOTOR_ON;
+ }
+
+ FdcWritePort (FdcDev, FDC_REGISTER_DOR, data);
+
+ //
+ // Experience value
+ //
+ MicroSecondDelay (4000);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+MotorOff (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+ Routine Description: Set a Timer and when Timer goes off, turn the motor off
+ Parameters:
+ FdcDev FDC_BLK_IO_DEV * : A pointer to the Data Structure FDC_BLK_IO_DEV
+ Returns:
+ EFI_SUCCESS: Set the Timer successfully
+ EFI_INVALID_PARAMETER: Fail to Set the timer
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+{
+ //
+ // Set the timer : 2s
+ //
+ return gBS->SetTimer (FdcDev->Event, TimerRelative, 20000000);
+}
+
+EFI_STATUS
+DisketChanged (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+ Routine Description: Detect the disk in the drive is changed or not
+ Parameters:
+ FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
+ Returns:
+ EFI_SUCCESS: No disk media change
+ EFI_DEVICE_ERROR: Fail to do the recalibrate or seek operation
+ EFI_NO_MEDIA: No disk in the drive
+ EFI_MEDIA_CHANGED: There is a new disk in the drive
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ UINT8 data;
+
+ //
+ // Check change line
+ //
+ data = FdcReadPort (FdcDev, FDC_REGISTER_DIR);
+
+ //
+ // Io delay
+ //
+ MicroSecondDelay (50);
+
+ if ((data & DIR_DCL) == 0x80) {
+ //
+ // disk change line is active
+ //
+ if (FdcDev->PresentCylinderNumber != 0) {
+ Status = Recalibrate (FdcDev);
+ } else {
+ Status = Seek (FdcDev, 0x30);
+ }
+
+ if (EFI_ERROR (Status)) {
+ FdcDev->ControllerState->NeedRecalibrate = TRUE;
+ return EFI_DEVICE_ERROR;
+ //
+ // Fail to do the seek or recalibrate operation
+ //
+ }
+
+ data = FdcReadPort (FdcDev, FDC_REGISTER_DIR);
+
+ //
+ // Io delay
+ //
+ MicroSecondDelay (50);
+
+ if ((data & DIR_DCL) == 0x80) {
+ return EFI_NO_MEDIA;
+ }
+
+ return EFI_MEDIA_CHANGED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+Specify (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+ Routine Description: Do the Specify command, this command sets DMA operation
+ and the initial values for each of the three internal
+ times: HUT, SRT and HLT
+ Parameters:
+ None
+ Returns:
+ EFI_SUCCESS: Execute the Specify command successfully
+ EFI_DEVICE_ERROR: Fail to execute the command
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+{
+ FDD_SPECIFY_CMD Command;
+ UINTN Index;
+ UINT8 *CommandPointer;
+
+ ZeroMem (&Command, sizeof (FDD_SPECIFY_CMD));
+ Command.CommandCode = SPECIFY_CMD;
+ //
+ // set SRT, HUT
+ //
+ Command.SrtHut = 0xdf;
+ //
+ // 0xdf;
+ //
+ // set HLT and DMA
+ //
+ Command.HltNd = 0x02;
+
+ CommandPointer = (UINT8 *) (&Command);
+ for (Index = 0; Index < sizeof (FDD_SPECIFY_CMD); Index++) {
+ if (EFI_ERROR (DataOutByte (FdcDev, CommandPointer++))) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+Recalibrate (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+ Routine Description: Set the head of floppy drive to track 0
+ Parameters:
+ FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
+ Returns:
+ EFI_SUCCESS: Execute the Recalibrate operation successfully
+ EFI_DEVICE_ERROR: Fail to execute the Recalibrate operation
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+{
+ FDD_COMMAND_PACKET2 Command;
+ UINTN Index;
+ UINT8 StatusRegister0;
+ UINT8 PresentCylinderNumber;
+ UINT8 *CommandPointer;
+ UINT8 Count;
+
+ Count = 2;
+
+ while (Count > 0) {
+ ZeroMem (&Command, sizeof (FDD_COMMAND_PACKET2));
+ Command.CommandCode = RECALIBRATE_CMD;
+ //
+ // drive select
+ //
+ if (FdcDev->Disk == FDC_DISK0) {
+ Command.DiskHeadSel = 0;
+ //
+ // 0
+ //
+ } else {
+ Command.DiskHeadSel = 1;
+ //
+ // 1
+ //
+ }
+
+ CommandPointer = (UINT8 *) (&Command);
+ for (Index = 0; Index < sizeof (FDD_COMMAND_PACKET2); Index++) {
+ if (EFI_ERROR (DataOutByte (FdcDev, CommandPointer++))) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ //
+ // Experience value
+ //
+ MicroSecondDelay (250000);
+ //
+ // need modify according to 1.44M or 2.88M
+ //
+ if (EFI_ERROR (SenseIntStatus (FdcDev, &StatusRegister0, &PresentCylinderNumber))) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ((StatusRegister0 & 0xf0) == 0x20 && PresentCylinderNumber == 0) {
+ FdcDev->PresentCylinderNumber = 0;
+ FdcDev->ControllerState->NeedRecalibrate = FALSE;
+ return EFI_SUCCESS;
+ } else {
+ Count--;
+ if (Count == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ }
+ //
+ // end while
+ //
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+Seek (
+ IN FDC_BLK_IO_DEV *FdcDev,
+ IN EFI_LBA Lba
+ )
+/*++
+
+ Routine Description: Set the head of floppy drive to the new cylinder
+ Parameters:
+ FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
+ Lba EFI_LBA : The logic block address want to seek
+ Returns:
+ EFI_SUCCESS: Execute the Seek operation successfully
+ EFI_DEVICE_ERROR: Fail to execute the Seek operation
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+// GC_TODO: Lba - add argument and description to function comment
+{
+ FDD_SEEK_CMD Command;
+ UINT8 EndOfTrack;
+ UINT8 Head;
+ UINT8 Cylinder;
+ UINT8 StatusRegister0;
+ UINT8 *CommandPointer;
+ UINT8 PresentCylinderNumber;
+ UINTN Index;
+ UINT8 DelayTime;
+
+ if (FdcDev->ControllerState->NeedRecalibrate) {
+ if (EFI_ERROR (Recalibrate (FdcDev))) {
+ FdcDev->ControllerState->NeedRecalibrate = TRUE;
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ EndOfTrack = DISK_1440K_EOT;
+ //
+ // Calculate cylinder based on Lba and EOT
+ //
+ Cylinder = (UINT8) ((UINTN) Lba / EndOfTrack / 2);
+
+ //
+ // if the destination cylinder is the present cylinder, unnecessary to do the
+ // seek operation
+ //
+ if (FdcDev->PresentCylinderNumber == Cylinder) {
+ return EFI_SUCCESS;
+ }
+ //
+ // Calculate the head : 0 or 1
+ //
+ Head = (UINT8) ((UINTN) Lba / EndOfTrack % 2);
+
+ ZeroMem (&Command, sizeof (FDD_SEEK_CMD));
+ Command.CommandCode = SEEK_CMD;
+ if (FdcDev->Disk == FDC_DISK0) {
+ Command.DiskHeadSel = 0;
+ //
+ // 0
+ //
+ } else {
+ Command.DiskHeadSel = 1;
+ //
+ // 1
+ //
+ }
+
+ Command.DiskHeadSel = (UINT8) (Command.DiskHeadSel | (Head << 2));
+ Command.NewCylinder = Cylinder;
+
+ CommandPointer = (UINT8 *) (&Command);
+ for (Index = 0; Index < sizeof (FDD_SEEK_CMD); Index++) {
+ if (EFI_ERROR (DataOutByte (FdcDev, CommandPointer++))) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ //
+ // Io delay
+ //
+ MicroSecondDelay (100);
+
+ //
+ // Calculate waiting time
+ //
+ if (FdcDev->PresentCylinderNumber > Cylinder) {
+ DelayTime = (UINT8) (FdcDev->PresentCylinderNumber - Cylinder);
+ } else {
+ DelayTime = (UINT8) (Cylinder - FdcDev->PresentCylinderNumber);
+ }
+
+ MicroSecondDelay ((DelayTime + 1) * 4000);
+
+ if (EFI_ERROR (SenseIntStatus (FdcDev, &StatusRegister0, &PresentCylinderNumber))) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ((StatusRegister0 & 0xf0) == 0x20) {
+ FdcDev->PresentCylinderNumber = Command.NewCylinder;
+ return EFI_SUCCESS;
+ } else {
+ FdcDev->ControllerState->NeedRecalibrate = TRUE;
+ return EFI_DEVICE_ERROR;
+ }
+}
+
+EFI_STATUS
+SenseIntStatus (
+ IN FDC_BLK_IO_DEV *FdcDev,
+ IN OUT UINT8 *StatusRegister0,
+ IN OUT UINT8 *PresentCylinderNumber
+ )
+/*++
+
+ Routine Description: Do the Sense Interrupt Status command, this command
+ resets the interrupt signal
+ Parameters:
+ StatusRegister0 UINT8 *: Be used to save Status Register 0 read from FDC
+ PresentCylinderNumber UINT8 *: Be used to save present cylinder number
+ read from FDC
+ Returns:
+ EFI_SUCCESS: Execute the Sense Interrupt Status command successfully
+ EFI_DEVICE_ERROR: Fail to execute the command
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+// GC_TODO: StatusRegister0 - add argument and description to function comment
+// GC_TODO: PresentCylinderNumber - add argument and description to function comment
+{
+ UINT8 command;
+
+ command = SENSE_INT_STATUS_CMD;
+ if (EFI_ERROR (DataOutByte (FdcDev, &command))) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (EFI_ERROR (DataInByte (FdcDev, StatusRegister0))) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (EFI_ERROR (DataInByte (FdcDev, PresentCylinderNumber))) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SenseDrvStatus (
+ IN FDC_BLK_IO_DEV *FdcDev,
+ IN EFI_LBA Lba
+ )
+/*++
+
+ Routine Description: Do the Sense Drive Status command
+ Parameters:
+ FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
+ Lba EFI_LBA : Logic block address
+ Returns:
+ EFI_SUCCESS: Execute the Sense Drive Status command successfully
+ EFI_DEVICE_ERROR: Fail to execute the command
+ EFI_WRITE_PROTECTED:The disk is write protected
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+// GC_TODO: Lba - add argument and description to function comment
+{
+ FDD_COMMAND_PACKET2 Command;
+ UINT8 Head;
+ UINT8 EndOfTrack;
+ UINTN Index;
+ UINT8 StatusRegister3;
+ UINT8 *CommandPointer;
+
+ //
+ // Sense Drive Status command obtains drive status information,
+ // it has not execution phase and goes directly to the result phase from the
+ // command phase, Status Register 3 contains the drive status information
+ //
+ ZeroMem (&Command, sizeof (FDD_COMMAND_PACKET2));
+ Command.CommandCode = SENSE_DRV_STATUS_CMD;
+
+ if (FdcDev->Disk == FDC_DISK0) {
+ Command.DiskHeadSel = 0;
+ } else {
+ Command.DiskHeadSel = 1;
+ }
+
+ EndOfTrack = DISK_1440K_EOT;
+ Head = (UINT8) ((UINTN) Lba / EndOfTrack % 2);
+ Command.DiskHeadSel = (UINT8) (Command.DiskHeadSel | (Head << 2));
+
+ CommandPointer = (UINT8 *) (&Command);
+ for (Index = 0; Index < sizeof (FDD_COMMAND_PACKET2); Index++) {
+ if (EFI_ERROR (DataOutByte (FdcDev, CommandPointer++))) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ if (EFI_ERROR (DataInByte (FdcDev, &StatusRegister3))) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Io delay
+ //
+ MicroSecondDelay (50);
+
+ //
+ // Check Status Register 3 to get drive status information
+ //
+ return CheckStatus3 (StatusRegister3);
+}
+
+EFI_STATUS
+DetectMedia (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+ Routine Description: Update the disk media properties and if necessary
+ reinstall Block I/O interface
+ Parameters:
+ FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
+ Returns:
+ EFI_SUCCESS: Do the operation successfully
+ EFI_DEVICE_ERROR: Fail to the operation
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ BOOLEAN bReset;
+ BOOLEAN bReadOnlyLastTime;
+ BOOLEAN bMediaPresentLastTime;
+
+ bReset = FALSE;
+ bReadOnlyLastTime = FdcDev->BlkIo.Media->ReadOnly;
+ bMediaPresentLastTime = FdcDev->BlkIo.Media->MediaPresent;
+
+ //
+ // Check disk change
+ //
+ Status = DisketChanged (FdcDev);
+ switch (Status) {
+ case EFI_MEDIA_CHANGED:
+ FdcDev->BlkIo.Media->MediaId++;
+ FdcDev->BlkIo.Media->MediaPresent = TRUE;
+ bReset = TRUE;
+ break;
+
+ case EFI_NO_MEDIA:
+ FdcDev->BlkIo.Media->MediaPresent = FALSE;
+ break;
+
+ case EFI_SUCCESS:
+ break;
+
+ default:
+ MotorOff (FdcDev);
+ return Status;
+ //
+ // EFI_DEVICE_ERROR
+ //
+ }
+
+ if (FdcDev->BlkIo.Media->MediaPresent) {
+ //
+ // Check disk write protected
+ //
+ Status = SenseDrvStatus (FdcDev, 0);
+ if (Status == EFI_WRITE_PROTECTED) {
+ FdcDev->BlkIo.Media->ReadOnly = TRUE;
+ } else {
+ FdcDev->BlkIo.Media->ReadOnly = FALSE;
+ }
+ }
+
+ if (FdcDev->BlkIo.Media->MediaPresent && (bReadOnlyLastTime != FdcDev->BlkIo.Media->ReadOnly)) {
+ bReset = TRUE;
+ }
+
+ if (bMediaPresentLastTime != FdcDev->BlkIo.Media->MediaPresent) {
+ bReset = TRUE;
+ }
+
+ if (bReset) {
+ Status = gBS->ReinstallProtocolInterface (
+ FdcDev->Handle,
+ &gEfiBlockIoProtocolGuid,
+ &FdcDev->BlkIo,
+ &FdcDev->BlkIo
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+Setup (
+ IN FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+ Routine Description: Set the data rate and so on
+ Parameters:
+ None
+ Returns:
+ EFI_SUCCESS:
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment
+{
+ EFI_STATUS Status;
+
+ //
+ // Set data rate 500kbs
+ //
+ FdcWritePort (FdcDev, FDC_REGISTER_CCR, 0x0);
+
+ //
+ // Io delay
+ //
+ MicroSecondDelay (50);
+
+ Status = Specify (FdcDev);
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ReadWriteDataSector (
+ IN FDC_BLK_IO_DEV *FdcDev,
+ IN VOID *HostAddress,
+ IN EFI_LBA Lba,
+ IN UINTN NumberOfBlocks,
+ IN BOOLEAN Read
+ )
+/*++
+
+ Routine Description: Read or Write a number of blocks in the same cylinder
+ Parameters:
+ FdcDev FDC_BLK_IO_DEV * : A pointer to Data Structure FDC_BLK_IO_DEV
+ Buffer VOID *:
+ Lba EFI_LBA:
+ NumberOfBlocks UINTN:
+ Read BOOLEAN:
+ Returns:
+ EFI_SUCCESS:
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+// GC_TODO: HostAddress - add argument and description to function comment
+// GC_TODO: Lba - add argument and description to function comment
+// GC_TODO: NumberOfBlocks - add argument and description to function comment
+// GC_TODO: Read - add argument and description to function comment
+// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment
+// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment
+// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment
+// GC_TODO: EFI_TIMEOUT - add return value to function comment
+// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment
+{
+ EFI_STATUS Status;
+ FDD_COMMAND_PACKET1 Command;
+ FDD_RESULT_PACKET Result;
+ UINTN Index;
+ UINTN Times;
+ UINT8 *CommandPointer;
+
+ EFI_PHYSICAL_ADDRESS DeviceAddress;
+ EFI_ISA_IO_PROTOCOL *IsaIo;
+ UINTN NumberofBytes;
+ VOID *Mapping;
+ EFI_ISA_IO_PROTOCOL_OPERATION Operation;
+ EFI_STATUS Status1;
+ UINT8 Channel;
+ EFI_ISA_ACPI_RESOURCE *ResourceItem;
+ UINT32 Attribute;
+
+ Status = Seek (FdcDev, Lba);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Map Dma
+ //
+ IsaIo = FdcDev->IsaIo;
+ NumberofBytes = NumberOfBlocks * 512;
+ if (Read == READ) {
+ Operation = EfiIsaIoOperationSlaveWrite;
+ } else {
+ Operation = EfiIsaIoOperationSlaveRead;
+ }
+
+ ResourceItem = IsaIo->ResourceList->ResourceItem;
+ Index = 0;
+ while (ResourceItem[Index].Type != EfiIsaAcpiResourceEndOfList) {
+ if (ResourceItem[Index].Type == EfiIsaAcpiResourceDma) {
+ break;
+ }
+
+ Index++;
+ }
+
+ if (ResourceItem[Index].Type == EfiIsaAcpiResourceEndOfList) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Channel = (UINT8) IsaIo->ResourceList->ResourceItem[Index].StartRange;
+ Attribute = IsaIo->ResourceList->ResourceItem[Index].Attribute;
+
+ Status1 = IsaIo->Map (
+ IsaIo,
+ Operation,
+ Channel,
+ Attribute,
+ HostAddress,
+ &NumberofBytes,
+ &DeviceAddress,
+ &Mapping
+ );
+ if (EFI_ERROR (Status1)) {
+ return Status1;
+ }
+
+ //
+ // Allocate Read or Write command packet
+ //
+ ZeroMem (&Command, sizeof (FDD_COMMAND_PACKET1));
+ if (Read == READ) {
+ Command.CommandCode = READ_DATA_CMD | CMD_MT | CMD_MFM | CMD_SK;
+ } else {
+ Command.CommandCode = WRITE_DATA_CMD | CMD_MT | CMD_MFM;
+ }
+
+ FillPara (FdcDev, Lba, &Command);
+
+ //
+ // Write command bytes to FDC
+ //
+ CommandPointer = (UINT8 *) (&Command);
+ for (Index = 0; Index < sizeof (FDD_COMMAND_PACKET1); Index++) {
+ if (EFI_ERROR (DataOutByte (FdcDev, CommandPointer++))) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ //
+ // wait for some time
+ //
+ Times = (STALL_1_SECOND / 50) + 1;
+ do {
+ if ((FdcReadPort (FdcDev, FDC_REGISTER_MSR) & 0xc0) == 0xc0) {
+ break;
+ }
+
+ MicroSecondDelay (50);
+ Times = Times - 1;
+ } while (Times);
+
+ if (Times == 0) {
+ return EFI_TIMEOUT;
+ }
+ //
+ // Read result bytes from FDC
+ //
+ CommandPointer = (UINT8 *) (&Result);
+ for (Index = 0; Index < sizeof (FDD_RESULT_PACKET); Index++) {
+ if (EFI_ERROR (DataInByte (FdcDev, CommandPointer++))) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ //
+ // Flush before Unmap
+ //
+ if (Read == READ) {
+ Status1 = IsaIo->Flush (IsaIo);
+ if (EFI_ERROR (Status1)) {
+ return Status1;
+ }
+ }
+ //
+ // Unmap Dma
+ //
+ Status1 = IsaIo->Unmap (IsaIo, Mapping);
+ if (EFI_ERROR (Status1)) {
+ return Status1;
+ }
+
+ return CheckResult (&Result, FdcDev);
+}
+
+VOID
+FillPara (
+ IN FDC_BLK_IO_DEV *FdcDev,
+ IN EFI_LBA Lba,
+ IN FDD_COMMAND_PACKET1 *Command
+ )
+/*++
+
+ Routine Description: Fill in Parameter
+ Parameters:
+ Returns:
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+// GC_TODO: Lba - add argument and description to function comment
+// GC_TODO: Command - add argument and description to function comment
+{
+ UINT8 EndOfTrack;
+
+ //
+ // Get EndOfTrack from the Para table
+ //
+ EndOfTrack = DISK_1440K_EOT;
+
+ //
+ // Fill the command parameter
+ //
+ if (FdcDev->Disk == FDC_DISK0) {
+ Command->DiskHeadSel = 0;
+ } else {
+ Command->DiskHeadSel = 1;
+ }
+
+ Command->Cylinder = (UINT8) ((UINTN) Lba / EndOfTrack / 2);
+ Command->Head = (UINT8) ((UINTN) Lba / EndOfTrack % 2);
+ Command->Sector = (UINT8) ((UINT8) ((UINTN) Lba % EndOfTrack) + 1);
+ Command->DiskHeadSel = (UINT8) (Command->DiskHeadSel | (Command->Head << 2));
+ Command->Number = DISK_1440K_NUMBER;
+ Command->EndOfTrack = DISK_1440K_EOT;
+ Command->GapLength = DISK_1440K_GPL;
+ Command->DataLength = DISK_1440K_DTL;
+}
+
+EFI_STATUS
+DataInByte (
+ IN FDC_BLK_IO_DEV *FdcDev,
+ IN OUT UINT8 *Pointer
+ )
+/*++
+
+ Routine Description: Read result byte from Data Register of FDC
+ Parameters:
+ Pointer UINT8 *: Be used to save result byte read from FDC
+ Returns:
+ EFI_SUCCESS: Read result byte from FDC successfully
+ EFI_DEVICE_ERROR: The FDC is not ready to be read
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+// GC_TODO: Pointer - add argument and description to function comment
+{
+ UINT8 data;
+
+ //
+ // wait for 1ms and detect the FDC is ready to be read
+ //
+ if (EFI_ERROR (FddDRQReady (FdcDev, DATA_IN, 1))) {
+ return EFI_DEVICE_ERROR;
+ //
+ // is not ready
+ //
+ }
+
+ data = FdcReadPort (FdcDev, FDC_REGISTER_DTR);
+
+ //
+ // Io delay
+ //
+ MicroSecondDelay (50);
+
+ *Pointer = data;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DataOutByte (
+ IN FDC_BLK_IO_DEV *FdcDev,
+ IN UINT8 *Pointer
+ )
+/*++
+
+ Routine Description: Write command byte to Data Register of FDC
+ Parameters:
+ Pointer UINT8 *: Be used to save command byte written to FDC
+ Returns:
+ EFI_SUCCESS: Write command byte to FDC successfully
+ EFI_DEVICE_ERROR: The FDC is not ready to be written
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+// GC_TODO: Pointer - add argument and description to function comment
+{
+ UINT8 data;
+
+ //
+ // wait for 1ms and detect the FDC is ready to be written
+ //
+ if (EFI_ERROR (FddDRQReady (FdcDev, DATA_OUT, 1))) {
+ return EFI_DEVICE_ERROR;
+ //
+ // is not ready
+ //
+ }
+
+ data = *Pointer;
+
+ FdcWritePort (FdcDev, FDC_REGISTER_DTR, data);
+
+ //
+ // Io delay
+ //
+ MicroSecondDelay (50);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FddWaitForBSYClear (
+ IN FDC_BLK_IO_DEV *FdcDev,
+ IN UINTN TimeoutInSeconds
+ )
+/*++
+
+ Routine Description: Detect the specified floppy logic drive is busy or
+ not within a period of time
+ Parameters:
+ Disk EFI_FDC_DISK: Indicate it is drive A or drive B
+ TimeoutInSeconds UINTN: the time period for waiting
+ Returns:
+ EFI_SUCCESS: The drive and command are not busy
+ EFI_TIMEOUT: The drive or command is still busy after a period time that
+ set by TimeoutInSeconds
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+// GC_TODO: TimeoutInSeconds - add argument and description to function comment
+{
+ UINTN Delay;
+ UINT8 StatusRegister;
+ UINT8 Mask;
+
+ //
+ // How to determine drive and command are busy or not: by the bits of
+ // Main Status Register
+ // bit0: Drive 0 busy (drive A)
+ // bit1: Drive 1 busy (drive B)
+ // bit4: Command busy
+ //
+ //
+ // set mask: for drive A set bit0 & bit4; for drive B set bit1 & bit4
+ //
+ Mask = (UINT8) ((FdcDev->Disk == FDC_DISK0 ? MSR_DAB : MSR_DBB) | MSR_CB);
+
+ Delay = ((TimeoutInSeconds * STALL_1_MSECOND) / 50) + 1;
+ do {
+ StatusRegister = FdcReadPort (FdcDev, FDC_REGISTER_MSR);
+ if ((StatusRegister & Mask) == 0x00) {
+ break;
+ //
+ // not busy
+ //
+ }
+
+ MicroSecondDelay (50);
+ Delay = Delay - 1;
+ } while (Delay);
+
+ if (Delay == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FddDRQReady (
+ IN FDC_BLK_IO_DEV *FdcDev,
+ IN BOOLEAN Dio,
+ IN UINTN TimeoutInSeconds
+ )
+/*++
+
+ Routine Description: Determine whether FDC is ready to write or read
+ Parameters:
+ Dio BOOLEAN: Indicate the FDC is waiting to write or read
+ TimeoutInSeconds UINTN: The time period for waiting
+ Returns:
+ EFI_SUCCESS: FDC is ready to write or read
+ EFI_NOT_READY: FDC is not ready within the specified time period
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+// GC_TODO: Dio - add argument and description to function comment
+// GC_TODO: TimeoutInSeconds - add argument and description to function comment
+{
+ UINTN Delay;
+ UINT8 StatusRegister;
+ UINT8 DataInOut;
+
+ //
+ // Before writing to FDC or reading from FDC, the Host must examine
+ // the bit7(RQM) and bit6(DIO) of the Main Status Register.
+ // That is to say:
+ // command bytes can not be written to Data Register
+ // unless RQM is 1 and DIO is 0
+ // result bytes can not be read from Data Register
+ // unless RQM is 1 and DIO is 1
+ //
+ DataInOut = (UINT8) (Dio << 6);
+ //
+ // in order to compare bit6
+ //
+ Delay = ((TimeoutInSeconds * STALL_1_MSECOND) / 50) + 1;
+ do {
+ StatusRegister = FdcReadPort (FdcDev, FDC_REGISTER_MSR);
+ if ((StatusRegister & MSR_RQM) == MSR_RQM && (StatusRegister & MSR_DIO) == DataInOut) {
+ break;
+ //
+ // FDC is ready
+ //
+ }
+
+ MicroSecondDelay (50);
+ //
+ // Stall for 50 us
+ //
+ Delay = Delay - 1;
+ } while (Delay);
+
+ if (Delay == 0) {
+ return EFI_NOT_READY;
+ //
+ // FDC is not ready within the specified time period
+ //
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CheckResult (
+ IN FDD_RESULT_PACKET *Result,
+ IN OUT FDC_BLK_IO_DEV *FdcDev
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Result - GC_TODO: add argument description
+ FdcDev - GC_TODO: add argument description
+
+Returns:
+
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_SUCCESS - GC_TODO: Add description for return value
+
+--*/
+{
+ //
+ // Check Status Register0
+ //
+ if ((Result->Status0 & STS0_IC) != IC_NT) {
+ if ((Result->Status0 & STS0_SE) == 0x20) {
+ //
+ // seek error
+ //
+ FdcDev->ControllerState->NeedRecalibrate = TRUE;
+ }
+
+ FdcDev->ControllerState->NeedRecalibrate = TRUE;
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Check Status Register1
+ //
+ if (Result->Status1 & (STS1_EN | STS1_DE | STS1_OR | STS1_ND | STS1_NW | STS1_MA)) {
+ FdcDev->ControllerState->NeedRecalibrate = TRUE;
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Check Status Register2
+ //
+ if (Result->Status2 & (STS2_CM | STS2_DD | STS2_WC | STS2_BC | STS2_MD)) {
+ FdcDev->ControllerState->NeedRecalibrate = TRUE;
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CheckStatus3 (
+ IN UINT8 StatusRegister3
+ )
+/*++
+
+ Routine Description: Check the drive status information
+ Parameters:
+ StatusRegister3 UINT8: the value of Status Register 3
+ Returns:
+ EFI_SUCCESS:
+ EFI_WRITE_PROTECTED: The disk is write protected
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: StatusRegister3 - add argument and description to function comment
+{
+ if (StatusRegister3 & STS3_WP) {
+ return EFI_WRITE_PROTECTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+UINTN
+GetTransferBlockCount (
+ IN FDC_BLK_IO_DEV *FdcDev,
+ IN EFI_LBA LBA,
+ IN UINTN NumberOfBlocks
+ )
+/*++
+
+ Routine Description: Calculate the number of block in the same cylinder
+ according to LBA
+ Parameters:
+ FdcDev FDC_BLK_IO_DEV *: A pointer to Data Structure FDC_BLK_IO_DEV
+ LBA EFI_LBA: The starting logic block address
+ NumberOfBlocks UINTN: The number of blocks
+ Returns:
+ UINTN : The number of blocks in the same cylinder which the starting
+ logic block address is LBA
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+// GC_TODO: LBA - add argument and description to function comment
+// GC_TODO: NumberOfBlocks - add argument and description to function comment
+{
+ UINT8 EndOfTrack;
+ UINT8 Head;
+ UINT8 SectorsInTrack;
+
+ //
+ // Calculate the number of block in the same cylinder
+ //
+ EndOfTrack = DISK_1440K_EOT;
+ Head = (UINT8) ((UINTN) LBA / EndOfTrack % 2);
+
+ SectorsInTrack = (UINT8) (EndOfTrack * (2 - Head) - (UINT8) ((UINTN) LBA % EndOfTrack));
+ if (SectorsInTrack < NumberOfBlocks) {
+ return SectorsInTrack;
+ } else {
+ return NumberOfBlocks;
+ }
+}
+
+VOID
+EFIAPI
+FddTimerProc (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+
+ Routine Description: When the Timer(2s) off, turn the drive's motor off
+ Parameters:
+ Event EFI_EVENT: Event(the timer) whose notification function is being
+ invoked
+ Context VOID *: Pointer to the notification function's context
+ Returns:
+ VOID
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: Event - add argument and description to function comment
+// GC_TODO: Context - add argument and description to function comment
+{
+ FDC_BLK_IO_DEV *FdcDev;
+ UINT8 data;
+
+ FdcDev = (FDC_BLK_IO_DEV *) Context;
+
+ //
+ // Get the motor status
+ //
+ data = FdcReadPort (FdcDev, FDC_REGISTER_DOR);
+
+ if (((FdcDev->Disk == FDC_DISK0) && ((data & 0x10) != 0x10)) ||
+ ((FdcDev->Disk == FDC_DISK1) && ((data & 0x21) != 0x21))
+ ) {
+ return ;
+ }
+ //
+ // the motor is on, so need motor off
+ //
+ data = 0x0C;
+ data = (UINT8) (data | (SELECT_DRV & FdcDev->Disk));
+ FdcWritePort (FdcDev, FDC_REGISTER_DOR, data);
+ MicroSecondDelay (500);
+}
+
+UINT8
+FdcReadPort (
+ IN FDC_BLK_IO_DEV *FdcDev,
+ IN UINT32 Offset
+ )
+/*++
+
+ Routine Description: Read I/O port for FDC
+ Parameters:
+ Returns:
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+// GC_TODO: Offset - add argument and description to function comment
+{
+ UINT8 Data;
+
+ //
+ // Call IsaIo
+ //
+ FdcDev->IsaIo->Io.Read (
+ FdcDev->IsaIo,
+ EfiIsaIoWidthUint8,
+ FdcDev->BaseAddress + Offset,
+ 1,
+ &Data
+ );
+
+ return Data;
+}
+
+VOID
+FdcWritePort (
+ IN FDC_BLK_IO_DEV *FdcDev,
+ IN UINT32 Offset,
+ IN UINT8 Data
+ )
+/*++
+
+ Routine Description: Write I/O port for FDC
+ Parameters:
+ Returns:
+
+--*/
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: FdcDev - add argument and description to function comment
+// GC_TODO: Offset - add argument and description to function comment
+// GC_TODO: Data - add argument and description to function comment
+{
+
+ //
+ // Call IsaIo
+ //
+ FdcDev->IsaIo->Io.Write (
+ FdcDev->IsaIo,
+ EfiIsaIoWidthUint8,
+ FdcDev->BaseAddress + Offset,
+ 1,
+ &Data
+ );
+}
diff --git a/Bus/Isa/IsaFloppy/Pei/Fdc.h b/Bus/Isa/IsaFloppy/Pei/Fdc.h
new file mode 100644
index 0000000..0664286
--- /dev/null
+++ b/Bus/Isa/IsaFloppy/Pei/Fdc.h
@@ -0,0 +1,215 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation. All rights reserved.
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ fdc.h
+
+Abstract:
+
+
+Revision History
+--*/
+
+#ifndef _PEI_RECOVERY_FDC_H
+#define _PEI_RECOVERY_FDC_H
+
+//
+// FDC Registers
+//
+#define FDC_REGISTER_DOR 2 // 0x3F2 //Digital Output Register
+#define FDC_REGISTER_MSR 4 // 0x3F4 //Main Status Register
+#define FDC_REGISTER_DTR 5 // 0x3F5 //Data Register
+#define FDC_REGISTER_CCR 7 // 0x3F7 //Configuration Control Register(data rate select)
+#define FDC_REGISTER_DIR 7 // 0x3F7 //Digital Input Register(diskchange)
+//
+// FDC Register Bit Definitions
+//
+//
+// Digital Out Register(WO)
+//
+#define SELECT_DRV BIT0 // Select Drive: 0=A 1=B
+#define RESET_FDC BIT2 // Reset FDC
+#define INT_DMA_ENABLE BIT3 // Enable Int & DMA
+#define DRVA_MOTOR_ON BIT4 // Turn On Drive A Motor
+#define DRVB_MOTOR_ON BIT5 // Turn On Drive B Motor
+//
+// Main Status Register(RO)
+//
+#define MSR_DAB BIT0 // Drive A Busy
+#define MSR_DBB BIT1 // Drive B Busy
+#define MSR_CB BIT4 // FDC Busy
+#define MSR_NDM BIT5 // Non-DMA Mode
+#define MSR_DIO BIT6 // Data Input/Output
+#define MSR_RQM BIT7 // Request For Master
+//
+// Configuration Control Register(WO)
+//
+#define CCR_DRC (BIT0 | BIT1) // Data Rate select
+//
+// Digital Input Register(RO)
+//
+#define DIR_DCL BIT7 // Disk change line
+#define DRC_500KBS 0x0 // 500K
+#define DRC_300KBS 0x01 // 300K
+#define DRC_250KBS 0x02 // 250K
+//
+// FDC Command Code
+//
+#define READ_DATA_CMD 0x06
+#define SEEK_CMD 0x0F
+#define RECALIBRATE_CMD 0x07
+#define SENSE_INT_STATUS_CMD 0x08
+#define SPECIFY_CMD 0x03
+#define SENSE_DRV_STATUS_CMD 0x04
+
+//
+// CMD_MT: Multi_Track Selector
+// when set , this flag selects the multi-track operating mode.
+// In this mode, the FDC treats a complete cylinder under head0 and 1 as a single track
+//
+#define CMD_MT BIT7
+
+//
+// CMD_MFM: MFM/FM Mode Selector
+// A one selects the double density(MFM) mode
+// A zero selects single density (FM) mode
+//
+#define CMD_MFM BIT6
+
+//
+// CMD_SK: Skip Flag
+// When set to 1, sectors containing a deleted data address mark will automatically be skipped
+// during the execution of Read Data.
+// When set to 0, the sector is read or written the same as the read and write commands.
+//
+#define CMD_SK BIT5
+
+//
+// FDC Status Register Bit Definitions
+//
+//
+// Status Register 0
+//
+#define STS0_IC (BIT7 | BIT6) // Interrupt Code
+#define STS0_SE BIT5 // Seek End: the FDC completed a seek or recalibrate command
+#define STS0_EC BIT4 // Equipment Check
+#define STS0_NR BIT3 // Not Ready(unused), this bit is always 0
+#define STS0_HA BIT2 // Head Address: the current head address
+// STS0_US1 & STS0_US0: Drive Select(the current selected drive)
+//
+#define STS0_US1 BIT1 // Unit Select1
+#define STS0_US0 BIT0 // Unit Select0
+//
+// Status Register 1
+//
+#define STS1_EN BIT7 // End of Cylinder
+// BIT6 is unused
+//
+#define STS1_DE BIT5 // Data Error: The FDC detected a CRC error in either the ID field or data field of a sector
+#define STS1_OR BIT4 // Overrun/Underrun: Becomes set if FDC does not receive CPU or DMA service within the required time interval
+// BIT3 is unused
+//
+#define STS1_ND BIT2 // No data
+#define STS1_NW BIT1 // Not Writable
+#define STS1_MA BIT0 // Missing Address Mark
+//
+// Status Register 2
+//
+// BIT7 is unused
+//
+#define STS2_CM BIT6 // Control Mark
+#define STS2_DD BIT5 // Data Error in Data Field: The FDC detected a CRC error in the data field
+#define STS2_WC BIT4 // Wrong Cylinder: The track address from sector ID field is different from the track address maintained inside FDC
+// #define STS2_SH BIT3 // Scan Equal Hit
+// #define STS2_SN BIT2 // Scan Not Satisfied
+// BIT3 is unused
+// BIT2 is unused
+//
+#define STS2_BC BIT1 // Bad Cylinder
+#define STS2_MD BIT0 // Missing Address Mark in DataField
+// Status Register 3
+// #define STS3_FT BIT7 // Fault
+// BIT7 is unused
+//
+#define STS3_WP BIT6 // Write Protected
+// #define STS3_RDY BIT5 // Ready
+// BIT5 is unused
+//
+#define STS3_T0 BIT4 // Track 0
+// #define STS3_TS BIT3 // Two Side
+// BIT3 is unused
+//
+#define STS3_HD BIT2 // Head Address
+// STS3_US1 & STS3_US0 : Drive Select
+//
+#define STS3_US1 BIT1 // Unit Select1
+#define STS3_US0 BIT0 // Unit Select0
+//
+// Status Register 0 Interrupt Code Description
+//
+#define IC_NT 0x0 // Normal Termination of Command
+#define IC_AT 0x40 // Abnormal Termination of Command
+#define IC_IC 0x80 // Invalid Command
+#define IC_ATRC 0xC0 // Abnormal Termination caused by Polling
+typedef struct {
+ UINT8 EOT; // End of track
+ UINT8 GPL; // Gap length
+ UINT8 DTL; // Data length
+ UINT8 Number; // Number of bytes per sector
+ UINT8 MaxTrackNum;
+ UINT8 MotorStartTime;
+ UINT8 MotorOffTime;
+ UINT8 HeadSettlingTime;
+ UINT8 DataTransferRate;
+} DISKET_PARA_TABLE;
+
+typedef struct {
+ UINT8 CommandCode;
+ UINT8 DiskHeadSel;
+ UINT8 Cylinder;
+ UINT8 Head;
+ UINT8 Sector;
+ UINT8 Number;
+ UINT8 EndOfTrack;
+ UINT8 GapLength;
+ UINT8 DataLength;
+} FDC_COMMAND_PACKET1;
+
+typedef struct {
+ UINT8 CommandCode;
+ UINT8 DiskHeadSel;
+} FDC_COMMAND_PACKET2;
+
+typedef struct {
+ UINT8 CommandCode;
+ UINT8 SrtHut;
+ UINT8 HltNd;
+} FDC_SPECIFY_CMD;
+
+typedef struct {
+ UINT8 CommandCode;
+ UINT8 DiskHeadSel;
+ UINT8 NewCylinder;
+} FDC_SEEK_CMD;
+
+typedef struct {
+ UINT8 Status0;
+ UINT8 Status1;
+ UINT8 Status2;
+ UINT8 C;
+ UINT8 H;
+ UINT8 S;
+ UINT8 Number;
+} FDC_RESULT_PACKET;
+
+#endif
diff --git a/Bus/Isa/IsaFloppy/Pei/FloppyPeim.c b/Bus/Isa/IsaFloppy/Pei/FloppyPeim.c
new file mode 100644
index 0000000..22bddf9
--- /dev/null
+++ b/Bus/Isa/IsaFloppy/Pei/FloppyPeim.c
@@ -0,0 +1,1785 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation. All rights reserved. <BR>
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ FloppyPeim.c
+
+Abstract:
+
+
+Revision History
+--*/
+
+
+#include "FloppyPeim.h"
+#include "IndustryStandard/Pcat.h"
+//
+// #include "sio.h"
+//
+
+#define PageSize 4096
+#define ISA_MAX_MEMORY_ADDRESS 0x1000000 // 16 MB Memory Range
+UINT16 FdcBaseAddress = 0x3f0;
+
+static DISKET_PARA_TABLE DiskPara[9] = {
+ {
+ 0x09,
+ 0x50,
+ 0xff,
+ 0x2,
+ 0x27,
+ 0x4,
+ 0x25,
+ 0x14,
+ 0x80
+ },
+ {
+ 0x09,
+ 0x2a,
+ 0xff,
+ 0x2,
+ 0x27,
+ 0x4,
+ 0x25,
+ 0x0f,
+ 0x40
+ },
+ {
+ 0x0f,
+ 0x54,
+ 0xff,
+ 0x2,
+ 0x4f,
+ 0x4,
+ 0x25,
+ 0x0f,
+ 0x0
+ },
+ {
+ 0x09,
+ 0x50,
+ 0xff,
+ 0x2,
+ 0x4f,
+ 0x4,
+ 0x25,
+ 0x0f,
+ 0x80
+ },
+ {
+ 0x09,
+ 0x2a,
+ 0xff,
+ 0x2,
+ 0x4f,
+ 0x4,
+ 0x25,
+ 0x0f,
+ 0x80
+ },
+ {
+ 0x12,
+ 0x1b,
+ 0xff,
+ 0x2,
+ 0x4f,
+ 0x4,
+ 0x25,
+ 0x0f,
+ 0x0
+ },
+ {
+ 0x09,
+ 0x2a,
+ 0xff,
+ 0x2,
+ 0x4f,
+ 0x4,
+ 0x25,
+ 0x0f,
+ 0x80
+ },
+ {
+ 0x12,
+ 0x1b,
+ 0xff,
+ 0x2,
+ 0x4f,
+ 0x4,
+ 0x25,
+ 0x0f,
+ 0x0
+ },
+ {
+ 0x24,
+ 0x1b,
+ 0xff,
+ 0x2,
+ 0x4f,
+ 0x4,
+ 0x25,
+ 0x0f,
+ 0xc0
+ }
+};
+
+static UINTN BytePerSector[6] = { 0, 256, 512, 1024, 2048, 4096 };
+
+//
+// PEIM Entry Ppint
+//
+
+EFI_STATUS
+FdcPeimEntry (
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices
+ )
+/*++
+
+Routine Description:
+
+ Initializes the Fdc Block Io PPI
+
+Arguments:
+
+ PeiServices - General purpose services available to every PEIM.
+ FfsHeader - Ffs header pointer
+
+Returns:
+
+ EFI_UNSUPPORTED - Can't find neccessary Ppi.
+ EFI_OUT_OF_RESOURCES - Have no enough memory to create instance or descriptors.
+ EFI_SUCCESS - Success.
+
+--*/
+{
+ UINTN MemPages;
+ EFI_STATUS Status;
+ FDC_BLK_IO_DEV *FdcBlkIoDev;
+ EFI_PHYSICAL_ADDRESS TempPtr;
+
+ //
+ // Initializing PEI floppy driver.
+ //
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, EFI_PERIPHERAL_REMOVABLE_MEDIA + EFI_P_PC_INIT);
+
+ //
+ // Data
+ //
+ // Allocate PEI instance data.
+ //
+ MemPages = sizeof (FDC_BLK_IO_DEV) / PageSize + 1;
+ Status = PeiServicesAllocatePages (
+ EfiConventionalMemory,
+ MemPages,
+ &TempPtr
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Initialize PEI instance data.
+ //
+ FdcBlkIoDev = (FDC_BLK_IO_DEV *) ((UINTN) TempPtr);
+ FdcBlkIoDev->Signature = FDC_BLK_IO_DEV_SIGNATURE;
+
+ //
+ // InitSio ();
+ //
+ FdcEnumeration (FdcBlkIoDev);
+
+ FdcBlkIoDev->FdcBlkIo.GetNumberOfBlockDevices = FdcGetNumberOfBlockDevices;
+ FdcBlkIoDev->FdcBlkIo.GetBlockDeviceMediaInfo = FdcGetBlockDeviceMediaInfo;
+ FdcBlkIoDev->FdcBlkIo.ReadBlocks = FdcReadBlocks;
+
+ FdcBlkIoDev->PpiDescriptor.Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
+ FdcBlkIoDev->PpiDescriptor.Guid = &gEfiPei144FloppyBlockIoPpiGuid;
+ FdcBlkIoDev->PpiDescriptor.Ppi = &FdcBlkIoDev->FdcBlkIo;
+
+ if (FdcBlkIoDev->DeviceCount != 0) {
+ Status = PeiServicesInstallPpi (&FdcBlkIoDev->PpiDescriptor);
+ if (EFI_ERROR (Status)) {
+ //
+ // PeiServicesFreePages (TempPtr, MemPages);
+ //
+ return EFI_OUT_OF_RESOURCES;
+ }
+ } else {
+ //
+ // PeiServicesFreePages (TempPtr, MemPages);
+ //
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+FdcGetNumberOfBlockDevices (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
+ OUT UINTN *NumberBlockDevices
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+// GC_TODO: This - add argument and description to function comment
+// GC_TODO: NumberBlockDevices - add argument and description to function comment
+// GC_TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// GC_TODO: EFI_SUCCESS - add return value to function comment
+{
+ FDC_BLK_IO_DEV *FdcBlkIoDev;
+
+ FdcBlkIoDev = NULL;
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FdcBlkIoDev = PEI_RECOVERY_FDC_FROM_BLKIO_THIS (This);
+
+ *NumberBlockDevices = FdcBlkIoDev->DeviceCount;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+FdcGetBlockDeviceMediaInfo (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
+ IN UINTN DeviceIndex,
+ OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ DeviceIndex - GC_TODO: add argument description
+ MediaInfo - GC_TODO: add argument description
+
+Returns:
+
+ EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
+ EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_SUCCESS - GC_TODO: Add description for return value
+
+--*/
+{
+ UINTN DeviceCount;
+ FDC_BLK_IO_DEV *FdcBlkIoDev;
+ BOOLEAN bStatus;
+
+ FdcBlkIoDev = NULL;
+
+ if (This == NULL || MediaInfo == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FdcBlkIoDev = PEI_RECOVERY_FDC_FROM_BLKIO_THIS (This);
+
+ DeviceCount = FdcBlkIoDev->DeviceCount;
+
+ //
+ // DeviceIndex is zero-based value.
+ //
+ if (DeviceIndex > DeviceCount - 1) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // probe media and retrieve latest media information
+ //
+ bStatus = DiscoverFdcDevice (
+ FdcBlkIoDev,
+ &FdcBlkIoDev->DeviceInfo[DeviceIndex],
+ MediaInfo
+ );
+
+ if (!bStatus) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ CopyMem (
+ &(FdcBlkIoDev->DeviceInfo[DeviceIndex].MediaInfo),
+ MediaInfo,
+ sizeof (EFI_PEI_BLOCK_IO_MEDIA)
+ );
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+FdcReadBlocks (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
+ IN UINTN DeviceIndex,
+ IN EFI_PEI_LBA StartLba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ This - GC_TODO: add argument description
+ DeviceIndex - GC_TODO: add argument description
+ StartLba - GC_TODO: add argument description
+ BufferSize - GC_TODO: add argument description
+ Buffer - GC_TODO: add argument description
+
+Returns:
+
+ EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
+ EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
+ EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
+ EFI_NO_MEDIA - GC_TODO: Add description for return value
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_SUCCESS - GC_TODO: Add description for return value
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+
+--*/
+{
+
+ EFI_PEI_BLOCK_IO_MEDIA MediaInfo;
+ EFI_STATUS Status;
+ UINTN i;
+ UINTN NumberOfBlocks;
+ UINTN BlockSize;
+ FDC_BLK_IO_DEV *FdcBlkIoDev;
+ EFI_PHYSICAL_ADDRESS MemPage;
+
+ FdcBlkIoDev = NULL;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FdcBlkIoDev = PEI_RECOVERY_FDC_FROM_BLKIO_THIS (This);
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = FdcGetBlockDeviceMediaInfo (PeiServices, This, DeviceIndex, &MediaInfo);
+ if (Status != EFI_SUCCESS) {
+ return Status;
+ }
+
+ BlockSize = MediaInfo.BlockSize;
+
+ if (BufferSize % BlockSize != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!MediaInfo.MediaPresent) {
+ return EFI_NO_MEDIA;
+ }
+
+ NumberOfBlocks = BufferSize / BlockSize;
+
+ //
+ // allocate 40 blocks: 5*4k=20k=20*1024=40blocks
+ //
+ MemPage = ISA_MAX_MEMORY_ADDRESS - 1;
+ Status = PeiServicesAllocatePages (
+ EfiConventionalMemory,
+ ((BufferSize % EFI_PAGE_SIZE) ? (BufferSize / EFI_PAGE_SIZE + 1) : (BufferSize / EFI_PAGE_SIZE)),
+ &MemPage
+ );
+ if (EFI_ERROR (Status) || (MemPage >= ISA_MAX_MEMORY_ADDRESS)) {
+ //
+ // If failed, designate the address space for DMA
+ //
+ MemPage = 0x0f00000;
+ //
+ // return EFI_OUT_OF_RESOURCES;
+ //
+ }
+ //
+ // MemPage = (EFI_PHYSICAL_ADDRESS)(UINTN)Temp;
+ //
+ Status = MotorOn (FdcBlkIoDev, &(FdcBlkIoDev->DeviceInfo[DeviceIndex]));
+ if (Status != EFI_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = Setup (FdcBlkIoDev, FdcBlkIoDev->DeviceInfo[DeviceIndex].DevPos);
+ if (Status != EFI_SUCCESS) {
+ MotorOff (FdcBlkIoDev, &(FdcBlkIoDev->DeviceInfo[DeviceIndex]));
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // read blocks in the same cylinder.
+ // in a cylinder , there are 18 * 2 = 36 blocks
+ //
+ while ((i = GetTransferBlockCount (
+ &(FdcBlkIoDev->DeviceInfo[DeviceIndex]),
+ StartLba,
+ NumberOfBlocks
+ )) != 0 && Status == EFI_SUCCESS) {
+ Status = ReadWriteDataSector (
+ FdcBlkIoDev,
+ &(FdcBlkIoDev->DeviceInfo[DeviceIndex]),
+ (UINT8 *) (UINTN) MemPage,
+ StartLba,
+ i,
+ READ
+ );
+ CopyMem ((UINT8 *) Buffer, (UINT8 *) (UINTN) MemPage, BlockSize * i);
+ StartLba += i;
+ NumberOfBlocks -= i;
+ Buffer = (VOID *) ((UINTN) Buffer + i * BlockSize);
+ }
+ //
+ // PeiServicesFreePages (MemPage, 5);
+ //
+ MotorOff (FdcBlkIoDev, &(FdcBlkIoDev->DeviceInfo[DeviceIndex]));
+
+ switch (Status) {
+ case EFI_SUCCESS:
+ return EFI_SUCCESS;
+
+ default:
+ FdcReset (FdcBlkIoDev, FdcBlkIoDev->DeviceInfo[DeviceIndex].DevPos);
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // return Status;
+ //
+}
+//
+// Internal function Implementation
+//
+UINT8
+FdcEnumeration (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev
+ )
+/*++
+
+Routine Description:
+
+ Enumerate floppy device
+
+Arguments:
+
+ FdcBlkIoDev - Instance of floppy device controller
+
+Returns:
+
+ DevNo - Device No.
+
+--*/
+{
+ UINT8 DevPos;
+ UINT8 DevNo;
+ EFI_PEI_BLOCK_IO_MEDIA MediaInfo;
+ EFI_STATUS Status;
+
+ DevNo = 0;
+
+ //
+ // DevPos=0 means A: 1 means B:
+ //
+ for (DevPos = 0; DevPos < 2; DevPos++) {
+ //
+ // Detecting device presence
+ //
+ REPORT_STATUS_CODE (EFI_PROGRESS_CODE, EFI_PERIPHERAL_REMOVABLE_MEDIA + EFI_P_PC_PRESENCE_DETECT);
+
+ //
+ // Data
+ //
+ // Reset FDC
+ //
+ Status = FdcReset (FdcBlkIoDev, DevPos);
+
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ FdcBlkIoDev->DeviceInfo[DevPos].DevPos = DevPos;
+ FdcBlkIoDev->DeviceInfo[DevPos].Pcn = 0;
+ FdcBlkIoDev->DeviceInfo[DevPos].MotorOn = FALSE;
+ FdcBlkIoDev->DeviceInfo[DevPos].NeedRecalibrate = TRUE;
+ FdcBlkIoDev->DeviceInfo[DevPos].Type = _1440K_1440K;
+
+ //
+ // Discover FDC device
+ //
+ if (DiscoverFdcDevice (FdcBlkIoDev, &(FdcBlkIoDev->DeviceInfo[DevPos]), &MediaInfo)) {
+ FdcBlkIoDev->DeviceInfo[DevNo].DevPos = DevPos;
+
+ FdcBlkIoDev->DeviceInfo[DevNo].Pcn = FdcBlkIoDev->DeviceInfo[DevPos].Pcn;
+ FdcBlkIoDev->DeviceInfo[DevNo].MotorOn = FdcBlkIoDev->DeviceInfo[DevPos].MotorOn;
+ FdcBlkIoDev->DeviceInfo[DevNo].NeedRecalibrate = FdcBlkIoDev->DeviceInfo[DevPos].NeedRecalibrate;
+ FdcBlkIoDev->DeviceInfo[DevNo].Type = FdcBlkIoDev->DeviceInfo[DevPos].Type;
+
+ CopyMem (
+ &(FdcBlkIoDev->DeviceInfo[DevNo].MediaInfo),
+ &MediaInfo,
+ sizeof (EFI_PEI_BLOCK_IO_MEDIA)
+ );
+
+ DevNo++;
+ } else {
+ //
+ // Assume controller error
+ //
+ REPORT_STATUS_CODE (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ EFI_PERIPHERAL_REMOVABLE_MEDIA + EFI_P_EC_CONTROLLER_ERROR
+ );
+
+ //
+ // Data
+ //
+ }
+ }
+
+ FdcBlkIoDev->DeviceCount = DevNo;
+ return DevNo;
+}
+
+BOOLEAN
+DiscoverFdcDevice (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN OUT PEI_FLOPPY_DEVICE_INFO *Info,
+ OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcBlkIoDev - GC_TODO: add argument description
+ Info - GC_TODO: add argument description
+ MediaInfo - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ EFI_STATUS Status;
+ DISKET_PARA_TABLE *Para;
+
+ Status = MotorOn (FdcBlkIoDev, Info);
+ if (Status != EFI_SUCCESS) {
+ return FALSE;
+ }
+
+ Status = Recalibrate (FdcBlkIoDev, Info);
+
+ if (Status != EFI_SUCCESS) {
+ MotorOff (FdcBlkIoDev, Info);
+ return FALSE;
+ }
+ //
+ // Set Media Parameter
+ //
+ MediaInfo->DeviceType = LegacyFloppy;
+ MediaInfo->MediaPresent = TRUE;
+
+ //
+ // Check Media
+ //
+ Status = DisketChanged (FdcBlkIoDev, Info);
+ switch (Status) {
+ case EFI_NO_MEDIA:
+ MediaInfo->MediaPresent = FALSE;
+ break;
+
+ case EFI_MEDIA_CHANGED:
+ case EFI_SUCCESS:
+ break;
+
+ default:
+ //
+ // EFI_DEVICE_ERROR
+ //
+ MotorOff (FdcBlkIoDev, Info);
+ return FALSE;
+ }
+
+ MotorOff (FdcBlkIoDev, Info);
+
+ Para = (DISKET_PARA_TABLE *) ((UINT8 *) DiskPara + sizeof (DISKET_PARA_TABLE) * Info->Type);
+ MediaInfo->BlockSize = BytePerSector[Para->Number];
+ MediaInfo->LastBlock = Para->EOT * 2 * (Para->MaxTrackNum + 1) - 1;
+
+ return TRUE;
+}
+
+EFI_STATUS
+FdcReset (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN UINT8 DevPos
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcBlkIoDev - GC_TODO: add argument description
+ DevPos - GC_TODO: add argument description
+
+Returns:
+
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_SUCCESS - GC_TODO: Add description for return value
+
+--*/
+{
+ UINT8 data;
+ UINT8 sts0;
+ UINT8 pcn;
+ UINTN i;
+
+ //
+ // Reset specified Floppy Logic Drive according to Fdd -> Disk
+ // Set Digital Output Register(DOR) to do reset work
+ // bit0 & bit1 of DOR : Drive Select
+ // bit2 : Reset bit
+ // bit3 : DMA and Int bit
+ // Reset : A "0" written to bit2 resets the FDC, this reset will remain active until
+ // a "1" is written to this bit.
+ // Reset step 1:
+ // use bit0 & bit1 to select the logic drive
+ // write "0" to bit2
+ //
+ data = 0x0;
+ data = (UINT8) (data | (SELECT_DRV & DevPos));
+ IoWrite8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_DOR), data);
+
+ //
+ // wait some time,at least 120us
+ //
+ MicroSecondDelay (500);
+ //
+ // Reset step 2:
+ // write "1" to bit2
+ // write "1" to bit3 : enable DMA
+ //
+ data |= 0x0C;
+ IoWrite8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_DOR), data);
+
+ MicroSecondDelay (2000);
+
+ //
+ // wait specified floppy logic drive is not busy
+ //
+ if (FdcWaitForBSYClear (FdcBlkIoDev, DevPos, 1) != EFI_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Set the Transfer Data Rate
+ //
+ IoWrite8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_CCR), 0x0);
+
+ MicroSecondDelay (100);
+
+ //
+ // Issue Sense interrupt command for each drive (total 4 drives)
+ //
+ for (i = 0; i < 4; i++) {
+ if (SenseIntStatus (FdcBlkIoDev, &sts0, &pcn) != EFI_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ //
+ // issue Specify command
+ //
+ if (Specify (FdcBlkIoDev) != EFI_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FdcWaitForBSYClear (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN UINT8 DevPos,
+ IN UINTN TimeoutInSeconds
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcBlkIoDev - GC_TODO: add argument description
+ DevPos - GC_TODO: add argument description
+ TimeoutInSeconds - GC_TODO: add argument description
+
+Returns:
+
+ EFI_TIMEOUT - GC_TODO: Add description for return value
+ EFI_SUCCESS - GC_TODO: Add description for return value
+
+--*/
+{
+ UINTN Delay;
+ UINT8 StatusRegister;
+ UINT8 Mask;
+
+ //
+ // How to determine drive and command are busy or not: by the bits of Main Status Register
+ // bit0: Drive 0 busy (drive A)
+ // bit1: Drive 1 busy (drive B)
+ // bit4: Command busy
+ //
+ // set mask: for drive A set bit0 & bit4; for drive B set bit1 & bit4
+ //
+ Mask = (UINT8) ((DevPos == 0 ? MSR_DAB : MSR_DBB) | MSR_CB);
+
+ Delay = ((TimeoutInSeconds * STALL_1_MSECOND) / 50) + 1;
+
+ do {
+ StatusRegister = IoRead8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_MSR));
+
+ if ((StatusRegister & Mask) == 0x00) {
+ break;
+ //
+ // not busy
+ //
+ }
+
+ MicroSecondDelay (50);
+ } while (--Delay);
+
+ if (Delay == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SenseIntStatus (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN OUT UINT8 *sts0,
+ IN OUT UINT8 *pcn
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcBlkIoDev - GC_TODO: add argument description
+ sts0 - GC_TODO: add argument description
+ pcn - GC_TODO: add argument description
+
+Returns:
+
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_SUCCESS - GC_TODO: Add description for return value
+
+--*/
+{
+ UINT8 command;
+
+ command = SENSE_INT_STATUS_CMD;
+ if (DataOutByte (FdcBlkIoDev, &command) != EFI_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (DataInByte (FdcBlkIoDev, sts0) != EFI_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (DataInByte (FdcBlkIoDev, pcn) != EFI_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+Specify (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcBlkIoDev - GC_TODO: add argument description
+
+Returns:
+
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_SUCCESS - GC_TODO: Add description for return value
+
+--*/
+{
+ FDC_SPECIFY_CMD Command;
+ UINTN i;
+ UINT8 *pt;
+
+ ZeroMem (&Command, sizeof (FDC_SPECIFY_CMD));
+ Command.CommandCode = SPECIFY_CMD;
+ //
+ // set SRT, HUT
+ //
+ Command.SrtHut = 0xdf;
+ //
+ // 0xdf;
+ // set HLT and DMA
+ //
+ Command.HltNd = 0x02;
+
+ pt = (UINT8 *) (&Command);
+ for (i = 0; i < sizeof (FDC_SPECIFY_CMD); i++) {
+ if (DataOutByte (FdcBlkIoDev, pt++) != EFI_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DataInByte (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN OUT UINT8 *pt
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcBlkIoDev - GC_TODO: add argument description
+ pt - GC_TODO: add argument description
+
+Returns:
+
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_SUCCESS - GC_TODO: Add description for return value
+
+--*/
+{
+ UINT8 data;
+
+ //
+ // wait for 1ms and detect the FDC is ready to be read
+ //
+ if (FdcDRQReady (FdcBlkIoDev, DATA_IN, 1) != EFI_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ //
+ // is not ready
+ //
+ }
+
+ data = IoRead8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_DTR));
+ MicroSecondDelay (50);
+ *pt = data;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DataOutByte (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN UINT8 *pt
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcBlkIoDev - GC_TODO: add argument description
+ pt - GC_TODO: add argument description
+
+Returns:
+
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_SUCCESS - GC_TODO: Add description for return value
+
+--*/
+{
+ UINT8 data;
+
+ //
+ // wait for 1ms and detect the FDC is ready to be written
+ //
+ if (FdcDRQReady (FdcBlkIoDev, DATA_OUT, 1) != EFI_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ //
+ // is not ready
+ //
+ }
+
+ data = *pt;
+ IoWrite8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_DTR), data);
+ MicroSecondDelay (50);
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FdcDRQReady (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN BOOLEAN Dio,
+ IN UINTN TimeoutInSeconds
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcBlkIoDev - GC_TODO: add argument description
+ Dio - GC_TODO: add argument description
+ TimeoutInSeconds - GC_TODO: add argument description
+
+Returns:
+
+ EFI_NOT_READY - GC_TODO: Add description for return value
+ EFI_SUCCESS - GC_TODO: Add description for return value
+
+--*/
+{
+ UINTN Delay;
+ UINT8 StatusRegister;
+ UINT8 DataInOut;
+
+ //
+ // Before writing to FDC or reading from FDC, the Host must examine
+ // the bit7(RQM) and bit6(DIO) of the Main Status Register.
+ // That is to say:
+ // command bytes can not be written to Data Register unless RQM is 1 and DIO is 0
+ // result bytes can not be read from Data Register unless RQM is 1 and DIO is 1
+ //
+ DataInOut = (UINT8) (Dio << 6);
+ //
+ // in order to compare bit6
+ //
+ Delay = ((TimeoutInSeconds * STALL_1_MSECOND) / 50) + 1;
+ do {
+ StatusRegister = IoRead8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_MSR));
+ if ((StatusRegister & MSR_RQM) == MSR_RQM && (StatusRegister & MSR_DIO) == DataInOut) {
+ break;
+ //
+ // FDC is ready
+ //
+ }
+
+ MicroSecondDelay (50);
+ } while (--Delay);
+
+ if (Delay == 0) {
+ return EFI_NOT_READY;
+ //
+ // FDC is not ready within the specified time period
+ //
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+MotorOn (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN OUT PEI_FLOPPY_DEVICE_INFO *Info
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcBlkIoDev - GC_TODO: add argument description
+ Info - GC_TODO: add argument description
+
+Returns:
+
+ EFI_SUCCESS - GC_TODO: Add description for return value
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_SUCCESS - GC_TODO: Add description for return value
+
+--*/
+{
+ //
+ // EFI_STATUS Status;
+ //
+ UINT8 data;
+ UINT8 DevPos;
+
+ //
+ // Control of the floppy drive motors is a big pain. If motor is off, you have to turn it
+ // on first. But you can not leave the motor on all the time, since that would wear out the
+ // disk. On the other hand, if you turn the motor off after each operation, the system performance
+ // will be awful. The compromise used in this driver is to leave the motor on for 2 seconds after
+ // each operation. If a new operation is started in that interval(2s), the motor need not be
+ // turned on again. If no new operation is started, a timer goes off and the motor is turned off
+ //
+ DevPos = Info->DevPos;
+
+ if (Info->MotorOn) {
+ return EFI_SUCCESS;
+ }
+ //
+ // The drive's motor is off, so need turn it on
+ // first look at command and drive are busy or not
+ //
+ if (FdcWaitForBSYClear (FdcBlkIoDev, DevPos, 1) != EFI_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // for drive A: 1CH, drive B: 2DH
+ //
+ data = 0x0C;
+ data = (UINT8) (data | (SELECT_DRV & DevPos));
+ if (DevPos == 0) {
+ data |= DRVA_MOTOR_ON;
+ //
+ // FdcTimer[1].MotorOn = FALSE;
+ // Info->MotorOn = FALSE;
+ //
+ } else {
+ data |= DRVB_MOTOR_ON;
+ //
+ // FdcTimer[0].MotorOn = FALSE;
+ // Info->MotorOn = FALSE;
+ //
+ }
+
+ Info->MotorOn = FALSE;
+
+ IoWrite8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_DOR), data);
+
+ MicroSecondDelay (4000);
+ //
+ // FdcTimer[DevPos].MotorOn = TRUE;
+ //
+ Info->MotorOn = TRUE;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+MotorOff (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN OUT PEI_FLOPPY_DEVICE_INFO *Info
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcBlkIoDev - GC_TODO: add argument description
+ Info - GC_TODO: add argument description
+
+Returns:
+
+ EFI_SUCCESS - GC_TODO: Add description for return value
+ EFI_SUCCESS - GC_TODO: Add description for return value
+
+--*/
+{
+ UINT8 data;
+ UINT8 DevPos;
+
+ DevPos = Info->DevPos;
+
+ if (!Info->MotorOn) {
+ return EFI_SUCCESS;
+ }
+ //
+ // the motor is on, so need motor off
+ //
+ data = 0x0C;
+ data = (UINT8) (data | (SELECT_DRV & DevPos));
+
+ IoWrite8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_DOR), data);
+ MicroSecondDelay (50);
+ //
+ // FdcTimer[DevPos].MotorOn = FALSE;
+ //
+ Info->MotorOn = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DisketChanged (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN OUT PEI_FLOPPY_DEVICE_INFO *Info
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcBlkIoDev - GC_TODO: add argument description
+ Info - GC_TODO: add argument description
+
+Returns:
+
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_NO_MEDIA - GC_TODO: Add description for return value
+ EFI_MEDIA_CHANGED - GC_TODO: Add description for return value
+ EFI_SUCCESS - GC_TODO: Add description for return value
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT8 data;
+
+ //
+ // Check change line
+ //
+ data = IoRead8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_DIR));
+
+ MicroSecondDelay (50);
+
+ if ((data & DIR_DCL) == 0x80) {
+ if (Info->Pcn != 0) {
+ Status = Recalibrate (FdcBlkIoDev, Info);
+ } else {
+ Status = Seek (FdcBlkIoDev, Info, 0x30);
+ }
+
+ if (Status != EFI_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ //
+ // Fail to do the seek or recalibrate operation
+ //
+ }
+
+ data = IoRead8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_DIR));
+
+ MicroSecondDelay (50);
+
+ if ((data & DIR_DCL) == 0x80) {
+ return EFI_NO_MEDIA;
+ }
+
+ return EFI_MEDIA_CHANGED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+Recalibrate (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN OUT PEI_FLOPPY_DEVICE_INFO *Info
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcBlkIoDev - GC_TODO: add argument description
+ Info - GC_TODO: add argument description
+
+Returns:
+
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_SUCCESS - GC_TODO: Add description for return value
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_SUCCESS - GC_TODO: Add description for return value
+
+--*/
+{
+ FDC_COMMAND_PACKET2 Command;
+ UINTN i;
+ UINT8 sts0;
+ UINT8 pcn;
+ UINT8 *pt;
+ UINT8 Count;
+ UINT8 DevPos;
+
+ Count = 2;
+ DevPos = Info->DevPos;
+
+ while (Count > 0) {
+ ZeroMem (&Command, sizeof (FDC_COMMAND_PACKET2));
+ Command.CommandCode = RECALIBRATE_CMD;
+ //
+ // drive select
+ //
+ if (DevPos == 0) {
+ Command.DiskHeadSel = 0;
+ //
+ // 0
+ //
+ } else {
+ Command.DiskHeadSel = 1;
+ //
+ // 1
+ //
+ }
+
+ pt = (UINT8 *) (&Command);
+ for (i = 0; i < sizeof (FDC_COMMAND_PACKET2); i++) {
+ if (DataOutByte (FdcBlkIoDev, pt++) != EFI_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ MicroSecondDelay (250000);
+
+ if (SenseIntStatus (FdcBlkIoDev, &sts0, &pcn) != EFI_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ((sts0 & 0xf0) == 0x20 && pcn == 0) {
+ //
+ // FdcTimer[DevPos].Pcn = 0;
+ //
+ Info->Pcn = 0;
+ //
+ // FdcTimer[DevPos].NeedRecalibrate = FALSE;
+ //
+ Info->NeedRecalibrate = FALSE;
+ return EFI_SUCCESS;
+ } else {
+ Count--;
+ if (Count == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ }
+ //
+ // end while
+ //
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+Seek (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN OUT PEI_FLOPPY_DEVICE_INFO *Info,
+ IN EFI_PEI_LBA Lba
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcBlkIoDev - GC_TODO: add argument description
+ Info - GC_TODO: add argument description
+ Lba - GC_TODO: add argument description
+
+Returns:
+
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_SUCCESS - GC_TODO: Add description for return value
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_SUCCESS - GC_TODO: Add description for return value
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+
+--*/
+{
+ FDC_SEEK_CMD Command;
+ DISKET_PARA_TABLE *Para;
+ UINT8 EndOfTrack;
+ UINT8 Head;
+ UINT8 Cylinder;
+ UINT8 sts0;
+ UINT8 *pt;
+ UINT8 pcn;
+ UINTN i;
+ UINT8 x;
+ UINT8 DevPos;
+
+ DevPos = Info->DevPos;
+ if (Info->NeedRecalibrate) {
+ if (Recalibrate (FdcBlkIoDev, Info) != EFI_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Recalibrate Success
+ //
+ Info->NeedRecalibrate = FALSE;
+ }
+
+ Para = (DISKET_PARA_TABLE *) ((UINT8 *) DiskPara + sizeof (DISKET_PARA_TABLE) * Info->Type);
+ EndOfTrack = Para->EOT;
+ //
+ // Calculate cylinder based on Lba and EOT
+ //
+ Cylinder = (UINT8) ((UINTN) Lba / EndOfTrack / 2);
+
+ //
+ // if the dest cylinder is the present cylinder, unnecessary to do the seek operation
+ //
+ if (Info->Pcn == Cylinder) {
+ return EFI_SUCCESS;
+ }
+ //
+ // Calculate the head : 0 or 1
+ //
+ Head = (UINT8) ((UINTN) Lba / EndOfTrack % 2);
+
+ ZeroMem (&Command, sizeof (FDC_SEEK_CMD));
+ Command.CommandCode = SEEK_CMD;
+ if (DevPos == 0) {
+ Command.DiskHeadSel = 0;
+ //
+ // 0
+ //
+ } else {
+ Command.DiskHeadSel = 1;
+ //
+ // 1
+ //
+ }
+
+ Command.DiskHeadSel = (UINT8) (Command.DiskHeadSel | (Head << 2));
+ Command.NewCylinder = Cylinder;
+
+ pt = (UINT8 *) (&Command);
+ for (i = 0; i < sizeof (FDC_SEEK_CMD); i++) {
+ if (DataOutByte (FdcBlkIoDev, pt++) != EFI_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ MicroSecondDelay (50);
+
+ //
+ // Calculate waiting time
+ //
+ if (Info->Pcn > Cylinder) {
+ x = (UINT8) (Info->Pcn - Cylinder);
+ } else {
+ x = (UINT8) (Cylinder - Info->Pcn);
+ }
+
+ MicroSecondDelay ((x + 1) * 4000);
+
+ if (SenseIntStatus (FdcBlkIoDev, &sts0, &pcn) != EFI_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ((sts0 & 0xf0) == 0x20) {
+ Info->Pcn = Command.NewCylinder;
+ Info->NeedRecalibrate = FALSE;
+ return EFI_SUCCESS;
+ } else {
+ Info->NeedRecalibrate = TRUE;
+ return EFI_DEVICE_ERROR;
+ }
+}
+
+UINTN
+GetTransferBlockCount (
+ IN PEI_FLOPPY_DEVICE_INFO *Info,
+ IN EFI_PEI_LBA LBA,
+ IN UINTN NumberOfBlocks
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Info - GC_TODO: add argument description
+ LBA - GC_TODO: add argument description
+ NumberOfBlocks - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ DISKET_PARA_TABLE *Para;
+ UINT8 EndOfTrack;
+ UINT8 Head;
+ UINT8 SectorsInTrack;
+
+ Para = (DISKET_PARA_TABLE *) ((UINT8 *) DiskPara + sizeof (DISKET_PARA_TABLE) * Info->Type);
+ EndOfTrack = Para->EOT;
+ Head = (UINT8) ((UINTN) LBA / EndOfTrack % 2);
+
+ SectorsInTrack = (UINT8) (EndOfTrack * (2 - Head) - (UINT8) ((UINTN) LBA % EndOfTrack));
+ if (SectorsInTrack < NumberOfBlocks) {
+ return SectorsInTrack;
+ } else {
+ return NumberOfBlocks;
+ }
+}
+
+EFI_STATUS
+ReadWriteDataSector (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN OUT PEI_FLOPPY_DEVICE_INFO *Info,
+ IN VOID *Buffer,
+ IN EFI_PEI_LBA Lba,
+ IN UINTN NumberOfBlocks,
+ IN BOOLEAN Read
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcBlkIoDev - GC_TODO: add argument description
+ Info - GC_TODO: add argument description
+ Buffer - GC_TODO: add argument description
+ Lba - GC_TODO: add argument description
+ NumberOfBlocks - GC_TODO: add argument description
+ Read - GC_TODO: add argument description
+
+Returns:
+
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_TIMEOUT - GC_TODO: Add description for return value
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+
+--*/
+{
+ EFI_STATUS Status;
+ FDC_COMMAND_PACKET1 Command;
+ FDC_RESULT_PACKET Result;
+ UINTN i;
+ UINTN Times;
+ UINT8 *pt;
+ //
+ // UINT8 Temp;
+ //
+ Status = Seek (FdcBlkIoDev, Info, Lba);
+ if (Status != EFI_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Set up DMA
+ //
+ SetDMA (FdcBlkIoDev, Buffer, NumberOfBlocks, Read);
+
+ //
+ // Allocate Read or Write command packet
+ //
+ ZeroMem (&Command, sizeof (FDC_COMMAND_PACKET1));
+ if (Read == READ) {
+ Command.CommandCode = READ_DATA_CMD | CMD_MT | CMD_MFM | CMD_SK;
+ }
+ //
+ // else
+ // Command.CommandCode = WRITE_DATA_CMD | CMD_MT | CMD_MFM;
+ //
+ FillPara (Info, Lba, &Command);
+
+ //
+ // Write command bytes to FDC
+ //
+ pt = (UINT8 *) (&Command);
+ for (i = 0; i < sizeof (FDC_COMMAND_PACKET1); i++) {
+ if (DataOutByte (FdcBlkIoDev, pt++) != EFI_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ //
+ // wait for some time
+ //
+ Times = (STALL_1_SECOND / 50) + 1;
+ do {
+ if ((IoRead8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_MSR)) & 0xc0) == 0xc0) {
+ break;
+ }
+
+ MicroSecondDelay (50);
+ } while (--Times);
+
+ if (Times == 0) {
+ return EFI_TIMEOUT;
+ }
+ //
+ // Read result bytes from FDC
+ //
+ pt = (UINT8 *) (&Result);
+ for (i = 0; i < sizeof (FDC_RESULT_PACKET); i++) {
+ if (DataInByte (FdcBlkIoDev, pt++) != EFI_SUCCESS) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ return CheckResult (&Result, Info);
+}
+
+EFI_STATUS
+CheckResult (
+ IN FDC_RESULT_PACKET *Result,
+ IN OUT PEI_FLOPPY_DEVICE_INFO *Info
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Result - GC_TODO: add argument description
+ Info - GC_TODO: add argument description
+
+Returns:
+
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_DEVICE_ERROR - GC_TODO: Add description for return value
+ EFI_SUCCESS - GC_TODO: Add description for return value
+
+--*/
+{
+ if ((Result->Status0 & STS0_IC) != IC_NT) {
+ if ((Result->Status0 & STS0_SE) == 0x20) {
+ //
+ // seek error
+ //
+ Info->NeedRecalibrate = TRUE;
+ }
+
+ Info->NeedRecalibrate = TRUE;
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Check Status Register1
+ //
+ if (Result->Status1 & (STS1_EN | STS1_DE | STS1_OR | STS1_ND | STS1_NW | STS1_MA)) {
+ Info->NeedRecalibrate = TRUE;
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Check Status Register2
+ //
+ if (Result->Status2 & (STS2_CM | STS2_DD | STS2_WC | STS2_BC | STS2_MD)) {
+ Info->NeedRecalibrate = TRUE;
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+VOID
+FillPara (
+ IN PEI_FLOPPY_DEVICE_INFO *Info,
+ IN EFI_PEI_LBA Lba,
+ IN FDC_COMMAND_PACKET1 *Command
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Info - GC_TODO: add argument description
+ Lba - GC_TODO: add argument description
+ Command - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ DISKET_PARA_TABLE *Para;
+ UINT8 EndOfTrack;
+ UINT8 DevPos;
+
+ DevPos = Info->DevPos;
+ Para = (DISKET_PARA_TABLE *) ((UINT8 *) DiskPara + sizeof (DISKET_PARA_TABLE) * Info->Type);
+ EndOfTrack = Para->EOT;
+
+ if (DevPos == 0) {
+ Command->DiskHeadSel = 0;
+ } else {
+ Command->DiskHeadSel = 1;
+ }
+
+ Command->Cylinder = (UINT8) ((UINTN) Lba / EndOfTrack / 2);
+ Command->Head = (UINT8) ((UINTN) Lba / EndOfTrack % 2);
+ Command->Sector = (UINT8) ((UINT8) ((UINTN) Lba % EndOfTrack) + 1);
+ Command->DiskHeadSel = (UINT8) (Command->DiskHeadSel | (Command->Head << 2));
+ Command->Number = Para->Number;
+ Command->EndOfTrack = Para->EOT;
+ Command->GapLength = Para->GPL;
+ Command->DataLength = Para->DTL;
+}
+
+EFI_STATUS
+Setup (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN UINT8 DevPos
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcBlkIoDev - GC_TODO: add argument description
+ DevPos - GC_TODO: add argument description
+
+Returns:
+
+ EFI_SUCCESS - GC_TODO: Add description for return value
+
+--*/
+{
+ IoWrite8 ((UINT16) (FdcBaseAddress + FDC_REGISTER_CCR), 0x0);
+
+ MicroSecondDelay (100);
+
+ Specify (FdcBlkIoDev);
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SetDMA (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN VOID *Buffer,
+ IN UINTN NumberOfBlocks,
+ IN BOOLEAN Read
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FdcBlkIoDev - GC_TODO: add argument description
+ Buffer - GC_TODO: add argument description
+ NumberOfBlocks - GC_TODO: add argument description
+ Read - GC_TODO: add argument description
+
+Returns:
+
+ EFI_SUCCESS - GC_TODO: Add description for return value
+
+--*/
+{
+ UINT8 data;
+ UINTN count;
+
+ //
+ // mask DMA channel 2;
+ //
+ IoWrite8 (R_8237_DMA_WRSMSK_CH0_3, B_8237_DMA_WRSMSK_CMS | 2);
+
+ //
+ // clear first/last flip flop
+ //
+ IoWrite8 (R_8237_DMA_CBPR_CH0_3, B_8237_DMA_WRSMSK_CMS | 2);
+
+ //
+ // set mode
+ //
+ if (Read == READ) {
+ IoWrite8 (R_8237_DMA_CHMODE_CH0_3, V_8237_DMA_CHMODE_SINGLE | V_8237_DMA_CHMODE_IO2MEM | 2);
+ } else {
+ IoWrite8 (R_8237_DMA_CHMODE_CH0_3, V_8237_DMA_CHMODE_SINGLE | V_8237_DMA_CHMODE_MEM2IO | 2);
+ }
+ //
+ // set base address and page register
+ //
+ data = (UINT8) (UINTN) Buffer;
+ IoWrite8 (R_8237_DMA_BASE_CA_CH2, data);
+ data = (UINT8) ((UINTN) Buffer >> 8);
+ IoWrite8 (R_8237_DMA_BASE_CA_CH2, data);
+
+ data = (UINT8) ((UINTN) Buffer >> 16);
+ IoWrite8 (R_8237_DMA_MEM_LP_CH2, data);
+
+ //
+ // set count register
+ //
+ count = 512 * NumberOfBlocks - 1;
+ data = (UINT8) (count & 0xff);
+ IoWrite8 (R_8237_DMA_BASE_CC_CH2, data);
+ data = (UINT8) (count >> 8);
+ IoWrite8 (R_8237_DMA_BASE_CC_CH2, data);
+
+ //
+ // clear channel 2 mask
+ //
+ IoWrite8 (R_8237_DMA_WRSMSK_CH0_3, 0x02);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Bus/Isa/IsaFloppy/Pei/FloppyPeim.dxs b/Bus/Isa/IsaFloppy/Pei/FloppyPeim.dxs
new file mode 100644
index 0000000..742a9f2
--- /dev/null
+++ b/Bus/Isa/IsaFloppy/Pei/FloppyPeim.dxs
@@ -0,0 +1,34 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation. All rights reserved.
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ floppypeim.dxs
+
+Abstract:
+
+ Dependency expression file for Status Code PEIM.
+
+--*/
+
+#include <PeimDepex.h>
+
+DEPENDENCY_START
+ EFI_PEI_PERMANENT_MEMORY_INSTALLED_PPI_GUID AND
+ EFI_PEI_FV_FILE_LOADER_GUID AND
+ EFI_PEI_BOOT_IN_RECOVERY_MODE_PEIM_PPI
+DEPENDENCY_END
+
+
+
+
+
diff --git a/Bus/Isa/IsaFloppy/Pei/FloppyPeim.h b/Bus/Isa/IsaFloppy/Pei/FloppyPeim.h
new file mode 100644
index 0000000..f2a9811
--- /dev/null
+++ b/Bus/Isa/IsaFloppy/Pei/FloppyPeim.h
@@ -0,0 +1,254 @@
+/*++
+
+Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ FloppyPeim.h
+
+Abstract:
+
+
+Revision History
+--*/
+
+#ifndef _RECOVERY_FLOPPY_H
+#define _RECOVERY_FLOPPY_H
+
+//
+// The package level header files this module uses
+//
+#include <PiPei.h>
+#include <FrameworkPei.h>
+
+#include <Ppi/BlockIo.h>
+//
+// The Library classes this module consumes
+//
+#include <Library/DebugLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/TimerLib.h>
+#include <Library/IoLib.h>
+
+#include "Fdc.h"
+//
+// define some macro
+//
+#define STALL_1_SECOND 1000000
+#define STALL_1_MSECOND 1000
+
+#define DATA_IN 1
+#define DATA_OUT 0
+#define READ 0
+#define WRITE 1
+
+typedef enum {
+ _360K_360K = 0,
+ _360K_1200K,
+ _1200K_1200K,
+ _720K_720K,
+ _720K_1440K,
+ _1440K_1440K,
+ _720K_2880K,
+ _1440K_2880K,
+ _2880K_2880K
+} FDC_DISKET_TYPE;
+
+typedef struct {
+ UINT8 DevPos;
+ UINT8 Pcn;
+ BOOLEAN MotorOn;
+ BOOLEAN NeedRecalibrate;
+ FDC_DISKET_TYPE Type;
+ EFI_PEI_BLOCK_IO_MEDIA MediaInfo;
+} PEI_FLOPPY_DEVICE_INFO;
+
+#define FDC_BLK_IO_DEV_SIGNATURE EFI_SIGNATURE_32 ('F', 'b', 'i', 'o')
+
+typedef struct {
+ UINTN Signature;
+ EFI_PEI_RECOVERY_BLOCK_IO_PPI FdcBlkIo;
+ EFI_PEI_PPI_DESCRIPTOR PpiDescriptor;
+ UINTN DeviceCount;
+ PEI_FLOPPY_DEVICE_INFO DeviceInfo[2];
+} FDC_BLK_IO_DEV;
+
+#define PEI_RECOVERY_FDC_FROM_BLKIO_THIS(a) CR (a, FDC_BLK_IO_DEV, FdcBlkIo, FDC_BLK_IO_DEV_SIGNATURE)
+
+//
+// PEI Recovery Block I/O PPI
+//
+EFI_STATUS
+EFIAPI
+FdcGetNumberOfBlockDevices (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
+ OUT UINTN *NumberBlockDevices
+ );
+
+EFI_STATUS
+EFIAPI
+FdcGetBlockDeviceMediaInfo (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
+ IN UINTN DeviceIndex,
+ OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo
+ );
+
+EFI_STATUS
+EFIAPI
+FdcReadBlocks (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
+ IN UINTN DeviceIndex,
+ IN EFI_PEI_LBA StartLba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+//
+// Internal function declare
+//
+UINT8
+FdcEnumeration (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev
+ );
+
+EFI_STATUS
+FdcReset (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN UINT8 DevPos
+ );
+
+BOOLEAN
+DiscoverFdcDevice (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN OUT PEI_FLOPPY_DEVICE_INFO *Info,
+ OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo
+ );
+
+EFI_STATUS
+Recalibrate (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN OUT PEI_FLOPPY_DEVICE_INFO *Info
+ );
+
+EFI_STATUS
+Seek (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN OUT PEI_FLOPPY_DEVICE_INFO *Info,
+ IN EFI_PEI_LBA Lba
+ );
+
+EFI_STATUS
+MotorOn (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN OUT PEI_FLOPPY_DEVICE_INFO *Info
+ );
+
+EFI_STATUS
+MotorOff (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN OUT PEI_FLOPPY_DEVICE_INFO *Info
+ );
+
+EFI_STATUS
+FdcWaitForBSYClear (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN UINT8 DevPos,
+ IN UINTN TimeoutInSeconds
+ );
+
+EFI_STATUS
+SenseIntStatus (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN OUT UINT8 *sts0,
+ IN OUT UINT8 *pcn
+ );
+
+EFI_STATUS
+Specify (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev
+ );
+
+EFI_STATUS
+DisketChanged (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN OUT PEI_FLOPPY_DEVICE_INFO *Info
+ );
+
+EFI_STATUS
+DataInByte (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN OUT UINT8 *pt
+ );
+
+EFI_STATUS
+DataOutByte (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN UINT8 *pt
+ );
+
+EFI_STATUS
+FdcDRQReady (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN BOOLEAN Dio,
+ IN UINTN TimeoutInSeconds
+ );
+
+UINTN
+GetTransferBlockCount (
+ IN PEI_FLOPPY_DEVICE_INFO *Info,
+ IN EFI_PEI_LBA LBA,
+ IN UINTN NumberOfBlocks
+ );
+
+EFI_STATUS
+ReadWriteDataSector (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN OUT PEI_FLOPPY_DEVICE_INFO *Info,
+ IN VOID *Buffer,
+ IN EFI_PEI_LBA Lba,
+ IN UINTN NumberOfBlocks,
+ IN BOOLEAN Read
+ );
+
+EFI_STATUS
+SetDMA (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN VOID *Buffer,
+ IN UINTN NumberOfBlocks,
+ IN BOOLEAN Read
+ );
+
+VOID
+FillPara (
+ IN PEI_FLOPPY_DEVICE_INFO *Info,
+ IN EFI_PEI_LBA Lba,
+ IN FDC_COMMAND_PACKET1 *Command
+ );
+
+EFI_STATUS
+Setup (
+ IN FDC_BLK_IO_DEV *FdcBlkIoDev,
+ IN UINT8 DevPos
+ );
+
+EFI_STATUS
+CheckResult (
+ IN FDC_RESULT_PACKET *Result,
+ IN OUT PEI_FLOPPY_DEVICE_INFO *Info
+ );
+
+#endif
diff --git a/Bus/Isa/IsaFloppy/Pei/FloppyPeim.inf b/Bus/Isa/IsaFloppy/Pei/FloppyPeim.inf
new file mode 100644
index 0000000..1c4ce58
--- /dev/null
+++ b/Bus/Isa/IsaFloppy/Pei/FloppyPeim.inf
@@ -0,0 +1,103 @@
+#/** @file
+# Floppy Peim to support Fv Recovery.
+#
+# This module detects Floppy devices. If found, it will install BlockIo PPI.
+# This module is only dispatched in Recovery Boot mode.
+# Copyright (c) 2006 - 2007, Intel Corporation.
+#
+# All rights reserved.
+# This software and associated documentation (if any) is furnished
+# under a license and may only be used or copied in accordance
+# with the terms of the license. Except as permitted by such
+# license, no part of this software or documentation may be
+# reproduced, stored in a retrieval system, or transmitted in any
+# form or by any means without the express written consent of
+# Intel Corporation.
+#
+#
+#**/
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FloppyPeim
+ FILE_GUID = B7A5041B-78BA-48e3-B63B-44C7578113B6
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+
+ ENTRY_POINT = FdcPeimEntry
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+################################################################################
+#
+# Sources Section - list of files that are required for the build to succeed.
+#
+################################################################################
+
+[Sources.common]
+ FloppyPeim.c
+ FloppyPeim.h
+ Fdc.h
+
+
+################################################################################
+#
+# Package Dependency Section - list of Package files that are required for
+# this module.
+#
+################################################################################
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+
+
+################################################################################
+#
+# Library Class Section - list of Library Classes that are required for
+# this module.
+#
+################################################################################
+
+[LibraryClasses]
+ IoLib
+ TimerLib
+ ReportStatusCodeLib
+ BaseMemoryLib
+ PeiServicesLib
+ PeimEntryPoint
+ DebugLib
+
+
+################################################################################
+#
+# PPI C Name Section - list of PPI and PPI Notify C Names that this module
+# uses or produces.
+#
+################################################################################
+
+[Ppis]
+ gEfiPei144FloppyBlockIoPpiGuid # PPI ALWAYS_PRODUCED
+
+
+################################################################################
+#
+# Dependency Expression Section - list of Dependency expressions that are required for
+# this module.
+#
+################################################################################
+
+[Depex]
+ gEfiPeiMemoryDiscoveredPpiGuid AND gEfiPeiFvFileLoaderPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid
+
diff --git a/Bus/Isa/IsaFloppy/Pei/FloppyPeim.msa b/Bus/Isa/IsaFloppy/Pei/FloppyPeim.msa
new file mode 100644
index 0000000..13a61ff
--- /dev/null
+++ b/Bus/Isa/IsaFloppy/Pei/FloppyPeim.msa
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ModuleSurfaceArea xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd" xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <MsaHeader>
+ <ModuleName>FloppyPeim</ModuleName>
+ <ModuleType>PEIM</ModuleType>
+ <GuidValue>B7A5041B-78BA-48e3-B63B-44C7578113B6</GuidValue>
+ <Version>1.0</Version>
+ <Abstract>Floppy Peim to support Fv Recovery.</Abstract>
+ <Description>This module detects Floppy devices. If found, it will install BlockIo PPI.
+ This module is only dispatched in Recovery Boot mode.</Description>
+ <Copyright>Copyright (c) 2006 - 2007, Intel Corporation.</Copyright>
+ <License>All rights reserved.
+ This software and associated documentation (if any) is furnished
+ under a license and may only be used or copied in accordance
+ with the terms of the license. Except as permitted by such
+ license, no part of this software or documentation may be
+ reproduced, stored in a retrieval system, or transmitted in any
+ form or by any means without the express written consent of
+ Intel Corporation.</License>
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
+ </MsaHeader>
+ <ModuleDefinitions>
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
+ <BinaryModule>false</BinaryModule>
+ <OutputFileBasename>FloppyPeim</OutputFileBasename>
+ </ModuleDefinitions>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DebugLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>PeimEntryPoint</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>PeiServicesLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>BaseMemoryLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>ReportStatusCodeLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>TimerLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>IoLib</Keyword>
+ </LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>floppypeim.dxs</Filename>
+ <Filename>fdc.h</Filename>
+ <Filename>floppypeim.h</Filename>
+ <Filename>FloppyPeim.c</Filename>
+ </SourceFiles>
+ <PackageDependencies>
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
+ <Package PackageGuid="bea835f9-fd62-464a-81ff-f3a806360c6b"/>
+ </PackageDependencies>
+ <PPIs>
+ <Ppi Usage="ALWAYS_PRODUCED">
+ <PpiCName>gEfiPeiBlockIoPpiGuid</PpiCName>
+ </Ppi>
+ </PPIs>
+ <Externs>
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
+ <Extern>
+ <ModuleEntryPoint>FdcPeimEntry</ModuleEntryPoint>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea> \ No newline at end of file