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