]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Import IsaFloppy Dxe and Pei in IntelFrameworkModulePkg.
authoryshang1 <yshang1@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 10 Jul 2007 09:04:15 +0000 (09:04 +0000)
committeryshang1 <yshang1@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 10 Jul 2007 09:04:15 +0000 (09:04 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3168 6f19259b-4bc3-4df7-8a09-765794883524

21 files changed:
IntelFrameworkModulePkg/Bus/Isa/IsaFloppy/Dxe/ComponentName.c [new file with mode: 0644]
IntelFrameworkModulePkg/Bus/Isa/IsaFloppy/Dxe/ComponentName.h [new file with mode: 0644]
IntelFrameworkModulePkg/Bus/Isa/IsaFloppy/Dxe/EntryPoint.c [new file with mode: 0644]
IntelFrameworkModulePkg/Bus/Isa/IsaFloppy/Dxe/IsaFloppy.c [new file with mode: 0644]
IntelFrameworkModulePkg/Bus/Isa/IsaFloppy/Dxe/IsaFloppy.h [new file with mode: 0644]
IntelFrameworkModulePkg/Bus/Isa/IsaFloppy/Dxe/IsaFloppy.inf [new file with mode: 0644]
IntelFrameworkModulePkg/Bus/Isa/IsaFloppy/Dxe/IsaFloppy.msa [new file with mode: 0644]
IntelFrameworkModulePkg/Bus/Isa/IsaFloppy/Dxe/IsaFloppyBlock.c [new file with mode: 0644]
IntelFrameworkModulePkg/Bus/Isa/IsaFloppy/Dxe/IsaFloppyCtrl.c [new file with mode: 0644]
IntelFrameworkModulePkg/Bus/Isa/IsaFloppy/Pei/Fdc.h [new file with mode: 0644]
IntelFrameworkModulePkg/Bus/Isa/IsaFloppy/Pei/FloppyPeim.c [new file with mode: 0644]
IntelFrameworkModulePkg/Bus/Isa/IsaFloppy/Pei/FloppyPeim.dxs [new file with mode: 0644]
IntelFrameworkModulePkg/Bus/Isa/IsaFloppy/Pei/FloppyPeim.h [new file with mode: 0644]
IntelFrameworkModulePkg/Bus/Isa/IsaFloppy/Pei/FloppyPeim.inf [new file with mode: 0644]
IntelFrameworkModulePkg/Bus/Isa/IsaFloppy/Pei/FloppyPeim.msa [new file with mode: 0644]
IntelFrameworkModulePkg/IntelFrameworkModulePkg.dsc
MdePkg/Library/PeiIoLibCpuIo/IoHighLevel.c [new file with mode: 0644]
MdePkg/Library/PeiIoLibCpuIo/IoLib.c [new file with mode: 0644]
MdePkg/Library/PeiIoLibCpuIo/IoLibMmioBuffer.c [new file with mode: 0644]
MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.inf [new file with mode: 0644]
MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.msa [new file with mode: 0644]

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