summaryrefslogtreecommitdiff
path: root/EdkModulePkg/Bus/Pci
diff options
context:
space:
mode:
authorbbahnsen <bbahnsen@6f19259b-4bc3-4df7-8a09-765794883524>2006-04-21 22:54:32 +0000
committerbbahnsen <bbahnsen@6f19259b-4bc3-4df7-8a09-765794883524>2006-04-21 22:54:32 +0000
commit878ddf1fc3540a715f63594ed22b6929e881afb4 (patch)
treec56c44dac138137b510e1fba7c3efe5e4d84bea2 /EdkModulePkg/Bus/Pci
downloadedk2-878ddf1fc3540a715f63594ed22b6929e881afb4.zip
edk2-878ddf1fc3540a715f63594ed22b6929e881afb4.tar.gz
edk2-878ddf1fc3540a715f63594ed22b6929e881afb4.tar.bz2
Initial import.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'EdkModulePkg/Bus/Pci')
-rw-r--r--EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.c2226
-rw-r--r--EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.h916
-rw-r--r--EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.mbd42
-rw-r--r--EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.msa65
-rw-r--r--EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/ComponentName.c154
-rw-r--r--EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/build.xml47
-rw-r--r--EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430.c346
-rw-r--r--EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430.h254
-rw-r--r--EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430.mbd42
-rw-r--r--EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430.msa66
-rw-r--r--EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430UgaDraw.c1036
-rw-r--r--EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/ComponentName.c222
-rw-r--r--EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/build.xml47
-rw-r--r--EdkModulePkg/Bus/Pci/IdeBus/Dxe/ComponentName.c224
-rw-r--r--EdkModulePkg/Bus/Pci/IdeBus/Dxe/ComponentName.h118
-rw-r--r--EdkModulePkg/Bus/Pci/IdeBus/Dxe/DriverConfiguration.c378
-rw-r--r--EdkModulePkg/Bus/Pci/IdeBus/Dxe/DriverDiagnostics.c225
-rw-r--r--EdkModulePkg/Bus/Pci/IdeBus/Dxe/ata.c3690
-rw-r--r--EdkModulePkg/Bus/Pci/IdeBus/Dxe/atapi.c2591
-rw-r--r--EdkModulePkg/Bus/Pci/IdeBus/Dxe/build.xml74
-rw-r--r--EdkModulePkg/Bus/Pci/IdeBus/Dxe/ide.c1964
-rw-r--r--EdkModulePkg/Bus/Pci/IdeBus/Dxe/ide.h1806
-rw-r--r--EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.c1400
-rw-r--r--EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.h439
-rw-r--r--EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.mbd45
-rw-r--r--EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.msa90
-rw-r--r--EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebusLite.mbd44
-rw-r--r--EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebusLite.msa86
-rw-r--r--EdkModulePkg/Bus/Pci/IdeBus/Dxe/idedata.h879
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/ComponentName.c133
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/ComponentName.h91
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/LightPciBus.mbd43
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/LightPciBus.msa112
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/LightPciLib.c881
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBus.mbd43
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBus.msa121
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBusLite.mbd43
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBusLite.msa111
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/PciCommand.c207
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/PciCommand.h134
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDeviceSupport.c1345
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDeviceSupport.h477
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDriverOverride.c290
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDriverOverride.h108
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumerator.c2164
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumerator.h628
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumeratorSupport.c2261
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumeratorSupport.h598
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/PciHotPlugSupport.c462
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/PciHotPlugSupport.h269
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/PciIo.c1964
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/PciIo.h773
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/PciLib.c1398
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/PciLib.h247
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/PciOptionRomSupport.c543
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/PciOptionRomSupport.h119
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/PciPowerManagement.c83
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/PciPowerManagement.h48
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/PciResourceSupport.c2276
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/PciResourceSupport.h740
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/PciRomTable.c457
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/PciRomTable.h107
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/build.xml101
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/pcibus.c375
-rw-r--r--EdkModulePkg/Bus/Pci/PciBus/Dxe/pcibus.h243
-rw-r--r--EdkModulePkg/Bus/Pci/Uhci/Dxe/ComponentName.c189
-rw-r--r--EdkModulePkg/Bus/Pci/Uhci/Dxe/Uhci.mbd42
-rw-r--r--EdkModulePkg/Bus/Pci/Uhci/Dxe/Uhci.msa66
-rw-r--r--EdkModulePkg/Bus/Pci/Uhci/Dxe/build.xml47
-rw-r--r--EdkModulePkg/Bus/Pci/Uhci/Dxe/uhchlp.c4237
-rw-r--r--EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.c3498
-rw-r--r--EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.h1187
-rw-r--r--EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Decode.c1661
-rw-r--r--EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/E100b.c3772
-rw-r--r--EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/E100b.h668
-rw-r--r--EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Init.c1162
-rw-r--r--EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Undi.mbd47
-rw-r--r--EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Undi.msa92
-rw-r--r--EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Undi32.h208
-rw-r--r--EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/build.xml47
80 files changed, 56434 insertions, 0 deletions
diff --git a/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.c b/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.c
new file mode 100644
index 0000000..6fe81d1
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.c
@@ -0,0 +1,2226 @@
+/*++
+
+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:
+
+ AtapiPassThru.c
+
+Abstract:
+
+
+Revision History
+--*/
+
+#include "AtapiPassThru.h"
+
+EFI_STATUS
+EFIAPI
+AtapiScsiPassThruDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+EFIAPI
+AtapiScsiPassThruDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+EFIAPI
+AtapiScsiPassThruDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+//
+// IDE registers' fixed address
+//
+static IDE_BASE_REGISTERS gAtapiIoPortRegisters[2] = {
+ { 0x1f0, { 0x1f1 }, 0x1f2, 0x1f3, 0x1f4, 0x1f5, 0x1f6, { 0x1f7 }, { 0x3f6 }, 0x3f7, 0 },
+ { 0x170, { 0x171 }, 0x172, 0x173, 0x174, 0x175, 0x176, { 0x177 }, { 0x376 }, 0x377, 0 }
+};
+
+static SCSI_COMMAND_SET gEndTable = { 0xff, 0xff };
+
+//
+// This table contains all the supported ATAPI commands.
+//
+static SCSI_COMMAND_SET gSupportedATAPICommands[] = {
+ { OP_INQUIRY, DataIn },
+ { OP_LOAD_UNLOAD_CD, NoData },
+ { OP_MECHANISM_STATUS, DataIn },
+ { OP_MODE_SELECT_10, DataOut },
+ { OP_MODE_SENSE_10, DataIn },
+ { OP_PAUSE_RESUME, NoData },
+ { OP_PLAY_AUDIO_10, DataIn },
+ { OP_PLAY_AUDIO_MSF, DataIn },
+ { OP_PLAY_CD, DataIn },
+ { OP_PLAY_CD_MSF, DataIn },
+ { OP_PREVENT_ALLOW_MEDIUM_REMOVAL,NoData },
+ { OP_READ_10, DataIn },
+ { OP_READ_12, DataIn },
+ { OP_READ_CAPACITY, DataIn },
+ { OP_READ_CD, DataIn },
+ { OP_READ_CD_MSF, DataIn },
+ { OP_READ_HEADER, DataIn },
+ { OP_READ_SUB_CHANNEL, DataIn },
+ { OP_READ_TOC, DataIn },
+ { OP_REQUEST_SENSE, DataIn },
+ { OP_SCAN, NoData },
+ { OP_SEEK_10, NoData },
+ { OP_SET_CD_SPEED, DataOut },
+ { OP_STOPPLAY_SCAN, NoData },
+ { OP_START_STOP_UNIT, NoData },
+ { OP_TEST_UNIT_READY, NoData },
+ { OP_FORMAT_UNIT, DataOut },
+ { OP_READ_FORMAT_CAPACITIES, DataIn },
+ { OP_VERIFY, DataOut },
+ { OP_WRITE_10, DataOut },
+ { OP_WRITE_12, DataOut },
+ { OP_WRITE_AND_VERIFY, DataOut },
+ { 0xff, 0xff }
+};
+
+static CHAR16 *gControllerNameString = (CHAR16 *) L"ATAPI Controller";
+static CHAR16 *gAtapiChannelString = (CHAR16 *) L"ATAPI Channel";
+
+EFI_DRIVER_BINDING_PROTOCOL gAtapiScsiPassThruDriverBinding = {
+ AtapiScsiPassThruDriverBindingSupported,
+ AtapiScsiPassThruDriverBindingStart,
+ AtapiScsiPassThruDriverBindingStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+EFI_STATUS
+EFIAPI
+AtapiScsiPassThruDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+ Routine Description:
+ Supported.
+
+ Arguments:
+ (Standard DriverBinding Protocol Supported() function)
+
+ Returns:
+ EFI_STATUS
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Controller - add argument and description to function comment
+// TODO: RemainingDevicePath - add argument and description to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
+
+ //
+ // Open the IO Abstraction(s) needed to perform the supported test
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Use the PCI I/O Protocol to see if Controller is a IDE Controller that
+ // can be managed by this driver. Read the PCI Configuration Header
+ // for this device.
+ //
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (Pci) / sizeof (UINT32),
+ &Pci
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return EFI_UNSUPPORTED;
+ }
+
+ if (Pci.Hdr.ClassCode[2] != PCI_CLASS_MASS_STORAGE || Pci.Hdr.ClassCode[1] != PCI_CLASS_IDE) {
+
+ Status = EFI_UNSUPPORTED;
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+AtapiScsiPassThruDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+ Routine Description:
+ Create handles for IDE channels specified by RemainingDevicePath.
+ Install SCSI Pass Thru Protocol onto each created handle.
+
+ Arguments:
+ (Standard DriverBinding Protocol Start() function)
+
+ Returns:
+ EFI_STATUS
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Controller - add argument and description to function comment
+// TODO: RemainingDevicePath - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ PciIo = NULL;
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationEnable,
+ EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Create SCSI Pass Thru instance for the IDE channel.
+ //
+ Status = RegisterAtapiScsiPassThru (This, Controller, PciIo);
+
+Done:
+ if (EFI_ERROR (Status)) {
+ if (PciIo) {
+ PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationDisable,
+ EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE,
+ NULL
+ );
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+AtapiScsiPassThruDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+/*++
+
+ Routine Description:
+ Stop.
+
+ Arguments:
+ (Standard DriverBinding Protocol Stop() function)
+
+ Returns:
+ EFI_STATUS
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Controller - add argument and description to function comment
+// TODO: NumberOfChildren - add argument and description to function comment
+// TODO: ChildHandleBuffer - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru;
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate;
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiScsiPassThruProtocolGuid,
+ (VOID **) &ScsiPassThru,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ AtapiScsiPrivate = ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS (ScsiPassThru);
+
+ Status = gBS->UninstallProtocolInterface (
+ Controller,
+ &gEfiScsiPassThruProtocolGuid,
+ &AtapiScsiPrivate->ScsiPassThru
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Release Pci Io protocol on the controller handle.
+ //
+ AtapiScsiPrivate->PciIo->Attributes (
+ AtapiScsiPrivate->PciIo,
+ EfiPciIoAttributeOperationDisable,
+ EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE,
+ NULL
+ );
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ gBS->FreePool (AtapiScsiPrivate);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+RegisterAtapiScsiPassThru (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_PCI_IO_PROTOCOL *PciIo
+ )
+/*++
+
+ Routine Description:
+ Attaches SCSI Pass Thru Protocol for specified IDE channel.
+
+ Arguments:
+ Controller: Parent device handle to the IDE channel.
+ PciIo: PCI I/O protocol attached on the "Controller".
+
+ Returns:
+ Always return EFI_SUCCESS unless installing SCSI Pass Thru Protocol failed.
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Controller - add argument and description to function comment
+// TODO: PciIo - add argument and description to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+{
+ EFI_STATUS Status;
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate;
+ UINT64 Attributes;
+
+ AtapiScsiPrivate = AllocateZeroPool (sizeof (ATAPI_SCSI_PASS_THRU_DEV));
+ if (AtapiScsiPrivate == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Attributes = EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE;
+ CopyMem (AtapiScsiPrivate->ChannelName, gAtapiChannelString, sizeof (gAtapiChannelString));
+
+ //
+ // Enable channel
+ //
+ PciIo->Attributes (PciIo, EfiPciIoAttributeOperationSet, Attributes, NULL);
+
+ AtapiScsiPrivate->Signature = ATAPI_SCSI_PASS_THRU_DEV_SIGNATURE;
+ AtapiScsiPrivate->Handle = Controller;
+
+ //
+ // will reset the IoPort inside each API function.
+ //
+ AtapiScsiPrivate->IoPort = gAtapiIoPortRegisters;
+ AtapiScsiPrivate->PciIo = PciIo;
+
+ //
+ // initialize SCSI Pass Thru Protocol interface
+ //
+ AtapiScsiPrivate->ScsiPassThru.Mode = &AtapiScsiPrivate->ScsiPassThruMode;
+ AtapiScsiPrivate->ScsiPassThru.PassThru = AtapiScsiPassThruFunction;
+ AtapiScsiPrivate->ScsiPassThru.GetNextDevice = AtapiScsiPassThruGetNextDevice;
+ AtapiScsiPrivate->ScsiPassThru.BuildDevicePath = AtapiScsiPassThruBuildDevicePath;
+ AtapiScsiPrivate->ScsiPassThru.GetTargetLun = AtapiScsiPassThruGetTargetLun;
+ AtapiScsiPrivate->ScsiPassThru.ResetChannel = AtapiScsiPassThruResetChannel;
+ AtapiScsiPrivate->ScsiPassThru.ResetTarget = AtapiScsiPassThruResetTarget;
+
+ //
+ // Set Mode
+ //
+ CopyMem (AtapiScsiPrivate->ControllerName, gControllerNameString, sizeof (gControllerNameString));
+
+ AtapiScsiPrivate->ScsiPassThruMode.ControllerName = AtapiScsiPrivate->ControllerName;
+ AtapiScsiPrivate->ScsiPassThruMode.ChannelName = AtapiScsiPrivate->ChannelName;
+ AtapiScsiPrivate->ScsiPassThruMode.AdapterId = 4;
+ //
+ // non-RAID SCSI controllers should set both physical and logical attributes
+ //
+ AtapiScsiPrivate->ScsiPassThruMode.Attributes = EFI_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL |
+ EFI_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;
+ AtapiScsiPrivate->ScsiPassThruMode.IoAlign = 0;
+
+ //
+ // Initialize the LatestTargetId to 0xFFFFFFFF (for the GetNextDevice() call).
+ //
+ AtapiScsiPrivate->LatestTargetId = 0xFFFFFFFF;
+ AtapiScsiPrivate->LatestLun = 0;
+
+ Status = gBS->InstallProtocolInterface (
+ &Controller,
+ &gEfiScsiPassThruProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &AtapiScsiPrivate->ScsiPassThru
+ );
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+AtapiScsiPassThruFunction (
+ IN EFI_SCSI_PASS_THRU_PROTOCOL *This,
+ IN UINT32 Target,
+ IN UINT64 Lun,
+ IN OUT EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,
+ IN EFI_EVENT Event OPTIONAL
+ )
+/*++
+
+ Routine Description:
+ Implements EFI_SCSI_PASS_THRU_PROTOCOL.PassThru() function.
+
+ Arguments:
+ This: The EFI_SCSI_PASS_THRU_PROTOCOL instance.
+ Target: The Target ID of the ATAPI device to send the SCSI
+ Request Packet. To ATAPI devices attached on an IDE
+ Channel, Target ID 0 indicates Master device;Target
+ ID 1 indicates Slave device.
+ Lun: The LUN of the ATAPI device to send the SCSI Request
+ Packet. To the ATAPI device, Lun is always 0.
+ Packet: The SCSI Request Packet to send to the ATAPI device
+ specified by Target and Lun.
+ Event: If non-blocking I/O is not supported then Event is ignored,
+ and blocking I/O is performed.
+ If Event is NULL, then blocking I/O is performed.
+ If Event is not NULL and non blocking I/O is supported,
+ then non-blocking I/O is performed, and Event will be signaled
+ when the SCSI Request Packet completes.
+
+ Returns:
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate;
+ EFI_STATUS Status;
+
+ AtapiScsiPrivate = ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS (This);
+
+ //
+ // Target is not allowed beyond MAX_TARGET_ID
+ //
+ if (Target > MAX_TARGET_ID) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // check the data fields in Packet parameter.
+ //
+ Status = CheckSCSIRequestPacket (Packet);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // If Request Packet targets at the IDE channel itself,
+ // do nothing.
+ //
+ if (Target == This->Mode->AdapterId) {
+ Packet->TransferLength = 0;
+ return EFI_SUCCESS;
+ }
+
+ //
+ // According to Target ID, reset the Atapi I/O Register mapping
+ // (Target Id in [0,1] area, using gAtapiIoPortRegisters[0],
+ // Target Id in [2,3] area, using gAtapiIoPortRegisters[1]
+ //
+ if ((Target / 2) == 0) {
+ AtapiScsiPrivate->IoPort = &gAtapiIoPortRegisters[0];
+ } else {
+ AtapiScsiPrivate->IoPort = &gAtapiIoPortRegisters[1];
+ }
+
+ //
+ // the ATAPI SCSI interface does not support non-blocking I/O
+ // ignore the Event parameter
+ //
+ // Performs blocking I/O.
+ //
+ Status = SubmitBlockingIoCommand (AtapiScsiPrivate, Target, Packet);
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+AtapiScsiPassThruGetNextDevice (
+ IN EFI_SCSI_PASS_THRU_PROTOCOL *This,
+ IN OUT UINT32 *Target,
+ IN OUT UINT64 *Lun
+ )
+/*++
+
+ Routine Description:
+ Used to retrieve the list of legal Target IDs for SCSI devices
+ on a SCSI channel.
+
+ Arguments:
+ This - Protocol instance pointer.
+ Target - On input, a pointer to the Target ID of a SCSI
+ device present on the SCSI channel. On output,
+ a pointer to the Target ID of the next SCSI device
+ present on a SCSI channel. An input value of
+ 0xFFFFFFFF retrieves the Target ID of the first
+ SCSI device present on a SCSI channel.
+ Lun - On input, a pointer to the LUN of a SCSI device
+ present on the SCSI channel. On output, a pointer
+ to the LUN of the next SCSI device present on
+ a SCSI channel.
+
+ Returns:
+ EFI_SUCCESS - The Target ID and Lun of the next SCSI device
+ on the SCSI channel was returned in Target and Lun.
+ EFI_NOT_FOUND - There are no more SCSI devices on this SCSI channel.
+ EFI_INVALID_PARAMETER - Target is not 0xFFFFFFFF,and Target and Lun were not
+ returned on a previous call to GetNextDevice().
+--*/
+{
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate;
+
+ //
+ // Retrieve Device Private Data Structure.
+ //
+ AtapiScsiPrivate = ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS (This);
+
+ //
+ // Check whether Target is valid.
+ //
+ if (Target == NULL || Lun == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((*Target != 0xFFFFFFFF) &&
+ ((*Target != AtapiScsiPrivate->LatestTargetId) ||
+ (*Lun != AtapiScsiPrivate->LatestLun))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*Target == MAX_TARGET_ID) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (*Target == 0xFFFFFFFF) {
+ *Target = 0;
+ } else {
+ *Target = AtapiScsiPrivate->LatestTargetId + 1;
+ }
+
+ *Lun = 0;
+
+ //
+ // Update the LatestTargetId.
+ //
+ AtapiScsiPrivate->LatestTargetId = *Target;
+ AtapiScsiPrivate->LatestLun = *Lun;
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+EFIAPI
+AtapiScsiPassThruBuildDevicePath (
+ IN EFI_SCSI_PASS_THRU_PROTOCOL *This,
+ IN UINT32 Target,
+ IN UINT64 Lun,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
+ )
+/*++
+
+ Routine Description:
+ Used to allocate and build a device path node for a SCSI device
+ on a SCSI channel. Would not build device path for a SCSI Host Controller.
+
+ Arguments:
+ This - Protocol instance pointer.
+ Target - The Target ID of the SCSI device for which
+ a device path node is to be allocated and built.
+ Lun - The LUN of the SCSI device for which a device
+ path node is to be allocated and built.
+ DevicePath - A pointer to a single device path node that
+ describes the SCSI device specified by
+ Target and Lun. This function is responsible
+ for allocating the buffer DevicePath with the boot
+ service AllocatePool(). It is the caller's
+ responsibility to free DevicePath when the caller
+ is finished with DevicePath.
+ Returns:
+ EFI_SUCCESS - The device path node that describes the SCSI device
+ specified by Target and Lun was allocated and
+ returned in DevicePath.
+ EFI_NOT_FOUND - The SCSI devices specified by Target and Lun does
+ not exist on the SCSI channel.
+ EFI_INVALID_PARAMETER - DevicePath is NULL.
+ EFI_OUT_OF_RESOURCES - There are not enough resources to allocate
+ DevicePath.
+--*/
+{
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate;
+ EFI_DEV_PATH *Node;
+
+ //
+ // Retrieve Device Private Data Structure.
+ //
+ AtapiScsiPrivate = ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS (This);
+
+ //
+ // Validate parameters passed in.
+ //
+
+ if (DevicePath == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // can not build device path for the SCSI Host Controller.
+ //
+ if ((Target > (MAX_TARGET_ID - 1)) || (Lun != 0)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Node = AllocateZeroPool (sizeof (EFI_DEV_PATH));
+ if (Node == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Node->DevPath.Type = MESSAGING_DEVICE_PATH;
+ Node->DevPath.SubType = MSG_ATAPI_DP;
+ SetDevicePathNodeLength (&Node->DevPath, sizeof (ATAPI_DEVICE_PATH));
+
+ Node->Atapi.PrimarySecondary = (UINT8) (Target / 2);
+ Node->Atapi.SlaveMaster = (UINT8) (Target % 2);
+ Node->Atapi.Lun = (UINT16) Lun;
+
+ *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Node;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+AtapiScsiPassThruGetTargetLun (
+ IN EFI_SCSI_PASS_THRU_PROTOCOL *This,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT UINT32 *Target,
+ OUT UINT64 *Lun
+ )
+/*++
+
+ Routine Description:
+ Used to translate a device path node to a Target ID and LUN.
+
+ Arguments:
+ This - Protocol instance pointer.
+ DevicePath - A pointer to the device path node that
+ describes a SCSI device on the SCSI channel.
+ Target - A pointer to the Target ID of a SCSI device
+ on the SCSI channel.
+ Lun - A pointer to the LUN of a SCSI device on
+ the SCSI channel.
+ Returns:
+ EFI_SUCCESS - DevicePath was successfully translated to a
+ Target ID and LUN, and they were returned
+ in Target and Lun.
+ EFI_INVALID_PARAMETER - DevicePath is NULL.
+ EFI_INVALID_PARAMETER - Target is NULL.
+ EFI_INVALID_PARAMETER - Lun is NULL.
+ EFI_UNSUPPORTED - This driver does not support the device path
+ node type in DevicePath.
+ EFI_NOT_FOUND - A valid translation from DevicePath to a
+ Target ID and LUN does not exist.
+--*/
+{
+ EFI_DEV_PATH *Node;
+
+ //
+ // Validate parameters passed in.
+ //
+ if (DevicePath == NULL || Target == NULL || Lun == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check whether the DevicePath belongs to SCSI_DEVICE_PATH
+ //
+ if ((DevicePath->Type != MESSAGING_DEVICE_PATH) ||
+ (DevicePath->SubType != MSG_ATAPI_DP) ||
+ (DevicePathNodeLength(DevicePath) != sizeof(ATAPI_DEVICE_PATH))) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Node = (EFI_DEV_PATH *) DevicePath;
+
+ *Target = Node->Atapi.PrimarySecondary * 2 + Node->Atapi.SlaveMaster;
+ *Lun = Node->Atapi.Lun;
+
+ if (*Target > (MAX_TARGET_ID - 1) || *Lun != 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+AtapiScsiPassThruResetChannel (
+ IN EFI_SCSI_PASS_THRU_PROTOCOL *This
+ )
+/*++
+
+ Routine Description:
+ Resets a SCSI channel.This operation resets all the
+ SCSI devices connected to the SCSI channel.
+
+ Arguments:
+ This - Protocol instance pointer.
+
+ Returns:
+ EFI_SUCCESS - The SCSI channel was reset.
+ EFI_UNSUPPORTED - The SCSI channel does not support
+ a channel reset operation.
+ EFI_DEVICE_ERROR - A device error occurred while
+ attempting to reset the SCSI channel.
+ EFI_TIMEOUT - A timeout occurred while attempting
+ to reset the SCSI channel.
+--*/
+{
+ UINT8 DeviceControlValue;
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate;
+ UINT8 Index;
+
+ AtapiScsiPrivate = ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS (This);
+
+ //
+ // Reset both Primary channel and Secondary channel.
+ // so, the IoPort pointer must point to the right I/O Register group
+ //
+ for (Index = 0; Index < 2; Index++) {
+ //
+ // Reset
+ //
+ AtapiScsiPrivate->IoPort = &gAtapiIoPortRegisters[Index];
+
+ DeviceControlValue = 0;
+ //
+ // set SRST bit to initiate soft reset
+ //
+ DeviceControlValue |= SRST;
+ //
+ // disable Interrupt
+ //
+ DeviceControlValue |= bit (1);
+ WritePortB (
+ AtapiScsiPrivate->PciIo,
+ AtapiScsiPrivate->IoPort->Alt.DeviceControl,
+ DeviceControlValue
+ );
+
+ //
+ // Wait 10us
+ //
+ gBS->Stall (10);
+
+ //
+ // Clear SRST bit
+ // 0xfb:1111,1011
+ //
+ DeviceControlValue &= 0xfb;
+
+ WritePortB (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Alt.DeviceControl, DeviceControlValue);
+
+ //
+ // slave device needs at most 31s to clear BSY
+ //
+ if (StatusWaitForBSYClear (AtapiScsiPrivate, 31000) == EFI_TIMEOUT) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+AtapiScsiPassThruResetTarget (
+ IN EFI_SCSI_PASS_THRU_PROTOCOL *This,
+ IN UINT32 Target,
+ IN UINT64 Lun
+ )
+/*++
+
+ Routine Description:
+ Resets a SCSI device that is connected to a SCSI channel.
+
+ Arguments:
+ This - Protocol instance pointer.
+ Target - The Target ID of the SCSI device to reset.
+ Lun - The LUN of the SCSI device to reset.
+
+ Returns:
+ EFI_SUCCESS - The SCSI device specified by Target and
+ Lun was reset.
+ EFI_UNSUPPORTED - The SCSI channel does not support a target
+ reset operation.
+ EFI_INVALID_PARAMETER - Target or Lun are invalid.
+ EFI_DEVICE_ERROR - A device error occurred while attempting
+ to reset the SCSI device specified by Target
+ and Lun.
+ EFI_TIMEOUT - A timeout occurred while attempting to reset
+ the SCSI device specified by Target and Lun.
+--*/
+{
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate;
+ UINT8 Command;
+ UINT8 DeviceSelect;
+
+ AtapiScsiPrivate = ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS (This);
+
+ if (Target > MAX_TARGET_ID) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Directly return EFI_SUCCESS if want to reset the host controller
+ //
+ if (Target == This->Mode->AdapterId) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // According to Target ID, reset the Atapi I/O Register mapping
+ // (Target Id in [0,1] area, using gAtapiIoPortRegisters[0],
+ // Target Id in [2,3] area, using gAtapiIoPortRegisters[1]
+ //
+ if ((Target / 2) == 0) {
+ AtapiScsiPrivate->IoPort = &gAtapiIoPortRegisters[0];
+ } else {
+ AtapiScsiPrivate->IoPort = &gAtapiIoPortRegisters[1];
+ }
+
+ //
+ // for ATAPI device, no need to wait DRDY ready after device selecting.
+ //
+ // bit7 and bit5 are both set to 1 for backward compatibility
+ //
+ DeviceSelect = (UINT8) (((bit (7) | bit (5)) | (Target << 4)));
+ WritePortB (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Head, DeviceSelect);
+
+ Command = ATAPI_SOFT_RESET_CMD;
+ WritePortB (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Reg.Command, Command);
+
+ //
+ // BSY clear is the only status return to the host by the device
+ // when reset is complete.
+ // slave device needs at most 31s to clear BSY
+ //
+ if (EFI_ERROR (StatusWaitForBSYClear (AtapiScsiPrivate, 31000))) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // stall 5 seconds to make the device status stable
+ //
+ gBS->Stall (5000000);
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+CheckSCSIRequestPacket (
+ EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
+ )
+/*++
+
+ Checks the parameters in the SCSI Request Packet to make sure
+ they are valid for a SCSI Pass Thru request.
+
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: function comment is missing 'Returns:'
+// TODO: Packet - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ if (Packet == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!ValidCdbLength (Packet->CdbLength)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Packet->Cdb == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Checks whether the request command is supported.
+ //
+ if (!IsCommandValid (Packet)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+IsCommandValid (
+ EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
+ )
+/*++
+
+ Checks the requested SCSI command:
+ Is it supported by this driver?
+ Is the Data transfer direction reasonable?
+
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: function comment is missing 'Returns:'
+// TODO: Packet - add argument and description to function comment
+{
+ UINT8 Index;
+ UINT8 *OpCode;
+
+ OpCode = (UINT8 *) (Packet->Cdb);
+
+ for (Index = 0; CompareMem (&gSupportedATAPICommands[Index], &gEndTable, sizeof (SCSI_COMMAND_SET)); Index++) {
+
+ if (*OpCode == gSupportedATAPICommands[Index].OpCode) {
+ //
+ // Check whether the requested Command is supported by this driver
+ //
+ if (Packet->DataDirection == DataIn) {
+ //
+ // Check whether the requested data direction conforms to
+ // what it should be.
+ //
+ if (gSupportedATAPICommands[Index].Direction == DataOut) {
+ return FALSE;
+ }
+ }
+
+ if (Packet->DataDirection == DataOut) {
+ //
+ // Check whether the requested data direction conforms to
+ // what it should be.
+ //
+ if (gSupportedATAPICommands[Index].Direction == DataIn) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+EFI_STATUS
+SubmitBlockingIoCommand (
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate,
+ UINT32 Target,
+ EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
+ )
+/*++
+
+Routine Description:
+ Performs blocking I/O request.
+
+ Arguments:
+ AtapiScsiPrivate: Private data structure for the specified channel.
+ Target: The Target ID of the ATAPI device to send the SCSI
+ Request Packet. To ATAPI devices attached on an IDE
+ Channel, Target ID 0 indicates Master device;Target
+ ID 1 indicates Slave device.
+ Packet: The SCSI Request Packet to send to the ATAPI device
+ specified by Target.
+
+ Returns:
+
+--*/
+// TODO: AtapiScsiPrivate - add argument and description to function comment
+{
+ UINT8 PacketCommand[12];
+ UINT64 TimeoutInMicroSeconds;
+ EFI_STATUS PacketCommandStatus;
+
+ //
+ // Fill ATAPI Command Packet according to CDB
+ //
+ ZeroMem (&PacketCommand, 12);
+ CopyMem (&PacketCommand, Packet->Cdb, Packet->CdbLength);
+
+ //
+ // Timeout is 100ns unit, convert it to 1000ns (1us) unit.
+ //
+ TimeoutInMicroSeconds = DivU64x32 (Packet->Timeout, (UINT32) 10);
+
+ //
+ // Submit ATAPI Command Packet
+ //
+ PacketCommandStatus = AtapiPacketCommand (
+ AtapiScsiPrivate,
+ Target,
+ PacketCommand,
+ Packet->DataBuffer,
+ &(Packet->TransferLength),
+ Packet->DataDirection,
+ TimeoutInMicroSeconds
+ );
+ if (!EFI_ERROR (PacketCommandStatus) || (Packet->SenseData == NULL)) {
+ Packet->SenseDataLength = 0;
+ return PacketCommandStatus;
+ }
+ //
+ // Return SenseData if PacketCommandStatus matches
+ // the following return codes.
+ //
+ if ((PacketCommandStatus == EFI_WARN_BUFFER_TOO_SMALL) ||
+ (PacketCommandStatus == EFI_DEVICE_ERROR) ||
+ (PacketCommandStatus == EFI_TIMEOUT)) {
+
+ //
+ // avoid submit request sense command continuously.
+ //
+ if (PacketCommand[0] == OP_REQUEST_SENSE) {
+ Packet->SenseDataLength = 0;
+ return PacketCommandStatus;
+ }
+
+ RequestSenseCommand (
+ AtapiScsiPrivate,
+ Target,
+ Packet->Timeout,
+ Packet->SenseData,
+ &Packet->SenseDataLength
+ );
+ }
+
+ return PacketCommandStatus;
+}
+
+EFI_STATUS
+RequestSenseCommand (
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate,
+ UINT32 Target,
+ UINT64 Timeout,
+ VOID *SenseData,
+ UINT8 *SenseDataLength
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AtapiScsiPrivate - TODO: add argument description
+ Target - TODO: add argument description
+ Timeout - TODO: add argument description
+ SenseData - TODO: add argument description
+ SenseDataLength - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET Packet;
+ UINT8 Cdb[12];
+ EFI_STATUS Status;
+
+ ZeroMem (&Packet, sizeof (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET));
+ ZeroMem (Cdb, 12);
+
+ Cdb[0] = OP_REQUEST_SENSE;
+ Cdb[4] = (UINT8) (*SenseDataLength);
+
+ Packet.Timeout = Timeout;
+ Packet.DataBuffer = SenseData;
+ Packet.SenseData = NULL;
+ Packet.Cdb = Cdb;
+ Packet.TransferLength = *SenseDataLength;
+ Packet.CdbLength = 12;
+ Packet.DataDirection = DataIn;
+
+ Status = SubmitBlockingIoCommand (AtapiScsiPrivate, Target, &Packet);
+ *SenseDataLength = (UINT8) (Packet.TransferLength);
+ return Status;
+}
+
+EFI_STATUS
+AtapiPacketCommand (
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate,
+ UINT32 Target,
+ UINT8 *PacketCommand,
+ VOID *Buffer,
+ UINT32 *ByteCount,
+ DATA_DIRECTION Direction,
+ UINT64 TimeoutInMicroSeconds
+ )
+/*++
+
+ Routine Description:
+ Submits ATAPI command packet to the specified ATAPI device.
+
+ Arguments:
+ AtapiScsiPrivate: Private data structure for the specified channel.
+ Target: The Target ID of the ATAPI device to send the SCSI
+ Request Packet. To ATAPI devices attached on an IDE
+ Channel, Target ID 0 indicates Master device;Target
+ ID 1 indicates Slave device.
+ PacketCommand: Points to the ATAPI command packet.
+ Buffer: Points to the transferred data.
+ ByteCount: When input,indicates the buffer size; when output,
+ indicates the actually transferred data size.
+ Direction: Indicates the data transfer direction.
+ TimeoutInMicroSeconds:
+ The timeout, in micro second units, to use for the
+ execution of this ATAPI command.
+ A TimeoutInMicroSeconds value of 0 means that
+ this function will wait indefinitely for the ATAPI
+ command to execute.
+ If TimeoutInMicroSeconds is greater than zero, then
+ this function will return EFI_TIMEOUT if the time
+ required to execute the ATAPI command is greater
+ than TimeoutInMicroSeconds.
+
+ Returns:
+
+
+--*/
+// TODO: AtapiScsiPrivate - add argument and description to function comment
+// TODO: PacketCommand - add argument and description to function comment
+// TODO: Buffer - add argument and description to function comment
+// TODO: ByteCount - add argument and description to function comment
+// TODO: Direction - add argument and description to function comment
+{
+
+ UINT16 *CommandIndex;
+ UINT8 Count;
+ EFI_STATUS Status;
+
+ //
+ // Set all the command parameters by fill related registers.
+ // Before write to all the following registers, BSY and DRQ must be 0.
+ //
+ Status = StatusDRQClear (AtapiScsiPrivate, TimeoutInMicroSeconds);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_ABORTED) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ *ByteCount = 0;
+ return Status;
+ }
+ //
+ // Select device via Device/Head Register.
+ // "Target = 0" indicates device 0; "Target = 1" indicates device 1
+ //
+ WritePortB (
+ AtapiScsiPrivate->PciIo,
+ AtapiScsiPrivate->IoPort->Head,
+ (UINT8) ((Target << 4) | DEFAULT_CMD) // DEFAULT_CMD: 0xa0 (1010,0000)
+ );
+
+ //
+ // No OVL; No DMA (by setting feature register)
+ //
+ WritePortB (
+ AtapiScsiPrivate->PciIo,
+ AtapiScsiPrivate->IoPort->Reg1.Feature,
+ 0x00
+ );
+
+ //
+ // set the transfersize to MAX_ATAPI_BYTE_COUNT to let the device
+ // determine how much data should be transfered.
+ //
+ WritePortB (
+ AtapiScsiPrivate->PciIo,
+ AtapiScsiPrivate->IoPort->CylinderLsb,
+ (UINT8) (MAX_ATAPI_BYTE_COUNT & 0x00ff)
+ );
+ WritePortB (
+ AtapiScsiPrivate->PciIo,
+ AtapiScsiPrivate->IoPort->CylinderMsb,
+ (UINT8) (MAX_ATAPI_BYTE_COUNT >> 8)
+ );
+
+ //
+ // DEFAULT_CTL:0x0a (0000,1010)
+ // Disable interrupt
+ //
+ WritePortB (
+ AtapiScsiPrivate->PciIo,
+ AtapiScsiPrivate->IoPort->Alt.DeviceControl,
+ DEFAULT_CTL
+ );
+
+ //
+ // Send Packet command to inform device
+ // that the following data bytes are command packet.
+ //
+ WritePortB (
+ AtapiScsiPrivate->PciIo,
+ AtapiScsiPrivate->IoPort->Reg.Command,
+ PACKET_CMD
+ );
+
+ //
+ // Before data transfer, BSY should be 0 and DRQ should be 1.
+ // if they are not in specified time frame,
+ // retrieve Sense Key from Error Register before return.
+ //
+ Status = StatusDRQReady (AtapiScsiPrivate, TimeoutInMicroSeconds);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_ABORTED) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ *ByteCount = 0;
+ return Status;
+ }
+
+ //
+ // Send out command packet
+ //
+ CommandIndex = (UINT16 *) PacketCommand;
+ for (Count = 0; Count < 6; Count++, CommandIndex++) {
+ WritePortW (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Data, *CommandIndex);
+ }
+
+ //
+ // call AtapiPassThruPioReadWriteData() function to get
+ // requested transfer data form device.
+ //
+ return AtapiPassThruPioReadWriteData (
+ AtapiScsiPrivate,
+ Buffer,
+ ByteCount,
+ Direction,
+ TimeoutInMicroSeconds
+ );
+}
+
+EFI_STATUS
+AtapiPassThruPioReadWriteData (
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate,
+ UINT16 *Buffer,
+ UINT32 *ByteCount,
+ DATA_DIRECTION Direction,
+ UINT64 TimeoutInMicroSeconds
+ )
+/*++
+
+ Routine Description:
+ Performs data transfer between ATAPI device and host after the
+ ATAPI command packet is sent.
+
+ Arguments:
+ AtapiScsiPrivate: Private data structure for the specified channel.
+ Buffer: Points to the transferred data.
+ ByteCount: When input,indicates the buffer size; when output,
+ indicates the actually transferred data size.
+ Direction: Indicates the data transfer direction.
+ TimeoutInMicroSeconds:
+ The timeout, in micro second units, to use for the
+ execution of this ATAPI command.
+ A TimeoutInMicroSeconds value of 0 means that
+ this function will wait indefinitely for the ATAPI
+ command to execute.
+ If TimeoutInMicroSeconds is greater than zero, then
+ this function will return EFI_TIMEOUT if the time
+ required to execute the ATAPI command is greater
+ than TimeoutInMicroSeconds.
+
+ Returns:
+
+
+--*/
+// TODO: AtapiScsiPrivate - add argument and description to function comment
+// TODO: Buffer - add argument and description to function comment
+// TODO: ByteCount - add argument and description to function comment
+// TODO: Direction - add argument and description to function comment
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+// TODO: EFI_WARN_BUFFER_TOO_SMALL - add return value to function comment
+{
+ UINT32 Index;
+ UINT32 RequiredWordCount;
+ UINT32 ActualWordCount;
+
+ UINT32 WordCount;
+ EFI_STATUS Status;
+ UINT16 *ptrBuffer;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Non Data transfer request is also supported.
+ //
+ if (*ByteCount == 0 || Buffer == NULL) {
+ *ByteCount = 0;
+ if (EFI_ERROR (StatusWaitForBSYClear (AtapiScsiPrivate, TimeoutInMicroSeconds))) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ ptrBuffer = Buffer;
+ RequiredWordCount = *ByteCount / 2;
+
+ //
+ // ActuralWordCount means the word count of data really transfered.
+ //
+ ActualWordCount = 0;
+
+ while (ActualWordCount < RequiredWordCount) {
+ //
+ // before each data transfer stream, the host should poll DRQ bit ready,
+ // which indicates device's ready for data transfer .
+ //
+ Status = StatusDRQReady (AtapiScsiPrivate, TimeoutInMicroSeconds);
+ if (EFI_ERROR (Status)) {
+ *ByteCount = ActualWordCount * 2;
+
+ AtapiPassThruCheckErrorStatus (AtapiScsiPrivate);
+
+ if (ActualWordCount == 0) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // ActualWordCount > 0
+ //
+ if (ActualWordCount < RequiredWordCount) {
+ return EFI_WARN_BUFFER_TOO_SMALL;
+ }
+ }
+ //
+ // get current data transfer size from Cylinder Registers.
+ //
+ WordCount =
+ (
+ (ReadPortB (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->CylinderMsb) << 8) |
+ ReadPortB (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->CylinderLsb)
+ ) & 0xffff;
+ WordCount /= 2;
+
+ //
+ // perform a series data In/Out.
+ //
+ for (Index = 0; (Index < WordCount) && (ActualWordCount < RequiredWordCount); Index++, ActualWordCount++) {
+
+ if (Direction == DataIn) {
+
+ *ptrBuffer = ReadPortW (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Data);
+ } else {
+
+ WritePortW (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Data, *ptrBuffer);
+ }
+
+ ptrBuffer++;
+
+ }
+ }
+ //
+ // After data transfer is completed, normally, DRQ bit should clear.
+ //
+ StatusDRQClear (AtapiScsiPrivate, TimeoutInMicroSeconds);
+
+ //
+ // read status register to check whether error happens.
+ //
+ Status = AtapiPassThruCheckErrorStatus (AtapiScsiPrivate);
+
+ *ByteCount = ActualWordCount * 2;
+
+ return Status;
+}
+
+
+UINT8
+ReadPortB (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 Port
+ )
+/*++
+ Read one byte from a specified I/O port.
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: function comment is missing 'Returns:'
+// TODO: PciIo - add argument and description to function comment
+// TODO: Port - add argument and description to function comment
+{
+ UINT8 Data;
+
+ Data = 0;
+ PciIo->Io.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) Port,
+ 1,
+ &Data
+ );
+ return Data;
+}
+
+
+UINT16
+ReadPortW (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 Port
+ )
+/*++
+ Read one word from a specified I/O port.
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: function comment is missing 'Returns:'
+// TODO: PciIo - add argument and description to function comment
+// TODO: Port - add argument and description to function comment
+{
+ UINT16 Data;
+
+ Data = 0;
+ PciIo->Io.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) Port,
+ 1,
+ &Data
+ );
+ return Data;
+}
+
+
+VOID
+WritePortB (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 Port,
+ IN UINT8 Data
+ )
+/*++
+ Write one byte to a specified I/O port.
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: function comment is missing 'Returns:'
+// TODO: PciIo - add argument and description to function comment
+// TODO: Port - add argument and description to function comment
+// TODO: Data - add argument and description to function comment
+{
+
+ PciIo->Io.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) Port,
+ 1,
+ &Data
+ );
+
+}
+
+
+VOID
+WritePortW (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 Port,
+ IN UINT16 Data
+ )
+/*++
+ Write one word to a specified I/O port.
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: function comment is missing 'Returns:'
+// TODO: PciIo - add argument and description to function comment
+// TODO: Port - add argument and description to function comment
+// TODO: Data - add argument and description to function comment
+{
+
+ PciIo->Io.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) Port,
+ 1,
+ &Data
+ );
+}
+
+EFI_STATUS
+StatusDRQClear (
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate,
+ UINT64 TimeoutInMicroSeconds
+ )
+/*++
+ Check whether DRQ is clear in the Status Register. (BSY must also be cleared)
+ If TimeoutInMicroSeconds is zero, this routine should wait infinitely for
+ DRQ clear. Otherwise, it will return EFI_TIMEOUT when specified time is
+ elapsed.
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: function comment is missing 'Returns:'
+// TODO: AtapiScsiPrivate - add argument and description to function comment
+// TODO: TimeoutInMicroSeconds - add argument and description to function comment
+// TODO: EFI_ABORTED - add return value to function comment
+// TODO: EFI_TIMEOUT - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINT64 Delay;
+ UINT8 StatusRegister;
+ UINT8 ErrRegister;
+
+ if (TimeoutInMicroSeconds == 0) {
+ Delay = 2;
+ } else {
+ Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1;
+ }
+
+ do {
+
+ StatusRegister = ReadPortB (
+ AtapiScsiPrivate->PciIo,
+ AtapiScsiPrivate->IoPort->Reg.Status
+ );
+
+ //
+ // wait for BSY == 0 and DRQ == 0
+ //
+ if ((StatusRegister & (DRQ | BSY)) == 0) {
+ break;
+ }
+ //
+ // check whether the command is aborted by the device
+ //
+ if ((StatusRegister & (BSY | ERR)) == ERR) {
+
+ ErrRegister = ReadPortB (
+ AtapiScsiPrivate->PciIo,
+ AtapiScsiPrivate->IoPort->Reg1.Error
+ );
+ if ((ErrRegister & ABRT_ERR) == ABRT_ERR) {
+
+ return EFI_ABORTED;
+ }
+ }
+ //
+ // Stall for 30 us
+ //
+ gBS->Stall (30);
+
+ //
+ // Loop infinitely if not meeting expected condition
+ //
+ if (TimeoutInMicroSeconds == 0) {
+ Delay = 2;
+ }
+
+ Delay--;
+ } while (Delay);
+
+ if (Delay == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AltStatusDRQClear (
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate,
+ UINT64 TimeoutInMicroSeconds
+ )
+/*++
+ Check whether DRQ is clear in the Alternate Status Register.
+ (BSY must also be cleared).
+ If TimeoutInMicroSeconds is zero, this routine should wait infinitely for
+ DRQ clear. Otherwise, it will return EFI_TIMEOUT when specified time is
+ elapsed.
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: function comment is missing 'Returns:'
+// TODO: AtapiScsiPrivate - add argument and description to function comment
+// TODO: TimeoutInMicroSeconds - add argument and description to function comment
+// TODO: EFI_ABORTED - add return value to function comment
+// TODO: EFI_TIMEOUT - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINT64 Delay;
+ UINT8 AltStatusRegister;
+ UINT8 ErrRegister;
+
+ if (TimeoutInMicroSeconds == 0) {
+ Delay = 2;
+ } else {
+ Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1;
+ }
+
+ do {
+
+ AltStatusRegister = ReadPortB (
+ AtapiScsiPrivate->PciIo,
+ AtapiScsiPrivate->IoPort->Alt.AltStatus
+ );
+
+ //
+ // wait for BSY == 0 and DRQ == 0
+ //
+ if ((AltStatusRegister & (DRQ | BSY)) == 0) {
+ break;
+ }
+
+ if ((AltStatusRegister & (BSY | ERR)) == ERR) {
+
+ ErrRegister = ReadPortB (
+ AtapiScsiPrivate->PciIo,
+ AtapiScsiPrivate->IoPort->Reg1.Error
+ );
+ if ((ErrRegister & ABRT_ERR) == ABRT_ERR) {
+
+ return EFI_ABORTED;
+ }
+ }
+ //
+ // Stall for 30 us
+ //
+ gBS->Stall (30);
+
+ //
+ // Loop infinitely if not meeting expected condition
+ //
+ if (TimeoutInMicroSeconds == 0) {
+ Delay = 2;
+ }
+
+ Delay--;
+ } while (Delay);
+
+ if (Delay == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+StatusDRQReady (
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate,
+ UINT64 TimeoutInMicroSeconds
+ )
+/*++
+ Check whether DRQ is ready in the Status Register. (BSY must also be cleared)
+ If TimeoutInMicroSeconds is zero, this routine should wait infinitely for
+ DRQ ready. Otherwise, it will return EFI_TIMEOUT when specified time is
+ elapsed.
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: function comment is missing 'Returns:'
+// TODO: AtapiScsiPrivate - add argument and description to function comment
+// TODO: TimeoutInMicroSeconds - add argument and description to function comment
+// TODO: EFI_ABORTED - add return value to function comment
+// TODO: EFI_TIMEOUT - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINT64 Delay;
+ UINT8 StatusRegister;
+ UINT8 ErrRegister;
+
+ if (TimeoutInMicroSeconds == 0) {
+ Delay = 2;
+ } else {
+ Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1;
+ }
+
+ do {
+ //
+ // read Status Register will clear interrupt
+ //
+ StatusRegister = ReadPortB (
+ AtapiScsiPrivate->PciIo,
+ AtapiScsiPrivate->IoPort->Reg.Status
+ );
+
+ //
+ // BSY==0,DRQ==1
+ //
+ if ((StatusRegister & (BSY | DRQ)) == DRQ) {
+ break;
+ }
+
+ if ((StatusRegister & (BSY | ERR)) == ERR) {
+
+ ErrRegister = ReadPortB (
+ AtapiScsiPrivate->PciIo,
+ AtapiScsiPrivate->IoPort->Reg1.Error
+ );
+ if ((ErrRegister & ABRT_ERR) == ABRT_ERR) {
+ return EFI_ABORTED;
+ }
+ }
+
+ //
+ // Stall for 30 us
+ //
+ gBS->Stall (30);
+
+ //
+ // Loop infinitely if not meeting expected condition
+ //
+ if (TimeoutInMicroSeconds == 0) {
+ Delay = 2;
+ }
+
+ Delay--;
+ } while (Delay);
+
+ if (Delay == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AltStatusDRQReady (
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate,
+ UINT64 TimeoutInMicroSeconds
+ )
+/*++
+ Check whether DRQ is ready in the Alternate Status Register.
+ (BSY must also be cleared)
+ If TimeoutInMicroSeconds is zero, this routine should wait infinitely for
+ DRQ ready. Otherwise, it will return EFI_TIMEOUT when specified time is
+ elapsed.
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: function comment is missing 'Returns:'
+// TODO: AtapiScsiPrivate - add argument and description to function comment
+// TODO: TimeoutInMicroSeconds - add argument and description to function comment
+// TODO: EFI_ABORTED - add return value to function comment
+// TODO: EFI_TIMEOUT - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINT64 Delay;
+ UINT8 AltStatusRegister;
+ UINT8 ErrRegister;
+
+ if (TimeoutInMicroSeconds == 0) {
+ Delay = 2;
+ } else {
+ Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1;
+ }
+
+ do {
+ //
+ // read Status Register will clear interrupt
+ //
+ AltStatusRegister = ReadPortB (
+ AtapiScsiPrivate->PciIo,
+ AtapiScsiPrivate->IoPort->Alt.AltStatus
+ );
+ //
+ // BSY==0,DRQ==1
+ //
+ if ((AltStatusRegister & (BSY | DRQ)) == DRQ) {
+ break;
+ }
+
+ if ((AltStatusRegister & (BSY | ERR)) == ERR) {
+
+ ErrRegister = ReadPortB (
+ AtapiScsiPrivate->PciIo,
+ AtapiScsiPrivate->IoPort->Reg1.Error
+ );
+ if ((ErrRegister & ABRT_ERR) == ABRT_ERR) {
+ return EFI_ABORTED;
+ }
+ }
+
+ //
+ // Stall for 30 us
+ //
+ gBS->Stall (30);
+
+ //
+ // Loop infinitely if not meeting expected condition
+ //
+ if (TimeoutInMicroSeconds == 0) {
+ Delay = 2;
+ }
+
+ Delay--;
+ } while (Delay);
+
+ if (Delay == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+StatusWaitForBSYClear (
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate,
+ UINT64 TimeoutInMicroSeconds
+ )
+/*++
+ Check whether BSY is clear in the Status Register.
+ If TimeoutInMicroSeconds is zero, this routine should wait infinitely for
+ BSY clear. Otherwise, it will return EFI_TIMEOUT when specified time is
+ elapsed.
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: function comment is missing 'Returns:'
+// TODO: AtapiScsiPrivate - add argument and description to function comment
+// TODO: TimeoutInMicroSeconds - add argument and description to function comment
+// TODO: EFI_TIMEOUT - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINT64 Delay;
+ UINT8 StatusRegister;
+
+ if (TimeoutInMicroSeconds == 0) {
+ Delay = 2;
+ } else {
+ Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1;
+ }
+
+ do {
+
+ StatusRegister = ReadPortB (
+ AtapiScsiPrivate->PciIo,
+ AtapiScsiPrivate->IoPort->Reg.Status
+ );
+ if ((StatusRegister & BSY) == 0x00) {
+ break;
+ }
+
+ //
+ // Stall for 30 us
+ //
+ gBS->Stall (30);
+
+ //
+ // Loop infinitely if not meeting expected condition
+ //
+ if (TimeoutInMicroSeconds == 0) {
+ Delay = 2;
+ }
+
+ Delay--;
+ } while (Delay);
+
+ if (Delay == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AltStatusWaitForBSYClear (
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate,
+ UINT64 TimeoutInMicroSeconds
+ )
+/*++
+ Check whether BSY is clear in the Alternate Status Register.
+ If TimeoutInMicroSeconds is zero, this routine should wait infinitely for
+ BSY clear. Otherwise, it will return EFI_TIMEOUT when specified time is
+ elapsed.
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: function comment is missing 'Returns:'
+// TODO: AtapiScsiPrivate - add argument and description to function comment
+// TODO: TimeoutInMicroSeconds - add argument and description to function comment
+// TODO: EFI_TIMEOUT - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINT64 Delay;
+ UINT8 AltStatusRegister;
+
+ if (TimeoutInMicroSeconds == 0) {
+ Delay = 2;
+ } else {
+ Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1;
+ }
+
+ do {
+
+ AltStatusRegister = ReadPortB (
+ AtapiScsiPrivate->PciIo,
+ AtapiScsiPrivate->IoPort->Alt.AltStatus
+ );
+ if ((AltStatusRegister & BSY) == 0x00) {
+ break;
+ }
+
+ //
+ // Stall for 30 us
+ //
+ gBS->Stall (30);
+ //
+ // Loop infinitely if not meeting expected condition
+ //
+ if (TimeoutInMicroSeconds == 0) {
+ Delay = 2;
+ }
+
+ Delay--;
+ } while (Delay);
+
+ if (Delay == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+StatusDRDYReady (
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate,
+ UINT64 TimeoutInMicroSeconds
+ )
+/*++
+ Check whether DRDY is ready in the Status Register.
+ (BSY must also be cleared)
+ If TimeoutInMicroSeconds is zero, this routine should wait infinitely for
+ DRDY ready. Otherwise, it will return EFI_TIMEOUT when specified time is
+ elapsed.
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: function comment is missing 'Returns:'
+// TODO: AtapiScsiPrivate - add argument and description to function comment
+// TODO: TimeoutInMicroSeconds - add argument and description to function comment
+// TODO: EFI_ABORTED - add return value to function comment
+// TODO: EFI_TIMEOUT - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINT64 Delay;
+ UINT8 StatusRegister;
+ UINT8 ErrRegister;
+
+ if (TimeoutInMicroSeconds == 0) {
+ Delay = 2;
+ } else {
+ Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1;
+ }
+
+ do {
+ StatusRegister = ReadPortB (
+ AtapiScsiPrivate->PciIo,
+ AtapiScsiPrivate->IoPort->Reg.Status
+ );
+ //
+ // BSY == 0 , DRDY == 1
+ //
+ if ((StatusRegister & (DRDY | BSY)) == DRDY) {
+ break;
+ }
+
+ if ((StatusRegister & (BSY | ERR)) == ERR) {
+
+ ErrRegister = ReadPortB (
+ AtapiScsiPrivate->PciIo,
+ AtapiScsiPrivate->IoPort->Reg1.Error
+ );
+ if ((ErrRegister & ABRT_ERR) == ABRT_ERR) {
+ return EFI_ABORTED;
+ }
+ }
+
+ //
+ // Stall for 30 us
+ //
+ gBS->Stall (30);
+ //
+ // Loop infinitely if not meeting expected condition
+ //
+ if (TimeoutInMicroSeconds == 0) {
+ Delay = 2;
+ }
+
+ Delay--;
+ } while (Delay);
+
+ if (Delay == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AltStatusDRDYReady (
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate,
+ UINT64 TimeoutInMicroSeconds
+ )
+/*++
+ Check whether DRDY is ready in the Alternate Status Register.
+ (BSY must also be cleared)
+ If TimeoutInMicroSeconds is zero, this routine should wait infinitely for
+ DRDY ready. Otherwise, it will return EFI_TIMEOUT when specified time is
+ elapsed.
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: function comment is missing 'Returns:'
+// TODO: AtapiScsiPrivate - add argument and description to function comment
+// TODO: TimeoutInMicroSeconds - add argument and description to function comment
+// TODO: EFI_ABORTED - add return value to function comment
+// TODO: EFI_TIMEOUT - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINT64 Delay;
+ UINT8 AltStatusRegister;
+ UINT8 ErrRegister;
+
+ if (TimeoutInMicroSeconds == 0) {
+ Delay = 2;
+ } else {
+ Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1;
+ }
+
+ do {
+ AltStatusRegister = ReadPortB (
+ AtapiScsiPrivate->PciIo,
+ AtapiScsiPrivate->IoPort->Alt.AltStatus
+ );
+ //
+ // BSY == 0 , DRDY == 1
+ //
+ if ((AltStatusRegister & (DRDY | BSY)) == DRDY) {
+ break;
+ }
+
+ if ((AltStatusRegister & (BSY | ERR)) == ERR) {
+
+ ErrRegister = ReadPortB (
+ AtapiScsiPrivate->PciIo,
+ AtapiScsiPrivate->IoPort->Reg1.Error
+ );
+ if ((ErrRegister & ABRT_ERR) == ABRT_ERR) {
+ return EFI_ABORTED;
+ }
+ }
+
+ //
+ // Stall for 30 us
+ //
+ gBS->Stall (30);
+ //
+ // Loop infinitely if not meeting expected condition
+ //
+ if (TimeoutInMicroSeconds == 0) {
+ Delay = 2;
+ }
+
+ Delay--;
+ } while (Delay);
+
+ if (Delay == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AtapiPassThruCheckErrorStatus (
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate
+ )
+/*++
+ Check Error Register for Error Information.
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: function comment is missing 'Returns:'
+// TODO: AtapiScsiPrivate - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+{
+ UINT8 StatusRegister;
+
+//#ifdef EFI_DEBUG
+
+ UINT8 ErrorRegister;
+
+//#endif
+
+ StatusRegister = ReadPortB (
+ AtapiScsiPrivate->PciIo,
+ AtapiScsiPrivate->IoPort->Reg.Status
+ );
+ DEBUG_CODE (
+
+ if (StatusRegister & DWF) {
+ DEBUG (
+ (EFI_D_BLKIO,
+ "AtapiPassThruCheckErrorStatus()-- %02x : Error : Write Fault\n",
+ StatusRegister)
+ );
+ }
+
+ if (StatusRegister & CORR) {
+ DEBUG (
+ (EFI_D_BLKIO,
+ "AtapiPassThruCheckErrorStatus()-- %02x : Error : Corrected Data\n",
+ StatusRegister)
+ );
+ }
+
+ if (StatusRegister & ERR) {
+ ErrorRegister = ReadPortB (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Reg1.Error);
+
+ if (ErrorRegister & BBK_ERR) {
+ DEBUG (
+ (EFI_D_BLKIO,
+ "AtapiPassThruCheckErrorStatus()-- %02x : Error : Bad Block Detected\n",
+ ErrorRegister)
+ );
+ }
+
+ if (ErrorRegister & UNC_ERR) {
+ DEBUG (
+ (EFI_D_BLKIO,
+ "AtapiPassThruCheckErrorStatus()-- %02x : Error : Uncorrectable Data\n",
+ ErrorRegister)
+ );
+ }
+
+ if (ErrorRegister & MC_ERR) {
+ DEBUG (
+ (EFI_D_BLKIO,
+ "AtapiPassThruCheckErrorStatus()-- %02x : Error : Media Change\n",
+ ErrorRegister)
+ );
+ }
+
+ if (ErrorRegister & ABRT_ERR) {
+ DEBUG (
+ (EFI_D_BLKIO,
+ "AtapiPassThruCheckErrorStatus()-- %02x : Error : Abort\n",
+ ErrorRegister)
+ );
+ }
+
+ if (ErrorRegister & TK0NF_ERR) {
+ DEBUG (
+ (EFI_D_BLKIO,
+ "AtapiPassThruCheckErrorStatus()-- %02x : Error : Track 0 Not Found\n",
+ ErrorRegister)
+ );
+ }
+
+ if (ErrorRegister & AMNF_ERR) {
+ DEBUG (
+ (EFI_D_BLKIO,
+ "AtapiPassThruCheckErrorStatus()-- %02x : Error : Address Mark Not Found\n",
+ ErrorRegister)
+ );
+ }
+
+ }
+ );
+
+ if ((StatusRegister & (ERR | DWF | CORR)) == 0) {
+
+ return EFI_SUCCESS;
+ }
+
+ return EFI_DEVICE_ERROR;
+
+}
diff --git a/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.h b/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.h
new file mode 100644
index 0000000..486fd2d
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.h
@@ -0,0 +1,916 @@
+/*++
+
+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:
+
+ AtapiPassThru.h
+
+Abstract:
+
+
+Revision History
+--*/
+
+#ifndef _APT_H
+#define _APT_H
+
+
+#include <IndustryStandard/Pci22.h>
+
+//
+// bit definition
+//
+#define bit(a) 1 << (a)
+
+#define MAX_TARGET_ID 4
+//
+// IDE Registers
+//
+typedef union {
+ UINT16 Command; /* when write */
+ UINT16 Status; /* when read */
+} IDE_CMD_OR_STATUS;
+
+typedef union {
+ UINT16 Error; /* when read */
+ UINT16 Feature; /* when write */
+} IDE_ERROR_OR_FEATURE;
+
+typedef union {
+ UINT16 AltStatus; /* when read */
+ UINT16 DeviceControl; /* when write */
+} IDE_AltStatus_OR_DeviceControl;
+
+//
+// IDE registers set
+//
+typedef struct {
+ UINT16 Data;
+ IDE_ERROR_OR_FEATURE Reg1;
+ UINT16 SectorCount;
+ UINT16 SectorNumber;
+ UINT16 CylinderLsb;
+ UINT16 CylinderMsb;
+ UINT16 Head;
+ IDE_CMD_OR_STATUS Reg;
+
+ IDE_AltStatus_OR_DeviceControl Alt;
+ UINT16 DriveAddress;
+
+ UINT16 MasterSlave;
+} IDE_BASE_REGISTERS;
+
+#define ATAPI_SCSI_PASS_THRU_DEV_SIGNATURE EFI_SIGNATURE_32 ('a', 's', 'p', 't')
+
+typedef struct {
+ UINTN Signature;
+
+ EFI_HANDLE Handle;
+ EFI_SCSI_PASS_THRU_PROTOCOL ScsiPassThru;
+ EFI_SCSI_PASS_THRU_MODE ScsiPassThruMode;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ //
+ // Local Data goes here
+ //
+ IDE_BASE_REGISTERS *IoPort;
+
+ CHAR16 ControllerName[100];
+ CHAR16 ChannelName[100];
+
+ UINT32 LatestTargetId;
+ UINT64 LatestLun;
+
+} ATAPI_SCSI_PASS_THRU_DEV;
+
+#define ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS(a) \
+ CR (a, \
+ ATAPI_SCSI_PASS_THRU_DEV, \
+ ScsiPassThru, \
+ ATAPI_SCSI_PASS_THRU_DEV_SIGNATURE \
+ )
+
+//
+// Global Variables
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gAtapiScsiPassThruDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gAtapiScsiPassThruComponentName;
+
+//
+// ATAPI Command op code
+//
+#define OP_INQUIRY 0x12
+#define OP_LOAD_UNLOAD_CD 0xa6
+#define OP_MECHANISM_STATUS 0xbd
+#define OP_MODE_SELECT_10 0x55
+#define OP_MODE_SENSE_10 0x5a
+#define OP_PAUSE_RESUME 0x4b
+#define OP_PLAY_AUDIO_10 0x45
+#define OP_PLAY_AUDIO_MSF 0x47
+#define OP_PLAY_CD 0xbc
+#define OP_PLAY_CD_MSF 0xb4
+#define OP_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e
+#define OP_READ_10 0x28
+#define OP_READ_12 0xa8
+#define OP_READ_CAPACITY 0x25
+#define OP_READ_CD 0xbe
+#define OP_READ_CD_MSF 0xb9
+#define OP_READ_HEADER 0x44
+#define OP_READ_SUB_CHANNEL 0x42
+#define OP_READ_TOC 0x43
+#define OP_REQUEST_SENSE 0x03
+#define OP_SCAN 0xba
+#define OP_SEEK_10 0x2b
+#define OP_SET_CD_SPEED 0xbb
+#define OP_STOPPLAY_SCAN 0x4e
+#define OP_START_STOP_UNIT 0x1b
+#define OP_TEST_UNIT_READY 0x00
+
+#define OP_FORMAT_UNIT 0x04
+#define OP_READ_FORMAT_CAPACITIES 0x23
+#define OP_VERIFY 0x2f
+#define OP_WRITE_10 0x2a
+#define OP_WRITE_12 0xaa
+#define OP_WRITE_AND_VERIFY 0x2e
+
+//
+// ATA Command
+//
+#define ATAPI_SOFT_RESET_CMD 0x08
+
+typedef enum {
+ DataIn = 0,
+ DataOut = 1,
+ NoData = 2,
+ End = 0xff
+} DATA_DIRECTION;
+
+typedef struct {
+ UINT8 OpCode;
+ DATA_DIRECTION Direction;
+} SCSI_COMMAND_SET;
+
+#define MAX_CHANNEL 2
+
+#define ValidCdbLength(Len) ((Len) == 6 || (Len) == 10 || (Len) == 12) ? 1 : 0
+
+//
+// IDE registers bit definitions
+//
+// ATA Err Reg bitmap
+//
+#define BBK_ERR bit (7) /* Bad block detected */
+#define UNC_ERR bit (6) /* Uncorrectable Data */
+#define MC_ERR bit (5) /* Media Change */
+#define IDNF_ERR bit (4) /* ID Not Found */
+#define MCR_ERR bit (3) /* Media Change Requested */
+#define ABRT_ERR bit (2) /* Aborted Command */
+#define TK0NF_ERR bit (1) /* Track 0 Not Found */
+#define AMNF_ERR bit (0) /* Address Mark Not Found */
+
+//
+// ATAPI Err Reg bitmap
+//
+#define SENSE_KEY_ERR (bit (7) | bit (6) | bit (5) | bit (4))
+#define EOM_ERR bit (1) /* End of Media Detected */
+#define ILI_ERR bit (0) /* Illegal Length Indication */
+
+//
+// Device/Head Reg
+//
+#define LBA_MODE bit (6)
+#define DEV bit (4)
+#define HS3 bit (3)
+#define HS2 bit (2)
+#define HS1 bit (1)
+#define HS0 bit (0)
+#define CHS_MODE (0)
+#define DRV0 (0)
+#define DRV1 (1)
+#define MST_DRV DRV0
+#define SLV_DRV DRV1
+
+//
+// Status Reg
+//
+#define BSY bit (7) /* Controller Busy */
+#define DRDY bit (6) /* Drive Ready */
+#define DWF bit (5) /* Drive Write Fault */
+#define DSC bit (4) /* Disk Seek Complete */
+#define DRQ bit (3) /* Data Request */
+#define CORR bit (2) /* Corrected Data */
+#define IDX bit (1) /* Index */
+#define ERR bit (0) /* Error */
+#define CHECK bit (0) /* Check bit for ATAPI Status Reg */
+
+//
+// Device Control Reg
+//
+#define SRST bit (2) /* Software Reset */
+#define IEN_L bit (1) /* Interrupt Enable #*/
+
+//
+// ATAPI Feature Register
+//
+#define OVERLAP bit (1)
+#define DMA bit (0)
+
+//
+// ATAPI Interrupt Reason Reson Reg (ATA Sector Count Register)
+//
+#define RELEASE bit (2)
+#define IO bit (1)
+#define CoD bit (0)
+
+#define PACKET_CMD 0xA0
+
+#define DEFAULT_CMD (0xa0)
+//
+// default content of device control register, disable INT
+//
+#define DEFAULT_CTL (0x0a)
+#define MAX_ATAPI_BYTE_COUNT (0xfffe)
+
+//
+// function prototype
+//
+EFI_STATUS
+EFIAPI
+AtapiScsiPassThruDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+ /*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ ImageHandle - TODO: add argument description
+ SystemTable - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+RegisterAtapiScsiPassThru (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_PCI_IO_PROTOCOL *PciIo
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Controller - TODO: add argument description
+ PciIo - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+AtapiScsiPassThruFunction (
+ IN EFI_SCSI_PASS_THRU_PROTOCOL *This,
+ IN UINT32 Target,
+ IN UINT64 Lun,
+ IN OUT EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,
+ IN EFI_EVENT Event OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Target - TODO: add argument description
+ Lun - TODO: add argument description
+ Packet - TODO: add argument description
+ Event - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+AtapiScsiPassThruGetNextDevice (
+ IN EFI_SCSI_PASS_THRU_PROTOCOL *This,
+ IN OUT UINT32 *Target,
+ IN OUT UINT64 *Lun
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Target - TODO: add argument description
+ Lun - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+AtapiScsiPassThruBuildDevicePath (
+ IN EFI_SCSI_PASS_THRU_PROTOCOL *This,
+ IN UINT32 Target,
+ IN UINT64 Lun,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Target - TODO: add argument description
+ Lun - TODO: add argument description
+ DevicePath - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+AtapiScsiPassThruGetTargetLun (
+ IN EFI_SCSI_PASS_THRU_PROTOCOL *This,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT UINT32 *Target,
+ OUT UINT64 *Lun
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ DevicePath - TODO: add argument description
+ Target - TODO: add argument description
+ Lun - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+AtapiScsiPassThruResetChannel (
+ IN EFI_SCSI_PASS_THRU_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+AtapiScsiPassThruResetTarget (
+ IN EFI_SCSI_PASS_THRU_PROTOCOL *This,
+ IN UINT32 Target,
+ IN UINT64 Lun
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Target - TODO: add argument description
+ Lun - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+CheckSCSIRequestPacket (
+ EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Packet - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+SubmitBlockingIoCommand (
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate,
+ UINT32 Target,
+ EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AtapiScsiPrivate - TODO: add argument description
+ Target - TODO: add argument description
+ Packet - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+IsCommandValid (
+ EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
+ )
+ /*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Packet - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+RequestSenseCommand (
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate,
+ UINT32 Target,
+ UINT64 Timeout,
+ VOID *SenseData,
+ UINT8 *SenseDataLength
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AtapiScsiPrivate - TODO: add argument description
+ Target - TODO: add argument description
+ Timeout - TODO: add argument description
+ SenseData - TODO: add argument description
+ SenseDataLength - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtapiPacketCommand (
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate,
+ UINT32 Target,
+ UINT8 *PacketCommand,
+ VOID *Buffer,
+ UINT32 *ByteCount,
+ DATA_DIRECTION Direction,
+ UINT64 TimeOutInMicroSeconds
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AtapiScsiPrivate - TODO: add argument description
+ Target - TODO: add argument description
+ PacketCommand - TODO: add argument description
+ Buffer - TODO: add argument description
+ ByteCount - TODO: add argument description
+ Direction - TODO: add argument description
+ TimeOutInMicroSeconds - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+
+UINT8
+ReadPortB (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 Port
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIo - TODO: add argument description
+ Port - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+
+UINT16
+ReadPortW (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 Port
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIo - TODO: add argument description
+ Port - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+
+VOID
+WritePortB (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 Port,
+ IN UINT8 Data
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIo - TODO: add argument description
+ Port - TODO: add argument description
+ Data - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+
+VOID
+WritePortW (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 Port,
+ IN UINT16 Data
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIo - TODO: add argument description
+ Port - TODO: add argument description
+ Data - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+StatusDRQClear (
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate,
+ UINT64 TimeOutInMicroSeconds
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AtapiScsiPrivate - TODO: add argument description
+ TimeOutInMicroSeconds - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AltStatusDRQClear (
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate,
+ UINT64 TimeOutInMicroSeconds
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AtapiScsiPrivate - TODO: add argument description
+ TimeOutInMicroSeconds - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+StatusDRQReady (
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate,
+ UINT64 TimeOutInMicroSeconds
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AtapiScsiPrivate - TODO: add argument description
+ TimeOutInMicroSeconds - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AltStatusDRQReady (
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate,
+ UINT64 TimeOutInMicroSeconds
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AtapiScsiPrivate - TODO: add argument description
+ TimeOutInMicroSeconds - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+StatusWaitForBSYClear (
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate,
+ UINT64 TimeoutInMicroSeconds
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AtapiScsiPrivate - TODO: add argument description
+ TimeoutInMicroSeconds - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AltStatusWaitForBSYClear (
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate,
+ UINT64 TimeoutInMicroSeconds
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AtapiScsiPrivate - TODO: add argument description
+ TimeoutInMicroSeconds - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+StatusDRDYReady (
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate,
+ UINT64 TimeoutInMicroSeconds
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AtapiScsiPrivate - TODO: add argument description
+ TimeoutInMicroSeconds - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AltStatusDRDYReady (
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate,
+ UINT64 TimeoutInMicroSeconds
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AtapiScsiPrivate - TODO: add argument description
+ TimeoutInMicroSeconds - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtapiPassThruPioReadWriteData (
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate,
+ UINT16 *Buffer,
+ UINT32 *ByteCount,
+ DATA_DIRECTION Direction,
+ UINT64 TimeOutInMicroSeconds
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AtapiScsiPrivate - TODO: add argument description
+ Buffer - TODO: add argument description
+ ByteCount - TODO: add argument description
+ Direction - TODO: add argument description
+ TimeOutInMicroSeconds - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtapiPassThruCheckErrorStatus (
+ ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AtapiScsiPrivate - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+#endif
diff --git a/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.mbd b/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.mbd
new file mode 100644
index 0000000..903a092
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.mbd
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MbdHeader>
+ <BaseName>AtapiPassThru</BaseName>
+ <Guid>E49061CE-99A7-41d3-AB3A-36E5CFBAD63E</Guid>
+ <Version>0</Version>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Created>2006-03-12 17:09</Created>
+ <Modified>2006-03-19 15:18</Modified>
+ </MbdHeader>
+ <Libraries>
+ <Library>UefiBootServicesTableLib</Library>
+ <Library>UefiMemoryLib</Library>
+ <Library>UefiLib</Library>
+ <Library>UefiDriverEntryPoint</Library>
+ <Library>UefiDriverModelLib</Library>
+ <Library>DxeReportStatusCodeLib</Library>
+ <Library>BaseDebugLibReportStatusCode</Library>
+ <Library>EdkDxePrintLib</Library>
+ <Library>BaseLib</Library>
+ <Library>DxeMemoryAllocationLib</Library>
+ </Libraries>
+</ModuleBuildDescription>
diff --git a/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.msa b/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.msa
new file mode 100644
index 0000000..1c13016
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.msa
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MsaHeader>
+ <BaseName>AtapiPassThru</BaseName>
+ <ModuleType>UEFI_DRIVER</ModuleType>
+ <ComponentType>BS_DRIVER</ComponentType>
+ <Guid>E49061CE-99A7-41d3-AB3A-36E5CFBAD63E</Guid>
+ <Version>0</Version>
+ <Abstract>Description file for the Atapi Passthru component.</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Specification>0</Specification>
+ <Created>2006-03-12 17:09</Created>
+ <Updated>2006-03-19 15:18</Updated>
+ </MsaHeader>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverModelLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverEntryPoint</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">MemoryAllocationLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiBootServicesTableLib</LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>AtapiPassThru.h</Filename>
+ <Filename>AtapiPassThru.c</Filename>
+ <Filename>ComponentName.c</Filename>
+ </SourceFiles>
+ <Includes>
+ <PackageName>MdePkg</PackageName>
+ </Includes>
+ <Protocols>
+ <Protocol Usage="TO_START">PciIo</Protocol>
+ <Protocol Usage="BY_START">ScsiPassThru</Protocol>
+ </Protocols>
+ <Externs>
+ <Extern>
+ <ModuleEntryPoint></ModuleEntryPoint>
+ </Extern>
+ <Extern>
+ <DriverBinding>gAtapiScsiPassThruDriverBinding</DriverBinding>
+ <ComponentName>gAtapiScsiPassThruComponentName</ComponentName>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea>
diff --git a/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/ComponentName.c b/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/ComponentName.c
new file mode 100644
index 0000000..14658b0
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/ComponentName.c
@@ -0,0 +1,154 @@
+/*++
+
+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:
+
+ ComponentName.c
+
+Abstract:
+
+--*/
+#include "AtapiPassThru.h"
+
+//
+// EFI Component Name Functions
+//
+EFI_STATUS
+EFIAPI
+AtapiScsiPassThruComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+EFI_STATUS
+EFIAPI
+AtapiScsiPassThruComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+//
+// EFI Component Name Protocol
+//
+EFI_COMPONENT_NAME_PROTOCOL gAtapiScsiPassThruComponentName = {
+ AtapiScsiPassThruComponentNameGetDriverName,
+ AtapiScsiPassThruComponentNameGetControllerName,
+ "eng"
+};
+
+static EFI_UNICODE_STRING_TABLE mAtapiScsiPassThruDriverNameTable[] = {
+ { "eng", (CHAR16 *) L"ATAPI SCSI Pass Thru Driver" },
+ { NULL , NULL }
+};
+
+EFI_STATUS
+EFIAPI
+AtapiScsiPassThruComponentNameGetDriverName (
+ 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,
+ gAtapiScsiPassThruComponentName.SupportedLanguages,
+ mAtapiScsiPassThruDriverNameTable,
+ DriverName
+ );
+}
+
+EFI_STATUS
+EFIAPI
+AtapiScsiPassThruComponentNameGetControllerName (
+ 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.
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/build.xml b/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/build.xml
new file mode 100644
index 0000000..d9b2b66
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/build.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- 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.-->
+<project basedir="." default="AtapiPassThru"><!--Apply external ANT tasks-->
+ <taskdef resource="GenBuild.tasks"/>
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+ <property environment="env"/>
+ <property name="WORKSPACE_DIR" value="${env.WORKSPACE}"/>
+ <import file="${WORKSPACE_DIR}\Tools\Conf\BuildMacro.xml"/><!--MODULE_RELATIVE PATH is relative to PACKAGE_DIR-->
+ <property name="MODULE_RELATIVE_PATH" value="Bus\Pci\AtapiPassThru\Dxe"/>
+ <property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
+ <property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
+ <target name="AtapiPassThru">
+ <GenBuild baseName="AtapiPassThru" mbdFilename="${MODULE_DIR}\AtapiPassThru.mbd" msaFilename="${MODULE_DIR}\AtapiPassThru.msa"/>
+ </target>
+ <target depends="AtapiPassThru_clean" name="clean"/>
+ <target depends="AtapiPassThru_cleanall" name="cleanall"/>
+ <target name="AtapiPassThru_clean">
+ <OutputDirSetup baseName="AtapiPassThru" mbdFilename="${MODULE_DIR}\AtapiPassThru.mbd" msaFilename="${MODULE_DIR}\AtapiPassThru.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\AtapiPassThru_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\AtapiPassThru_build.xml" target="clean"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
+ </target>
+ <target name="AtapiPassThru_cleanall">
+ <OutputDirSetup baseName="AtapiPassThru" mbdFilename="${MODULE_DIR}\AtapiPassThru.mbd" msaFilename="${MODULE_DIR}\AtapiPassThru.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\AtapiPassThru_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\AtapiPassThru_build.xml" target="cleanall"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}"/>
+ <delete dir="${DEST_DIR_DEBUG}"/>
+ <delete>
+ <fileset dir="${BIN_DIR}" includes="**AtapiPassThru*"/>
+ </delete>
+ </target>
+</project> \ No newline at end of file
diff --git a/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430.c b/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430.c
new file mode 100644
index 0000000..91d6acc
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430.c
@@ -0,0 +1,346 @@
+/*++
+
+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:
+
+ CirrusLogic5430.c
+
+Abstract:
+
+ Cirrus Logic 5430 Controller Driver.
+ This driver is a sample implementation of the UGA Draw Protocol for the
+ Cirrus Logic 5430 family of PCI video controllers. This driver is only
+ usable in the EFI pre-boot environment. This sample is intended to show
+ how the UGA Draw Protocol is able to function. The UGA I/O Protocol is not
+ implemented in this sample. A fully compliant EFI UGA driver requires both
+ the UGA Draw and the UGA I/O Protocol. Please refer to Microsoft's
+ documentation on UGA for details on how to write a UGA driver that is able
+ to function both in the EFI pre-boot environment and from the OS runtime.
+
+Revision History:
+
+--*/
+
+//
+// Cirrus Logic 5430 Controller Driver
+//
+
+#include "CirrusLogic5430.h"
+
+EFI_DRIVER_BINDING_PROTOCOL gCirrusLogic5430DriverBinding = {
+ CirrusLogic5430ControllerDriverSupported,
+ CirrusLogic5430ControllerDriverStart,
+ CirrusLogic5430ControllerDriverStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+EFI_STATUS
+EFIAPI
+CirrusLogic5430ControllerDriverSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Controller - add argument and description to function comment
+// TODO: RemainingDevicePath - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
+
+ //
+ // Open the PCI I/O Protocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Read the PCI Configuration Header from the PCI Device
+ //
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (Pci) / sizeof (UINT32),
+ &Pci
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = EFI_UNSUPPORTED;
+ //
+ // See if the I/O enable is on. Most systems only allow one VGA device to be turned on
+ // at a time, so see if this is one that is turned on.
+ //
+ // if (((Pci.Hdr.Command & 0x01) == 0x01)) {
+ //
+ // See if this is a Cirrus Logic PCI controller
+ //
+ if (Pci.Hdr.VendorId == CIRRUS_LOGIC_VENDOR_ID) {
+ //
+ // See if this is a 5430 or a 5446 PCI controller
+ //
+ if (Pci.Hdr.DeviceId == CIRRUS_LOGIC_5430_DEVICE_ID) {
+ Status = EFI_SUCCESS;
+ }
+
+ if (Pci.Hdr.DeviceId == CIRRUS_LOGIC_5430_ALTERNATE_DEVICE_ID) {
+ Status = EFI_SUCCESS;
+ }
+
+ if (Pci.Hdr.DeviceId == CIRRUS_LOGIC_5446_DEVICE_ID) {
+ Status = EFI_SUCCESS;
+ }
+ }
+
+Done:
+ //
+ // Close the PCI I/O Protocol
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+CirrusLogic5430ControllerDriverStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Controller - add argument and description to function comment
+// TODO: RemainingDevicePath - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ CIRRUS_LOGIC_5430_PRIVATE_DATA *Private;
+
+ //
+ // Allocate Private context data for UGA Draw inteface.
+ //
+ Private = NULL;
+ Private = AllocateZeroPool (sizeof (CIRRUS_LOGIC_5430_PRIVATE_DATA));
+ if (Private == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ //
+ // Set up context record
+ //
+ Private->Signature = CIRRUS_LOGIC_5430_PRIVATE_DATA_SIGNATURE;
+ Private->Handle = Controller;
+
+ //
+ // Open PCI I/O Protocol
+ //
+ Status = gBS->OpenProtocol (
+ Private->Handle,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &Private->PciIo,
+ This->DriverBindingHandle,
+ Private->Handle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ Status = Private->PciIo->Attributes (
+ Private->PciIo,
+ EfiPciIoAttributeOperationEnable,
+ EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ //
+ // Start the UGA Draw software stack.
+ //
+ Status = CirrusLogic5430UgaDrawConstructor (Private);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ //
+ // Publish the UGA Draw interface to the world
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Private->Handle,
+ &gEfiUgaDrawProtocolGuid,
+ &Private->UgaDraw,
+ NULL
+ );
+
+Error:
+ if (EFI_ERROR (Status)) {
+ if (Private) {
+ if (Private->PciIo) {
+ Private->PciIo->Attributes (
+ Private->PciIo,
+ EfiPciIoAttributeOperationDisable,
+ EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO,
+ NULL
+ );
+ }
+ }
+
+ //
+ // Close the PCI I/O Protocol
+ //
+ gBS->CloseProtocol (
+ Private->Handle,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Private->Handle
+ );
+ if (Private) {
+ gBS->FreePool (Private);
+ }
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+CirrusLogic5430ControllerDriverStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Controller - add argument and description to function comment
+// TODO: NumberOfChildren - add argument and description to function comment
+// TODO: ChildHandleBuffer - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_UGA_DRAW_PROTOCOL *UgaDraw;
+ EFI_STATUS Status;
+ CIRRUS_LOGIC_5430_PRIVATE_DATA *Private;
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiUgaDrawProtocolGuid,
+ (VOID **) &UgaDraw,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // If the UGA Draw interface does not exist the driver is not started
+ //
+ return Status;
+ }
+
+ //
+ // Get our private context information
+ //
+ Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_UGA_DRAW_THIS (UgaDraw);
+
+ //
+ // Remove the UGA Draw interface from the system
+ //
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ Private->Handle,
+ &gEfiUgaDrawProtocolGuid,
+ &Private->UgaDraw,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Shutdown the hardware
+ //
+ CirrusLogic5430UgaDrawDestructor (Private);
+
+ Private->PciIo->Attributes (
+ Private->PciIo,
+ EfiPciIoAttributeOperationDisable,
+ EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO,
+ NULL
+ );
+
+ //
+ // Close the PCI I/O Protocol
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ //
+ // Free our instance data
+ //
+ gBS->FreePool (Private);
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430.h b/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430.h
new file mode 100644
index 0000000..5eba019
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430.h
@@ -0,0 +1,254 @@
+/*++
+
+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:
+
+ CirrusLogic5430.h
+
+Abstract:
+
+ Cirrus Logic 5430 Controller Driver
+
+Revision History
+
+--*/
+
+//
+// Cirrus Logic 5430 Controller Driver
+//
+
+#ifndef _CIRRUS_LOGIC_5430_H_
+#define _CIRRUS_LOGIC_5430_H_
+
+
+#include <IndustryStandard/Pci22.h>
+//
+// Cirrus Logic 5430 PCI Configuration Header values
+//
+#define CIRRUS_LOGIC_VENDOR_ID 0x1013
+#define CIRRUS_LOGIC_5430_DEVICE_ID 0x00a8
+#define CIRRUS_LOGIC_5430_ALTERNATE_DEVICE_ID 0x00a0
+#define CIRRUS_LOGIC_5446_DEVICE_ID 0x00b8
+
+//
+// Cirrus Logic Graphical Mode Data
+//
+#define CIRRUS_LOGIC_5430_UGA_DRAW_MODE_COUNT 3
+
+typedef struct {
+ UINT32 HorizontalResolution;
+ UINT32 VerticalResolution;
+ UINT32 ColorDepth;
+ UINT32 RefreshRate;
+} CIRRUS_LOGIC_5430_UGA_DRAW_MODE_DATA;
+
+//
+// Cirrus Logic 5440 Private Data Structure
+//
+#define CIRRUS_LOGIC_5430_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('C', 'L', '5', '4')
+
+typedef struct {
+ UINT64 Signature;
+ EFI_HANDLE Handle;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_UGA_DRAW_PROTOCOL UgaDraw;
+
+ //
+ // UGA Draw Private Data
+ //
+ BOOLEAN HardwareNeedsStarting;
+ UINTN CurrentMode;
+ UINTN MaxMode;
+ CIRRUS_LOGIC_5430_UGA_DRAW_MODE_DATA ModeData[CIRRUS_LOGIC_5430_UGA_DRAW_MODE_COUNT];
+ UINT8 *LineBuffer;
+} CIRRUS_LOGIC_5430_PRIVATE_DATA;
+
+#define CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_UGA_DRAW_THIS(a) \
+ CR(a, CIRRUS_LOGIC_5430_PRIVATE_DATA, UgaDraw, CIRRUS_LOGIC_5430_PRIVATE_DATA_SIGNATURE)
+
+//
+// Global Variables
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gCirrusLogic5430DriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gCirrusLogic5430ComponentName;
+
+//
+// Io Registers defined by VGA
+//
+#define CRTC_ADDRESS_REGISTER 0x3d4
+#define CRTC_DATA_REGISTER 0x3d5
+#define SEQ_ADDRESS_REGISTER 0x3c4
+#define SEQ_DATA_REGISTER 0x3c5
+#define GRAPH_ADDRESS_REGISTER 0x3ce
+#define GRAPH_DATA_REGISTER 0x3cf
+#define ATT_ADDRESS_REGISTER 0x3c0
+#define MISC_OUTPUT_REGISTER 0x3c2
+#define INPUT_STATUS_1_REGISTER 0x3da
+#define DAC_PIXEL_MASK_REGISTER 0x3c6
+#define PALETTE_INDEX_REGISTER 0x3c8
+#define PALETTE_DATA_REGISTER 0x3c9
+
+//
+// UGA Draw Hardware abstraction internal worker functions
+//
+EFI_STATUS
+CirrusLogic5430UgaDrawConstructor (
+ CIRRUS_LOGIC_5430_PRIVATE_DATA *Private
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Private - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+CirrusLogic5430UgaDrawDestructor (
+ CIRRUS_LOGIC_5430_PRIVATE_DATA *Private
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Private - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+//
+// EFI 1.1 driver model prototypes for Cirrus Logic 5430 UGA Draw
+//
+EFI_STATUS
+EFIAPI
+CirrusLogic5430DriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ ImageHandle - TODO: add argument description
+ SystemTable - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+//
+// EFI_DRIVER_BINDING_PROTOCOL Protocol Interface
+//
+EFI_STATUS
+EFIAPI
+CirrusLogic5430ControllerDriverSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Controller - TODO: add argument description
+ RemainingDevicePath - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+CirrusLogic5430ControllerDriverStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Controller - TODO: add argument description
+ RemainingDevicePath - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+CirrusLogic5430ControllerDriverStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Controller - TODO: add argument description
+ NumberOfChildren - TODO: add argument description
+ ChildHandleBuffer - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430.mbd b/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430.mbd
new file mode 100644
index 0000000..16bc289
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430.mbd
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MbdHeader>
+ <BaseName>CirrusLogic5430UgaDraw</BaseName>
+ <Guid>555F76EA-785F-40d7-9174-153C43636C68</Guid>
+ <Version>0</Version>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Created>2006-03-12 17:09</Created>
+ <Modified>2006-03-19 15:18</Modified>
+ </MbdHeader>
+ <Libraries>
+ <Library>UefiBootServicesTableLib</Library>
+ <Library>UefiMemoryLib</Library>
+ <Library>UefiLib</Library>
+ <Library>UefiDriverEntryPoint</Library>
+ <Library>UefiDriverModelLib</Library>
+ <Library>DxeReportStatusCodeLib</Library>
+ <Library>BaseDebugLibReportStatusCode</Library>
+ <Library>EdkDxePrintLib</Library>
+ <Library>BaseLib</Library>
+ <Library>DxeMemoryAllocationLib</Library>
+ </Libraries>
+</ModuleBuildDescription>
diff --git a/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430.msa b/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430.msa
new file mode 100644
index 0000000..bbc9c2e
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430.msa
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MsaHeader>
+ <BaseName>CirrusLogic5430UgaDraw</BaseName>
+ <ModuleType>UEFI_DRIVER</ModuleType>
+ <ComponentType>BS_DRIVER</ComponentType>
+ <Guid>555F76EA-785F-40d7-9174-153C43636C68</Guid>
+ <Version>0</Version>
+ <Abstract>Component description file for CirrusLogic5430 module</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Specification>0</Specification>
+ <Created>2006-03-12 17:09</Created>
+ <Updated>2006-03-19 15:18</Updated>
+ </MsaHeader>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverModelLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverEntryPoint</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">MemoryAllocationLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiBootServicesTableLib</LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>CirrusLogic5430.h</Filename>
+ <Filename>CirrusLogic5430.c</Filename>
+ <Filename>CirrusLogic5430UgaDraw.c</Filename>
+ <Filename>ComponentName.c</Filename>
+ </SourceFiles>
+ <Includes>
+ <PackageName>MdePkg</PackageName>
+ </Includes>
+ <Protocols>
+ <Protocol Usage="TO_START">PciIo</Protocol>
+ <Protocol Usage="ALWAYS_PRODUCED">UgaDraw</Protocol>
+ </Protocols>
+ <Externs>
+ <Extern>
+ <ModuleEntryPoint></ModuleEntryPoint>
+ </Extern>
+ <Extern>
+ <DriverBinding>gCirrusLogic5430DriverBinding</DriverBinding>
+ <ComponentName>gCirrusLogic5430ComponentName</ComponentName>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea>
diff --git a/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430UgaDraw.c b/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430UgaDraw.c
new file mode 100644
index 0000000..c33918b
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430UgaDraw.c
@@ -0,0 +1,1036 @@
+/*++
+
+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:
+
+ CirrusLogic5430UgaDraw.c
+
+Abstract:
+
+ This file produces the graphics abstration of UGA Draw. It is called by
+ CirrusLogic5430.c file which deals with the EFI 1.1 driver model.
+ This file just does graphics.
+
+--*/
+
+#include "CirrusLogic5430.h"
+
+//
+// Video Mode structure
+//
+typedef struct {
+ UINT32 Width;
+ UINT32 Height;
+ UINT32 ColorDepth;
+ UINT32 RefreshRate;
+ UINT8 *CrtcSettings;
+ UINT16 *SeqSettings;
+ UINT8 MiscSetting;
+} CIRRUS_LOGIC_5430_VIDEO_MODES;
+
+//
+// Generic Attribute Controller Register Settings
+//
+static UINT8 AttributeController[21] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x41, 0x00, 0x0F, 0x00, 0x00
+};
+
+//
+// Generic Graphics Controller Register Settings
+//
+static UINT8 GraphicsController[9] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF
+};
+
+//
+// 640 x 480 x 256 color @ 60 Hertz
+//
+static UINT8 Crtc_640_480_256_60[28] = {
+ 0x5d, 0x4f, 0x50, 0x82, 0x53, 0x9f, 0x00, 0x3e,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xe1, 0x83, 0xdf, 0x50, 0x00, 0xe7, 0x04, 0xe3,
+ 0xff, 0x00, 0x00, 0x22
+};
+
+static UINT16 Seq_640_480_256_60[15] = {
+ 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b,
+ 0x5b0c, 0x450d, 0x7e0e, 0x2b1b, 0x2f1c, 0x301d, 0x331e
+};
+
+//
+// 800 x 600 x 256 color @ 60 Hertz
+//
+static UINT8 Crtc_800_600_256_60[28] = {
+ 0x7F, 0x63, 0x64, 0x80, 0x6B, 0x1B, 0x72, 0xF0,
+ 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x58, 0x8C, 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22
+};
+
+static UINT16 Seq_800_600_256_60[15] = {
+ 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b,
+ 0x5b0c, 0x450d, 0x510e, 0x2b1b, 0x2f1c, 0x301d, 0x3a1e
+};
+
+//
+// 1024 x 768 x 256 color @ 60 Hertz
+//
+static UINT8 Crtc_1024_768_256_60[28] = {
+ 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,
+ 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x88, 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3,
+ 0xFF, 0x4A, 0x00, 0x22
+};
+
+static UINT16 Seq_1024_768_256_60[15] = {
+ 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b,
+ 0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e
+};
+
+//
+// Table of supported video modes
+//
+static CIRRUS_LOGIC_5430_VIDEO_MODES CirrusLogic5430VideoModes[] = {
+ { 640, 480, 8, 60, Crtc_640_480_256_60, Seq_640_480_256_60, 0xe3 },
+ { 800, 600, 8, 60, Crtc_800_600_256_60, Seq_800_600_256_60, 0xef },
+ { 1024, 768, 8, 60, Crtc_1024_768_256_60, Seq_1024_768_256_60, 0xef }
+};
+
+//
+// Local Function Prototypes
+//
+VOID
+InitializeGraphicsMode (
+ CIRRUS_LOGIC_5430_PRIVATE_DATA *Private,
+ CIRRUS_LOGIC_5430_VIDEO_MODES *ModeData
+ );
+
+VOID
+SetPaletteColor (
+ CIRRUS_LOGIC_5430_PRIVATE_DATA *Private,
+ UINTN Index,
+ UINT8 Red,
+ UINT8 Green,
+ UINT8 Blue
+ );
+
+VOID
+SetDefaultPalette (
+ CIRRUS_LOGIC_5430_PRIVATE_DATA *Private
+ );
+
+STATIC
+VOID
+ClearScreen (
+ CIRRUS_LOGIC_5430_PRIVATE_DATA *Private
+ );
+
+VOID
+DrawLogo (
+ CIRRUS_LOGIC_5430_PRIVATE_DATA *Private
+ );
+
+VOID
+outb (
+ CIRRUS_LOGIC_5430_PRIVATE_DATA *Private,
+ UINTN Address,
+ UINT8 Data
+ );
+
+VOID
+outw (
+ CIRRUS_LOGIC_5430_PRIVATE_DATA *Private,
+ UINTN Address,
+ UINT16 Data
+ );
+
+UINT8
+inb (
+ CIRRUS_LOGIC_5430_PRIVATE_DATA *Private,
+ UINTN Address
+ );
+
+UINT16
+inw (
+ CIRRUS_LOGIC_5430_PRIVATE_DATA *Private,
+ UINTN Address
+ );
+
+//
+// UGA Draw Protocol Member Functions
+//
+EFI_STATUS
+EFIAPI
+CirrusLogic5430UgaDrawGetMode (
+ IN EFI_UGA_DRAW_PROTOCOL *This,
+ OUT UINT32 *HorizontalResolution,
+ OUT UINT32 *VerticalResolution,
+ OUT UINT32 *ColorDepth,
+ OUT UINT32 *RefreshRate
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ HorizontalResolution - TODO: add argument description
+ VerticalResolution - TODO: add argument description
+ ColorDepth - TODO: add argument description
+ RefreshRate - TODO: add argument description
+
+Returns:
+
+ EFI_NOT_STARTED - TODO: Add description for return value
+ EFI_INVALID_PARAMETER - TODO: Add description for return value
+ EFI_SUCCESS - TODO: Add description for return value
+
+--*/
+{
+ CIRRUS_LOGIC_5430_PRIVATE_DATA *Private;
+
+ Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_UGA_DRAW_THIS (This);
+
+ if (Private->HardwareNeedsStarting) {
+ return EFI_NOT_STARTED;
+ }
+
+ if ((HorizontalResolution == NULL) ||
+ (VerticalResolution == NULL) ||
+ (ColorDepth == NULL) ||
+ (RefreshRate == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *HorizontalResolution = Private->ModeData[Private->CurrentMode].HorizontalResolution;
+ *VerticalResolution = Private->ModeData[Private->CurrentMode].VerticalResolution;
+ *ColorDepth = Private->ModeData[Private->CurrentMode].ColorDepth;
+ *RefreshRate = Private->ModeData[Private->CurrentMode].RefreshRate;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+CirrusLogic5430UgaDrawSetMode (
+ IN EFI_UGA_DRAW_PROTOCOL *This,
+ IN UINT32 HorizontalResolution,
+ IN UINT32 VerticalResolution,
+ IN UINT32 ColorDepth,
+ IN UINT32 RefreshRate
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ HorizontalResolution - TODO: add argument description
+ VerticalResolution - TODO: add argument description
+ ColorDepth - TODO: add argument description
+ RefreshRate - TODO: add argument description
+
+Returns:
+
+ EFI_OUT_OF_RESOURCES - TODO: Add description for return value
+ EFI_SUCCESS - TODO: Add description for return value
+ EFI_NOT_FOUND - TODO: Add description for return value
+
+--*/
+{
+ CIRRUS_LOGIC_5430_PRIVATE_DATA *Private;
+ UINTN Index;
+
+ Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_UGA_DRAW_THIS (This);
+
+ for (Index = 0; Index < Private->MaxMode; Index++) {
+
+ if (HorizontalResolution != Private->ModeData[Index].HorizontalResolution) {
+ continue;
+ }
+
+ if (VerticalResolution != Private->ModeData[Index].VerticalResolution) {
+ continue;
+ }
+
+ if (ColorDepth != Private->ModeData[Index].ColorDepth) {
+ continue;
+ }
+
+ if (RefreshRate != Private->ModeData[Index].RefreshRate) {
+ continue;
+ }
+
+ if (Private->LineBuffer) {
+ gBS->FreePool (Private->LineBuffer);
+ }
+
+ Private->LineBuffer = NULL;
+ Private->LineBuffer = AllocatePool (HorizontalResolution);
+ if (Private->LineBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ InitializeGraphicsMode (Private, &CirrusLogic5430VideoModes[Index]);
+
+ Private->CurrentMode = Index;
+
+ Private->HardwareNeedsStarting = FALSE;
+
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+EFIAPI
+CirrusLogic5430UgaDrawBlt (
+ IN EFI_UGA_DRAW_PROTOCOL *This,
+ IN EFI_UGA_PIXEL *BltBuffer, OPTIONAL
+ IN EFI_UGA_BLT_OPERATION BltOperation,
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN UINTN Delta
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ BltBuffer - TODO: add argument description
+ BltOperation - TODO: add argument description
+ SourceX - TODO: add argument description
+ SourceY - TODO: add argument description
+ DestinationX - TODO: add argument description
+ DestinationY - TODO: add argument description
+ Width - TODO: add argument description
+ Height - TODO: add argument description
+ Delta - TODO: add argument description
+
+Returns:
+
+ EFI_INVALID_PARAMETER - TODO: Add description for return value
+ EFI_INVALID_PARAMETER - TODO: Add description for return value
+ EFI_INVALID_PARAMETER - TODO: Add description for return value
+ EFI_INVALID_PARAMETER - TODO: Add description for return value
+ EFI_INVALID_PARAMETER - TODO: Add description for return value
+ EFI_INVALID_PARAMETER - TODO: Add description for return value
+ EFI_SUCCESS - TODO: Add description for return value
+
+--*/
+{
+ CIRRUS_LOGIC_5430_PRIVATE_DATA *Private;
+ EFI_TPL OriginalTPL;
+ UINTN DstY;
+ UINTN SrcY;
+ EFI_UGA_PIXEL *Blt;
+ UINTN X;
+ UINT8 Pixel;
+ UINT32 WidePixel;
+ UINTN ScreenWidth;
+ UINTN Offset;
+ UINTN SourceOffset;
+
+ Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_UGA_DRAW_THIS (This);
+
+ if ((BltOperation < 0) || (BltOperation >= EfiUgaBltMax)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width == 0 || Height == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // If Delta is zero, then the entire BltBuffer is being used, so Delta
+ // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
+ // the number of bytes in each row can be computed.
+ //
+ if (Delta == 0) {
+ Delta = Width * sizeof (EFI_UGA_PIXEL);
+ }
+
+ //
+ // We need to fill the Virtual Screen buffer with the blt data.
+ // The virtual screen is upside down, as the first row is the bootom row of
+ // the image.
+ //
+
+ //
+ // Make sure the SourceX, SourceY, DestinationX, DestinationY, Width, and Height parameters
+ // are valid for the operation and the current screen geometry.
+ //
+ if (BltOperation == EfiUgaVideoToBltBuffer) {
+ //
+ // Video to BltBuffer: Source is Video, destination is BltBuffer
+ //
+ if (SourceY + Height > Private->ModeData[Private->CurrentMode].VerticalResolution) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (SourceX + Width > Private->ModeData[Private->CurrentMode].HorizontalResolution) {
+ return EFI_INVALID_PARAMETER;
+ }
+ } else {
+ //
+ // BltBuffer to Video: Source is BltBuffer, destination is Video
+ //
+ if (DestinationY + Height > Private->ModeData[Private->CurrentMode].VerticalResolution) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (DestinationX + Width > Private->ModeData[Private->CurrentMode].HorizontalResolution) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ //
+ // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
+ // We would not want a timer based event (Cursor, ...) to come in while we are
+ // doing this operation.
+ //
+ OriginalTPL = gBS->RaiseTPL (EFI_TPL_NOTIFY);
+
+ switch (BltOperation) {
+ case EfiUgaVideoToBltBuffer:
+ //
+ // Video to BltBuffer: Source is Video, destination is BltBuffer
+ //
+ for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) {
+
+ Offset = (SrcY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + SourceX;
+ if (((Offset & 0x03) == 0) && ((Width & 0x03) == 0)) {
+ Private->PciIo->Mem.Read (
+ Private->PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ Offset,
+ Width >> 2,
+ Private->LineBuffer
+ );
+ } else {
+ Private->PciIo->Mem.Read (
+ Private->PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ Offset,
+ Width,
+ Private->LineBuffer
+ );
+ }
+
+ for (X = 0; X < Width; X++) {
+ Blt = (EFI_UGA_PIXEL *) ((UINT8 *) BltBuffer + (DstY * Delta) + (DestinationX + X) * sizeof (EFI_UGA_PIXEL));
+
+ Blt->Red = (UINT8) (Private->LineBuffer[X] & 0xe0);
+ Blt->Green = (UINT8) ((Private->LineBuffer[X] & 0x1c) << 3);
+ Blt->Blue = (UINT8) ((Private->LineBuffer[X] & 0x03) << 6);
+ }
+ }
+ break;
+
+ case EfiUgaVideoToVideo:
+ //
+ // Perform hardware acceleration for Video to Video operations
+ //
+ ScreenWidth = Private->ModeData[Private->CurrentMode].HorizontalResolution;
+ SourceOffset = (SourceY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + (SourceX);
+ Offset = (DestinationY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + (DestinationX);
+
+ outw (Private, GRAPH_ADDRESS_REGISTER, 0x0000);
+ outw (Private, GRAPH_ADDRESS_REGISTER, 0x0010);
+ outw (Private, GRAPH_ADDRESS_REGISTER, 0x0012);
+ outw (Private, GRAPH_ADDRESS_REGISTER, 0x0014);
+
+ outw (Private, GRAPH_ADDRESS_REGISTER, 0x0001);
+ outw (Private, GRAPH_ADDRESS_REGISTER, 0x0011);
+ outw (Private, GRAPH_ADDRESS_REGISTER, 0x0013);
+ outw (Private, GRAPH_ADDRESS_REGISTER, 0x0015);
+
+ outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) (((Width << 8) & 0xff00) | 0x20));
+ outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((Width & 0xff00) | 0x21));
+ outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) (((Height << 8) & 0xff00) | 0x22));
+ outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((Height & 0xff00) | 0x23));
+ outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) (((ScreenWidth << 8) & 0xff00) | 0x24));
+ outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((ScreenWidth & 0xff00) | 0x25));
+ outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) (((ScreenWidth << 8) & 0xff00) | 0x26));
+ outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((ScreenWidth & 0xff00) | 0x27));
+ outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((Offset) << 8) & 0xff00) | 0x28));
+ outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((Offset) >> 0) & 0xff00) | 0x29));
+ outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((Offset) >> 8) & 0xff00) | 0x2a));
+ outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((SourceOffset) << 8) & 0xff00) | 0x2c));
+ outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((SourceOffset) >> 0) & 0xff00) | 0x2d));
+ outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((SourceOffset) >> 8) & 0xff00) | 0x2e));
+ outw (Private, GRAPH_ADDRESS_REGISTER, 0x002f);
+ outw (Private, GRAPH_ADDRESS_REGISTER, 0x0030);
+ outw (Private, GRAPH_ADDRESS_REGISTER, 0x0d32);
+ outw (Private, GRAPH_ADDRESS_REGISTER, 0x0033);
+ outw (Private, GRAPH_ADDRESS_REGISTER, 0x0034);
+ outw (Private, GRAPH_ADDRESS_REGISTER, 0x0035);
+
+ outw (Private, GRAPH_ADDRESS_REGISTER, 0x0231);
+
+ outb (Private, GRAPH_ADDRESS_REGISTER, 0x31);
+ while ((inb (Private, GRAPH_DATA_REGISTER) & 0x01) == 0x01)
+ ;
+ break;
+
+ case EfiUgaVideoFill:
+ Blt = BltBuffer;
+ Pixel = (UINT8) ((Blt->Red & 0xe0) | ((Blt->Green >> 3) & 0x1c) | ((Blt->Blue >> 6) & 0x03));
+ WidePixel = (Pixel << 8) | Pixel;
+ WidePixel = (WidePixel << 16) | WidePixel;
+
+ if (DestinationX == 0 && Width == Private->ModeData[Private->CurrentMode].HorizontalResolution) {
+ Offset = DestinationY * Private->ModeData[Private->CurrentMode].HorizontalResolution;
+ if (((Offset & 0x03) == 0) && (((Width * Height) & 0x03) == 0)) {
+ Private->PciIo->Mem.Write (
+ Private->PciIo,
+ EfiPciIoWidthFillUint32,
+ 0,
+ Offset,
+ (Width * Height) >> 2,
+ &WidePixel
+ );
+ } else {
+ Private->PciIo->Mem.Write (
+ Private->PciIo,
+ EfiPciIoWidthFillUint8,
+ 0,
+ Offset,
+ Width * Height,
+ &Pixel
+ );
+ }
+ } else {
+ for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
+ Offset = (DstY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + DestinationX;
+ if (((Offset & 0x03) == 0) && ((Width & 0x03) == 0)) {
+ Private->PciIo->Mem.Write (
+ Private->PciIo,
+ EfiPciIoWidthFillUint32,
+ 0,
+ Offset,
+ Width >> 2,
+ &WidePixel
+ );
+ } else {
+ Private->PciIo->Mem.Write (
+ Private->PciIo,
+ EfiPciIoWidthFillUint8,
+ 0,
+ Offset,
+ Width,
+ &Pixel
+ );
+ }
+ }
+ }
+ break;
+
+ case EfiUgaBltBufferToVideo:
+ for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) {
+
+ for (X = 0; X < Width; X++) {
+ Blt = (EFI_UGA_PIXEL *) ((UINT8 *) BltBuffer + (SrcY * Delta) + (SourceX + X) * sizeof (EFI_UGA_PIXEL));
+ Private->LineBuffer[X] = (UINT8) ((Blt->Red & 0xe0) | ((Blt->Green >> 3) & 0x1c) | ((Blt->Blue >> 6) & 0x03));
+ }
+
+ Offset = (DstY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + DestinationX;
+
+ if (((Offset & 0x03) == 0) && ((Width & 0x03) == 0)) {
+ Private->PciIo->Mem.Write (
+ Private->PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ Offset,
+ Width >> 2,
+ Private->LineBuffer
+ );
+ } else {
+ Private->PciIo->Mem.Write (
+ Private->PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ Offset,
+ Width,
+ Private->LineBuffer
+ );
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ gBS->RestoreTPL (OriginalTPL);
+
+ return EFI_SUCCESS;
+}
+
+//
+// Construction and Destruction functions
+//
+
+EFI_STATUS
+CirrusLogic5430UgaDrawConstructor (
+ CIRRUS_LOGIC_5430_PRIVATE_DATA *Private
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Private - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_UGA_DRAW_PROTOCOL *UgaDraw;
+ UINTN Index;
+
+ //
+ // Fill in Private->UgaDraw protocol
+ //
+ UgaDraw = &Private->UgaDraw;
+
+ UgaDraw->GetMode = CirrusLogic5430UgaDrawGetMode;
+ UgaDraw->SetMode = CirrusLogic5430UgaDrawSetMode;
+ UgaDraw->Blt = CirrusLogic5430UgaDrawBlt;
+
+ //
+ // Initialize the private data
+ //
+ Private->MaxMode = CIRRUS_LOGIC_5430_UGA_DRAW_MODE_COUNT;
+ Private->CurrentMode = 0;
+ for (Index = 0; Index < Private->MaxMode; Index++) {
+ Private->ModeData[Index].HorizontalResolution = CirrusLogic5430VideoModes[Index].Width;
+ Private->ModeData[Index].VerticalResolution = CirrusLogic5430VideoModes[Index].Height;
+ Private->ModeData[Index].ColorDepth = 32;
+ Private->ModeData[Index].RefreshRate = CirrusLogic5430VideoModes[Index].RefreshRate;
+ }
+
+ Private->HardwareNeedsStarting = TRUE;
+ Private->LineBuffer = NULL;
+
+ //
+ // Initialize the hardware
+ //
+ UgaDraw->SetMode (
+ UgaDraw,
+ Private->ModeData[Private->CurrentMode].HorizontalResolution,
+ Private->ModeData[Private->CurrentMode].VerticalResolution,
+ Private->ModeData[Private->CurrentMode].ColorDepth,
+ Private->ModeData[Private->CurrentMode].RefreshRate
+ );
+ DrawLogo (Private);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CirrusLogic5430UgaDrawDestructor (
+ CIRRUS_LOGIC_5430_PRIVATE_DATA *Private
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Private - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ return EFI_SUCCESS;
+}
+
+VOID
+outb (
+ CIRRUS_LOGIC_5430_PRIVATE_DATA *Private,
+ UINTN Address,
+ UINT8 Data
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Private - TODO: add argument description
+ Address - TODO: add argument description
+ Data - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ Private->PciIo->Io.Write (
+ Private->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ Address,
+ 1,
+ &Data
+ );
+}
+
+VOID
+outw (
+ CIRRUS_LOGIC_5430_PRIVATE_DATA *Private,
+ UINTN Address,
+ UINT16 Data
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Private - TODO: add argument description
+ Address - TODO: add argument description
+ Data - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ Private->PciIo->Io.Write (
+ Private->PciIo,
+ EfiPciIoWidthUint16,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ Address,
+ 1,
+ &Data
+ );
+}
+
+UINT8
+inb (
+ CIRRUS_LOGIC_5430_PRIVATE_DATA *Private,
+ UINTN Address
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Private - TODO: add argument description
+ Address - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ UINT8 Data;
+
+ Private->PciIo->Io.Read (
+ Private->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ Address,
+ 1,
+ &Data
+ );
+ return Data;
+}
+
+UINT16
+inw (
+ CIRRUS_LOGIC_5430_PRIVATE_DATA *Private,
+ UINTN Address
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Private - TODO: add argument description
+ Address - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ UINT16 Data;
+
+ Private->PciIo->Io.Read (
+ Private->PciIo,
+ EfiPciIoWidthUint16,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ Address,
+ 1,
+ &Data
+ );
+ return Data;
+}
+
+VOID
+SetPaletteColor (
+ CIRRUS_LOGIC_5430_PRIVATE_DATA *Private,
+ UINTN Index,
+ UINT8 Red,
+ UINT8 Green,
+ UINT8 Blue
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Private - TODO: add argument description
+ Index - TODO: add argument description
+ Red - TODO: add argument description
+ Green - TODO: add argument description
+ Blue - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ outb (Private, PALETTE_INDEX_REGISTER, (UINT8) Index);
+ outb (Private, PALETTE_DATA_REGISTER, (UINT8) (Red >> 2));
+ outb (Private, PALETTE_DATA_REGISTER, (UINT8) (Green >> 2));
+ outb (Private, PALETTE_DATA_REGISTER, (UINT8) (Blue >> 2));
+}
+
+VOID
+SetDefaultPalette (
+ CIRRUS_LOGIC_5430_PRIVATE_DATA *Private
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Private - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ UINTN Index;
+ UINTN RedIndex;
+ UINTN GreenIndex;
+ UINTN BlueIndex;
+
+ Index = 0;
+ for (RedIndex = 0; RedIndex < 8; RedIndex++) {
+ for (GreenIndex = 0; GreenIndex < 8; GreenIndex++) {
+ for (BlueIndex = 0; BlueIndex < 4; BlueIndex++) {
+ SetPaletteColor (Private, Index, (UINT8) (RedIndex << 5), (UINT8) (GreenIndex << 5), (UINT8) (BlueIndex << 6));
+ Index++;
+ }
+ }
+ }
+}
+
+STATIC
+VOID
+ClearScreen (
+ CIRRUS_LOGIC_5430_PRIVATE_DATA *Private
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Private - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ UINT32 Color;
+
+ Color = 0;
+ Private->PciIo->Mem.Write (
+ Private->PciIo,
+ EfiPciIoWidthFillUint32,
+ 0,
+ 0,
+ 0x100000 >> 2,
+ &Color
+ );
+}
+
+VOID
+DrawLogo (
+ CIRRUS_LOGIC_5430_PRIVATE_DATA *Private
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Private - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ UINTN Offset;
+ UINTN X;
+ UINTN Y;
+ UINTN ScreenWidth;
+ UINTN ScreenHeight;
+ UINT8 Color;
+
+ ScreenWidth = Private->ModeData[Private->CurrentMode].HorizontalResolution;
+ ScreenHeight = Private->ModeData[Private->CurrentMode].VerticalResolution;
+
+ Offset = 0;
+ for (Y = 0; Y < ScreenHeight; Y++) {
+ for (X = 0; X < ScreenWidth; X++) {
+ Color = (UINT8) (256 * (X + Y) / (ScreenWidth + ScreenHeight));
+ Private->LineBuffer[X] = Color;
+ }
+
+ Private->PciIo->Mem.Write (
+ Private->PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ Offset + (Y * ScreenWidth),
+ ScreenWidth >> 2,
+ Private->LineBuffer
+ );
+ }
+}
+
+VOID
+InitializeGraphicsMode (
+ CIRRUS_LOGIC_5430_PRIVATE_DATA *Private,
+ CIRRUS_LOGIC_5430_VIDEO_MODES *ModeData
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Private - TODO: add argument description
+ ModeData - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ UINT8 Byte;
+ UINTN Index;
+
+ outw (Private, SEQ_ADDRESS_REGISTER, 0x1206);
+ outw (Private, SEQ_ADDRESS_REGISTER, 0x0012);
+
+ for (Index = 0; Index < 15; Index++) {
+ outw (Private, SEQ_ADDRESS_REGISTER, ModeData->SeqSettings[Index]);
+ }
+
+ outb (Private, SEQ_ADDRESS_REGISTER, 0x0f);
+ Byte = (UINT8) ((inb (Private, SEQ_DATA_REGISTER) & 0xc7) ^ 0x30);
+ outb (Private, SEQ_DATA_REGISTER, Byte);
+
+ outb (Private, MISC_OUTPUT_REGISTER, ModeData->MiscSetting);
+ outw (Private, GRAPH_ADDRESS_REGISTER, 0x0506);
+ outw (Private, SEQ_ADDRESS_REGISTER, 0x0300);
+ outw (Private, CRTC_ADDRESS_REGISTER, 0x2011);
+
+ for (Index = 0; Index < 28; Index++) {
+ outw (Private, CRTC_ADDRESS_REGISTER, (UINT16) ((ModeData->CrtcSettings[Index] << 8) | Index));
+ }
+
+ for (Index = 0; Index < 9; Index++) {
+ outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((GraphicsController[Index] << 8) | Index));
+ }
+
+ inb (Private, INPUT_STATUS_1_REGISTER);
+
+ for (Index = 0; Index < 21; Index++) {
+ outb (Private, ATT_ADDRESS_REGISTER, (UINT8) Index);
+ outb (Private, ATT_ADDRESS_REGISTER, AttributeController[Index]);
+ }
+
+ outb (Private, ATT_ADDRESS_REGISTER, 0x20);
+
+ outw (Private, GRAPH_ADDRESS_REGISTER, 0x0009);
+ outw (Private, GRAPH_ADDRESS_REGISTER, 0x000a);
+ outw (Private, GRAPH_ADDRESS_REGISTER, 0x000b);
+ outb (Private, DAC_PIXEL_MASK_REGISTER, 0xff);
+
+ SetDefaultPalette (Private);
+ ClearScreen (Private);
+}
diff --git a/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/ComponentName.c b/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/ComponentName.c
new file mode 100644
index 0000000..5c10b6d
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/ComponentName.c
@@ -0,0 +1,222 @@
+/*++
+
+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:
+
+ ComponentName.c
+
+Abstract:
+
+--*/
+
+#include "CirrusLogic5430.h"
+
+//
+// EFI Component Name Functions
+//
+EFI_STATUS
+EFIAPI
+CirrusLogic5430ComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+EFI_STATUS
+EFIAPI
+CirrusLogic5430ComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+//
+// EFI Component Name Protocol
+//
+EFI_COMPONENT_NAME_PROTOCOL gCirrusLogic5430ComponentName = {
+ CirrusLogic5430ComponentNameGetDriverName,
+ CirrusLogic5430ComponentNameGetControllerName,
+ "eng"
+};
+
+static EFI_UNICODE_STRING_TABLE mCirrusLogic5430DriverNameTable[] = {
+ { "eng", (CHAR16 *) L"Cirrus Logic 5430 UGA Driver" },
+ { NULL , NULL }
+};
+
+static EFI_UNICODE_STRING_TABLE mCirrusLogic5430ControllerNameTable[] = {
+ { "eng", (CHAR16 *) L"Cirrus Logic 5430 PCI Adapter" },
+ { NULL , NULL }
+};
+
+EFI_STATUS
+EFIAPI
+CirrusLogic5430ComponentNameGetDriverName (
+ 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,
+ gCirrusLogic5430ComponentName.SupportedLanguages,
+ mCirrusLogic5430DriverNameTable,
+ DriverName
+ );
+}
+
+EFI_STATUS
+EFIAPI
+CirrusLogic5430ComponentNameGetControllerName (
+ 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_UGA_DRAW_PROTOCOL *UgaDraw;
+ EFI_STATUS Status;
+ CIRRUS_LOGIC_5430_PRIVATE_DATA *Private;
+ EFI_PCI_IO_PROTOCOL *PciIoProtocol;
+
+ //
+ // This is a device driver, so ChildHandle must be NULL.
+ //
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Check Controller's handle
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIoProtocol,
+ gCirrusLogic5430DriverBinding.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (!EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiPciIoProtocolGuid,
+ gCirrusLogic5430DriverBinding.DriverBindingHandle,
+ ControllerHandle
+ );
+
+ return EFI_UNSUPPORTED;
+ }
+
+ if (Status != EFI_ALREADY_STARTED) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get the UGA Draw Protocol on Controller
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiUgaDrawProtocolGuid,
+ (VOID **) &UgaDraw,
+ gCirrusLogic5430DriverBinding.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get the Cirrus Logic 5430's Device structure
+ //
+ Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_UGA_DRAW_THIS (UgaDraw);
+
+ return LookupUnicodeString (
+ Language,
+ gCirrusLogic5430ComponentName.SupportedLanguages,
+ mCirrusLogic5430ControllerNameTable,
+ ControllerName
+ );
+}
diff --git a/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/build.xml b/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/build.xml
new file mode 100644
index 0000000..c8e44b1
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/build.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- 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.-->
+<project basedir="." default="CirrusLogic5430UgaDraw"><!--Apply external ANT tasks-->
+ <taskdef resource="GenBuild.tasks"/>
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+ <property environment="env"/>
+ <property name="WORKSPACE_DIR" value="${env.WORKSPACE}"/>
+ <import file="${WORKSPACE_DIR}\Tools\Conf\BuildMacro.xml"/><!--MODULE_RELATIVE PATH is relative to PACKAGE_DIR-->
+ <property name="MODULE_RELATIVE_PATH" value="Bus\Pci\CirrusLogic\Dxe"/>
+ <property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
+ <property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
+ <target name="CirrusLogic5430UgaDraw">
+ <GenBuild baseName="CirrusLogic5430UgaDraw" mbdFilename="${MODULE_DIR}\CirrusLogic5430.mbd" msaFilename="${MODULE_DIR}\CirrusLogic5430.msa"/>
+ </target>
+ <target depends="CirrusLogic5430UgaDraw_clean" name="clean"/>
+ <target depends="CirrusLogic5430UgaDraw_cleanall" name="cleanall"/>
+ <target name="CirrusLogic5430UgaDraw_clean">
+ <OutputDirSetup baseName="CirrusLogic5430UgaDraw" mbdFilename="${MODULE_DIR}\CirrusLogic5430.mbd" msaFilename="${MODULE_DIR}\CirrusLogic5430.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\CirrusLogic5430UgaDraw_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\CirrusLogic5430UgaDraw_build.xml" target="clean"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
+ </target>
+ <target name="CirrusLogic5430UgaDraw_cleanall">
+ <OutputDirSetup baseName="CirrusLogic5430UgaDraw" mbdFilename="${MODULE_DIR}\CirrusLogic5430.mbd" msaFilename="${MODULE_DIR}\CirrusLogic5430.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\CirrusLogic5430UgaDraw_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\CirrusLogic5430UgaDraw_build.xml" target="cleanall"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}"/>
+ <delete dir="${DEST_DIR_DEBUG}"/>
+ <delete>
+ <fileset dir="${BIN_DIR}" includes="**CirrusLogic5430UgaDraw*"/>
+ </delete>
+ </target>
+</project> \ No newline at end of file
diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ComponentName.c b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ComponentName.c
new file mode 100644
index 0000000..8008527
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ComponentName.c
@@ -0,0 +1,224 @@
+/*++
+
+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:
+
+ ComponentName.c
+
+Abstract:
+
+--*/
+
+#include "IDEBus.h"
+
+//
+// EFI Component Name Protocol
+//
+EFI_COMPONENT_NAME_PROTOCOL gIDEBusComponentName = {
+ IDEBusComponentNameGetDriverName,
+ IDEBusComponentNameGetControllerName,
+ "eng"
+};
+
+STATIC EFI_UNICODE_STRING_TABLE mIDEBusDriverNameTable[] = {
+ { "eng", (CHAR16 *) L"PCI IDE/ATAPI Bus Driver" },
+ { NULL , NULL }
+};
+
+STATIC EFI_UNICODE_STRING_TABLE mIDEBusControllerNameTable[] = {
+ { "eng", (CHAR16 *) L"PCI IDE/ATAPI Controller" },
+ { NULL , NULL }
+};
+
+EFI_STATUS
+EFIAPI
+IDEBusComponentNameGetDriverName (
+ 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,
+ gIDEBusComponentName.SupportedLanguages,
+ mIDEBusDriverNameTable,
+ DriverName
+ );
+}
+
+EFI_STATUS
+EFIAPI
+IDEBusComponentNameGetControllerName (
+ 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 *BlockIo;
+ IDE_BLK_IO_DEV *IdeBlkIoDevice;
+
+ //
+ // Get the controller context
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiCallerIdGuid,
+ NULL,
+ gIDEBusDriverBinding.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (ChildHandle == NULL) {
+ return LookupUnicodeString (
+ Language,
+ gIDEBusComponentName.SupportedLanguages,
+ mIDEBusControllerNameTable,
+ ControllerName
+ );
+ }
+
+ //
+ // Get the child context
+ //
+ Status = gBS->OpenProtocol (
+ ChildHandle,
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlockIo,
+ gIDEBusDriverBinding.DriverBindingHandle,
+ ChildHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (BlockIo);
+
+ return LookupUnicodeString (
+ Language,
+ gIDEBusComponentName.SupportedLanguages,
+ IdeBlkIoDevice->ControllerNameTable,
+ ControllerName
+ );
+}
+
+VOID
+AddName (
+ IN IDE_BLK_IO_DEV *IdeBlkIoDevicePtr
+ )
+/*++
+
+ Routine Description:
+ Add the component name for the IDE/ATAPI device
+
+ Arguments:
+ IdeBlkIoDevicePtr - A pointer to the IDE_BLK_IO_DEV instance.
+
+ Returns:
+
+--*/
+{
+ UINTN StringIndex;
+ CHAR16 ModelName[41];
+
+ //
+ // Add Component Name for the IDE/ATAPI device that was discovered.
+ //
+ IdeBlkIoDevicePtr->ControllerNameTable = NULL;
+ for (StringIndex = 0; StringIndex < 41; StringIndex++) {
+ ModelName[StringIndex] = IdeBlkIoDevicePtr->ModelName[StringIndex];
+ }
+
+ AddUnicodeString (
+ "eng",
+ gIDEBusComponentName.SupportedLanguages,
+ &IdeBlkIoDevicePtr->ControllerNameTable,
+ ModelName
+ );
+}
diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ComponentName.h b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ComponentName.h
new file mode 100644
index 0000000..f6c3feb
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ComponentName.h
@@ -0,0 +1,118 @@
+/*++
+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:
+
+ ComponentName.h
+
+Abstract:
+
+
+Revision History
+--*/
+
+#ifndef _IDE_BUS_COMPONENT_NAME_H
+#define _IDE_BUS_COMPONENT_NAME_H
+
+
+#ifndef EFI_SIZE_REDUCTION_APPLIED
+
+#define ADD_NAME(x) AddName ((x));
+
+extern EFI_COMPONENT_NAME_PROTOCOL gIDEBusComponentName;
+
+#else
+
+#define ADD_NAME(x)
+
+#endif
+
+
+//
+// EFI Component Name Functions
+//
+EFI_STATUS
+EFIAPI
+IDEBusComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Language - TODO: add argument description
+ DriverName - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+IDEBusComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ ControllerHandle - TODO: add argument description
+ ChildHandle - TODO: add argument description
+ Language - TODO: add argument description
+ ControllerName - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+VOID
+AddName (
+ IN IDE_BLK_IO_DEV *IdeBlkIoDevicePtr
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeBlkIoDevicePtr - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/DriverConfiguration.c b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/DriverConfiguration.c
new file mode 100644
index 0000000..b8f71fd
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/DriverConfiguration.c
@@ -0,0 +1,378 @@
+/*++
+
+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:
+
+ DriverConfiguration.c
+
+Abstract:
+
+--*/
+
+#include "IDEBus.h"
+
+CHAR16 *OptionString[4] = {
+ L"Enable Primary Master (Y/N)? -->",
+ L"Enable Primary Slave (Y/N)? -->",
+ L"Enable Secondary Master (Y/N)? -->",
+ L"Enable Secondary Slave (Y/N)? -->"
+};
+//
+// EFI Driver Configuration Functions
+//
+EFI_STATUS
+IDEBusDriverConfigurationSetOptions (
+ IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired
+ );
+
+EFI_STATUS
+IDEBusDriverConfigurationOptionsValid (
+ IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL
+ );
+
+EFI_STATUS
+IDEBusDriverConfigurationForceDefaults (
+ IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN UINT32 DefaultType,
+ OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired
+ );
+
+//
+// EFI Driver Configuration Protocol
+//
+EFI_DRIVER_CONFIGURATION_PROTOCOL gIDEBusDriverConfiguration = {
+ IDEBusDriverConfigurationSetOptions,
+ IDEBusDriverConfigurationOptionsValid,
+ IDEBusDriverConfigurationForceDefaults,
+ "eng"
+};
+
+EFI_STATUS
+GetResponse (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_ABORTED - TODO: Add description for return value
+ EFI_SUCCESS - TODO: Add description for return value
+ EFI_NOT_FOUND - TODO: Add description for return value
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_INPUT_KEY Key;
+
+ while (TRUE) {
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ if (!EFI_ERROR (Status)) {
+ if (Key.ScanCode == SCAN_ESC) {
+ return EFI_ABORTED;
+ }
+
+ switch (Key.UnicodeChar) {
+
+ //
+ // fall through
+ //
+ case L'y':
+ case L'Y':
+ gST->ConOut->OutputString (gST->ConOut, L"Y\n");
+ return EFI_SUCCESS;
+
+ //
+ // fall through
+ //
+ case L'n':
+ case L'N':
+ gST->ConOut->OutputString (gST->ConOut, L"N\n");
+ return EFI_NOT_FOUND;
+ }
+
+ }
+ }
+}
+
+EFI_STATUS
+IDEBusDriverConfigurationSetOptions (
+ IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired
+ )
+/*++
+
+ Routine Description:
+ Allows the user to set controller specific options for a controller that a
+ driver is currently managing.
+
+ Arguments:
+ This - A pointer to the EFI_DRIVER_CONFIGURATION_ PROTOCOL
+ instance.
+ ControllerHandle - The handle of the controller to set options on.
+ ChildHandle - The handle of the child controller to set options on.
+ This is an optional parameter that may be NULL.
+ It will be NULL for device drivers, and for a bus drivers
+ that wish to set options for the bus controller.
+ It will not be NULL for a bus driver that wishes to set
+ options for one of its child controllers.
+ Language - A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the user interface
+ that should be presented to the user, 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.
+ ActionRequired - A pointer to the action that the calling agent is
+ required to perform when this function returns.
+ See "Related Definitions" for a list of the actions that
+ the calling agent is required to perform prior to
+ accessing ControllerHandle again.
+
+ Returns:
+ EFI_SUCCESS - The driver specified by This successfully set the
+ configuration options for the controller specified
+ by ControllerHandle..
+ 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 - ActionRequired is NULL.
+ EFI_UNSUPPORTED - The driver specified by This does not support
+ setting configuration options for the controller
+ specified by ControllerHandle and ChildHandle.
+ EFI_UNSUPPORTED - The driver specified by This does not support the
+ language specified by Language.
+ EFI_DEVICE_ERROR - A device error occurred while attempt to set the
+ configuration options for the controller specified
+ by ControllerHandle and ChildHandle.
+ EFI_OUT_RESOURCES - There are not enough resources available to set the
+ configuration options for the controller specified
+ by ControllerHandle and ChildHandle.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT8 Value;
+ UINT8 NewValue;
+ UINTN DataSize;
+ UINTN Index;
+ UINT32 Attributes;
+
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ *ActionRequired = EfiDriverConfigurationActionNone;
+
+ DataSize = sizeof (Value);
+ Status = gRT->GetVariable (
+ L"Configuration",
+ &gEfiCallerIdGuid,
+ &Attributes,
+ &DataSize,
+ &Value
+ );
+
+ gST->ConOut->OutputString (gST->ConOut, L"IDE Bus Driver Configuration\n");
+ gST->ConOut->OutputString (gST->ConOut, L"===============================\n");
+
+ NewValue = 0;
+ for (Index = 0; Index < 4; Index++) {
+ gST->ConOut->OutputString (gST->ConOut, OptionString[Index]);
+
+ Status = GetResponse ();
+ if (Status == EFI_ABORTED) {
+ return EFI_SUCCESS;
+ }
+
+ if (!EFI_ERROR (Status)) {
+ NewValue |= (UINT8) (1 << Index);
+ }
+ }
+
+ if (EFI_ERROR (Status) || (NewValue != Value)) {
+ gRT->SetVariable (
+ L"Configuration",
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ sizeof (NewValue),
+ &NewValue
+ );
+
+ *ActionRequired = EfiDriverConfigurationActionRestartController;
+ } else {
+ *ActionRequired = EfiDriverConfigurationActionNone;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+IDEBusDriverConfigurationOptionsValid (
+ IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL
+ )
+/*++
+
+ Routine Description:
+ Tests to see if a controller's current configuration options are valid.
+
+ Arguments:
+ This - A pointer to the EFI_DRIVER_CONFIGURATION_PROTOCOL
+ instance.
+ ControllerHandle - The handle of the controller to test if it's current
+ configuration options are valid.
+ ChildHandle - The handle of the child controller to test if it's
+ current
+ configuration options are valid. 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 test the configuration options for the bus
+ controller. It will not be NULL for a bus driver that
+ wishes to test configuration options for one of
+ its child controllers.
+
+ Returns:
+ EFI_SUCCESS - The controller specified by ControllerHandle and
+ ChildHandle that is being managed by the driver
+ specified by This has a valid set of configuration
+ options.
+ 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_UNSUPPORTED - The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+ EFI_DEVICE_ERROR - The controller specified by ControllerHandle and
+ ChildHandle that is being managed by the driver
+ specified by This has an invalid set of
+ configuration options.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT8 Value;
+ UINTN DataSize;
+ UINT32 Attributes;
+
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ DataSize = sizeof (Value);
+ Status = gRT->GetVariable (
+ L"Configuration",
+ &gEfiCallerIdGuid,
+ &Attributes,
+ &DataSize,
+ &Value
+ );
+ if (EFI_ERROR (Status) || Value > 0x0f) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+IDEBusDriverConfigurationForceDefaults (
+ IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN UINT32 DefaultType,
+ OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired
+ )
+/*++
+
+ Routine Description:
+ Forces a driver to set the default configuration options for a controller.
+
+ Arguments:
+ This - A pointer to the EFI_DRIVER_CONFIGURATION_ PROTOCOL
+ instance.
+ ControllerHandle - The handle of the controller to force default
+ configuration options on.
+ ChildHandle - The handle of the child controller to force default
+ configuration options on 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
+ force default configuration options for the bus
+ controller. It will not be NULL for a bus driver that
+ wishes to force default configuration options for one
+ of its child controllers.
+ DefaultType - The type of default configuration options to force on
+ the controller specified by ControllerHandle and
+ ChildHandle. See Table 9-1 for legal values.
+ A DefaultType of 0x00000000 must be supported
+ by this protocol.
+ ActionRequired - A pointer to the action that the calling agent
+ is required to perform when this function returns.
+
+
+ Returns:
+ EFI_SUCCESS - The driver specified by This successfully forced
+ the default configuration options on the
+ controller specified by ControllerHandle and
+ ChildHandle.
+ 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 - ActionRequired is NULL.
+ EFI_UNSUPPORTED - The driver specified by This does not support
+ forcing the default configuration options on
+ the controller specified by ControllerHandle
+ and ChildHandle.
+ EFI_UNSUPPORTED - The driver specified by This does not support
+ the configuration type specified by DefaultType.
+ EFI_DEVICE_ERROR - A device error occurred while attempt to force
+ the default configuration options on the controller
+ specified by ControllerHandle and ChildHandle.
+ EFI_OUT_RESOURCES - There are not enough resources available to force
+ the default configuration options on the controller
+ specified by ControllerHandle and ChildHandle.
+
+--*/
+{
+ UINT8 Value;
+
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Value = 0x0f;
+ gRT->SetVariable (
+ L"Configuration",
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ sizeof (Value),
+ &Value
+ );
+ *ActionRequired = EfiDriverConfigurationActionRestartController;
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/DriverDiagnostics.c b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/DriverDiagnostics.c
new file mode 100644
index 0000000..ce3be14
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/DriverDiagnostics.c
@@ -0,0 +1,225 @@
+/*++
+
+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:
+
+ DriverDiagnostics.c
+
+Abstract:
+
+--*/
+
+#include "IDEBus.h"
+
+#define IDE_BUS_DIAGNOSTIC_ERROR L"PCI IDE/ATAPI Driver Diagnostics Failed"
+
+//
+// EFI Driver Diagnostics Functions
+//
+EFI_STATUS
+IDEBusDriverDiagnosticsRunDiagnostics (
+ IN EFI_DRIVER_DIAGNOSTICS_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN EFI_DRIVER_DIAGNOSTIC_TYPE DiagnosticType,
+ IN CHAR8 *Language,
+ OUT EFI_GUID **ErrorType,
+ OUT UINTN *BufferSize,
+ OUT CHAR16 **Buffer
+ );
+
+//
+// EFI Driver Diagnostics Protocol
+//
+EFI_DRIVER_DIAGNOSTICS_PROTOCOL gIDEBusDriverDiagnostics = {
+ IDEBusDriverDiagnosticsRunDiagnostics,
+ "eng"
+};
+
+EFI_STATUS
+IDEBusDriverDiagnosticsRunDiagnostics (
+ IN EFI_DRIVER_DIAGNOSTICS_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN EFI_DRIVER_DIAGNOSTIC_TYPE DiagnosticType,
+ IN CHAR8 *Language,
+ OUT EFI_GUID **ErrorType,
+ OUT UINTN *BufferSize,
+ OUT CHAR16 **Buffer
+ )
+/*++
+
+ Routine Description:
+ Runs diagnostics on a controller.
+
+ Arguments:
+ This - A pointer to the EFI_DRIVER_DIAGNOSTICS_PROTOCOL
+ instance.
+ ControllerHandle - The handle of the controller to run diagnostics on.
+ ChildHandle - The handle of the child controller to run diagnostics on
+ 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 run diagnostics on the bus
+ controller. It will not be NULL for a bus driver that
+ wishes to run diagnostics on one of its child
+ controllers.
+ DiagnosticType - Indicates type of diagnostics to perform on the
+ controller specified by ControllerHandle and ChildHandle.
+ See "Related Definitions" for the list of supported
+ types.
+ Language - A pointer to a three character ISO 639-2 language
+ identifier. This is the language in which the optional
+ error message should be returned in Buffer, 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.
+ ErrorType - A GUID that defines the format of the data returned in
+ Buffer.
+ BufferSize - The size, in bytes, of the data returned in Buffer.
+ Buffer - A buffer that contains a Null-terminated Unicode string
+ plus some additional data whose format is defined by
+ ErrorType. Buffer is allocated by this function with
+ AllocatePool(), and it is the caller's responsibility
+ to free it with a call to FreePool().
+
+ Returns:
+ EFI_SUCCESS - The controller specified by ControllerHandle and
+ ChildHandle passed the diagnostic.
+ 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 - ErrorType is NULL.
+ EFI_INVALID_PARAMETER - BufferType is NULL.
+ EFI_INVALID_PARAMETER - Buffer is NULL.
+ EFI_UNSUPPORTED - The driver specified by This does not support
+ running diagnostics for the controller specified
+ by ControllerHandle and ChildHandle.
+ EFI_UNSUPPORTED - The driver specified by This does not support the
+ type of diagnostic specified by DiagnosticType.
+ EFI_UNSUPPORTED - The driver specified by This does not support the
+ language specified by Language.
+ EFI_OUT_OF_RESOURCES - There are not enough resources available to complete
+ the diagnostics.
+ EFI_OUT_OF_RESOURCES - There are not enough resources available to return
+ the status information in ErrorType, BufferSize,
+ and Buffer.
+ EFI_DEVICE_ERROR - The controller specified by ControllerHandle and
+ ChildHandle did not pass the diagnostic.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;
+ IDE_BLK_IO_DEV *IdeBlkIoDevice;
+ UINT32 VendorDeviceId;
+ VOID *BlockBuffer;
+
+ *ErrorType = NULL;
+ *BufferSize = 0;
+
+ if (ChildHandle == NULL) {
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiCallerIdGuid,
+ NULL,
+ gIDEBusDriverBinding.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ gIDEBusDriverBinding.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Use services of PCI I/O Protocol to test the PCI IDE/ATAPI Controller
+ // The following test simply reads the Device ID and Vendor ID.
+ // It should never fail. A real test would perform more advanced
+ // diagnostics.
+ //
+
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, 1, &VendorDeviceId);
+ if (EFI_ERROR (Status) || VendorDeviceId == 0xffffffff) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ Status = gBS->OpenProtocol (
+ ChildHandle,
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlkIo,
+ gIDEBusDriverBinding.DriverBindingHandle,
+ ChildHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo);
+
+ //
+ // Use services available from IdeBlkIoDevice to test the IDE/ATAPI device
+ //
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ IdeBlkIoDevice->BlkMedia.BlockSize,
+ (VOID **) &BlockBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = IdeBlkIoDevice->BlkIo.ReadBlocks (
+ &IdeBlkIoDevice->BlkIo,
+ IdeBlkIoDevice->BlkMedia.MediaId,
+ 0,
+ IdeBlkIoDevice->BlkMedia.BlockSize,
+ BlockBuffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ *ErrorType = &gEfiCallerIdGuid;
+ *BufferSize = sizeof (IDE_BUS_DIAGNOSTIC_ERROR);
+
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ (UINTN) (*BufferSize),
+ (VOID **) Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ EfiCopyMem (*Buffer, IDE_BUS_DIAGNOSTIC_ERROR, *BufferSize);
+
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ gBS->FreePool (BlockBuffer);
+
+ return Status;
+}
diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ata.c b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ata.c
new file mode 100644
index 0000000..88e81c0
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ata.c
@@ -0,0 +1,3690 @@
+/*++
+
+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:
+
+ ata.c
+
+Abstract:
+
+Revision History
+
+ 2002-6: Add Atapi6 enhancement, support >120GB hard disk, including
+ update - ATAIdentity() func
+ update - AtaBlockIoReadBlocks() func
+ update - AtaBlockIoWriteBlocks() func
+ add - AtaAtapi6Identify() func
+ add - AtaReadSectorsExt() func
+ add - AtaWriteSectorsExt() func
+ add - AtaPioDataInExt() func
+ add - AtaPioDataOutExt() func
+
+--*/
+
+#include "idebus.h"
+
+
+EFI_STATUS
+AtaReadSectorsExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN OUT VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks
+ );
+
+EFI_STATUS
+AtaWriteSectorsExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks
+ );
+
+EFI_STATUS
+AtaPioDataInExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN OUT VOID *Buffer,
+ IN UINT32 ByteCount,
+ IN UINT8 AtaCommand,
+ IN EFI_LBA StartLba,
+ IN UINT16 SectorCount
+ );
+
+EFI_STATUS
+AtaPioDataOutExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *Buffer,
+ IN UINT32 ByteCount,
+ IN UINT8 AtaCommand,
+ IN EFI_LBA StartLba,
+ IN UINT16 SectorCount
+ );
+
+EFI_STATUS
+ATAIdentify (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+ Name:
+ ATAIdentify
+
+
+ Purpose:
+ This function is called by DiscoverIdeDevice() during its device
+ identification. It sends out the ATA Identify Command to the
+ specified device. Only ATA device responses to this command. If
+ the command succeeds, it returns the Identify data structure which
+ contains information about the device. This function extracts the
+ information it needs to fill the IDE_BLK_IO_DEV data structure,
+ including device type, media block size, media capacity, and etc.
+
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure,used
+ to record all the information of the IDE device.
+
+
+ Returns:
+ EFI_SUCCESS
+ Identify ATA device successfully.
+
+ EFI_DEVICE_ERROR
+ ATA Identify Device Command failed or device is not
+ ATA device.
+
+
+ Notes:
+ parameter IdeDev will be updated in this function.
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ EFI_IDENTIFY_DATA *AtaIdentifyPointer;
+ UINT32 Capacity;
+ UINT8 DeviceSelect;
+
+ //
+ // AtaIdentifyPointer is used for accommodating returned IDENTIFY data of
+ // the ATA Identify command
+ //
+ AtaIdentifyPointer = (EFI_IDENTIFY_DATA *) AllocateZeroPool (sizeof (EFI_IDENTIFY_DATA));
+
+ //
+ // use ATA PIO Data In protocol to send ATA Identify command
+ // and receive data from device
+ //
+ DeviceSelect = 0;
+ DeviceSelect = (UINT8) ((IdeDev->Device) << 4);
+ Status = AtaPioDataIn (
+ IdeDev,
+ (VOID *) AtaIdentifyPointer,
+ sizeof (EFI_IDENTIFY_DATA),
+ IDENTIFY_DRIVE_CMD,
+ DeviceSelect,
+ 0,
+ 0,
+ 0,
+ 0
+ );
+ //
+ // If ATA Identify command succeeds, then according to the received
+ // IDENTIFY data,
+ // identify the device type ( ATA or not ).
+ // If ATA device, fill the information in IdeDev.
+ // If not ATA device, return IDE_DEVICE_ERROR
+ //
+ if (!EFI_ERROR (Status)) {
+
+ IdeDev->pIdData = AtaIdentifyPointer;
+
+ //
+ // Print ATA Module Name
+ //
+ PrintAtaModuleName (IdeDev);
+
+ //
+ // bit 15 of pAtaIdentify->config is used to identify whether device is
+ // ATA device or ATAPI device.
+ // if 0, means ATA device; if 1, means ATAPI device.
+ //
+ if ((AtaIdentifyPointer->AtaData.config & 0x8000) == 0x00) {
+ //
+ // Detect if support S.M.A.R.T. If yes, enable it as default
+ //
+ AtaSMARTSupport (IdeDev);
+
+ //
+ // Check whether this device needs 48-bit addressing (ATAPI-6 ata device)
+ //
+ Status = AtaAtapi6Identify (IdeDev);
+ if (!EFI_ERROR (Status)) {
+ //
+ // It's a disk with >120GB capacity, initialized in AtaAtapi6Identify()
+ //
+ return EFI_SUCCESS;
+ }
+ //
+ // This is a hard disk <= 120GB capacity, treat it as normal hard disk
+ //
+ IdeDev->Type = IdeHardDisk;
+
+ //
+ // Block Media Information:
+ // Media->LogicalPartition , Media->WriteCaching will be filled
+ // in the DiscoverIdeDevcie() function.
+ //
+ IdeDev->BlkIo.Media->IoAlign = 4;
+ IdeDev->BlkIo.Media->MediaId = 1;
+ IdeDev->BlkIo.Media->RemovableMedia = FALSE;
+ IdeDev->BlkIo.Media->MediaPresent = TRUE;
+ IdeDev->BlkIo.Media->ReadOnly = FALSE;
+ IdeDev->BlkIo.Media->BlockSize = 0x200;
+
+ //
+ // Calculate device capacity
+ //
+ Capacity = ((UINT32)AtaIdentifyPointer->AtaData.user_addressable_sectors_hi << 16) |
+ AtaIdentifyPointer->AtaData.user_addressable_sectors_lo ;
+ IdeDev->BlkIo.Media->LastBlock = Capacity - 1;
+
+ return EFI_SUCCESS;
+
+ }
+ }
+
+ gBS->FreePool (AtaIdentifyPointer);
+ //
+ // Make sure the pIdData will not be freed again.
+ //
+ IdeDev->pIdData = NULL;
+
+ return EFI_DEVICE_ERROR;
+}
+
+
+EFI_STATUS
+AtaAtapi6Identify (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+ Name:
+
+ AtaAtapi6Identify
+
+ Purpose:
+
+ This function is called by ATAIdentify() to identity whether this disk
+ supports ATA/ATAPI6 48bit addressing, ie support >120G capacity
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ Returns:
+
+ EFI_SUCCESS - The disk specified by IdeDev is a Atapi6 supported one
+ and 48-bit addressing must be used
+
+ EFI_UNSUPPORTED - The disk dosn't not support Atapi6 or it supports but
+ the capacity is below 120G, 48bit addressing is not
+ needed
+
+ Notes:
+
+ This function must be called after DEVICE_IDENTITY command has been
+ successfully returned
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+{
+ UINT8 Index;
+ EFI_LBA TmpLba;
+ EFI_LBA Capacity;
+ EFI_IDENTIFY_DATA *Atapi6IdentifyStruct;
+
+ if (IdeDev->pIdData == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Atapi6IdentifyStruct = IdeDev->pIdData;
+
+ if ((Atapi6IdentifyStruct->AtapiData.cmd_set_support_83 & bit10) == 0) {
+ //
+ // The device dosn't support 48 bit addressing
+ //
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // 48 bit address feature set is supported, get maximum capacity
+ //
+ Capacity = Atapi6IdentifyStruct->AtapiData.max_user_lba_for_48bit_addr[0];
+ for (Index = 1; Index < 4; Index++) {
+ //
+ // Lower byte goes first: word[100] is the lowest word, word[103] is highest
+ //
+ TmpLba = Atapi6IdentifyStruct->AtapiData.max_user_lba_for_48bit_addr[Index];
+ Capacity |= LShiftU64 (TmpLba, 16 * Index);
+ }
+
+ if (Capacity > MAX_28BIT_ADDRESSING_CAPACITY) {
+ //
+ // Capacity exceeds 120GB. 48-bit addressing is really needed
+ //
+ IdeDev->Type = Ide48bitAddressingHardDisk;
+
+ //
+ // Fill block media information:Media->LogicalPartition ,
+ // Media->WriteCaching will be filledin the DiscoverIdeDevcie() function.
+ //
+ IdeDev->BlkIo.Media->IoAlign = 4;
+ IdeDev->BlkIo.Media->MediaId = 1;
+ IdeDev->BlkIo.Media->RemovableMedia = FALSE;
+ IdeDev->BlkIo.Media->MediaPresent = TRUE;
+ IdeDev->BlkIo.Media->ReadOnly = FALSE;
+ IdeDev->BlkIo.Media->BlockSize = 0x200;
+ IdeDev->BlkIo.Media->LastBlock = Capacity - 1;
+
+ return EFI_SUCCESS;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+VOID
+PrintAtaModuleName (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+ Name:
+ PrintAtaModuleName
+
+
+ Purpose:
+ This function is called by ATAIdentify() or ATAPIIdentify()
+ to print device's module name.
+
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ Returns:
+ no returns.
+
+ Notes:
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+{
+ if (IdeDev->pIdData == NULL) {
+ return ;
+ }
+
+ SwapStringChars (IdeDev->ModelName, IdeDev->pIdData->AtaData.ModelName, 40);
+ IdeDev->ModelName[40] = 0x00;
+}
+
+EFI_STATUS
+AtaPioDataIn (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *Buffer,
+ IN UINT32 ByteCount,
+ IN UINT8 AtaCommand,
+ IN UINT8 Head,
+ IN UINT8 SectorCount,
+ IN UINT8 SectorNumber,
+ IN UINT8 CylinderLsb,
+ IN UINT8 CylinderMsb
+ )
+/*++
+ Name:
+ AtaPioDataIn
+
+
+ Purpose:
+ This function is used to send out ATA commands conforms to the
+ PIO Data In Protocol.
+
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ VOID IN *Buffer
+ buffer contained data transferred from device to host.
+
+ UINT32 IN ByteCount
+ data size in byte unit of the buffer.
+
+ UINT8 IN AtaCommand
+ value of the Command Register
+
+ UINT8 IN Head
+ value of the Head/Device Register
+
+ UINT8 IN SectorCount
+ value of the Sector Count Register
+
+ UINT8 IN SectorNumber
+ value of the Sector Number Register
+
+ UINT8 IN CylinderLsb
+ value of the low byte of the Cylinder Register
+
+ UINT8 IN CylinderMsb
+ value of the high byte of the Cylinder Register
+
+
+ Returns:
+ EFI_SUCCESS
+ send out the ATA command and device send required
+ data successfully.
+
+ EFI_DEVICE_ERROR
+ command sent failed.
+ Notes:
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: Buffer - add argument and description to function comment
+// TODO: ByteCount - add argument and description to function comment
+// TODO: AtaCommand - add argument and description to function comment
+// TODO: Head - add argument and description to function comment
+// TODO: SectorCount - add argument and description to function comment
+// TODO: SectorNumber - add argument and description to function comment
+// TODO: CylinderLsb - add argument and description to function comment
+// TODO: CylinderMsb - add argument and description to function comment
+{
+ UINTN WordCount;
+ UINTN Increment;
+ UINT16 *Buffer16;
+ EFI_STATUS Status;
+
+ Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // e0:1110,0000-- bit7 and bit5 are reserved bits.
+ // bit6 set means LBA mode
+ //
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ (UINT8) ((IdeDev->Device << 4) | 0xe0 | Head)
+ );
+
+ //
+ // All ATAPI device's ATA commands can be issued regardless of the
+ // state of the DRDY
+ //
+ if (IdeDev->Type == IdeHardDisk) {
+
+ Status = DRDYReady (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ //
+ // set all the command parameters
+ // Before write to all the following registers, BSY and DRQ must be 0.
+ //
+ Status = DRQClear2 (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (AtaCommand == SET_FEATURES_CMD) {
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03);
+ }
+
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, SectorNumber);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, CylinderLsb);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, CylinderMsb);
+
+ //
+ // send command via Command Register
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);
+
+ Buffer16 = (UINT16 *) Buffer;
+
+ //
+ // According to PIO data in protocol, host can perform a series of reads to
+ // the data register after each time device set DRQ ready;
+ // The data size of "a series of read" is command specific.
+ // For most ATA command, data size received from device will not exceed
+ // 1 sector, hence the data size for "a series of read" can be the whole data
+ // size of one command request.
+ // For ATA command such as Read Sector command, the data size of one ATA
+ // command request is often larger than 1 sector, according to the
+ // Read Sector command, the data size of "a series of read" is exactly 1
+ // sector.
+ // Here for simplification reason, we specify the data size for
+ // "a series of read" to 1 sector (256 words) if data size of one ATA command
+ // request is larger than 256 words.
+ //
+ Increment = 256;
+
+ //
+ // used to record bytes of currently transfered data
+ //
+ WordCount = 0;
+
+ while (WordCount < ByteCount / 2) {
+ //
+ // Poll DRQ bit set, data transfer can be performed only when DRQ is ready.
+ //
+ Status = DRQReady2 (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = CheckErrorStatus (IdeDev);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Get the byte count for one series of read
+ //
+ if ((WordCount + Increment) > ByteCount / 2) {
+ Increment = ByteCount / 2 - WordCount;
+ }
+
+ IDEReadPortWMultiple (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Data,
+ Increment,
+ Buffer16
+ );
+
+ WordCount += Increment;
+ Buffer16 += Increment;
+
+ }
+
+ DRQClear (IdeDev, ATATIMEOUT);
+
+ return CheckErrorStatus (IdeDev);
+}
+
+EFI_STATUS
+AtaPioDataOut (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *Buffer,
+ IN UINT32 ByteCount,
+ IN UINT8 AtaCommand,
+ IN UINT8 Head,
+ IN UINT8 SectorCount,
+ IN UINT8 SectorNumber,
+ IN UINT8 CylinderLsb,
+ IN UINT8 CylinderMsb
+ )
+/*++
+ Name:
+ AtaPioDataOut
+
+
+ Purpose:
+ This function is used to send out ATA commands conforms to the
+ PIO Data Out Protocol.
+
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ VOID IN *Buffer
+ buffer contained data transferred from host to device.
+
+ UINT32 IN ByteCount
+ data size in byte unit of the buffer.
+
+ UINT8 IN AtaCommand
+ value of the Command Register
+
+ UINT8 IN Head
+ value of the Head/Device Register
+
+ UINT8 IN SectorCount
+ value of the Sector Count Register
+
+ UINT8 IN SectorNumber
+ value of the Sector Number Register
+
+ UINT8 IN CylinderLsb
+ value of the low byte of the Cylinder Register
+
+ UINT8 IN CylinderMsb
+ value of the high byte of the Cylinder Register
+
+
+ Returns:
+ EFI_SUCCESS
+ send out the ATA command and device received required
+ data successfully.
+
+ EFI_DEVICE_ERROR
+ command sent failed.
+
+ Notes:
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: Buffer - add argument and description to function comment
+// TODO: ByteCount - add argument and description to function comment
+// TODO: AtaCommand - add argument and description to function comment
+// TODO: Head - add argument and description to function comment
+// TODO: SectorCount - add argument and description to function comment
+// TODO: SectorNumber - add argument and description to function comment
+// TODO: CylinderLsb - add argument and description to function comment
+// TODO: CylinderMsb - add argument and description to function comment
+{
+ UINTN WordCount;
+ UINTN Increment;
+ UINT16 *Buffer16;
+ EFI_STATUS Status;
+
+ Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // select device via Head/Device register.
+ // Before write Head/Device register, BSY and DRQ must be 0.
+ //
+ Status = DRQClear2 (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // e0:1110,0000-- bit7 and bit5 are reserved bits.
+ // bit6 set means LBA mode
+ //
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ (UINT8) ((IdeDev->Device << 4) | 0xe0 | Head)
+ );
+
+ Status = DRDYReady (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // set all the command parameters
+ // Before write to all the following registers, BSY and DRQ must be 0.
+ //
+ Status = DRQClear2 (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, SectorNumber);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, CylinderLsb);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, CylinderMsb);
+
+ //
+ // send command via Command Register
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);
+
+ Buffer16 = (UINT16 *) Buffer;
+
+ //
+ // According to PIO data out protocol, host can perform a series of
+ // writes to the data register after each time device set DRQ ready;
+ // The data size of "a series of read" is command specific.
+ // For most ATA command, data size written to device will not exceed 1 sector,
+ // hence the data size for "a series of write" can be the data size of one
+ // command request.
+ // For ATA command such as Write Sector command, the data size of one
+ // ATA command request is often larger than 1 sector, according to the
+ // Write Sector command, the data size of "a series of read" is exactly
+ // 1 sector.
+ // Here for simplification reason, we specify the data size for
+ // "a series of write" to 1 sector (256 words) if data size of one ATA command
+ // request is larger than 256 words.
+ //
+ Increment = 256;
+ WordCount = 0;
+
+ while (WordCount < ByteCount / 2) {
+
+ //
+ // DRQReady2-- read Alternate Status Register to determine the DRQ bit
+ // data transfer can be performed only when DRQ is ready.
+ //
+ Status = DRQReady2 (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = CheckErrorStatus (IdeDev);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Check the remaining byte count is less than 512 bytes
+ //
+ if ((WordCount + Increment) > ByteCount / 2) {
+ Increment = ByteCount / 2 - WordCount;
+ }
+ //
+ // perform a series of write without check DRQ ready
+ //
+
+ IDEWritePortWMultiple (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Data,
+ Increment,
+ Buffer16
+ );
+ WordCount += Increment;
+ Buffer16 += Increment;
+
+ }
+
+ DRQClear (IdeDev, ATATIMEOUT);
+
+ return CheckErrorStatus (IdeDev);
+}
+
+EFI_STATUS
+CheckErrorStatus (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+ Name:
+ CheckErrorStatus
+
+
+ Purpose:
+ This function is used to analyze the Status Register and print out
+ some debug information and if there is ERR bit set in the Status
+ Register, the Error Register's value is also be parsed and print out.
+
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ Returns:
+ EFI_SUCCESS
+ No err information in the Status Register.
+
+ EFI_DEVICE_ERROR
+ Any err information in the Status Register.
+
+ Notes:
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+{
+ UINT8 StatusRegister;
+
+//#ifdef EFI_DEBUG
+
+ UINT8 ErrorRegister;
+
+//#endif
+
+ StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
+
+ DEBUG_CODE (
+
+ if (StatusRegister & DWF) {
+ DEBUG (
+ (EFI_D_BLKIO,
+ "CheckErrorStatus()-- %02x : Error : Write Fault\n",
+ StatusRegister)
+ );
+ }
+
+ if (StatusRegister & CORR) {
+ DEBUG (
+ (EFI_D_BLKIO,
+ "CheckErrorStatus()-- %02x : Error : Corrected Data\n",
+ StatusRegister)
+ );
+ }
+
+ if (StatusRegister & ERR) {
+ ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
+
+ if (ErrorRegister & BBK_ERR) {
+ DEBUG (
+ (EFI_D_BLKIO,
+ "CheckErrorStatus()-- %02x : Error : Bad Block Detected\n",
+ ErrorRegister)
+ );
+ }
+
+ if (ErrorRegister & UNC_ERR) {
+ DEBUG (
+ (EFI_D_BLKIO,
+ "CheckErrorStatus()-- %02x : Error : Uncorrectable Data\n",
+ ErrorRegister)
+ );
+ }
+
+ if (ErrorRegister & MC_ERR) {
+ DEBUG (
+ (EFI_D_BLKIO,
+ "CheckErrorStatus()-- %02x : Error : Media Change\n",
+ ErrorRegister)
+ );
+ }
+
+ if (ErrorRegister & ABRT_ERR) {
+ DEBUG (
+ (EFI_D_BLKIO,
+ "CheckErrorStatus()-- %02x : Error : Abort\n",
+ ErrorRegister)
+ );
+ }
+
+ if (ErrorRegister & TK0NF_ERR) {
+ DEBUG (
+ (EFI_D_BLKIO,
+ "CheckErrorStatus()-- %02x : Error : Track 0 Not Found\n",
+ ErrorRegister)
+ );
+ }
+
+ if (ErrorRegister & AMNF_ERR) {
+ DEBUG (
+ (EFI_D_BLKIO,
+ "CheckErrorStatus()-- %02x : Error : Address Mark Not Found\n",
+ ErrorRegister)
+ );
+ }
+
+ }
+ );
+
+ if ((StatusRegister & (ERR | DWF | CORR)) == 0) {
+ return EFI_SUCCESS;
+ }
+
+ return EFI_DEVICE_ERROR;
+
+}
+
+EFI_STATUS
+AtaReadSectors (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA Lba,
+ IN UINTN NumberOfBlocks
+ )
+/*++
+ Name:
+ AtaReadSectors
+
+
+ Purpose:
+ This function is called by the AtaBlkIoReadBlocks() to perform
+ reading from media in block unit.
+
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ VOID IN *DataBuffer
+ A pointer to the destination buffer for the data.
+
+ EFI_LBA IN Lba
+ The starting logical block address to read from
+ on the device media.
+
+ UINTN IN NumberOfBlocks
+ The number of transfer data blocks.
+
+ Returns:
+ return status is fully dependent on the return status
+ of AtaPioDataIn() function.
+
+ Notes:
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: DataBuffer - add argument and description to function comment
+// TODO: Lba - add argument and description to function comment
+// TODO: NumberOfBlocks - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ UINTN BlocksRemaining;
+ UINT32 Lba32;
+ UINT8 Lba0;
+ UINT8 Lba1;
+ UINT8 Lba2;
+ UINT8 Lba3;
+ UINT8 AtaCommand;
+ UINT8 SectorCount8;
+ UINT16 SectorCount;
+ UINTN ByteCount;
+ VOID *Buffer;
+
+ Buffer = DataBuffer;
+
+ //
+ // Using ATA Read Sector(s) command (opcode=0x20) with PIO DATA IN protocol
+ //
+ AtaCommand = READ_SECTORS_CMD;
+
+
+ BlocksRemaining = NumberOfBlocks;
+
+ Lba32 = (UINT32) Lba;
+
+ Status = EFI_SUCCESS;
+
+ while (BlocksRemaining > 0) {
+
+ //
+ // in ATA-3 spec, LBA is in 28 bit width
+ //
+ Lba0 = (UINT8) Lba32;
+ Lba1 = (UINT8) (Lba32 >> 8);
+ Lba2 = (UINT8) (Lba32 >> 16);
+ //
+ // low 4 bit of Lba3 stands for LBA bit24~bit27.
+ //
+ Lba3 = (UINT8) ((Lba32 >> 24) & 0x0f);
+
+ if (BlocksRemaining >= 0x100) {
+
+ //
+ // SectorCount8 is sent to Sector Count register, 0x00 means 256
+ // sectors to be read
+ //
+ SectorCount8 = 0x00;
+ //
+ // SectorCount is used to record the number of sectors to be read
+ //
+ SectorCount = 256;
+ } else {
+
+ SectorCount8 = (UINT8) BlocksRemaining;
+ SectorCount = (UINT16) BlocksRemaining;
+ }
+
+ //
+ // ByteCount is the number of bytes that will be read
+ //
+ ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize);
+
+ //
+ // call AtaPioDataIn() to send Read Sector Command and receive data read
+ //
+ Status = AtaPioDataIn (
+ IdeDev,
+ Buffer,
+ (UINT32) ByteCount,
+ AtaCommand,
+ Lba3,
+ SectorCount8,
+ Lba0,
+ Lba1,
+ Lba2
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Lba32 += SectorCount;
+ Buffer = ((UINT8 *) Buffer + ByteCount);
+ BlocksRemaining -= SectorCount;
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+AtaWriteSectors (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *BufferData,
+ IN EFI_LBA Lba,
+ IN UINTN NumberOfBlocks
+ )
+/*++
+ Name:
+ AtaWriteSectors
+
+
+ Purpose:
+ This function is called by the AtaBlkIoWriteBlocks() to perform
+ writing onto media in block unit.
+
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure,used
+ to record all the information of the IDE device.
+
+ VOID IN *BufferData
+ A pointer to the source buffer for the data.
+
+ EFI_LBA IN Lba
+ The starting logical block address to write onto
+ the device media.
+
+ UINTN IN NumberOfBlocks
+ The number of transfer data blocks.
+
+
+ Returns:
+ return status is fully dependent on the return status
+ of AtaPioDataOut() function.
+
+ Notes:
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: BufferData - add argument and description to function comment
+// TODO: Lba - add argument and description to function comment
+// TODO: NumberOfBlocks - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ UINTN BlocksRemaining;
+ UINT32 Lba32;
+ UINT8 Lba0;
+ UINT8 Lba1;
+ UINT8 Lba2;
+ UINT8 Lba3;
+ UINT8 AtaCommand;
+ UINT8 SectorCount8;
+ UINT16 SectorCount;
+ UINTN ByteCount;
+ VOID *Buffer;
+
+ Buffer = BufferData;
+
+ //
+ // Using Write Sector(s) command (opcode=0x30) with PIO DATA OUT protocol
+ //
+ AtaCommand = WRITE_SECTORS_CMD;
+
+ BlocksRemaining = NumberOfBlocks;
+
+ Lba32 = (UINT32) Lba;
+
+ Status = EFI_SUCCESS;
+
+ while (BlocksRemaining > 0) {
+
+ Lba0 = (UINT8) Lba32;
+ Lba1 = (UINT8) (Lba32 >> 8);
+ Lba2 = (UINT8) (Lba32 >> 16);
+ Lba3 = (UINT8) ((Lba32 >> 24) & 0x0f);
+
+ if (BlocksRemaining >= 0x100) {
+
+ //
+ // SectorCount8 is sent to Sector Count register, 0x00 means 256 sectors
+ // to be written
+ //
+ SectorCount8 = 0x00;
+ //
+ // SectorCount is used to record the number of sectors to be written
+ //
+ SectorCount = 256;
+ } else {
+
+ SectorCount8 = (UINT8) BlocksRemaining;
+ SectorCount = (UINT16) BlocksRemaining;
+ }
+
+ ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize);
+
+ Status = AtaPioDataOut (
+ IdeDev,
+ Buffer,
+ (UINT32) ByteCount,
+ AtaCommand,
+ Lba3,
+ SectorCount8,
+ Lba0,
+ Lba1,
+ Lba2
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Lba32 += SectorCount;
+ Buffer = ((UINT8 *) Buffer + ByteCount);
+ BlocksRemaining -= SectorCount;
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+AtaSoftReset (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+ Name:
+ AtaSoftReset
+
+ Purpose:
+ This function is used to implement the Soft Reset on the specified
+ device. But, the ATA Soft Reset mechanism is so strong a reset method
+ that it will force resetting on both devices connected to the
+ same cable.
+ It is called by IdeBlkIoReset(), a interface function of Block
+ I/O protocol.
+ This function can also be used by the ATAPI device to perform reset when
+ ATAPI Reset command is failed.
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+ Returns:
+ EFI_SUCCESS
+ Soft reset completes successfully.
+
+ EFI_DEVICE_ERROR
+ Any step during the reset process is failed.
+ Notes:
+ The registers initial values after ATA soft reset are different
+ to the ATA device and ATAPI device.
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+{
+
+ UINT8 DeviceControl;
+
+ DeviceControl = 0;
+ //
+ // set SRST bit to initiate soft reset
+ //
+ DeviceControl |= SRST;
+
+ //
+ // disable Interrupt
+ //
+ DeviceControl |= bit1;
+
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
+
+ gBS->Stall (10);
+
+ //
+ // Enable interrupt to support UDMA, and clear SRST bit
+ //
+ DeviceControl = 0;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
+
+ //
+ // slave device needs at most 31s to clear BSY
+ //
+ if (WaitForBSYClear (IdeDev, 31000) == EFI_TIMEOUT) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AtaBlkIoReadBlocks (
+ IN IDE_BLK_IO_DEV *IdeBlkIoDevice,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+/*++
+ Name:
+ AtaBlkIoReadBlocks
+
+
+ Purpose:
+ This function is the ATA implementation for ReadBlocks in the
+ Block I/O Protocol interface.
+
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeBlkIoDevice
+ Indicates the calling context.
+
+ UINT32 IN MediaId
+ The media id that the read request is for.
+
+ EFI_LBA IN LBA
+ The starting logical block address to read from
+ on the device.
+
+ UINTN IN BufferSize
+ The size of the Buffer in bytes. This must be a
+ multiple of the intrinsic block size of the device.
+
+ VOID OUT *Buffer
+ A pointer to the destination buffer for the data.
+ The caller is responsible for either having implicit
+ or explicit ownership of the memory that data is read into.
+
+ Returns:
+ EFI_SUCCESS
+ Read Blocks successfully.
+
+ EFI_DEVICE_ERROR
+ Read Blocks failed.
+
+ EFI_NO_MEDIA
+ There is no media in the device.
+
+ EFI_MEDIA_CHANGE
+ 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 data buffer is not valid.
+
+ Notes:
+ If Read Block error because of device error, this function will call
+ AtaSoftReset() function to reset device.
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeBlkIoDevice - add argument and description to function comment
+// TODO: MediaId - add argument and description to function comment
+// TODO: LBA - add argument and description to function comment
+// TODO: BufferSize - add argument and description to function comment
+// TODO: Buffer - add argument and description to function comment
+// TODO: EFI_MEDIA_CHANGED - add return value to function comment
+{
+ EFI_BLOCK_IO_MEDIA *Media;
+ UINTN BlockSize;
+ UINTN NumberOfBlocks;
+ EFI_STATUS Status;
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Get the intrinsic block size
+ //
+ Media = IdeBlkIoDevice->BlkIo.Media;
+ BlockSize = Media->BlockSize;
+
+ NumberOfBlocks = BufferSize / BlockSize;
+
+ if (MediaId != Media->MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (BufferSize % BlockSize != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ if (!(Media->MediaPresent)) {
+ return EFI_NO_MEDIA;
+ }
+
+ if (LBA > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {
+ //
+ // For ATA/ATAPI-6 device(capcity > 120GB), use ATA-6 read block mechanism
+ //
+ Status = AtaUdmaReadExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
+ if (EFI_ERROR (Status)) {
+ Status = AtaReadSectorsExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
+ }
+ } else {
+ //
+ // For ATA-3 compatible device, use ATA-3 read block mechanism
+ // Notice DMA operation can only handle 32bit address
+ //
+ if ((UINTN) Buffer <= 0xFFFFFFFF) {
+ Status = AtaUdmaRead (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
+ }
+
+ if (EFI_ERROR (Status) || ((UINTN) Buffer > 0xFFFFFFFF)) {
+ Status = AtaReadSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
+ }
+ }
+
+ if (EFI_ERROR (Status)) {
+ AtaSoftReset (IdeBlkIoDevice);
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+AtaBlkIoWriteBlocks (
+ IN IDE_BLK_IO_DEV *IdeBlkIoDevice,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+/*++
+ Name:
+ AtaBlkIoWriteBlocks
+
+
+ Purpose:
+ This function is the ATA implementation for WriteBlocks in the
+ Block I/O Protocol interface.
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeBlkIoDevice
+ Indicates the calling context.
+
+ UINT32 IN MediaId
+ The media id that the write request is for.
+
+ EFI_LBA IN LBA
+ The starting logical block address to write onto
+ the device.
+
+ UINTN IN BufferSize
+ The size of the Buffer in bytes. This must be a
+ multiple of the intrinsic block size of the device.
+
+ VOID OUT *Buffer
+ A pointer to the source buffer for the data.
+ The caller is responsible for either having implicit
+ or explicit ownership of the memory that data is
+ written from.
+
+
+ Returns:
+ EFI_SUCCESS
+ Write Blocks successfully.
+
+ EFI_DEVICE_ERROR
+ Write Blocks failed.
+
+ EFI_NO_MEDIA
+ There is no media in the device.
+
+ EFI_MEDIA_CHANGE
+ 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 write request contains LBAs that are not valid,
+ or the data buffer is not valid.
+
+ Notes:
+ If Write Block error because of device error, this function will call
+ AtaSoftReset() function to reset device.
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeBlkIoDevice - add argument and description to function comment
+// TODO: MediaId - add argument and description to function comment
+// TODO: LBA - add argument and description to function comment
+// TODO: BufferSize - add argument and description to function comment
+// TODO: Buffer - add argument and description to function comment
+// TODO: EFI_MEDIA_CHANGED - add return value to function comment
+{
+
+ EFI_BLOCK_IO_MEDIA *Media;
+ UINTN BlockSize;
+ UINTN NumberOfBlocks;
+ EFI_STATUS Status;
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Get the intrinsic block size
+ //
+ Media = IdeBlkIoDevice->BlkIo.Media;
+ BlockSize = Media->BlockSize;
+ NumberOfBlocks = BufferSize / BlockSize;
+
+ if (MediaId != Media->MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (BufferSize % BlockSize != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ if (LBA > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {
+ //
+ // For ATA/ATAPI-6 device(capcity > 120GB), use ATA-6 write block mechanism
+ //
+ Status = AtaUdmaWriteExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
+ if (EFI_ERROR (Status)) {
+ Status = AtaWriteSectorsExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
+ }
+ } else {
+ //
+ // For ATA-3 compatible device, use ATA-3 write block mechanism
+ //
+ Status = AtaUdmaWrite (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
+ if (EFI_ERROR (Status) || ((UINTN) Buffer > 0xFFFFFFFF)) {
+ Status = AtaWriteSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
+ }
+ }
+
+ if (EFI_ERROR (Status)) {
+ AtaSoftReset (IdeBlkIoDevice);
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AtaReadSectorsExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks
+ )
+/*++
+ Name:
+
+ AtaReadSectorsExt
+
+ Purpose:
+
+ This function is called by the AtaBlkIoReadBlocks() to perform
+ reading from media in block unit. The function has been enhanced to
+ support >120GB access and transfer at most 65536 blocks per command
+
+ Parameters:
+
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ VOID IN *DataBuffer
+ A pointer to the destination buffer for the data.
+
+ EFI_LBA IN StartLba
+ The starting logical block address to read from
+ on the device media.
+
+ UINTN IN NumberOfBlocks
+ The number of transfer data blocks.
+
+ Returns:
+
+ return status is fully dependent on the return status
+ of AtaPioDataInExt() function.
+
+ Notes:
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: DataBuffer - add argument and description to function comment
+// TODO: StartLba - add argument and description to function comment
+// TODO: NumberOfBlocks - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ UINTN BlocksRemaining;
+ EFI_LBA Lba64;
+ UINT8 AtaCommand;
+ UINT16 SectorCount;
+ UINT32 ByteCount;
+ VOID *Buffer;
+
+ //
+ // Using ATA "Read Sectors Ext" command(opcode=0x24) with PIO DATA IN protocol
+ //
+ AtaCommand = READ_SECTORS_EXT_CMD;
+ Buffer = DataBuffer;
+ BlocksRemaining = NumberOfBlocks;
+ Lba64 = StartLba;
+ Status = EFI_SUCCESS;
+
+ while (BlocksRemaining > 0) {
+
+ if (BlocksRemaining >= 0x10000) {
+ //
+ // SectorCount is used to record the number of sectors to be read
+ // Max 65536 sectors can be transfered at a time.
+ //
+ SectorCount = 0xffff;
+ } else {
+ SectorCount = (UINT16) BlocksRemaining;
+ }
+
+ //
+ // ByteCount is the number of bytes that will be read
+ //
+ ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize);
+
+ //
+ // call AtaPioDataInExt() to send Read Sector Command and receive data read
+ //
+ Status = AtaPioDataInExt (
+ IdeDev,
+ Buffer,
+ ByteCount,
+ AtaCommand,
+ Lba64,
+ SectorCount
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Lba64 += SectorCount;
+ Buffer = ((UINT8 *) Buffer + ByteCount);
+ BlocksRemaining -= SectorCount;
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+AtaWriteSectorsExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks
+ )
+/*++
+ Name:
+
+ AtaWriteSectorsExt
+
+ Purpose:
+
+ This function is called by the AtaBlkIoWriteBlocks() to perform
+ writing onto media in block unit. The function has been enhanced to
+ support >120GB access and transfer at most 65536 blocks per command
+
+ Parameters:
+
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure,used
+ to record all the information of the IDE device.
+
+ VOID IN *DataBuffer
+ A pointer to the source buffer for the data.
+
+ EFI_LBA IN Lba
+ The starting logical block address to write onto
+ the device media.
+
+ UINTN IN NumberOfBlocks
+ The number of transfer data blocks.
+
+ Returns:
+
+ return status is fully dependent on the return status
+ of AtaPioDataOutExt() function.
+
+ Notes:
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: DataBuffer - add argument and description to function comment
+// TODO: StartLba - add argument and description to function comment
+// TODO: NumberOfBlocks - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ EFI_LBA Lba64;
+ UINTN BlocksRemaining;
+ UINT8 AtaCommand;
+ UINT16 SectorCount;
+ UINT32 ByteCount;
+ VOID *Buffer;
+
+ //
+ // Using ATA "Write Sectors Ext" cmd(opcode=0x24) with PIO DATA OUT protocol
+ //
+ AtaCommand = WRITE_SECTORS_EXT_CMD;
+ Lba64 = StartLba;
+ Buffer = DataBuffer;
+ BlocksRemaining = NumberOfBlocks;
+
+ Status = EFI_SUCCESS;
+
+ while (BlocksRemaining > 0) {
+
+ if (BlocksRemaining >= 0x10000) {
+ //
+ // SectorCount is used to record the number of sectors to be written.
+ // Max 65536 sectors can be transfered at a time.
+ //
+ SectorCount = 0xffff;
+ } else {
+ SectorCount = (UINT16) BlocksRemaining;
+ }
+
+ //
+ // ByteCount is the number of bytes that will be written
+ //
+ ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize);
+
+ //
+ // Call AtaPioDataOutExt() to send "Write Sectors Ext" Command
+ //
+ Status = AtaPioDataOutExt (
+ IdeDev,
+ Buffer,
+ ByteCount,
+ AtaCommand,
+ Lba64,
+ SectorCount
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Lba64 += SectorCount;
+ Buffer = ((UINT8 *) Buffer + ByteCount);
+ BlocksRemaining -= SectorCount;
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+AtaPioDataInExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN OUT VOID *Buffer,
+ IN UINT32 ByteCount,
+ IN UINT8 AtaCommand,
+ IN EFI_LBA StartLba,
+ IN UINT16 SectorCount
+ )
+/*++
+ Name:
+
+ AtaPioDataInExt
+
+ Purpose:
+
+ This function is used to send out ATA commands conforms to the
+ PIO Data In Protocol, supporting ATA/ATAPI-6 standard
+
+ Comparing with ATA-3 data in protocol, we have two differents here:
+ 1. Do NOT wait for DRQ clear before sending command into IDE device.(the
+ wait will frequently fail... cause writing function return error)
+
+ 2. Do NOT wait for DRQ clear after all data readed.(the wait greatly
+ slow down writing performance by 100 times!)
+
+
+ Parameters:
+
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ VOID IN OUT *Buffer
+ buffer contained data transferred from device to host.
+
+ UINT32 IN ByteCount
+ data size in byte unit of the buffer.
+
+ UINT8 IN AtaCommand
+ value of the Command Register
+
+ EFI_LBA IN StartLba
+ the start LBA of this transaction
+
+ UINT16 IN SectorCount
+ the count of sectors to be transfered
+
+ Returns:
+
+ EFI_SUCCESS
+ send out the ATA command and device send required
+ data successfully.
+
+ EFI_DEVICE_ERROR
+ command sent failed.
+ Notes:
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: Buffer - add argument and description to function comment
+// TODO: ByteCount - add argument and description to function comment
+// TODO: AtaCommand - add argument and description to function comment
+// TODO: StartLba - add argument and description to function comment
+// TODO: SectorCount - add argument and description to function comment
+{
+ UINT8 DevSel;
+ UINT8 SectorCount8;
+ UINT8 LbaLow;
+ UINT8 LbaMid;
+ UINT8 LbaHigh;
+ UINTN WordCount;
+ UINTN Increment;
+ UINT16 *Buffer16;
+ EFI_STATUS Status;
+
+ Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Select device, set bit6 as 1 to indicate LBA mode is used
+ //
+ DevSel = (UINT8) (IdeDev->Device << 4);
+ DevSel |= 0x40;
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ DevSel
+ );
+
+ //
+ // Wait for DRDY singnal asserting. ATAPI device needn't wait
+ //
+ if ( (IdeDev->Type == IdeHardDisk) ||
+ (IdeDev->Type == Ide48bitAddressingHardDisk)) {
+
+ Status = DRDYReady (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ //
+ // Fill feature register if needed
+ //
+ if (AtaCommand == SET_FEATURES_CMD) {
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03);
+ }
+
+ //
+ // Fill the sector count register, which is a two-byte FIFO. Need write twice.
+ //
+ SectorCount8 = (UINT8) (SectorCount >> 8);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);
+
+ SectorCount8 = (UINT8) SectorCount;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);
+
+ //
+ // Fill the start LBA registers, which are also two-byte FIFO
+ //
+ LbaLow = (UINT8) RShiftU64 (StartLba, 24);
+ LbaMid = (UINT8) RShiftU64 (StartLba, 32);
+ LbaHigh = (UINT8) RShiftU64 (StartLba, 40);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);
+
+ LbaLow = (UINT8) StartLba;
+ LbaMid = (UINT8) RShiftU64 (StartLba, 8);
+ LbaHigh = (UINT8) RShiftU64 (StartLba, 16);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);
+
+ //
+ // Send command via Command Register, invoking the processing of this command
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);
+
+ Buffer16 = (UINT16 *) Buffer;
+
+ //
+ // According to PIO data in protocol, host can perform a series of reads to
+ // the data register after each time device set DRQ ready;
+ //
+
+ //
+ // 256 words
+ //
+ Increment = 256;
+
+ //
+ // used to record bytes of currently transfered data
+ //
+ WordCount = 0;
+
+ while (WordCount < ByteCount / 2) {
+ //
+ // Poll DRQ bit set, data transfer can be performed only when DRQ is ready.
+ //
+ Status = DRQReady2 (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = CheckErrorStatus (IdeDev);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Get the byte count for one series of read
+ //
+ if ((WordCount + Increment) > ByteCount / 2) {
+ Increment = ByteCount / 2 - WordCount;
+ }
+
+ IDEReadPortWMultiple (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Data,
+ Increment,
+ Buffer16
+ );
+
+ WordCount += Increment;
+ Buffer16 += Increment;
+
+ }
+
+ return CheckErrorStatus (IdeDev);
+}
+
+EFI_STATUS
+AtaPioDataOutExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *Buffer,
+ IN UINT32 ByteCount,
+ IN UINT8 AtaCommand,
+ IN EFI_LBA StartLba,
+ IN UINT16 SectorCount
+ )
+/*++
+ Name:
+
+ AtaPioDataOutExt
+
+ Purpose:
+
+ This function is used to send out ATA commands conforms to the
+ PIO Data Out Protocol, supporting ATA/ATAPI-6 standard
+
+ Comparing with ATA-3 data out protocol, we have two differents here:
+ 1. Do NOT wait for DRQ clear before sending command into IDE device.(the
+ wait will frequently fail... cause writing function return error)
+
+ 2. Do NOT wait for DRQ clear after all data readed.(the wait greatly
+ slow down writing performance by 100 times!)
+
+ Parameters:
+
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ VOID IN *Buffer
+ buffer contained data transferred from host to device.
+
+ UINT32 IN ByteCount
+ data size in byte unit of the buffer.
+
+ UINT8 IN AtaCommand
+ value of the Command Register
+
+ EFI_LBA IN StartLba
+ the start LBA of this transaction
+
+ UINT16 IN SectorCount
+ the count of sectors to be transfered
+
+ Returns:
+
+ EFI_SUCCESS
+ send out the ATA command and device receive required
+ data successfully.
+
+ EFI_DEVICE_ERROR
+ command sent failed.
+ Notes:
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: Buffer - add argument and description to function comment
+// TODO: ByteCount - add argument and description to function comment
+// TODO: AtaCommand - add argument and description to function comment
+// TODO: StartLba - add argument and description to function comment
+// TODO: SectorCount - add argument and description to function comment
+{
+ UINT8 DevSel;
+ UINT8 SectorCount8;
+ UINT8 LbaLow;
+ UINT8 LbaMid;
+ UINT8 LbaHigh;
+ UINTN WordCount;
+ UINTN Increment;
+ UINT16 *Buffer16;
+ EFI_STATUS Status;
+
+ Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Select device. Set bit6 as 1 to indicate LBA mode is used
+ //
+ DevSel = (UINT8) (IdeDev->Device << 4);
+ DevSel |= 0x40;
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ DevSel
+ );
+
+ //
+ // Wait for DRDY singnal asserting.
+ //
+ Status = DRDYReady (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Fill feature register if needed
+ //
+ if (AtaCommand == SET_FEATURES_CMD) {
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03);
+ }
+
+ //
+ // Fill the sector count register, which is a two-byte FIFO. Need write twice.
+ //
+ SectorCount8 = (UINT8) (SectorCount >> 8);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);
+
+ SectorCount8 = (UINT8) SectorCount;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);
+
+ //
+ // Fill the start LBA registers, which are also two-byte FIFO
+ //
+ LbaLow = (UINT8) RShiftU64 (StartLba, 24);
+ LbaMid = (UINT8) RShiftU64 (StartLba, 32);
+ LbaHigh = (UINT8) RShiftU64 (StartLba, 40);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);
+
+ LbaLow = (UINT8) StartLba;
+ LbaMid = (UINT8) RShiftU64 (StartLba, 8);
+ LbaHigh = (UINT8) RShiftU64 (StartLba, 16);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);
+
+ //
+ // Send command via Command Register, invoking the processing of this command
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);
+
+ Buffer16 = (UINT16 *) Buffer;
+
+ //
+ // According to PIO Data Out protocol, host can perform a series of writes to
+ // the data register after each time device set DRQ ready;
+ //
+ Increment = 256;
+
+ //
+ // used to record bytes of currently transfered data
+ //
+ WordCount = 0;
+
+ while (WordCount < ByteCount / 2) {
+ //
+ // Poll DRQ bit set, data transfer can be performed only when DRQ is ready.
+ //
+ Status = DRQReady2 (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = CheckErrorStatus (IdeDev);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Write data into device by one series of writing to data register
+ //
+ if ((WordCount + Increment) > ByteCount / 2) {
+ Increment = ByteCount / 2 - WordCount;
+ }
+
+ IDEWritePortWMultiple (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Data,
+ Increment,
+ Buffer16
+ );
+
+ WordCount += Increment;
+ Buffer16 += Increment;
+
+ }
+ //
+ // while
+ //
+
+ return CheckErrorStatus (IdeDev);
+}
+
+
+VOID
+AtaSMARTSupport (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+ Name:
+ AtaSMARTSupport
+
+ Purpose:
+
+ Enable SMART of the disk if supported
+
+ Parameters:
+
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure,used
+ to record all the information of the IDE device.
+
+ Returns:
+
+ NONE
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ BOOLEAN SMARTSupported;
+ UINT8 Device;
+ EFI_IDENTIFY_DATA *TmpAtaIdentifyPointer;
+ UINT8 DeviceSelect;
+ UINT8 LBAMid;
+ UINT8 LBAHigh;
+
+ //
+ // Detect if the device supports S.M.A.R.T.
+ //
+ if ((IdeDev->pIdData->AtaData.command_set_supported_83 & 0xc000) != 0x4000) {
+ //
+ // Data in word 82 is not valid (bit15 shall be zero and bit14 shall be to one)
+ //
+ return ;
+ } else {
+ if ((IdeDev->pIdData->AtaData.command_set_supported_82 & 0x0001) != 0x0001) {
+ //
+ // S.M.A.R.T is not supported by the device
+ //
+ SMARTSupported = FALSE;
+ } else {
+ SMARTSupported = TRUE;
+ }
+ }
+
+ if (!SMARTSupported) {
+ //
+ // Report nonsupport status code
+ //
+ REPORT_STATUS_CODE (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED)
+ );
+ } else {
+ //
+ // Enable this feature
+ //
+ REPORT_STATUS_CODE (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_ENABLE)
+ );
+
+ Device = (UINT8) ((IdeDev->Device << 4) | 0xe0);
+ Status = AtaNonDataCommandIn (
+ IdeDev,
+ ATA_SMART_CMD,
+ Device,
+ ATA_SMART_ENABLE_OPERATION,
+ 0,
+ 0,
+ ATA_CONSTANT_4F,
+ ATA_CONSTANT_C2
+ );
+ //
+ // Detect if this feature is enabled
+ //
+ TmpAtaIdentifyPointer = (EFI_IDENTIFY_DATA *) AllocateZeroPool (sizeof (EFI_IDENTIFY_DATA));
+
+ DeviceSelect = (UINT8) ((IdeDev->Device) << 4);
+ Status = AtaPioDataIn (
+ IdeDev,
+ (VOID *) TmpAtaIdentifyPointer,
+ sizeof (EFI_IDENTIFY_DATA),
+ IDENTIFY_DRIVE_CMD,
+ DeviceSelect,
+ 0,
+ 0,
+ 0,
+ 0
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (TmpAtaIdentifyPointer);
+ return ;
+ }
+
+ //
+ // Check if the feature is enabled
+ //
+ if ((TmpAtaIdentifyPointer->AtaData.command_set_feature_enb_85 & 0x0001) == 0x0001) {
+ //
+ // Read status data
+ //
+ AtaNonDataCommandIn (
+ IdeDev,
+ ATA_SMART_CMD,
+ Device,
+ ATA_SMART_RETURN_STATUS,
+ 0,
+ 0,
+ ATA_CONSTANT_4F,
+ ATA_CONSTANT_C2
+ );
+ LBAMid = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb);
+ LBAHigh = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb);
+
+ if ((LBAMid == 0x4f) && (LBAHigh == 0xc2)) {
+ //
+ // The threshold exceeded condition is not detected by the device
+ //
+ REPORT_STATUS_CODE (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD)
+ );
+
+ } else if ((LBAMid == 0xf4) && (LBAHigh == 0x2c)) {
+ //
+ // The threshold exceeded condition is detected by the device
+ //
+ REPORT_STATUS_CODE (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD)
+ );
+ }
+
+ } else {
+ //
+ // Report disabled status code
+ //
+ REPORT_STATUS_CODE (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_DISABLED)
+ );
+ }
+
+ gBS->FreePool (TmpAtaIdentifyPointer);
+ }
+
+ return ;
+}
+
+EFI_STATUS
+AtaCommandIssueExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINT8 AtaCommand,
+ IN UINT8 Device,
+ IN UINT16 Feature,
+ IN UINT16 SectorCount,
+ IN EFI_LBA LbaAddress
+ )
+/*++
+
+Routine Description:
+
+ Send ATA Ext command into device with NON_DATA protocol
+
+Arguments:
+
+ IdeDev - Standard IDE device private data structure
+ AtaCommand - The ATA command to be sent
+ Device - The value in Device register
+ Feature - The value in Feature register
+ SectorCount - The value in SectorCount register
+ LbaAddress - The LBA address in 48-bit mode
+
+Returns:
+
+ EFI_SUCCESS - Reading succeed
+ EFI_DEVICE_ERROR - Error executing commands on this device
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT8 SectorCount8;
+ UINT8 Feature8;
+ UINT8 LbaLow;
+ UINT8 LbaMid;
+ UINT8 LbaHigh;
+
+ Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)
+ //
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ (UINT8) ((IdeDev->Device << 4) | 0xe0)
+ );
+
+ //
+ // ATA commands for ATA device must be issued when DRDY is set
+ //
+ Status = DRDYReady (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Pass parameter into device register block
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);
+
+ //
+ // Fill the feature register, which is a two-byte FIFO. Need write twice.
+ //
+ Feature8 = (UINT8) (Feature >> 8);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);
+
+ Feature8 = (UINT8) Feature;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);
+
+ //
+ // Fill the sector count register, which is a two-byte FIFO. Need write twice.
+ //
+ SectorCount8 = (UINT8) (SectorCount >> 8);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);
+
+ SectorCount8 = (UINT8) SectorCount;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);
+
+ //
+ // Fill the start LBA registers, which are also two-byte FIFO
+ //
+ LbaLow = (UINT8) RShiftU64 (LbaAddress, 24);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);
+ LbaLow = (UINT8) LbaAddress;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);
+
+ LbaMid = (UINT8) RShiftU64 (LbaAddress, 32);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);
+ LbaMid = (UINT8) RShiftU64 (LbaAddress, 8);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);
+
+ LbaHigh = (UINT8) RShiftU64 (LbaAddress, 40);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);
+ LbaHigh = (UINT8) RShiftU64 (LbaAddress, 16);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);
+
+ //
+ // Work around for Segate 160G disk writing
+ //
+ gBS->Stall (1800);
+
+ //
+ // Send command via Command Register
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);
+
+ //
+ // Stall at least 400ns
+ //
+ gBS->Stall (100);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AtaCommandIssue (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINT8 AtaCommand,
+ IN UINT8 Device,
+ IN UINT16 Feature,
+ IN UINT16 SectorCount,
+ IN EFI_LBA LbaAddress
+ )
+/*++
+
+Routine Description:
+
+ Send ATA Ext command into device with NON_DATA protocol
+
+Arguments:
+
+ IdeDev - Standard IDE device private data structure
+ AtaCommand - The ATA command to be sent
+ Device - The value in Device register
+ Feature - The value in Feature register
+ SectorCount - The value in SectorCount register
+ LbaAddress - The LBA address in 48-bit mode
+
+Returns:
+
+ EFI_SUCCESS - Reading succeed
+ EFI_DEVICE_ERROR - Error executing commands on this device
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT8 SectorCount8;
+ UINT8 Feature8;
+ UINT8 Lba0;
+ UINT8 Lba1;
+ UINT8 Lba2;
+ UINT8 Lba3;
+
+ Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)
+ //
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ (UINT8) ((IdeDev->Device << 4) | 0xe0)
+ );
+
+ //
+ // ATA commands for ATA device must be issued when DRDY is set
+ //
+ Status = DRDYReady (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Lba0 = (UINT8) LbaAddress;
+ Lba1 = (UINT8) RShiftU64 (LbaAddress, 8);
+ Lba2 = (UINT8) RShiftU64 (LbaAddress, 16);
+ Lba3 = (UINT8) RShiftU64 (LbaAddress, 24);
+ Device |= Lba3;
+
+ //
+ // Pass parameter into device register block
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);
+
+ //
+ // Fill the feature register, which is a two-byte FIFO. Need write twice.
+ //
+ Feature8 = (UINT8) Feature;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);
+
+ //
+ // Fill the sector count register, which is a two-byte FIFO. Need write twice.
+ //
+ SectorCount8 = (UINT8) SectorCount;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);
+
+ //
+ // Fill the start LBA registers, which are also two-byte FIFO
+ //
+
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, Lba0);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, Lba1);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, Lba2);
+
+ //
+ // Send command via Command Register
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);
+
+ //
+ // Stall at least 400ns
+ //
+ gBS->Stall (100);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AtaUdmaReadExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks
+ )
+/*++
+ Name:
+
+ AtaUdmaReadExt
+
+ Purpose:
+
+ This function is called by the AtaBlkIoReadBlocks() to perform
+ reading from media in block unit. The function has been enhanced to
+ support >120GB access and transfer at most 65536 blocks per command
+
+ Parameters:
+
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ VOID IN *DataBuffer
+ A pointer to the destination buffer for the data.
+
+ EFI_LBA IN StartLba
+ The starting logical block address to read from
+ on the device media.
+
+ UINTN IN NumberOfBlocks
+ The number of transfer data blocks.
+
+ Returns:
+
+ The device status of UDMA operation. If the operation is
+ successful, return EFI_SUCCESS.
+
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: DataBuffer - add argument and description to function comment
+// TODO: StartLba - add argument and description to function comment
+// TODO: NumberOfBlocks - add argument and description to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+{
+ IDE_DMA_PRD *PrdAddr;
+ IDE_DMA_PRD *UsedPrdAddr;
+ IDE_DMA_PRD *TempPrdAddr;
+ UINT8 RegisterValue;
+ UINT8 Device;
+ UINT64 IoPortForBmic;
+ UINT64 IoPortForBmis;
+ UINT64 IoPortForBmid;
+ EFI_STATUS Status;
+ UINTN PrdTableNum;
+ UINTN ByteCount;
+ UINTN ByteAvailable;
+ UINT8 *PrdBuffer;
+ UINTN RemainBlockNum;
+ UINT8 DeviceControl;
+
+ //
+ // Channel and device differential. Select device.
+ //
+ Device = (UINT8) ((IdeDev->Device << 4) | 0xe0);
+
+ //
+ // Enable interrupt to support UDMA and Select device
+ //
+ DeviceControl = 0;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
+
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);
+
+ if (IdePrimary == IdeDev->Channel) {
+ IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICP_OFFSET;
+ IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;
+ IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDP_OFFSET;
+ } else {
+ if (IdeSecondary == IdeDev->Channel) {
+ IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICS_OFFSET;
+ IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET;
+ IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDS_OFFSET;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ RemainBlockNum = NumberOfBlocks;
+ while (RemainBlockNum > 0) {
+
+ if (RemainBlockNum >= MAX_DMA_EXT_COMMAND_SECTORS) {
+ //
+ // SectorCount is used to record the number of sectors to be read
+ // Max 65536 sectors can be transfered at a time.
+ //
+ NumberOfBlocks = MAX_DMA_EXT_COMMAND_SECTORS;
+ RemainBlockNum -= MAX_DMA_EXT_COMMAND_SECTORS;
+ } else {
+ NumberOfBlocks = (UINT16) RemainBlockNum;
+ RemainBlockNum = 0;
+ }
+
+ //
+ // Calculate the number of PRD table to make sure the memory region
+ // not cross 64K boundary
+ //
+ ByteCount = NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;
+ PrdTableNum = ((ByteCount >> 16) + 1) + 1;
+
+ //
+ // Build PRD table
+ //
+ PrdAddr = (IDE_DMA_PRD *) AllocateZeroPool ((2 * PrdTableNum * sizeof (IDE_DMA_PRD)));
+
+ //
+ // To make sure PRD is allocated in one 64K page
+ //
+ if (((UINTN) PrdAddr & 0x0FFFF) > (((UINTN) PrdAddr + PrdTableNum * sizeof (IDE_DMA_PRD) - 1) & 0x0FFFF)) {
+ UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x10000) & 0xFFFF0000);
+ } else {
+ if ((UINTN) PrdAddr & 0x03) {
+ UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x04) & 0xFFFFFFFC);
+ } else {
+ UsedPrdAddr = PrdAddr;
+ }
+ }
+
+ //
+ // Build the PRD table
+ //
+ PrdBuffer = DataBuffer;
+ TempPrdAddr = UsedPrdAddr;
+ while (TRUE) {
+
+ ByteAvailable = 0x10000 - ((UINTN) PrdBuffer & 0xFFFF);
+
+ if (ByteCount <= ByteAvailable) {
+ TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);
+ TempPrdAddr->ByteCount = (UINT16) ByteCount;
+ TempPrdAddr->EndOfTable = 0x8000;
+ break;
+ }
+
+ TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);
+ TempPrdAddr->ByteCount = (UINT16) ByteAvailable;
+
+ ByteCount -= ByteAvailable;
+ PrdBuffer += ByteAvailable;
+ TempPrdAddr++;
+ }
+
+ //
+ // Set the base address to BMID register
+ //
+ IdeDev->PciIo->Io.Write (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint32,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmid,
+ 1,
+ &UsedPrdAddr
+ );
+
+ //
+ // Set BMIC register to identify the operation direction
+ //
+ IdeDev->PciIo->Io.Read (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+
+ RegisterValue |= BMIC_nREAD;
+
+ IdeDev->PciIo->Io.Write (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+
+ //
+ // Read BMIS register and clear ERROR and INTR bit
+ //
+ IdeDev->PciIo->Io.Read (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmis,
+ 1,
+ &RegisterValue
+ );
+
+ RegisterValue |= BMIS_INTERRUPT | BMIS_ERROR;
+
+ IdeDev->PciIo->Io.Write (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmis,
+ 1,
+ &RegisterValue
+ );
+
+ //
+ // Issue READ DMA EXT command
+ //
+ Status = AtaCommandIssueExt (
+ IdeDev,
+ READ_DMA_EXT_CMD,
+ Device,
+ 0,
+ (UINT16) NumberOfBlocks,
+ StartLba
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (PrdAddr);
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Set START bit of BMIC register
+ //
+ IdeDev->PciIo->Io.Read (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+
+ RegisterValue |= BMIC_START;
+
+ IdeDev->PciIo->Io.Write (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+
+ //
+ // Check the INTERRUPT and ERROR bit of BMIS
+ //
+ while (TRUE) {
+
+ IdeDev->PciIo->Io.Read (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmis,
+ 1,
+ &RegisterValue
+ );
+ if (RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) {
+ if (RegisterValue & BMIS_ERROR) {
+ gBS->FreePool (PrdAddr);
+ return EFI_DEVICE_ERROR;
+ }
+ break;
+ }
+
+ gBS->Stall (1000);
+ }
+
+ gBS->FreePool (PrdAddr);
+
+ //
+ // Set START bit of BMIC register
+ //
+ IdeDev->PciIo->Io.Read (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+
+ RegisterValue &= ~((UINT8) BMIC_START);
+
+ IdeDev->PciIo->Io.Write (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+
+ if (RegisterValue & BMIS_ERROR) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ DataBuffer = (UINT8 *) DataBuffer + NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;
+ StartLba += NumberOfBlocks;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AtaUdmaRead (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks
+ )
+/*++
+ Name:
+
+ AtaUdmaRead
+
+ Purpose:
+
+ This function is called by the AtaBlkIoReadBlocks() to perform
+ reading from media in block unit. The function has been enhanced to
+ support >120GB access and transfer at most 65536 blocks per command
+
+ Parameters:
+
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ VOID IN *DataBuffer
+ A pointer to the destination buffer for the data.
+
+ EFI_LBA IN StartLba
+ The starting logical block address to read from
+ on the device media.
+
+ UINTN IN NumberOfBlocks
+ The number of transfer data blocks.
+
+ Returns:
+
+ The device status of UDMA operation. If the operation is
+ successful, return EFI_SUCCESS.
+
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: DataBuffer - add argument and description to function comment
+// TODO: StartLba - add argument and description to function comment
+// TODO: NumberOfBlocks - add argument and description to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+{
+ IDE_DMA_PRD *PrdAddr;
+ IDE_DMA_PRD *UsedPrdAddr;
+ IDE_DMA_PRD *TempPrdAddr;
+ UINT8 RegisterValue;
+ UINT8 Device;
+ UINT64 IoPortForBmic;
+ UINT64 IoPortForBmis;
+ UINT64 IoPortForBmid;
+ EFI_STATUS Status;
+ UINTN PrdTableNum;
+ UINTN ByteCount;
+ UINTN ByteAvailable;
+ UINT8 *PrdBuffer;
+ UINTN RemainBlockNum;
+ UINT8 DeviceControl;
+
+ //
+ // Channel and device differential
+ //
+ Device = (UINT8) ((IdeDev->Device << 4) | 0xe0);
+
+ //
+ // Enable interrupt to support UDMA and Select device
+ //
+ DeviceControl = 0;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
+
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);
+
+ if (IdePrimary == IdeDev->Channel) {
+ IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICP_OFFSET;
+ IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;
+ IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDP_OFFSET;
+ } else {
+ if (IdeSecondary == IdeDev->Channel) {
+ IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICS_OFFSET;
+ IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET;
+ IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDS_OFFSET;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ RemainBlockNum = NumberOfBlocks;
+ while (RemainBlockNum > 0) {
+
+ if (RemainBlockNum >= MAX_DMA_COMMAND_SECTORS) {
+ //
+ // SectorCount is used to record the number of sectors to be read
+ // Max 256 sectors can be transfered at a time.
+ //
+ NumberOfBlocks = MAX_DMA_COMMAND_SECTORS;
+ RemainBlockNum -= MAX_DMA_COMMAND_SECTORS;
+ } else {
+ NumberOfBlocks = (UINT16) RemainBlockNum;
+ RemainBlockNum = 0;
+ }
+
+ //
+ // Calculate the number of PRD table to make sure the memory region
+ // not cross 64K boundary
+ //
+ ByteCount = NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;
+ PrdTableNum = ((ByteCount >> 16) + 1) + 1;
+
+ //
+ // Build PRD table
+ //
+ PrdAddr = (IDE_DMA_PRD *) AllocateZeroPool ((2 * PrdTableNum * sizeof (IDE_DMA_PRD)));
+ //
+ // To make sure PRD is allocated in one 64K page
+ //
+ if (((UINTN) PrdAddr & 0x0FFFF) > (((UINTN) PrdAddr + PrdTableNum * sizeof (IDE_DMA_PRD) - 1) & 0x0FFFF)) {
+ UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x10000) & 0xFFFF0000);
+ } else {
+ if ((UINTN) PrdAddr & 0x03) {
+ UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x04) & 0xFFFFFFFC);
+ } else {
+ UsedPrdAddr = PrdAddr;
+ }
+ }
+
+ //
+ // Build the PRD table
+ //
+ PrdBuffer = DataBuffer;
+ TempPrdAddr = UsedPrdAddr;
+ while (TRUE) {
+
+ ByteAvailable = 0x10000 - ((UINTN) PrdBuffer & 0xFFFF);
+
+ if (ByteCount <= ByteAvailable) {
+ TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);
+ TempPrdAddr->ByteCount = (UINT16) ByteCount;
+ TempPrdAddr->EndOfTable = 0x8000;
+ break;
+ }
+
+ TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);
+ TempPrdAddr->ByteCount = (UINT16) ByteAvailable;
+
+ ByteCount -= ByteAvailable;
+ PrdBuffer += ByteAvailable;
+ TempPrdAddr++;
+ }
+
+ //
+ // Set the base address to BMID register
+ //
+ IdeDev->PciIo->Io.Write (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint32,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmid,
+ 1,
+ &UsedPrdAddr
+ );
+
+ //
+ // Set BMIC register to identify the operation direction
+ //
+ IdeDev->PciIo->Io.Read (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+
+ RegisterValue |= BMIC_nREAD;
+
+ IdeDev->PciIo->Io.Write (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+
+ //
+ // Read BMIS register and clear ERROR and INTR bit
+ //
+ IdeDev->PciIo->Io.Read (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmis,
+ 1,
+ &RegisterValue
+ );
+
+ RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);
+
+ IdeDev->PciIo->Io.Write (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmis,
+ 1,
+ &RegisterValue
+ );
+
+ //
+ // Issue READ DMA command
+ //
+ Status = AtaCommandIssue (
+ IdeDev,
+ READ_DMA_CMD,
+ Device,
+ 0,
+ (UINT16) NumberOfBlocks,
+ StartLba
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (PrdAddr);
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Set START bit of BMIC register
+ //
+ IdeDev->PciIo->Io.Read (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+
+ RegisterValue |= BMIC_START;
+
+ IdeDev->PciIo->Io.Write (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+
+ //
+ // Check the INTERRUPT and ERROR bit of BMIS
+ //
+ while (TRUE) {
+
+ IdeDev->PciIo->Io.Read (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmis,
+ 1,
+ &RegisterValue
+ );
+ if (RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) {
+ if (RegisterValue & BMIS_ERROR) {
+ gBS->FreePool (PrdAddr);
+ return EFI_DEVICE_ERROR;
+ }
+ break;
+ }
+
+ gBS->Stall (1000);
+ }
+
+ gBS->FreePool (PrdAddr);
+
+ //
+ // Set START bit of BMIC register
+ //
+ IdeDev->PciIo->Io.Read (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+
+ RegisterValue &= ~((UINT8) BMIC_START);
+
+ IdeDev->PciIo->Io.Write (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+
+ if (RegisterValue & BMIS_ERROR) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ DataBuffer = (UINT8 *) DataBuffer + NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;
+ StartLba += NumberOfBlocks;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AtaUdmaWriteExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks
+ )
+/*++
+ Name:
+
+ AtaUdmaWriteExt
+
+ Purpose:
+
+ This function is called by the AtaBlkIoWriteBlocks() to perform
+ writing to media in block unit. The function has been enhanced to
+ support >120GB access and transfer at most 65536 blocks per command
+
+ Parameters:
+
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ VOID IN *DataBuffer
+ A pointer to the source buffer for the data.
+
+ EFI_LBA IN StartLba
+ The starting logical block address to write to
+ on the device media.
+
+ UINTN IN NumberOfBlocks
+ The number of transfer data blocks.
+
+ Returns:
+
+ The device status of UDMA operation. If the operation is
+ successful, return EFI_SUCCESS.
+
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: DataBuffer - add argument and description to function comment
+// TODO: StartLba - add argument and description to function comment
+// TODO: NumberOfBlocks - add argument and description to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+{
+ IDE_DMA_PRD *PrdAddr;
+ IDE_DMA_PRD *UsedPrdAddr;
+ IDE_DMA_PRD *TempPrdAddr;
+ UINT8 RegisterValue;
+ UINT8 Device;
+ UINT64 IoPortForBmic;
+ UINT64 IoPortForBmis;
+ UINT64 IoPortForBmid;
+ EFI_STATUS Status;
+ UINTN PrdTableNum;
+ UINTN ByteCount;
+ UINTN ByteAvailable;
+ UINT8 *PrdBuffer;
+ UINTN RemainBlockNum;
+ UINT8 DeviceControl;
+
+ //
+ // Channel and device differential
+ //
+ Device = (UINT8) ((IdeDev->Device << 4) | 0xe0);
+
+ //
+ // Enable interrupt to support UDMA and Select device
+ //
+ DeviceControl = 0;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
+
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);
+
+ if (IdePrimary == IdeDev->Channel) {
+ IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICP_OFFSET;
+ IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;
+ IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDP_OFFSET;
+ } else {
+ if (IdeSecondary == IdeDev->Channel) {
+ IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICS_OFFSET;
+ IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET;
+ IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDS_OFFSET;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ RemainBlockNum = NumberOfBlocks;
+ while (RemainBlockNum > 0) {
+
+ if (RemainBlockNum >= MAX_DMA_EXT_COMMAND_SECTORS) {
+ //
+ // SectorCount is used to record the number of sectors to be read
+ // Max 65536 sectors can be transfered at a time.
+ //
+ NumberOfBlocks = MAX_DMA_EXT_COMMAND_SECTORS;
+ RemainBlockNum -= MAX_DMA_EXT_COMMAND_SECTORS;
+ } else {
+ NumberOfBlocks = (UINT16) RemainBlockNum;
+ RemainBlockNum = 0;
+ }
+
+ //
+ // Calculate the number of PRD table to make sure the memory region
+ // not cross 64K boundary
+ //
+ ByteCount = NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;
+ PrdTableNum = ((ByteCount >> 16) + 1) + 1;
+
+ //
+ // Build PRD table
+ //
+ PrdAddr = (IDE_DMA_PRD *) AllocateZeroPool ((2 * PrdTableNum * sizeof (IDE_DMA_PRD)));
+ //
+ // To make sure PRD is allocated in one 64K page
+ //
+ if (((UINTN) PrdAddr & 0x0FFFF) > (((UINTN) PrdAddr + PrdTableNum * sizeof (IDE_DMA_PRD) - 1) & 0x0FFFF)) {
+ UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x10000) & 0xFFFF0000);
+ } else {
+ if ((UINTN) PrdAddr & 0x03) {
+ UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x04) & 0xFFFFFFFC);
+ } else {
+ UsedPrdAddr = PrdAddr;
+ }
+ }
+
+ //
+ // Build the PRD table
+ //
+ PrdBuffer = DataBuffer;
+ TempPrdAddr = UsedPrdAddr;
+ while (TRUE) {
+
+ ByteAvailable = 0x10000 - ((UINTN) PrdBuffer & 0xFFFF);
+
+ if (ByteCount <= ByteAvailable) {
+ TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);
+ TempPrdAddr->ByteCount = (UINT16) ByteCount;
+ TempPrdAddr->EndOfTable = 0x8000;
+ break;
+ }
+
+ TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);
+ TempPrdAddr->ByteCount = (UINT16) ByteAvailable;
+
+ ByteCount -= ByteAvailable;
+ PrdBuffer += ByteAvailable;
+ TempPrdAddr++;
+ }
+
+ //
+ // Set the base address to BMID register
+ //
+ IdeDev->PciIo->Io.Write (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint32,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmid,
+ 1,
+ &UsedPrdAddr
+ );
+
+ //
+ // Set BMIC register to identify the operation direction
+ //
+ IdeDev->PciIo->Io.Read (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+ //
+ // 0000 1000
+ //
+ RegisterValue &= ~((UINT8) BMIC_nREAD);
+
+ IdeDev->PciIo->Io.Write (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+
+ //
+ // Read BMIS register and clear ERROR and INTR bit
+ //
+ IdeDev->PciIo->Io.Read (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmis,
+ 1,
+ &RegisterValue
+ );
+
+ RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);
+
+ IdeDev->PciIo->Io.Write (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmis,
+ 1,
+ &RegisterValue
+ );
+
+ //
+ // Issue WRITE DMA EXT command
+ //
+ Status = AtaCommandIssueExt (
+ IdeDev,
+ WRITE_DMA_EXT_CMD,
+ Device,
+ 0,
+ (UINT16) NumberOfBlocks,
+ StartLba
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (PrdAddr);
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Set START bit of BMIC register
+ //
+ IdeDev->PciIo->Io.Read (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+
+ RegisterValue |= BMIC_START;
+
+ IdeDev->PciIo->Io.Write (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+
+ //
+ // Check the INTERRUPT and ERROR bit of BMIS
+ //
+ while (TRUE) {
+
+ IdeDev->PciIo->Io.Read (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmis,
+ 1,
+ &RegisterValue
+ );
+ if (RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) {
+ if (RegisterValue & BMIS_ERROR) {
+ gBS->FreePool (PrdAddr);
+ return EFI_DEVICE_ERROR;
+ }
+ break;
+ }
+
+ gBS->Stall (1000);
+ }
+
+ gBS->FreePool (PrdAddr);
+
+ //
+ // Set START bit of BMIC register
+ //
+ IdeDev->PciIo->Io.Read (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+
+ RegisterValue &= ~((UINT8) BMIC_START);
+
+ IdeDev->PciIo->Io.Write (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+
+ DataBuffer = (UINT8 *) DataBuffer + NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;
+ StartLba += NumberOfBlocks;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AtaUdmaWrite (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks
+ )
+/*++
+ Name:
+
+ AtaUdmaWrite
+
+ Purpose:
+
+ This function is called by the AtaBlkIoWriteBlocks() to perform
+ writing to media in block unit. The function has been enhanced to
+ support >120GB access and transfer at most 65536 blocks per command
+
+ Parameters:
+
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ VOID IN *DataBuffer
+ A pointer to the source buffer for the data.
+
+ EFI_LBA IN StartLba
+ The starting logical block address to write to
+ on the device media.
+
+ UINTN IN NumberOfBlocks
+ The number of transfer data blocks.
+
+ Returns:
+
+ The device status of UDMA operation. If the operation is
+ successful, return EFI_SUCCESS.
+
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: DataBuffer - add argument and description to function comment
+// TODO: StartLba - add argument and description to function comment
+// TODO: NumberOfBlocks - add argument and description to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+{
+ IDE_DMA_PRD *PrdAddr;
+ IDE_DMA_PRD *UsedPrdAddr;
+ IDE_DMA_PRD *TempPrdAddr;
+ UINT8 RegisterValue;
+ UINT8 Device;
+ UINT64 IoPortForBmic;
+ UINT64 IoPortForBmis;
+ UINT64 IoPortForBmid;
+ EFI_STATUS Status;
+ UINTN PrdTableNum;
+ UINTN ByteCount;
+ UINTN ByteAvailable;
+ UINT8 *PrdBuffer;
+ UINTN RemainBlockNum;
+ UINT8 DeviceControl;
+
+ //
+ // Channel and device differential
+ //
+ Device = (UINT8) ((IdeDev->Device << 4) | 0xe0);
+
+ //
+ // Enable interrupt to support UDMA
+ //
+ DeviceControl = 0;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
+
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);
+
+ if (IdePrimary == IdeDev->Channel) {
+ IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICP_OFFSET;
+ IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET;
+ IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDP_OFFSET;
+ } else {
+ if (IdeSecondary == IdeDev->Channel) {
+ IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICS_OFFSET;
+ IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET;
+ IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDS_OFFSET;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ RemainBlockNum = NumberOfBlocks;
+ while (RemainBlockNum > 0) {
+
+ if (RemainBlockNum >= MAX_DMA_COMMAND_SECTORS) {
+ //
+ // SectorCount is used to record the number of sectors to be read
+ // Max 256 sectors can be transfered at a time.
+ //
+ NumberOfBlocks = MAX_DMA_COMMAND_SECTORS;
+ RemainBlockNum -= MAX_DMA_COMMAND_SECTORS;
+ } else {
+ NumberOfBlocks = (UINT16) RemainBlockNum;
+ RemainBlockNum = 0;
+ }
+
+ //
+ // Calculate the number of PRD table to make sure the memory region
+ // not cross 64K boundary
+ //
+ ByteCount = NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;
+ PrdTableNum = ((ByteCount >> 16) + 1) + 1;
+
+ //
+ // Build PRD table
+ //
+ PrdAddr = (IDE_DMA_PRD *) AllocateZeroPool ((2 * PrdTableNum * sizeof (IDE_DMA_PRD)));
+
+ //
+ // To make sure PRD is allocated in one 64K page
+ //
+ if (((UINTN) PrdAddr & 0x0FFFF) > (((UINTN) PrdAddr + PrdTableNum * sizeof (IDE_DMA_PRD) - 1) & 0x0FFFF)) {
+ UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x10000) & 0xFFFF0000);
+ } else {
+ if ((UINTN) PrdAddr & 0x03) {
+ UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x04) & 0xFFFFFFFC);
+ } else {
+ UsedPrdAddr = PrdAddr;
+ }
+ }
+
+ //
+ // Build the PRD table
+ //
+ PrdBuffer = DataBuffer;
+ TempPrdAddr = UsedPrdAddr;
+ while (TRUE) {
+
+ ByteAvailable = 0x10000 - ((UINTN) PrdBuffer & 0xFFFF);
+
+ if (ByteCount <= ByteAvailable) {
+ TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);
+ TempPrdAddr->ByteCount = (UINT16) ByteCount;
+ TempPrdAddr->EndOfTable = 0x8000;
+ break;
+ }
+
+ TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer);
+ TempPrdAddr->ByteCount = (UINT16) ByteAvailable;
+
+ ByteCount -= ByteAvailable;
+ PrdBuffer += ByteAvailable;
+ TempPrdAddr++;
+ }
+
+ //
+ // Set the base address to BMID register
+ //
+ IdeDev->PciIo->Io.Write (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint32,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmid,
+ 1,
+ &UsedPrdAddr
+ );
+
+ //
+ // Set BMIC register to identify the operation direction
+ //
+ IdeDev->PciIo->Io.Read (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+ //
+ // 0000 1000
+ //
+ RegisterValue &= ~((UINT8) BMIC_nREAD);
+
+ IdeDev->PciIo->Io.Write (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+
+ //
+ // Read BMIS register and clear ERROR and INTR bit
+ //
+ IdeDev->PciIo->Io.Read (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmis,
+ 1,
+ &RegisterValue
+ );
+
+ RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR);
+
+ IdeDev->PciIo->Io.Write (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmis,
+ 1,
+ &RegisterValue
+ );
+
+ //
+ // Issue WRITE DMA command
+ //
+ Status = AtaCommandIssue (
+ IdeDev,
+ WRITE_DMA_CMD,
+ Device,
+ 0,
+ (UINT16) NumberOfBlocks,
+ StartLba
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (PrdAddr);
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Set START bit of BMIC register
+ //
+ IdeDev->PciIo->Io.Read (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+
+ RegisterValue |= BMIC_START;
+
+ IdeDev->PciIo->Io.Write (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+
+ //
+ // Check the INTERRUPT and ERROR bit of BMIS
+ //
+ while (TRUE) {
+
+ IdeDev->PciIo->Io.Read (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmis,
+ 1,
+ &RegisterValue
+ );
+ if (RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) {
+ if (RegisterValue & BMIS_ERROR) {
+ gBS->FreePool (PrdAddr);
+ return EFI_DEVICE_ERROR;
+ }
+ break;
+ }
+
+ gBS->Stall (1000);
+ }
+
+ gBS->FreePool (PrdAddr);
+
+ //
+ // Set START bit of BMIC register
+ //
+ IdeDev->PciIo->Io.Read (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+
+ RegisterValue &= ~((UINT8) BMIC_START);
+
+ IdeDev->PciIo->Io.Write (
+ IdeDev->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ IoPortForBmic,
+ 1,
+ &RegisterValue
+ );
+
+ DataBuffer = (UINT8 *) DataBuffer + NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize;
+ StartLba += NumberOfBlocks;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/atapi.c b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/atapi.c
new file mode 100644
index 0000000..fa004e3
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/atapi.c
@@ -0,0 +1,2591 @@
+/*++
+
+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:
+
+ atapi.c
+
+Abstract:
+
+
+Revision History
+--*/
+
+#include "idebus.h"
+
+STATIC
+EFI_STATUS
+LS120GetMediaStatus (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+ Name:
+ LS120GetMediaStatus
+
+ Purpose:
+ This function is used to get the current status of the media residing
+ in the LS-120 drive or ZIP drive. The media status is returned in the
+ Error Status.
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ Returns:
+ EFI_SUCCESS
+ The media status is achieved successfully and the media
+ can be read/written.
+
+ EFI_DEVICE_ERROR
+ Get Media Status Command is failed.
+
+ EFI_NO_MEDIA
+ There is no media in the drive.
+
+ EFI_WRITE_PROTECTED
+ The media is writing protected.
+
+ Notes:
+ This function must be called after the LS120EnableMediaStatus()
+ with second parameter set to TRUE
+ (means enable media status notification) is called.
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+{
+ UINT8 DeviceSelect;
+ UINT8 StatusValue;
+ EFI_STATUS EfiStatus;
+ //
+ // Poll Alternate Register for BSY clear within timeout.
+ //
+ EfiStatus = WaitForBSYClear2 (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (EfiStatus)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Select device via Device/Head Register.
+ //
+ DeviceSelect = (UINT8) ((IdeDev->Device) << 4 | 0xe0);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, DeviceSelect);
+
+ //
+ // Poll Alternate Register for DRDY set within timeout.
+ // After device is selected, DRDY set indicates the device is ready to
+ // accept command.
+ //
+ EfiStatus = DRDYReady2 (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (EfiStatus)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Get Media Status Command is sent
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, 0xDA);
+
+ //
+ // BSY bit will clear after command is complete.
+ //
+ EfiStatus = WaitForBSYClear2 (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (EfiStatus)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // the media status is returned by the command in the ERROR register
+ //
+ StatusValue = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
+
+ if (StatusValue & bit1) {
+ return EFI_NO_MEDIA;
+ }
+
+ if (StatusValue & bit6) {
+ return EFI_WRITE_PROTECTED;
+ } else {
+ return EFI_SUCCESS;
+ }
+}
+
+STATIC
+EFI_STATUS
+LS120EnableMediaStatus (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN BOOLEAN Enable
+ )
+/*++
+ Name:
+ LS120EnableMediaStatus
+
+ Purpose:
+ This function is used to send Enable Media Status Notification Command
+ or Disable Media Status Notification Command.
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ BOOLEAN IN Enable
+ a flag that indicates whether enable or disable media
+ status notification.
+
+ Returns:
+ EFI_SUCCESS
+ If command completes successfully.
+
+ EFI_DEVICE_ERROR
+ If command failed.
+
+
+ Notes:
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: Enable - add argument and description to function comment
+{
+ UINT8 DeviceSelect;
+ EFI_STATUS Status;
+
+ //
+ // Poll Alternate Register for BSY clear within timeout.
+ //
+ Status = WaitForBSYClear2 (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Select device via Device/Head Register.
+ //
+ DeviceSelect = (UINT8) ((IdeDev->Device) << 4 | 0xe0);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, DeviceSelect);
+
+ //
+ // Poll Alternate Register for DRDY set within timeout.
+ // After device is selected, DRDY set indicates the device is ready to
+ // accept command.
+ //
+ Status = DRDYReady2 (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (Enable) {
+ //
+ // 0x95: Enable media status notification
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x95);
+ } else {
+ //
+ // 0x31: Disable media status notification
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x31);
+ }
+ //
+ // Set Feature Command is sent
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, 0xEF);
+
+ //
+ // BSY bit will clear after command is complete.
+ //
+ Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ATAPIIdentify (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+ Name:
+ ATAPIIdentify
+
+
+ Purpose:
+ This function is called by DiscoverIdeDevice() during its device
+ identification.
+
+ Its main purpose is to get enough information for the device media
+ to fill in the Media data structure of the Block I/O Protocol interface.
+
+ There are 5 steps to reach such objective:
+
+ 1. Sends out the ATAPI Identify Command to the specified device.
+ Only ATAPI device responses to this command. If the command succeeds,
+ it returns the Identify data structure which filled with information
+ about the device. Since the ATAPI device contains removable media,
+ the only meaningful information is the device module name.
+
+ 2. Sends out ATAPI Inquiry Packet Command to the specified device.
+ This command will return inquiry data of the device, which contains
+ the device type information.
+
+ 3. Allocate sense data space for future use. We don't detect the media
+ presence here to improvement boot performance, especially when CD
+ media is present. The media detection will be performed just before
+ each BLK_IO read/write
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ Returns:
+ EFI_SUCCESS
+ Identify ATAPI device successfully.
+
+ EFI_DEVICE_ERROR
+ ATAPI Identify Device Command failed or device type
+ is not supported by this IDE driver.
+
+ Notes:
+ Parameter "IdeDev" will be updated in this function.
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+{
+ EFI_IDENTIFY_DATA *AtapiIdentifyPointer;
+ UINT8 DeviceSelect;
+ EFI_STATUS Status;
+
+ //
+ // device select bit
+ //
+ DeviceSelect = 0;
+ DeviceSelect = (UINT8) ((IdeDev->Device) << 4);
+
+ AtapiIdentifyPointer = AllocatePool (sizeof (EFI_IDENTIFY_DATA));
+ if (AtapiIdentifyPointer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Send ATAPI Identify Command to get IDENTIFY data.
+ //
+ Status = AtaPioDataIn (
+ IdeDev,
+ (VOID *) AtapiIdentifyPointer,
+ sizeof (EFI_IDENTIFY_DATA),
+ ATAPI_IDENTIFY_DEVICE_CMD,
+ DeviceSelect,
+ 0,
+ 0,
+ 0,
+ 0
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (AtapiIdentifyPointer);
+ return EFI_DEVICE_ERROR;
+ }
+
+ IdeDev->pIdData = AtapiIdentifyPointer;
+ PrintAtaModuleName (IdeDev);
+
+ //
+ // Send ATAPI Inquiry Packet Command to get INQUIRY data.
+ //
+ Status = AtapiInquiry (IdeDev);
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (IdeDev->pIdData);
+ //
+ // Make sure the pIdData will not be freed again.
+ //
+ IdeDev->pIdData = NULL;
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Get media removable info from INQUIRY data.
+ //
+ IdeDev->BlkIo.Media->RemovableMedia = (UINT8) ((IdeDev->pInquiryData->RMB & 0x80) == 0x80);
+
+ //
+ // Identify device type via INQUIRY data.
+ //
+ switch (IdeDev->pInquiryData->peripheral_type & 0x1f) {
+
+ //
+ // Magnetic Disk
+ //
+ case 0x00:
+
+ //
+ // device is LS120 or ZIP drive.
+ //
+ IdeDev->Type = IdeMagnetic;
+
+ IdeDev->BlkIo.Media->MediaId = 0;
+ //
+ // Give initial value
+ //
+ IdeDev->BlkIo.Media->MediaPresent = FALSE;
+
+ IdeDev->BlkIo.Media->LastBlock = 0;
+ IdeDev->BlkIo.Media->BlockSize = 0x200;
+ break;
+
+ //
+ // CD-ROM
+ //
+ case 0x05:
+
+ IdeDev->Type = IdeCdRom;
+ IdeDev->BlkIo.Media->MediaId = 0;
+ //
+ // Give initial value
+ //
+ IdeDev->BlkIo.Media->MediaPresent = FALSE;
+
+ IdeDev->BlkIo.Media->LastBlock = 0;
+ IdeDev->BlkIo.Media->BlockSize = 0x800;
+ IdeDev->BlkIo.Media->ReadOnly = TRUE;
+ break;
+
+ //
+ // Tape
+ //
+ case 0x01:
+
+ //
+ // WORM
+ //
+ case 0x04:
+
+ //
+ // Optical
+ //
+ case 0x07:
+
+ default:
+ IdeDev->Type = IdeUnknown;
+ gBS->FreePool (IdeDev->pIdData);
+ gBS->FreePool (IdeDev->pInquiryData);
+ //
+ // Make sure the pIdData and pInquiryData will not be freed again.
+ //
+ IdeDev->pIdData = NULL;
+ IdeDev->pInquiryData = NULL;
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // original sense data numbers
+ //
+ IdeDev->SenseDataNumber = 20;
+
+ IdeDev->SenseData = AllocatePool (IdeDev->SenseDataNumber * sizeof (REQUEST_SENSE_DATA));
+ if (IdeDev->SenseData == NULL) {
+ gBS->FreePool (IdeDev->pIdData);
+ gBS->FreePool (IdeDev->pInquiryData);
+ //
+ // Make sure the pIdData and pInquiryData will not be freed again.
+ //
+ IdeDev->pIdData = NULL;
+ IdeDev->pInquiryData = NULL;
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AtapiInquiry (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+ Name:
+ AtapiInquiry
+
+ Purpose:
+ Sends out ATAPI Inquiry Packet Command to the specified device.
+ This command will return INQUIRY data of the device.
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ Returns:
+ EFI_SUCCESS
+ Inquiry command completes successfully.
+
+ EFI_DEVICE_ERROR
+ Inquiry command failed.
+ Notes:
+ Parameter "IdeDev" will be updated in this function.
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+{
+ ATAPI_PACKET_COMMAND Packet;
+ EFI_STATUS Status;
+ INQUIRY_DATA *InquiryData;
+
+ //
+ // prepare command packet for the ATAPI Inquiry Packet Command.
+ //
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.Inquiry.opcode = INQUIRY;
+ Packet.Inquiry.page_code = 0;
+ Packet.Inquiry.allocation_length = sizeof (INQUIRY_DATA);
+
+ InquiryData = AllocatePool (sizeof (INQUIRY_DATA));
+ if (InquiryData == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Send command packet and get requested Inquiry data.
+ //
+ Status = AtapiPacketCommandIn (
+ IdeDev,
+ &Packet,
+ (UINT16 *) InquiryData,
+ sizeof (INQUIRY_DATA),
+ ATAPITIMEOUT
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (InquiryData);
+ return EFI_DEVICE_ERROR;
+ }
+
+ IdeDev->pInquiryData = InquiryData;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AtapiPacketCommandIn (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN ATAPI_PACKET_COMMAND *Packet,
+ IN UINT16 *Buffer,
+ IN UINT32 ByteCount,
+ IN UINTN TimeOut
+ )
+/*++
+ Name:
+ AtapiPacketCommandIn
+
+ Purpose:
+ This function is used to send out ATAPI commands conforms to the
+ Packet Command with PIO Data In Protocol.
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ ATAPI_PACKET_COMMAND IN *Packet
+ pointer pointing to ATAPI_PACKET_COMMAND data structure
+ which contains the contents of the command.
+
+ UINT16 IN *Buffer
+ buffer contained data transferred from device to host.
+
+ UINT32 IN ByteCount
+ data size in byte unit of the buffer.
+
+ UINTN IN TimeOut
+ this parameter is used to specify the timeout
+ value for the PioReadWriteData() function.
+
+ Returns:
+ EFI_SUCCESS
+ send out the ATAPI packet command successfully
+ and device sends data successfully.
+
+ EFI_DEVICE_ERROR
+ the device failed to send data.
+
+ Notes:
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: Packet - add argument and description to function comment
+// TODO: Buffer - add argument and description to function comment
+// TODO: ByteCount - add argument and description to function comment
+// TODO: TimeOut - add argument and description to function comment
+{
+ UINT16 *CommandIndex;
+ EFI_STATUS Status;
+ UINT32 Count;
+
+ //
+ // Set all the command parameters by fill related registers.
+ // Before write to all the following registers, BSY and DRQ must be 0.
+ //
+ Status = DRQClear2 (IdeDev, ATAPITIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Select device via Device/Head Register.
+ //
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ (UINT8) ((IdeDev->Device << 4) | DEFAULT_CMD) // DEFAULT_CMD: 0xa0 (1010,0000)
+ );
+
+ //
+ // No OVL; No DMA
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x00);
+
+ //
+ // set the transfersize to MAX_ATAPI_BYTE_COUNT to let the device
+ // determine how many data should be transferred.
+ //
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->CylinderLsb,
+ (UINT8) (MAX_ATAPI_BYTE_COUNT & 0x00ff)
+ );
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->CylinderMsb,
+ (UINT8) (MAX_ATAPI_BYTE_COUNT >> 8)
+ );
+
+ //
+ // DEFAULT_CTL:0x0a (0000,1010)
+ // Disable interrupt
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DEFAULT_CTL);
+
+ //
+ // Send Packet command to inform device
+ // that the following data bytes are command packet.
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, PACKET_CMD);
+
+ Status = DRQReady (IdeDev, ATAPITIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Send out command packet
+ //
+ CommandIndex = Packet->Data16;
+ for (Count = 0; Count < 6; Count++, CommandIndex++) {
+
+ IDEWritePortW (IdeDev->PciIo, IdeDev->IoPort->Data, *CommandIndex);
+ gBS->Stall (10);
+ }
+
+ //
+ // call PioReadWriteData() function to get
+ // requested transfer data form device.
+ //
+ return PioReadWriteData (IdeDev, Buffer, ByteCount, 1, TimeOut);
+}
+
+EFI_STATUS
+AtapiPacketCommandOut (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN ATAPI_PACKET_COMMAND *Packet,
+ IN UINT16 *Buffer,
+ IN UINT32 ByteCount,
+ IN UINTN TimeOut
+ )
+/*++
+ Name:
+ AtapiPacketCommandOut
+
+ Purpose:
+ This function is used to send out ATAPI commands conforms to the
+ Packet Command with PIO Data Out Protocol.
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ ATAPI_PACKET_COMMAND IN *Packet
+ pointer pointing to ATAPI_PACKET_COMMAND data structure
+ which contains the contents of the command.
+
+ VOID IN *Buffer
+ buffer contained data transferred from host to device.
+
+ UINT32 IN ByteCount
+ data size in byte unit of the buffer.
+
+ UINTN IN TimeOut
+ this parameter is used to specify the timeout
+ value for the PioReadWriteData() function.
+
+ Returns:
+ EFI_SUCCESS
+ send out the ATAPI packet command successfully
+ and device received data successfully.
+
+ EFI_DEVICE_ERROR
+ the device failed to send data.
+
+ Notes:
+
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: Packet - add argument and description to function comment
+// TODO: Buffer - add argument and description to function comment
+// TODO: ByteCount - add argument and description to function comment
+// TODO: TimeOut - add argument and description to function comment
+{
+ UINT16 *CommandIndex;
+ EFI_STATUS Status;
+ UINT32 Count;
+
+ //
+ // set all the command parameters
+ // Before write to all the following registers, BSY and DRQ must be 0.
+ //
+ Status = DRQClear2 (IdeDev, ATAPITIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Select device via Device/Head Register.
+ //
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ (UINT8) ((IdeDev->Device << 4) | DEFAULT_CMD) // DEFAULT_CMD: 0xa0 (1010,0000)
+ );
+
+ //
+ // No OVL; No DMA
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x00);
+
+ //
+ // set the transfersize to MAX_ATAPI_BYTE_COUNT to
+ // let the device determine how many data should be transferred.
+ //
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->CylinderLsb,
+ (UINT8) (MAX_ATAPI_BYTE_COUNT & 0x00ff)
+ );
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->CylinderMsb,
+ (UINT8) (MAX_ATAPI_BYTE_COUNT >> 8)
+ );
+
+ //
+ // DEFAULT_CTL:0x0a (0000,1010)
+ // Disable interrupt
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DEFAULT_CTL);
+
+ //
+ // Send Packet command to inform device
+ // that the following data bytes are command packet.
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, PACKET_CMD);
+
+ Status = DRQReady2 (IdeDev, ATAPITIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Send out command packet
+ //
+ CommandIndex = Packet->Data16;
+ for (Count = 0; Count < 6; Count++, CommandIndex++) {
+ IDEWritePortW (IdeDev->PciIo, IdeDev->IoPort->Data, *CommandIndex);
+ gBS->Stall (10);
+ }
+
+ //
+ // call PioReadWriteData() function to send requested transfer data to device.
+ //
+ return PioReadWriteData (IdeDev, Buffer, ByteCount, 0, TimeOut);
+}
+
+EFI_STATUS
+PioReadWriteData (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINT16 *Buffer,
+ IN UINT32 ByteCount,
+ IN BOOLEAN Read,
+ IN UINTN TimeOut
+ )
+/*++
+ Name:
+ PioReadWriteData
+
+ Purpose:
+ This function is called by either AtapiPacketCommandIn() or
+ AtapiPacketCommandOut(). It is used to transfer data between
+ host and device. The data direction is specified by the fourth
+ parameter.
+
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ VOID IN *Buffer
+ buffer contained data transferred between host and device.
+
+ UINT32 IN ByteCount
+ data size in byte unit of the buffer.
+
+ BOOLEAN IN Read
+ flag used to determine the data transfer direction.
+ Read equals 1, means data transferred from device to host;
+ Read equals 0, means data transferred from host to device.
+
+ UINTN IN TimeOut
+ timeout value for wait DRQ ready before each data
+ stream's transfer.
+
+ Returns:
+ EFI_SUCCESS
+ data is transferred successfully.
+
+ EFI_DEVICE_ERROR
+ the device failed to transfer data.
+
+ Notes:
+
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: Buffer - add argument and description to function comment
+// TODO: ByteCount - add argument and description to function comment
+// TODO: Read - add argument and description to function comment
+// TODO: TimeOut - add argument and description to function comment
+{
+ //
+ // required transfer data in word unit.
+ //
+ UINT32 RequiredWordCount;
+
+ //
+ // actual transfer data in word unit.
+ //
+ UINT32 ActualWordCount;
+ UINT32 WordCount;
+ EFI_STATUS Status;
+ UINT16 *PtrBuffer;
+
+ //
+ // containing status byte read from Status Register.
+ //
+ UINT8 StatusRegister;
+
+ //
+ // No data transfer is premitted.
+ //
+ if (ByteCount == 0) {
+ return EFI_SUCCESS;
+ }
+ //
+ // for performance, we assert the ByteCount is an even number
+ // which is actually a resonable assumption
+ ASSERT((ByteCount%2) == 0);
+
+ PtrBuffer = Buffer;
+ RequiredWordCount = ByteCount / 2;
+ //
+ // ActuralWordCount means the word count of data really transferred.
+ //
+ ActualWordCount = 0;
+
+ while (ActualWordCount < RequiredWordCount) {
+
+ //
+ // before each data transfer stream, the host should poll DRQ bit ready,
+ // to see whether indicates device is ready to transfer data.
+ //
+ Status = DRQReady2 (IdeDev, TimeOut);
+ if (EFI_ERROR (Status)) {
+ return CheckErrorStatus (IdeDev);
+ }
+
+ //
+ // read Status Register will clear interrupt
+ //
+ StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
+
+ //
+ // get current data transfer size from Cylinder Registers.
+ //
+ WordCount =
+ (
+ (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb) << 8) |
+ IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb)
+ ) & 0xffff;
+ WordCount /= 2;
+
+ WordCount = EFI_MIN (WordCount, (RequiredWordCount - ActualWordCount));
+
+ if (Read) {
+ IDEReadPortWMultiple (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Data,
+ WordCount,
+ PtrBuffer
+ );
+ } else {
+ IDEWritePortWMultiple (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Data,
+ WordCount,
+ PtrBuffer
+ );
+ }
+
+ PtrBuffer += WordCount;
+ ActualWordCount += WordCount;
+ }
+
+ //
+ // After data transfer is completed, normally, DRQ bit should clear.
+ //
+ Status = DRQClear2 (IdeDev, ATAPITIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // read status register to check whether error happens.
+ //
+ return CheckErrorStatus (IdeDev);
+}
+
+EFI_STATUS
+AtapiTestUnitReady (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+ Name:
+ AtapiTestUnitReady
+
+ Purpose:
+ Sends out ATAPI Test Unit Ready Packet Command to the specified device
+ to find out whether device is accessible.
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ Returns:
+ EFI_SUCCESS
+ device is accessible.
+
+ EFI_DEVICE_ERROR
+ device is not accessible.
+
+ Notes:
+
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+{
+ ATAPI_PACKET_COMMAND Packet;
+ EFI_STATUS Status;
+
+ //
+ // fill command packet
+ //
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.TestUnitReady.opcode = TEST_UNIT_READY;
+
+ //
+ // send command packet
+ //
+ Status = AtapiPacketCommandIn (IdeDev, &Packet, NULL, 0, ATAPITIMEOUT);
+ return Status;
+}
+
+EFI_STATUS
+AtapiRequestSense (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ OUT UINTN *SenseCounts
+ )
+/*++
+ Name:
+ AtapiRequestSense
+
+ Purpose:
+ Sends out ATAPI Request Sense Packet Command to the specified device.
+ This command will return all the current Sense data in the device.
+ This function will pack all the Sense data in one single buffer.
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ UINT16 OUT **SenseBuffers
+ allocated in this function, and freed by the calling function.
+ This buffer is used to accommodate all the sense data returned
+ by the device.
+
+ UINTN OUT *BufUnit
+ record the unit size of the sense data block in the SenseBuffers,
+
+ UINTN OUT *BufNumbers
+ record the number of units in the SenseBuffers.
+
+ Returns:
+ EFI_SUCCESS
+ Request Sense command completes successfully.
+
+ EFI_DEVICE_ERROR
+ Request Sense command failed.
+
+ Notes:
+
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: SenseCounts - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ REQUEST_SENSE_DATA *Sense;
+ UINT16 *Ptr;
+ BOOLEAN FetchSenseData;
+ ATAPI_PACKET_COMMAND Packet;
+
+ *SenseCounts = 0;
+
+ ZeroMem (IdeDev->SenseData, sizeof (REQUEST_SENSE_DATA) * (IdeDev->SenseDataNumber));
+ //
+ // fill command packet for Request Sense Packet Command
+ //
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.RequestSence.opcode = REQUEST_SENSE;
+ Packet.RequestSence.allocation_length = sizeof (REQUEST_SENSE_DATA);
+
+ //
+ // initialize pointer
+ //
+ Ptr = (UINT16 *) IdeDev->SenseData;
+ //
+ // request sense data from device continuously until no sense data
+ // exists in the device.
+ //
+ for (FetchSenseData = TRUE; FetchSenseData;) {
+
+ Sense = (REQUEST_SENSE_DATA *) Ptr;
+
+ //
+ // send out Request Sense Packet Command and get one Sense data form device
+ //
+ Status = AtapiPacketCommandIn (
+ IdeDev,
+ &Packet,
+ Ptr,
+ sizeof (REQUEST_SENSE_DATA),
+ ATAPITIMEOUT
+ );
+ //
+ // failed to get Sense data
+ //
+ if (EFI_ERROR (Status)) {
+ if (*SenseCounts == 0) {
+ return EFI_DEVICE_ERROR;
+ } else {
+ return EFI_SUCCESS;
+ }
+ }
+
+ (*SenseCounts)++;
+ //
+ // We limit MAX sense data count to 20 in order to avoid dead loop. Some
+ // incompatible ATAPI devices don't retrive NO_SENSE when there is no media.
+ // In this case, dead loop occurs if we don't have a gatekeeper. 20 is
+ // supposed to be large enough for any ATAPI device.
+ //
+ if ((Sense->sense_key != SK_NO_SENSE) && ((*SenseCounts) < 20)) {
+ //
+ // Ptr is word-based pointer
+ //
+ Ptr += sizeof (REQUEST_SENSE_DATA) / 2;
+
+ } else {
+ //
+ // when no sense key, skip out the loop
+ //
+ FetchSenseData = FALSE;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AtapiReadCapacity (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+ Name:
+ AtapiReadCapacity
+
+ Purpose:
+ Sends out ATAPI Read Capacity Packet Command to the specified device.
+ This command will return the information regarding the capacity of the
+ media in the device.
+
+ Current device status will impact device's response to the Read Capacity
+ Command. For example, if the device once reset, the Read Capacity
+ Command will fail. The Sense data record the current device status, so
+ if the Read Capacity Command failed, the Sense data must be requested
+ and be analyzed to determine if the Read Capacity Command should retry.
+
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ Returns:
+ EFI_SUCCESS
+ Read Capacity Command finally completes successfully.
+
+ EFI_DEVICE_ERROR
+ Read Capacity Command failed because of device error.
+
+ Notes:
+ parameter "IdeDev" will be updated in this function.
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: EFI_NOT_READY - add return value to function comment
+{
+ //
+ // status returned by Read Capacity Packet Command
+ //
+ EFI_STATUS Status;
+ ATAPI_PACKET_COMMAND Packet;
+
+ //
+ // used for capacity data returned from ATAPI device
+ //
+ READ_CAPACITY_DATA Data;
+ READ_FORMAT_CAPACITY_DATA FormatData;
+
+ ZeroMem (&Data, sizeof (Data));
+ ZeroMem (&FormatData, sizeof (FormatData));
+
+ if (IdeDev->Type == IdeCdRom) {
+
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.Inquiry.opcode = READ_CAPACITY;
+ Status = AtapiPacketCommandIn (
+ IdeDev,
+ &Packet,
+ (UINT16 *) &Data,
+ sizeof (READ_CAPACITY_DATA),
+ ATAPITIMEOUT
+ );
+
+ } else {
+ //
+ // Type == IdeMagnetic
+ //
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Packet.ReadFormatCapacity.opcode = READ_FORMAT_CAPACITY;
+ Packet.ReadFormatCapacity.allocation_length_lo = 12;
+ Status = AtapiPacketCommandIn (
+ IdeDev,
+ &Packet,
+ (UINT16 *) &FormatData,
+ sizeof (READ_FORMAT_CAPACITY_DATA),
+ ATAPITIMEOUT
+ );
+ }
+
+ if (!EFI_ERROR (Status)) {
+
+ if (IdeDev->Type == IdeCdRom) {
+
+ IdeDev->BlkIo.Media->LastBlock = (Data.LastLba3 << 24) |
+ (Data.LastLba2 << 16) |
+ (Data.LastLba1 << 8) |
+ Data.LastLba0;
+
+ if (IdeDev->BlkIo.Media->LastBlock != 0) {
+
+ IdeDev->BlkIo.Media->BlockSize = (Data.BlockSize3 << 24) |
+ (Data.BlockSize2 << 16) |
+ (Data.BlockSize1 << 8) |
+ Data.BlockSize0;
+
+ IdeDev->BlkIo.Media->MediaPresent = TRUE;
+ } else {
+ IdeDev->BlkIo.Media->MediaPresent = FALSE;
+ return EFI_DEVICE_ERROR;
+ }
+
+ IdeDev->BlkIo.Media->ReadOnly = TRUE;
+
+ //
+ // Because the user data portion in the sector of the Data CD supported
+ // is always 0x800
+ //
+ IdeDev->BlkIo.Media->BlockSize = 0x800;
+ }
+
+ if (IdeDev->Type == IdeMagnetic) {
+
+ if (FormatData.DesCode == 3) {
+ IdeDev->BlkIo.Media->MediaPresent = FALSE;
+ IdeDev->BlkIo.Media->LastBlock = 0;
+ } else {
+
+ IdeDev->BlkIo.Media->LastBlock = (FormatData.LastLba3 << 24) |
+ (FormatData.LastLba2 << 16) |
+ (FormatData.LastLba1 << 8) |
+ FormatData.LastLba0;
+ if (IdeDev->BlkIo.Media->LastBlock != 0) {
+ IdeDev->BlkIo.Media->LastBlock--;
+
+ IdeDev->BlkIo.Media->BlockSize = (FormatData.BlockSize2 << 16) |
+ (FormatData.BlockSize1 << 8) |
+ FormatData.BlockSize0;
+
+ IdeDev->BlkIo.Media->MediaPresent = TRUE;
+ } else {
+ IdeDev->BlkIo.Media->MediaPresent = FALSE;
+ //
+ // Return EFI_NOT_READY operation succeeds but returned capacity is 0
+ //
+ return EFI_NOT_READY;
+ }
+
+ IdeDev->BlkIo.Media->BlockSize = 0x200;
+
+ }
+ }
+
+ return EFI_SUCCESS;
+
+ } else {
+
+ return EFI_DEVICE_ERROR;
+ }
+}
+
+EFI_STATUS
+AtapiDetectMedia (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ OUT BOOLEAN *MediaChange
+ )
+/*++
+ Name:
+ AtapiDetectMedia
+
+ Purpose:
+ Used before read/write blocks from/to ATAPI device media.
+ Since ATAPI device media is removable, it is necessary to detect
+ whether media is present and get current present media's
+ information, and if media has been changed, Block I/O Protocol
+ need to be reinstalled.
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ BOOLEAN OUT *MediaChange
+ return value that indicates if the media of the device has been
+ changed.
+
+ Returns:
+ EFI_SUCCESS
+ media found successfully.
+
+ EFI_DEVICE_ERROR
+ any error encounters during media detection.
+
+ EFI_NO_MEDIA
+ media not found.
+
+ Notes:
+ parameter IdeDev may be updated in this function.
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: MediaChange - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ EFI_STATUS ReadCapacityStatus;
+ EFI_BLOCK_IO_MEDIA OldMediaInfo;
+ UINTN SenseCounts;
+ UINTN RetryIndex;
+ UINTN RetryTimes;
+ UINTN MaximumRetryTimes;
+ UINTN ReadyWaitFactor;
+ BOOLEAN NeedRetry;
+ //
+ // a flag used to determine whether need to perform Read Capacity command.
+ //
+ BOOLEAN NeedReadCapacity;
+ BOOLEAN WriteProtected;
+
+ //
+ // init
+ //
+ CopyMem (&OldMediaInfo, IdeDev->BlkIo.Media, sizeof (OldMediaInfo));
+ // OldMediaInfo = *(IdeDev->BlkIo.Media);
+ *MediaChange = FALSE;
+ ReadCapacityStatus = EFI_DEVICE_ERROR;
+
+ //
+ // if there is no media, or media is not changed,
+ // the request sense command will detect faster than read capacity command.
+ // read capacity command can be bypassed, thus improve performance.
+ //
+
+ //
+ // Test Unit Ready command is used to detect whether device is accessible,
+ // the device will produce corresponding Sense data.
+ //
+ for (RetryIndex = 0; RetryIndex < 2; RetryIndex++) {
+
+ Status = AtapiTestUnitReady (IdeDev);
+ if (!EFI_ERROR (Status)) {
+ //
+ // skip the loop if test unit command succeeds.
+ //
+ break;
+ }
+
+ Status = AtapiSoftReset (IdeDev);
+
+ if (EFI_ERROR (Status)) {
+ AtaSoftReset (IdeDev);
+ }
+ }
+
+ SenseCounts = 0;
+ NeedReadCapacity = TRUE;
+
+ //
+ // at most retry 5 times
+ //
+ MaximumRetryTimes = 5;
+ RetryTimes = 1;
+
+ for (RetryIndex = 0;
+ (RetryIndex < RetryTimes) && (RetryIndex < MaximumRetryTimes);
+ RetryIndex++) {
+
+ Status = AtapiRequestSense (IdeDev, &SenseCounts);
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // if first time there is no Sense Key, no need to read capacity any more
+ //
+ if (!HaveSenseKey (IdeDev->SenseData, SenseCounts) &&
+ (IdeDev->BlkIo.Media->MediaPresent)) {
+
+ if (RetryIndex == 0) {
+ NeedReadCapacity = FALSE;
+ }
+
+ } else {
+ //
+ // No Media
+ //
+ if (IsNoMedia (IdeDev->SenseData, SenseCounts)) {
+ NeedReadCapacity = FALSE;
+ IdeDev->BlkIo.Media->MediaPresent = FALSE;
+ IdeDev->BlkIo.Media->LastBlock = 0;
+ } else {
+ //
+ // Media Changed
+ //
+ if (IsMediaChange (IdeDev->SenseData, SenseCounts)) {
+ NeedReadCapacity = TRUE;
+ IdeDev->BlkIo.Media->MediaId++;
+ }
+ //
+ // Media Error
+ //
+ if (IsMediaError (IdeDev->SenseData, SenseCounts)) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ }
+ } else {
+ //
+ // retry once more, if request sense command met errors.
+ //
+ RetryTimes++;
+ }
+ }
+
+ if (NeedReadCapacity) {
+ //
+ // at most retry 5 times
+ //
+ MaximumRetryTimes = 5;
+ //
+ // initial retry twice
+ //
+ RetryTimes = 2;
+ ReadyWaitFactor = 2;
+
+ for (RetryIndex = 0;
+ (RetryIndex < RetryTimes) && (RetryIndex < MaximumRetryTimes);
+ RetryIndex++) {
+
+ ReadCapacityStatus = AtapiReadCapacity (IdeDev);
+
+ SenseCounts = 0;
+
+ if (!EFI_ERROR (ReadCapacityStatus)) {
+ //
+ // Read Capacity succeeded
+ //
+ break;
+
+ } else {
+
+ if (ReadCapacityStatus == EFI_NOT_READY) {
+ //
+ // If device not ready, wait here... waiting time increases by retry
+ // times.
+ //
+ gBS->Stall (ReadyWaitFactor * 2000 * STALL_1_MILLI_SECOND);
+ ReadyWaitFactor++;
+ //
+ // retry once more
+ //
+ RetryTimes++;
+ continue;
+ }
+
+ //
+ // Other errors returned, requery sense data
+ //
+ Status = AtapiRequestSense (IdeDev, &SenseCounts);
+
+ //
+ // If Request Sense data failed, reset the device and retry.
+ //
+ if (EFI_ERROR (Status)) {
+
+ Status = AtapiSoftReset (IdeDev);
+
+ //
+ // if ATAPI soft reset fail,
+ // use stronger reset mechanism -- ATA soft reset.
+ //
+ if (EFI_ERROR (Status)) {
+ AtaSoftReset (IdeDev);
+ }
+ //
+ // retry once more
+ //
+ RetryTimes++;
+ continue;
+ }
+
+ //
+ // No Media
+ //
+ if (IsNoMedia (IdeDev->SenseData, SenseCounts)) {
+
+ IdeDev->BlkIo.Media->MediaPresent = FALSE;
+ IdeDev->BlkIo.Media->LastBlock = 0;
+ return EFI_NO_MEDIA;
+ }
+
+ if (IsMediaError (IdeDev->SenseData, SenseCounts)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Media Changed
+ //
+ if (IsMediaChange (IdeDev->SenseData, SenseCounts)) {
+ IdeDev->BlkIo.Media->MediaId++;
+ }
+
+ if (!IsDriveReady (IdeDev->SenseData, SenseCounts, &NeedRetry)) {
+
+ //
+ // Drive not ready: if NeedRetry, then retry once more;
+ // else return error
+ //
+ if (NeedRetry) {
+ //
+ // Stall 1 second to wait for drive becoming ready
+ //
+ gBS->Stall (1000 * STALL_1_MILLI_SECOND);
+ //
+ // reset retry variable to zero,
+ // to make it retry for "drive in progress of becoming ready".
+ //
+ RetryIndex = 0;
+ continue;
+ } else {
+ AtapiSoftReset (IdeDev);
+ return EFI_DEVICE_ERROR;
+ }
+ }
+ //
+ // if read capacity fail not for above reasons, retry once more
+ //
+ RetryTimes++;
+ }
+
+ }
+
+ //
+ // tell whether the readcapacity process is successful or not in the end
+ //
+ if (EFI_ERROR (ReadCapacityStatus)) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ //
+ // the following code is to check the write-protected for LS120 media
+ //
+ if ((IdeDev->BlkIo.Media->MediaPresent) && (IdeDev->Type == IdeMagnetic)) {
+
+ Status = IsLS120orZipWriteProtected (IdeDev, &WriteProtected);
+ if (!EFI_ERROR (Status)) {
+
+ if (WriteProtected) {
+
+ IdeDev->BlkIo.Media->ReadOnly = TRUE;
+ } else {
+
+ IdeDev->BlkIo.Media->ReadOnly = FALSE;
+ }
+
+ }
+ }
+
+ if (IdeDev->BlkIo.Media->MediaId != OldMediaInfo.MediaId) {
+ //
+ // Media change information got from the device
+ //
+ *MediaChange = TRUE;
+ }
+
+ if (IdeDev->BlkIo.Media->ReadOnly != OldMediaInfo.ReadOnly) {
+ *MediaChange = TRUE;
+ IdeDev->BlkIo.Media->MediaId += 1;
+ }
+
+ if (IdeDev->BlkIo.Media->BlockSize != OldMediaInfo.BlockSize) {
+ *MediaChange = TRUE;
+ IdeDev->BlkIo.Media->MediaId += 1;
+ }
+
+ if (IdeDev->BlkIo.Media->LastBlock != OldMediaInfo.LastBlock) {
+ *MediaChange = TRUE;
+ IdeDev->BlkIo.Media->MediaId += 1;
+ }
+
+ if (IdeDev->BlkIo.Media->MediaPresent != OldMediaInfo.MediaPresent) {
+ if (IdeDev->BlkIo.Media->MediaPresent) {
+ //
+ // when change from no media to media present, reset the MediaId to 1.
+ //
+ IdeDev->BlkIo.Media->MediaId = 1;
+ } else {
+ //
+ // when no media, reset the MediaId to zero.
+ //
+ IdeDev->BlkIo.Media->MediaId = 0;
+ }
+
+ *MediaChange = TRUE;
+ }
+
+ //
+ // if any change on current existing media,
+ // the Block I/O protocol need to be reinstalled.
+ //
+ if (*MediaChange) {
+ gBS->ReinstallProtocolInterface (
+ IdeDev->Handle,
+ &gEfiBlockIoProtocolGuid,
+ &IdeDev->BlkIo,
+ &IdeDev->BlkIo
+ );
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+AtapiReadSectors (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *Buffer,
+ IN EFI_LBA Lba,
+ IN UINTN NumberOfBlocks
+ )
+/*++
+ Name:
+ AtapiReadSectors
+
+ Purpose:
+ This function is called by the AtapiBlkIoReadBlocks() to perform
+ read from media in block unit.
+
+ The main command used to access media here is READ(10) Command.
+ READ(10) Command requests that the ATAPI device media transfer
+ specified data to the host. Data is transferred in block(sector)
+ unit. The maximum number of blocks that can be transferred once is
+ 65536. This is the main difference between READ(10) and READ(12)
+ Command. The maximum number of blocks in READ(12) is 2 power 32.
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ VOID IN *Buffer
+ A pointer to the destination buffer for the data.
+
+ EFI_LBA IN Lba
+ The starting logical block address to read from
+ on the device media.
+
+ UINTN IN NumberOfBlocks
+ The number of transfer data blocks.
+
+ Returns:
+ return status is fully dependent on the return status
+ of AtapiPacketCommandIn() function.
+
+ Notes:
+
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: Buffer - add argument and description to function comment
+// TODO: Lba - add argument and description to function comment
+// TODO: NumberOfBlocks - add argument and description to function comment
+{
+
+ ATAPI_PACKET_COMMAND Packet;
+ READ10_CMD *Read10Packet;
+ EFI_STATUS Status;
+ UINTN BlocksRemaining;
+ UINT32 Lba32;
+ UINT32 BlockSize;
+ UINT32 ByteCount;
+ UINT16 SectorCount;
+ VOID *PtrBuffer;
+ UINT16 MaxBlock;
+ UINTN TimeOut;
+
+ //
+ // fill command packet for Read(10) command
+ //
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Read10Packet = &Packet.Read10;
+ Lba32 = (UINT32) Lba;
+ PtrBuffer = Buffer;
+
+ BlockSize = IdeDev->BlkIo.Media->BlockSize;
+
+ //
+ // limit the data bytes that can be transferred by one Read(10) Command
+ //
+ MaxBlock = (UINT16) (65536 / BlockSize);
+
+ BlocksRemaining = NumberOfBlocks;
+
+ Status = EFI_SUCCESS;
+ while (BlocksRemaining > 0) {
+
+ if (BlocksRemaining <= MaxBlock) {
+
+ SectorCount = (UINT16) BlocksRemaining;
+ } else {
+
+ SectorCount = MaxBlock;
+ }
+
+ //
+ // fill the Packet data structure
+ //
+
+ Read10Packet->opcode = READ_10;
+
+ //
+ // Lba0 ~ Lba3 specify the start logical block address of the data transfer.
+ // Lba0 is MSB, Lba3 is LSB
+ //
+ Read10Packet->Lba3 = (UINT8) (Lba32 & 0xff);
+ Read10Packet->Lba2 = (UINT8) (Lba32 >> 8);
+ Read10Packet->Lba1 = (UINT8) (Lba32 >> 16);
+ Read10Packet->Lba0 = (UINT8) (Lba32 >> 24);
+
+ //
+ // TranLen0 ~ TranLen1 specify the transfer length in block unit.
+ // TranLen0 is MSB, TranLen is LSB
+ //
+ Read10Packet->TranLen1 = (UINT8) (SectorCount & 0xff);
+ Read10Packet->TranLen0 = (UINT8) (SectorCount >> 8);
+
+ ByteCount = SectorCount * BlockSize;
+
+ if (IdeDev->Type == IdeCdRom) {
+ TimeOut = CDROMLONGTIMEOUT;
+ } else {
+ TimeOut = ATAPILONGTIMEOUT;
+ }
+
+ Status = AtapiPacketCommandIn (
+ IdeDev,
+ &Packet,
+ (UINT16 *) PtrBuffer,
+ ByteCount,
+ TimeOut
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Lba32 += SectorCount;
+ PtrBuffer = (UINT8 *) PtrBuffer + SectorCount * BlockSize;
+ BlocksRemaining -= SectorCount;
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+AtapiWriteSectors (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *Buffer,
+ IN EFI_LBA Lba,
+ IN UINTN NumberOfBlocks
+ )
+/*++
+ Name:
+ AtapiWriteSectors
+
+ Purpose:
+ This function is called by the AtapiBlkIoWriteBlocks() to perform
+ write onto media in block unit.
+ The main command used to access media here is Write(10) Command.
+ Write(10) Command requests that the ATAPI device media transfer
+ specified data to the host. Data is transferred in block (sector)
+ unit. The maximum number of blocks that can be transferred once is
+ 65536.
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ VOID IN *Buffer
+ A pointer to the source buffer for the data.
+
+ EFI_LBA IN Lba
+ The starting logical block address to write onto
+ the device media.
+
+ UINTN IN NumberOfBlocks
+ The number of transfer data blocks.
+
+ Returns:
+ return status is fully dependent on the return status
+ of AtapiPacketCommandOut() function.
+
+ Notes:
+
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: Buffer - add argument and description to function comment
+// TODO: Lba - add argument and description to function comment
+// TODO: NumberOfBlocks - add argument and description to function comment
+{
+
+ ATAPI_PACKET_COMMAND Packet;
+ READ10_CMD *Read10Packet;
+
+ EFI_STATUS Status;
+ UINTN BlocksRemaining;
+ UINT32 Lba32;
+ UINT32 BlockSize;
+ UINT32 ByteCount;
+ UINT16 SectorCount;
+ VOID *PtrBuffer;
+ UINT16 MaxBlock;
+
+ //
+ // fill command packet for Write(10) command
+ // Write(10) command packet has the same data structure as
+ // Read(10) command packet,
+ // so here use the Read10Packet data structure
+ // for the Write(10) command packet.
+ //
+ ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND));
+ Read10Packet = &Packet.Read10;
+
+ Lba32 = (UINT32) Lba;
+ PtrBuffer = Buffer;
+
+ BlockSize = IdeDev->BlkIo.Media->BlockSize;
+
+ //
+ // limit the data bytes that can be transferred by one Read(10) Command
+ //
+ MaxBlock = (UINT16) (65536 / BlockSize);
+
+ BlocksRemaining = NumberOfBlocks;
+
+ Status = EFI_SUCCESS;
+ while (BlocksRemaining > 0) {
+
+ if (BlocksRemaining >= MaxBlock) {
+ SectorCount = MaxBlock;
+ } else {
+ SectorCount = (UINT16) BlocksRemaining;
+ }
+
+ //
+ // Command code is WRITE_10.
+ //
+ Read10Packet->opcode = WRITE_10;
+
+ //
+ // Lba0 ~ Lba3 specify the start logical block address of the data transfer.
+ // Lba0 is MSB, Lba3 is LSB
+ //
+ Read10Packet->Lba3 = (UINT8) (Lba32 & 0xff);
+ Read10Packet->Lba2 = (UINT8) (Lba32 >> 8);
+ Read10Packet->Lba1 = (UINT8) (Lba32 >> 16);
+ Read10Packet->Lba0 = (UINT8) (Lba32 >> 24);
+
+ //
+ // TranLen0 ~ TranLen1 specify the transfer length in block unit.
+ // TranLen0 is MSB, TranLen is LSB
+ //
+ Read10Packet->TranLen1 = (UINT8) (SectorCount & 0xff);
+ Read10Packet->TranLen0 = (UINT8) (SectorCount >> 8);
+
+ ByteCount = SectorCount * BlockSize;
+
+ Status = AtapiPacketCommandOut (
+ IdeDev,
+ &Packet,
+ (UINT16 *) PtrBuffer,
+ ByteCount,
+ ATAPILONGTIMEOUT
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Lba32 += SectorCount;
+ PtrBuffer = ((UINT8 *) PtrBuffer + SectorCount * BlockSize);
+ BlocksRemaining -= SectorCount;
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+AtapiSoftReset (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+ Name:
+ AtapiSoftReset
+
+ Purpose:
+ This function is used to implement the Soft Reset on the specified
+ ATAPI device. Different from the AtaSoftReset(), here reset is a ATA
+ Soft Reset Command special for ATAPI device, and it only take effects
+ on the specified ATAPI device, not on the whole IDE bus.
+ Since the ATAPI soft reset is needed when device is in exceptional
+ condition (such as BSY bit is always set ), I think the Soft Reset
+ command should be sent without waiting for the BSY clear and DRDY
+ set.
+ This function is called by IdeBlkIoReset(),
+ a interface function of Block I/O protocol.
+
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ Returns:
+ EFI_SUCCESS
+ Soft reset completes successfully.
+
+ EFI_DEVICE_ERROR
+ Any step during the reset process is failed.
+
+ Notes:
+
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+{
+ UINT8 Command;
+ UINT8 DeviceSelect;
+ EFI_STATUS Status;
+
+ //
+ // for ATAPI device, no need to wait DRDY ready after device selecting.
+ // (bit7 and bit5 are both set to 1 for backward compatibility)
+ //
+ DeviceSelect = (UINT8) (((bit7 | bit5) | (IdeDev->Device << 4)));
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, DeviceSelect);
+
+ Command = ATAPI_SOFT_RESET_CMD;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, Command);
+
+ //
+ // BSY cleared is the only status return to the host by the device
+ // when reset is completed.
+ // slave device needs at most 31s to clear BSY
+ //
+ Status = WaitForBSYClear (IdeDev, 31000);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // stall 5 seconds to make the device status stable
+ //
+ gBS->Stall (5000000);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AtapiBlkIoReadBlocks (
+ IN IDE_BLK_IO_DEV *IdeBlkIoDevice,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+/*++
+ Name:
+ AtapiBlkIoReadBlocks
+
+ Purpose:
+ This function is the ATAPI implementation for ReadBlocks in the
+ Block I/O Protocol interface.
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeBlkIoDev
+ Indicates the calling context.
+
+ UINT32 IN MediaId
+ The media id that the read request is for.
+
+ EFI_LBA IN LBA
+ The starting logical block address to read from
+ on the device.
+
+ UINTN IN BufferSize
+ The size of the Buffer in bytes. This must be a
+ multiple of the intrinsic block size of the device.
+
+ VOID OUT *Buffer
+ A pointer to the destination buffer for the data.
+ The caller is responsible for either having implicit
+ or explicit ownership of the memory that data is read into.
+
+ Returns:
+ EFI_SUCCESS
+ Read Blocks successfully.
+
+ EFI_DEVICE_ERROR
+ Read Blocks failed.
+
+ 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 data buffer is not valid.
+
+ Notes:
+
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeBlkIoDevice - add argument and description to function comment
+// TODO: MediaId - add argument and description to function comment
+// TODO: LBA - add argument and description to function comment
+// TODO: BufferSize - add argument and description to function comment
+// TODO: Buffer - add argument and description to function comment
+{
+ EFI_BLOCK_IO_MEDIA *Media;
+ UINTN BlockSize;
+ UINTN NumberOfBlocks;
+ EFI_STATUS Status;
+
+ BOOLEAN MediaChange;
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // ATAPI device media is removable, so it is a must
+ // to detect media first before read operation
+ //
+ MediaChange = FALSE;
+ Status = AtapiDetectMedia (IdeBlkIoDevice, &MediaChange);
+ if (EFI_ERROR (Status)) {
+
+ if (IdeBlkIoDevice->Cache != NULL) {
+ gBS->FreePool (IdeBlkIoDevice->Cache);
+ IdeBlkIoDevice->Cache = NULL;
+ }
+
+ return Status;
+ }
+ //
+ // Get the intrinsic block size
+ //
+ Media = IdeBlkIoDevice->BlkIo.Media;
+ BlockSize = Media->BlockSize;
+
+ NumberOfBlocks = BufferSize / BlockSize;
+
+ if (!(Media->MediaPresent)) {
+
+ if (IdeBlkIoDevice->Cache != NULL) {
+ gBS->FreePool (IdeBlkIoDevice->Cache);
+ IdeBlkIoDevice->Cache = NULL;
+ }
+ return EFI_NO_MEDIA;
+
+ }
+
+ if ((MediaId != Media->MediaId) || MediaChange) {
+
+ if (IdeBlkIoDevice->Cache != NULL) {
+ gBS->FreePool (IdeBlkIoDevice->Cache);
+ IdeBlkIoDevice->Cache = NULL;
+ }
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (BufferSize % BlockSize != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ if (LBA > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // if all the parameters are valid, then perform read sectors command
+ // to transfer data from device to host.
+ //
+ Status = AtapiReadSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Read blocks succeeded
+ //
+
+ //
+ // save the first block to the cache for performance
+ //
+ if (LBA == 0 && !IdeBlkIoDevice->Cache) {
+ IdeBlkIoDevice->Cache = AllocatePool (BlockSize);
+ if (IdeBlkIoDevice != NULL) {
+ CopyMem ((UINT8 *) IdeBlkIoDevice->Cache, (UINT8 *) Buffer, BlockSize);
+ }
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+AtapiBlkIoWriteBlocks (
+ IN IDE_BLK_IO_DEV *IdeBlkIoDevice,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+/*++
+ Name:
+ AtapiBlkIoWriteBlocks
+
+ Purpose:
+ This function is the ATAPI implementation for WriteBlocks in the
+ Block I/O Protocol interface.
+
+ Parameters:
+ EFI_BLOCK_IO IN *This
+ Indicates the calling context.
+
+ UINT32 IN MediaId
+ The media id that the write request is for.
+
+ EFI_LBA IN LBA
+ The starting logical block address to write onto
+ the device.
+
+ UINTN IN BufferSize
+ The size of the Buffer in bytes. This must be a
+ multiple of the intrinsic block size of the device.
+
+ VOID OUT *Buffer
+ A pointer to the source buffer for the data.
+ The caller is responsible for either having implicit
+ or explicit ownership of the memory that data is
+ written from.
+
+ Returns:
+ EFI_SUCCESS
+ Write Blocks successfully.
+
+ EFI_DEVICE_ERROR
+ Write Blocks failed.
+
+ EFI_NO_MEDIA
+ There is no media in the device.
+
+ EFI_MEDIA_CHANGE
+ 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 write request contains LBAs that are not valid,
+ or the data buffer is not valid.
+
+ Notes:
+
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeBlkIoDevice - add argument and description to function comment
+// TODO: MediaId - add argument and description to function comment
+// TODO: LBA - add argument and description to function comment
+// TODO: BufferSize - add argument and description to function comment
+// TODO: Buffer - add argument and description to function comment
+// TODO: EFI_MEDIA_CHANGED - add return value to function comment
+// TODO: EFI_WRITE_PROTECTED - add return value to function comment
+{
+
+ EFI_BLOCK_IO_MEDIA *Media;
+ UINTN BlockSize;
+ UINTN NumberOfBlocks;
+ EFI_STATUS Status;
+ BOOLEAN MediaChange;
+
+ if (LBA == 0 && IdeBlkIoDevice->Cache) {
+ gBS->FreePool (IdeBlkIoDevice->Cache);
+ IdeBlkIoDevice->Cache = NULL;
+ }
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // ATAPI device media is removable,
+ // so it is a must to detect media first before write operation
+ //
+ MediaChange = FALSE;
+ Status = AtapiDetectMedia (IdeBlkIoDevice, &MediaChange);
+ if (EFI_ERROR (Status)) {
+
+ if (LBA == 0 && IdeBlkIoDevice->Cache) {
+ gBS->FreePool (IdeBlkIoDevice->Cache);
+ IdeBlkIoDevice->Cache = NULL;
+ }
+ return Status;
+ }
+
+ //
+ // Get the intrinsic block size
+ //
+ Media = IdeBlkIoDevice->BlkIo.Media;
+ BlockSize = Media->BlockSize;
+ NumberOfBlocks = BufferSize / BlockSize;
+
+ if (!(Media->MediaPresent)) {
+
+ if (LBA == 0 && IdeBlkIoDevice->Cache) {
+ gBS->FreePool (IdeBlkIoDevice->Cache);
+ IdeBlkIoDevice->Cache = NULL;
+ }
+ return EFI_NO_MEDIA;
+ }
+
+ if ((MediaId != Media->MediaId) || MediaChange) {
+
+ if (LBA == 0 && IdeBlkIoDevice->Cache) {
+ gBS->FreePool (IdeBlkIoDevice->Cache);
+ IdeBlkIoDevice->Cache = NULL;
+ }
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (Media->ReadOnly) {
+ return EFI_WRITE_PROTECTED;
+ }
+
+ if (BufferSize % BlockSize != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ if (LBA > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // if all the parameters are valid,
+ // then perform write sectors command to transfer data from host to device.
+ //
+ Status = AtapiWriteSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+//
+// The following functions are a set of helper functions,
+// which are used to parse sense key returned by the device.
+//
+
+BOOLEAN
+IsNoMedia (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ SenseData - TODO: add argument description
+ SenseCounts - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ REQUEST_SENSE_DATA *SensePointer;
+ UINTN Index;
+ BOOLEAN NoMedia;
+
+ NoMedia = FALSE;
+ SensePointer = SenseData;
+
+ for (Index = 0; Index < SenseCounts; Index++) {
+ //
+ // Sense Key is SK_NOT_READY (0x2),
+ // Additional Sense Code is ASC_NO_MEDIA (0x3A)
+ //
+ if ((SensePointer->sense_key == SK_NOT_READY) &&
+ (SensePointer->addnl_sense_code == ASC_NO_MEDIA)) {
+
+ NoMedia = TRUE;
+ }
+
+ SensePointer++;
+ }
+
+ return NoMedia;
+}
+
+BOOLEAN
+IsMediaError (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts
+ )
+/*++
+ Name:
+ IsMediaError
+
+ Purpose:
+ Test if the device meets a media error after media changed
+
+ Parameters:
+ EQUEST_SENSE_DATA IN *SenseData
+ pointer pointing to ATAPI device sense data list.
+ UINTN IN SenseCounts
+ sense data number of the list
+
+ Returns:
+ TRUE
+ Device meets a media error
+
+ FALSE
+ No media error
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: SenseData - add argument and description to function comment
+// TODO: SenseCounts - add argument and description to function comment
+{
+ REQUEST_SENSE_DATA *SensePointer;
+ UINTN Index;
+ BOOLEAN IsError;
+
+ IsError = FALSE;
+ SensePointer = SenseData;
+
+ for (Index = 0; Index < SenseCounts; Index++) {
+
+ switch (SensePointer->sense_key) {
+
+ case SK_MEDIUM_ERROR:
+ //
+ // Sense Key is SK_MEDIUM_ERROR (0x3)
+ //
+ switch (SensePointer->addnl_sense_code) {
+ case ASC_MEDIA_ERR1:
+ case ASC_MEDIA_ERR2:
+ case ASC_MEDIA_ERR3:
+ case ASC_MEDIA_ERR4:
+ IsError = TRUE;
+ break;
+
+ default:
+ break;
+ }
+
+ break;
+
+ case SK_NOT_READY:
+ //
+ // Sense Key is SK_NOT_READY (0x2)
+ //
+ switch (SensePointer->addnl_sense_code) {
+ //
+ // Additional Sense Code is ASC_MEDIA_UPSIDE_DOWN (0x6)
+ //
+ case ASC_MEDIA_UPSIDE_DOWN:
+ IsError = TRUE;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ SensePointer++;
+ }
+
+ return IsError;
+}
+
+BOOLEAN
+IsMediaChange (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ SenseData - TODO: add argument description
+ SenseCounts - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ REQUEST_SENSE_DATA *SensePointer;
+ UINTN Index;
+ BOOLEAN IsMediaChange;
+
+ IsMediaChange = FALSE;
+ SensePointer = SenseData;
+
+ for (Index = 0; Index < SenseCounts; Index++) {
+ //
+ // Sense Key is SK_UNIT_ATTENTION (0x6)
+ //
+ if ((SensePointer->sense_key == SK_UNIT_ATTENTION) &&
+ (SensePointer->addnl_sense_code == ASC_MEDIA_CHANGE)) {
+
+ IsMediaChange = TRUE;
+ }
+
+ SensePointer++;
+ }
+
+ return IsMediaChange;
+}
+
+BOOLEAN
+IsDriveReady (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts,
+ OUT BOOLEAN *NeedRetry
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ SenseData - TODO: add argument description
+ SenseCounts - TODO: add argument description
+ NeedRetry - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ REQUEST_SENSE_DATA *SensePointer;
+ UINTN Index;
+ BOOLEAN IsReady;
+
+ IsReady = TRUE;
+ *NeedRetry = FALSE;
+ SensePointer = SenseData;
+
+ for (Index = 0; Index < SenseCounts; Index++) {
+
+ switch (SensePointer->sense_key) {
+
+ case SK_NOT_READY:
+ //
+ // Sense Key is SK_NOT_READY (0x2)
+ //
+ switch (SensePointer->addnl_sense_code) {
+ case ASC_NOT_READY:
+ //
+ // Additional Sense Code is ASC_NOT_READY (0x4)
+ //
+ switch (SensePointer->addnl_sense_code_qualifier) {
+ case ASCQ_IN_PROGRESS:
+ //
+ // Additional Sense Code Qualifier is ASCQ_IN_PROGRESS (0x1)
+ //
+ IsReady = FALSE;
+ *NeedRetry = TRUE;
+ break;
+
+ default:
+ IsReady = FALSE;
+ *NeedRetry = FALSE;
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ SensePointer++;
+ }
+
+ return IsReady;
+}
+
+BOOLEAN
+HaveSenseKey (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ SenseData - TODO: add argument description
+ SenseCounts - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ BOOLEAN Have;
+
+ Have = TRUE;
+
+ //
+ // if first sense key in the Sense Data Array is SK_NO_SENSE,
+ // it indicates there is no more sense key in the Sense Data Array.
+ //
+ if (SenseData->sense_key == SK_NO_SENSE) {
+ Have = FALSE;
+ }
+
+ return Have;
+}
+
+EFI_STATUS
+IsLS120orZipWriteProtected (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ OUT BOOLEAN *WriteProtected
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ WriteProtected - TODO: add argument description
+
+Returns:
+
+ EFI_DEVICE_ERROR - TODO: Add description for return value
+ EFI_DEVICE_ERROR - TODO: Add description for return value
+ EFI_SUCCESS - TODO: Add description for return value
+
+--*/
+{
+ EFI_STATUS Status;
+
+ *WriteProtected = FALSE;
+
+ Status = LS120EnableMediaStatus (IdeDev, TRUE);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // the Get Media Status Command is only valid
+ // if a Set Features/Enable Media Status Command has been priviously issued.
+ //
+ if (LS120GetMediaStatus (IdeDev) == EFI_WRITE_PROTECTED) {
+
+ *WriteProtected = TRUE;
+ } else {
+
+ *WriteProtected = FALSE;
+ }
+
+ //
+ // After Get Media Status Command completes,
+ // Set Features/Disable Media Command should be sent.
+ //
+ Status = LS120EnableMediaStatus (IdeDev, FALSE);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/build.xml b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/build.xml
new file mode 100644
index 0000000..3a33a2b
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/build.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- 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.-->
+<project basedir="." default="IdeBus"><!--Apply external ANT tasks-->
+ <taskdef resource="GenBuild.tasks"/>
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+ <property environment="env"/>
+ <property name="WORKSPACE_DIR" value="${env.WORKSPACE}"/>
+ <import file="${WORKSPACE_DIR}\Tools\Conf\BuildMacro.xml"/><!--MODULE_RELATIVE PATH is relative to PACKAGE_DIR-->
+ <property name="MODULE_RELATIVE_PATH" value="Bus\Pci\IdeBus\Dxe"/>
+ <property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
+ <property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
+ <target name="IdeBusLite">
+ <GenBuild baseName="IdeBusLite" mbdFilename="${MODULE_DIR}\idebusLite.mbd" msaFilename="${MODULE_DIR}\idebusLite.msa"/>
+ </target>
+ <target name="IdeBus">
+ <GenBuild baseName="IdeBus" mbdFilename="${MODULE_DIR}\idebus.mbd" msaFilename="${MODULE_DIR}\idebus.msa"/>
+ </target>
+ <target depends="IdeBus_clean" name="clean"/>
+ <target depends="IdeBus_cleanall" name="cleanall"/>
+ <target name="IdeBusLite_clean">
+ <OutputDirSetup baseName="IdeBusLite" mbdFilename="${MODULE_DIR}\idebusLite.mbd" msaFilename="${MODULE_DIR}\idebusLite.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\IdeBusLite_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\IdeBusLite_build.xml" target="clean"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
+ </target>
+ <target name="IdeBus_clean">
+ <OutputDirSetup baseName="IdeBus" mbdFilename="${MODULE_DIR}\idebus.mbd" msaFilename="${MODULE_DIR}\idebus.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\IdeBus_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\IdeBus_build.xml" target="clean"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
+ </target>
+ <target name="IdeBusLite_cleanall">
+ <OutputDirSetup baseName="IdeBusLite" mbdFilename="${MODULE_DIR}\idebusLite.mbd" msaFilename="${MODULE_DIR}\idebusLite.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\IdeBusLite_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\IdeBusLite_build.xml" target="cleanall"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}"/>
+ <delete dir="${DEST_DIR_DEBUG}"/>
+ <delete>
+ <fileset dir="${BIN_DIR}" includes="**IdeBusLite*"/>
+ </delete>
+ </target>
+ <target name="IdeBus_cleanall">
+ <OutputDirSetup baseName="IdeBus" mbdFilename="${MODULE_DIR}\idebus.mbd" msaFilename="${MODULE_DIR}\idebus.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\IdeBus_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\IdeBus_build.xml" target="cleanall"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}"/>
+ <delete dir="${DEST_DIR_DEBUG}"/>
+ <delete>
+ <fileset dir="${BIN_DIR}" includes="**IdeBus*"/>
+ </delete>
+ </target>
+</project> \ No newline at end of file
diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ide.c b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ide.c
new file mode 100644
index 0000000..d318fd2
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ide.c
@@ -0,0 +1,1964 @@
+/*++
+
+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:
+
+ ide.c
+
+Abstract:
+
+
+Revision History
+--*/
+
+#include "idebus.h"
+
+BOOLEAN SlaveDeviceExist = FALSE;
+BOOLEAN MasterDeviceExist = FALSE;
+
+UINT8
+IDEReadPortB (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 Port
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIo - TODO: add argument description
+ Port - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ UINT8 Data;
+
+ Data = 0;
+ //
+ // perform 1-byte data read from register
+ //
+ PciIo->Io.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) Port,
+ 1,
+ &Data
+ );
+ return Data;
+}
+
+VOID
+IDEReadPortWMultiple (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 Port,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+ Reads multiple words of data from the IDE data port.
+ Call the IO abstraction once to do the complete read,
+ not one word at a time
+
+
+Arguments:
+ PciIo - Pointer to the EFI_PCI_IO instance
+ Port - IO port to read
+ Count - No. of UINT16's to read
+ Buffer - Pointer to the data buffer for read
+
+++*/
+// TODO: function comment should end with '--*/'
+// TODO: function comment is missing 'Returns:'
+{
+ UINT16 *AlignedBuffer;
+ UINT16 *WorkingBuffer;
+ UINTN Size;
+
+ //
+ // Prepare an 16-bit alligned working buffer. CpuIo will return failure and
+ // not perform actual I/O operations if buffer pointer passed in is not at
+ // natural boundary. The "Buffer" argument is passed in by user and may not
+ // at 16-bit natural boundary.
+ //
+ Size = sizeof (UINT16) * Count;
+
+ gBS->AllocatePool (
+ EfiBootServicesData,
+ Size + 1,
+ (VOID**)&WorkingBuffer
+ );
+
+ AlignedBuffer = (UINT16 *) ((UINTN)(((UINTN) WorkingBuffer + 0x1) & (~0x1)));
+
+ //
+ // Perform UINT16 data read from FIFO
+ //
+ PciIo->Io.Read (
+ PciIo,
+ EfiPciIoWidthFifoUint16,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) Port,
+ Count,
+ (UINT16*)AlignedBuffer
+ );
+
+ //
+ // Copy data to user buffer
+ //
+ CopyMem (Buffer, (UINT16*)AlignedBuffer, Size);
+ gBS->FreePool (WorkingBuffer);
+}
+
+VOID
+IDEWritePortB (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 Port,
+ IN UINT8 Data
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIo - TODO: add argument description
+ Port - TODO: add argument description
+ Data - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ //
+ // perform 1-byte data write to register
+ //
+ PciIo->Io.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) Port,
+ 1,
+ &Data
+ );
+
+}
+
+VOID
+IDEWritePortW (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 Port,
+ IN UINT16 Data
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIo - TODO: add argument description
+ Port - TODO: add argument description
+ Data - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ //
+ // perform 1-word data write to register
+ //
+ PciIo->Io.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) Port,
+ 1,
+ &Data
+ );
+}
+
+VOID
+IDEWritePortWMultiple (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 Port,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+ Write multiple words of data to the IDE data port.
+ Call the IO abstraction once to do the complete read,
+ not one word at a time
+
+
+Arguments:
+ PciIo - Pointer to the EFI_PCI_IO instance
+ Port - IO port to read
+ Count - No. of UINT16's to read
+ Buffer - Pointer to the data buffer for read
+
+++*/
+// TODO: function comment should end with '--*/'
+// TODO: function comment is missing 'Returns:'
+{
+ UINT16 *AlignedBuffer;
+ UINT32 *WorkingBuffer;
+ UINTN Size;
+
+ //
+ // Prepare an 16-bit alligned working buffer. CpuIo will return failure and
+ // not perform actual I/O operations if buffer pointer passed in is not at
+ // natural boundary. The "Buffer" argument is passed in by user and may not
+ // at 16-bit natural boundary.
+ //
+ Size = sizeof (UINT16) * Count;
+
+ gBS->AllocatePool (
+ EfiBootServicesData,
+ Size + 1,
+ (VOID **) &WorkingBuffer
+ );
+
+ AlignedBuffer = (UINT16 *) ((UINTN)(((UINTN) WorkingBuffer + 0x1) & (~0x1)));
+
+ //
+ // Copy data from user buffer to working buffer
+ //
+ CopyMem ((UINT16 *) AlignedBuffer, Buffer, Size);
+
+ //
+ // perform UINT16 data write to the FIFO
+ //
+ PciIo->Io.Write (
+ PciIo,
+ EfiPciIoWidthFifoUint16,
+ EFI_PCI_IO_PASS_THROUGH_BAR,
+ (UINT64) Port,
+ Count,
+ (UINT16 *) AlignedBuffer
+ );
+
+ gBS->FreePool (WorkingBuffer);
+}
+
+BOOLEAN
+BadIdeDeviceCheck (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ //
+ // check whether all registers return 0xff,
+ // if so, deem the channel is disabled.
+ //
+#ifdef EFI_DEBUG
+
+ if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Data) != 0xff) {
+ return FALSE;
+ }
+
+ if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature) != 0xff) {
+ return FALSE;
+ }
+
+ if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount) != 0xff) {
+ return FALSE;
+ }
+
+ if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber) != 0xff) {
+ return FALSE;
+ }
+
+ if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb) != 0xff) {
+ return FALSE;
+ }
+
+ if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb) != 0xff) {
+ return FALSE;
+ }
+
+ if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Head) != 0xff) {
+ return FALSE;
+ }
+
+ if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command) != 0xff) {
+ return FALSE;
+ }
+
+ if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus) != 0xff) {
+ return FALSE;
+ }
+
+ return TRUE;
+
+#else
+
+ return FALSE;
+
+#endif
+}
+
+//
+// GetIdeRegistersBaseAddr
+//
+EFI_STATUS
+GetIdeRegistersBaseAddr (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ OUT IDE_REGISTERS_BASE_ADDR *IdeRegsBaseAddr
+ )
+/*++
+
+Routine Description:
+ Get IDE IO port registers' base addresses by mode. In 'Compatibility' mode,
+ use fixed addresses. In Native-PCI mode, get base addresses from BARs in
+ the PCI IDE controller's Configuration Space.
+
+ The steps to get IDE IO port registers' base addresses for each channel
+ as follows:
+
+ 1. Examine the Programming Interface byte of the Class Code fields in PCI IDE
+ controller's Configuration Space to determine the operating mode.
+
+ 2. a) In 'Compatibility' mode, use fixed addresses shown in the Table 1 below.
+ ___________________________________________
+ | | Command Block | Control Block |
+ | Channel | Registers | Registers |
+ |___________|_______________|_______________|
+ | Primary | 1F0h - 1F7h | 3F6h - 3F7h |
+ |___________|_______________|_______________|
+ | Secondary | 170h - 177h | 376h - 377h |
+ |___________|_______________|_______________|
+
+ Table 1. Compatibility resource mappings
+
+ b) In Native-PCI mode, IDE registers are mapped into IO space using the BARs
+ in IDE controller's PCI Configuration Space, shown in the Table 2 below.
+ ___________________________________________________
+ | | Command Block | Control Block |
+ | Channel | Registers | Registers |
+ |___________|___________________|___________________|
+ | Primary | BAR at offset 0x10| BAR at offset 0x14|
+ |___________|___________________|___________________|
+ | Secondary | BAR at offset 0x18| BAR at offset 0x1C|
+ |___________|___________________|___________________|
+
+ Table 2. BARs for Register Mapping
+ Note: Refer to Intel ICH4 datasheet, Control Block Offset: 03F4h for
+ primary, 0374h for secondary. So 2 bytes extra offset should be
+ added to the base addresses read from BARs.
+
+ For more details, please refer to PCI IDE Controller Specification and Intel
+ ICH4 Datasheet.
+
+Arguments:
+ PciIo - Pointer to the EFI_PCI_IO_PROTOCOL instance
+ IdeRegsBaseAddr - Pointer to IDE_REGISTERS_BASE_ADDR to
+ receive IDE IO port registers' base addresses
+
+Returns:
+
+--*/
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_TYPE00 PciData;
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ sizeof (PciData),
+ &PciData
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if ((PciData.Hdr.ClassCode[0] & IDE_PRIMARY_OPERATING_MODE) == 0) {
+ IdeRegsBaseAddr[IdePrimary].CommandBlockBaseAddr = 0x1f0;
+ IdeRegsBaseAddr[IdePrimary].ControlBlockBaseAddr = 0x3f6;
+ IdeRegsBaseAddr[IdePrimary].BusMasterBaseAddr =
+ (UINT16)((PciData.Device.Bar[4] & 0x0000fff0));
+ } else {
+ //
+ // The BARs should be of IO type
+ //
+ if ((PciData.Device.Bar[0] & bit0) == 0 ||
+ (PciData.Device.Bar[1] & bit0) == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ IdeRegsBaseAddr[IdePrimary].CommandBlockBaseAddr =
+ (UINT16) (PciData.Device.Bar[0] & 0x0000fff8);
+ IdeRegsBaseAddr[IdePrimary].ControlBlockBaseAddr =
+ (UINT16) ((PciData.Device.Bar[1] & 0x0000fffc) + 2);
+ IdeRegsBaseAddr[IdePrimary].BusMasterBaseAddr =
+ (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0));
+ }
+
+ if ((PciData.Hdr.ClassCode[0] & IDE_SECONDARY_OPERATING_MODE) == 0) {
+ IdeRegsBaseAddr[IdeSecondary].CommandBlockBaseAddr = 0x170;
+ IdeRegsBaseAddr[IdeSecondary].ControlBlockBaseAddr = 0x376;
+ IdeRegsBaseAddr[IdeSecondary].BusMasterBaseAddr =
+ (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0));
+ } else {
+ //
+ // The BARs should be of IO type
+ //
+ if ((PciData.Device.Bar[2] & bit0) == 0 ||
+ (PciData.Device.Bar[3] & bit0) == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ IdeRegsBaseAddr[IdeSecondary].CommandBlockBaseAddr =
+ (UINT16) (PciData.Device.Bar[2] & 0x0000fff8);
+ IdeRegsBaseAddr[IdeSecondary].ControlBlockBaseAddr =
+ (UINT16) ((PciData.Device.Bar[3] & 0x0000fffc) + 2);
+ IdeRegsBaseAddr[IdeSecondary].BusMasterBaseAddr =
+ (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0));
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ReassignIdeResources (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+
+Routine Description:
+ This function is used to requery IDE resources. The IDE controller will
+ probably switch between native and legacy modes during the EFI->CSM->OS
+ transfer. We do this everytime before an BlkIo operation to ensure its
+ succeess.
+
+Arguments:
+ IdeDev - The BLK_IO private data which specifies the IDE device
+
+++*/
+// TODO: function comment should end with '--*/'
+// TODO: function comment is missing 'Returns:'
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr[IdeMaxChannel];
+ UINT16 CommandBlockBaseAddr;
+ UINT16 ControlBlockBaseAddr;
+
+ //
+ // Requery IDE IO port registers' base addresses in case of the switch of
+ // native and legacy modes
+ //
+ Status = GetIdeRegistersBaseAddr (IdeDev->PciIo, IdeRegsBaseAddr);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ZeroMem (IdeDev->IoPort, sizeof (IDE_BASE_REGISTERS));
+ CommandBlockBaseAddr = IdeRegsBaseAddr[IdeDev->Channel].CommandBlockBaseAddr;
+ ControlBlockBaseAddr = IdeRegsBaseAddr[IdeDev->Channel].ControlBlockBaseAddr;
+
+ IdeDev->IoPort->Data = CommandBlockBaseAddr;
+ (*(UINT16 *) &IdeDev->IoPort->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01);
+ IdeDev->IoPort->SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02);
+ IdeDev->IoPort->SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03);
+ IdeDev->IoPort->CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04);
+ IdeDev->IoPort->CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05);
+ IdeDev->IoPort->Head = (UINT16) (CommandBlockBaseAddr + 0x06);
+
+ (*(UINT16 *) &IdeDev->IoPort->Reg) = (UINT16) (CommandBlockBaseAddr + 0x07);
+ (*(UINT16 *) &IdeDev->IoPort->Alt) = ControlBlockBaseAddr;
+ IdeDev->IoPort->DriveAddress = (UINT16) (ControlBlockBaseAddr + 0x01);
+ IdeDev->IoPort->MasterSlave = (UINT16) ((IdeDev->Device == IdeMaster) ? 1 : 0);
+
+ IdeDev->IoPort->BusMasterBaseAddr = IdeRegsBaseAddr[IdeDev->Channel].BusMasterBaseAddr;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CheckPowerMode (
+ IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+ Routine Description:
+
+ Read SATA registers to detect SATA disks
+
+ Arguments:
+
+ IdeDev - The BLK_IO private data which specifies the IDE device
+
+++*/
+// TODO: function comment should end with '--*/'
+// TODO: function comment is missing 'Returns:'
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+{
+ UINT8 ErrorRegister;
+ EFI_STATUS Status;
+
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ (UINT8) ((IdeDev->Device << 4) | 0xe0)
+ );
+
+ //
+ // Wait 31 seconds for BSY clear. BSY should be in clear state if there exists
+ // a device (initial state). Normally, BSY is also in clear state if there is
+ // no device
+ //
+ Status = WaitForBSYClear (IdeDev, 31000);
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // select device, read error register
+ //
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ (UINT8) ((IdeDev->Device << 4) | 0xe0)
+ );
+ Status = DRDYReady (IdeDev, 200);
+
+ ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
+ if ((ErrorRegister == 0x01) || (ErrorRegister == 0x81)) {
+ return EFI_SUCCESS;
+ } else {
+ return EFI_NOT_FOUND;
+ }
+}
+
+//
+// DiscoverIdeDevice
+//
+EFI_STATUS
+DiscoverIdeDevice (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+ Routine Description:
+
+ Detect if there is disk connected to this port
+
+ Arguments:
+
+ IdeDev - The BLK_IO private data which specifies the IDE device
+
+++*/
+// TODO: function comment should end with '--*/'
+// TODO: function comment is missing 'Returns:'
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ BOOLEAN SataFlag;
+
+ SataFlag = FALSE;
+ //
+ // This extra detection is for SATA disks
+ //
+ Status = CheckPowerMode (IdeDev);
+ if (Status == EFI_SUCCESS) {
+ SataFlag = TRUE;
+ }
+
+ //
+ // If a channel has not been checked, check it now. Then set it to "checked" state
+ // After this step, all devices in this channel have been checked.
+ //
+ Status = DetectIDEController (IdeDev);
+
+ if ((EFI_ERROR (Status)) && !SataFlag) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Device exists. test if it is an ATA device
+ //
+ Status = ATAIdentify (IdeDev);
+ if (EFI_ERROR (Status)) {
+ //
+ // if not ATA device, test if it is an ATAPI device
+ //
+ Status = ATAPIIdentify (IdeDev);
+ if (EFI_ERROR (Status)) {
+ //
+ // if not ATAPI device either, return error.
+ //
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ //
+ // Init Block I/O interface
+ //
+ IdeDev->BlkIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION;
+ IdeDev->BlkIo.Reset = IDEBlkIoReset;
+ IdeDev->BlkIo.ReadBlocks = IDEBlkIoReadBlocks;
+ IdeDev->BlkIo.WriteBlocks = IDEBlkIoWriteBlocks;
+ IdeDev->BlkIo.FlushBlocks = IDEBlkIoFlushBlocks;
+
+ IdeDev->BlkMedia.LogicalPartition = FALSE;
+ IdeDev->BlkMedia.WriteCaching = FALSE;
+
+ //
+ // Init Disk Info interface
+ //
+ gBS->CopyMem (&IdeDev->DiskInfo.Interface, &gEfiDiskInfoIdeInterfaceGuid, sizeof (EFI_GUID));
+ IdeDev->DiskInfo.Inquiry = IDEDiskInfoInquiry;
+ IdeDev->DiskInfo.Identify = IDEDiskInfoIdentify;
+ IdeDev->DiskInfo.SenseData = IDEDiskInfoSenseData;
+ IdeDev->DiskInfo.WhichIde = IDEDiskInfoWhichIde;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DetectIDEController (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+
+ Name: DetectIDEController
+
+
+ Purpose:
+ This function is called by DiscoverIdeDevice(). It is used for detect
+ whether the IDE device exists in the specified Channel as the specified
+ Device Number.
+
+ There is two IDE channels: one is Primary Channel, the other is
+ Secondary Channel.(Channel is the logical name for the physical "Cable".)
+ Different channel has different register group.
+
+ On each IDE channel, at most two IDE devices attach,
+ one is called Device 0 (Master device), the other is called Device 1
+ (Slave device). The devices on the same channel co-use the same register
+ group, so before sending out a command for a specified device via command
+ register, it is a must to select the current device to accept the command
+ by set the device number in the Head/Device Register.
+
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+
+ Returns:
+ TRUE
+ successfully detects device.
+
+ FALSE
+ any failure during detection process will return this
+ value.
+
+
+ Notes:
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+{
+ EFI_STATUS Status;
+ UINT8 ErrorReg;
+ UINT8 StatusReg;
+ UINT8 InitStatusReg;
+ EFI_STATUS DeviceStatus;
+
+ //
+ // Slave device has been detected with master device.
+ //
+ if ((IdeDev->Device) == 1) {
+ if (SlaveDeviceExist) {
+ //
+ // If master not exists but slave exists, slave have to wait a while
+ //
+ if (!MasterDeviceExist) {
+ //
+ // if single slave can't be detected, add delay 4s here.
+ //
+ gBS->Stall (4000000);
+ }
+
+ return EFI_SUCCESS;
+ } else {
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ //
+ // Select slave device
+ //
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ (UINT8) ((1 << 4) | 0xe0)
+ );
+ gBS->Stall (100);
+
+ //
+ // Save the init slave status register
+ //
+ InitStatusReg = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
+
+ //
+ // Select master back
+ //
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ (UINT8) ((0 << 4) | 0xe0)
+ );
+ gBS->Stall (100);
+ //
+ // Send ATA Device Execut Diagnostic command.
+ // This command should work no matter DRDY is ready or not
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, 0x90);
+
+ Status = WaitForBSYClear (IdeDev, 3500);
+
+ ErrorReg = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
+
+ //
+ // Master Error register is 0x01. D0 passed, D1 passed or not present.
+ // Master Error register is 0x81. D0 passed, D1 failed. Return.
+ // Master Error register is other value. D0 failed, D1 passed or not present..
+ //
+ if (ErrorReg == 0x01) {
+ MasterDeviceExist = TRUE;
+ DeviceStatus = EFI_SUCCESS;
+ } else if (ErrorReg == 0x81) {
+
+ MasterDeviceExist = TRUE;
+ DeviceStatus = EFI_SUCCESS;
+ SlaveDeviceExist = FALSE;
+
+ return DeviceStatus;
+ } else {
+ MasterDeviceExist = FALSE;
+ DeviceStatus = EFI_NOT_FOUND;
+ }
+
+ //
+ // Master Error register is not 0x81, Go on check Slave
+ //
+
+ //
+ // select slave
+ //
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ (UINT8) ((1 << 4) | 0xe0)
+ );
+
+ gBS->Stall (300);
+ ErrorReg = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
+
+ //
+ // Slave Error register is not 0x01, D1 failed. Return.
+ //
+ if (ErrorReg != 0x01) {
+ SlaveDeviceExist = FALSE;
+ return DeviceStatus;
+ }
+
+ StatusReg = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
+
+ //
+ // Most ATAPI devices don't set DRDY bit, so test with a slow but accurate
+ // "ATAPI TEST UNIT READY" command
+ //
+ if (((StatusReg & DRDY) == 0) && ((InitStatusReg & DRDY) == 0)) {
+ Status = AtapiTestUnitReady (IdeDev);
+
+ //
+ // Still fail, Slave doesn't exist.
+ //
+ if (EFI_ERROR (Status)) {
+ SlaveDeviceExist = FALSE;
+ return DeviceStatus;
+ }
+ }
+
+ //
+ // Error reg is 0x01 and DRDY is ready,
+ // or ATAPI test unit ready success,
+ // or init Slave status DRDY is ready
+ // Slave exists.
+ //
+ SlaveDeviceExist = TRUE;
+
+ return DeviceStatus;
+
+}
+
+EFI_STATUS
+DRQClear (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN TimeoutInMilliSeconds
+ )
+/*++
+ Name: DRQClear
+
+
+ Purpose:
+ This function is used to poll for the DRQ bit clear in the Status
+ Register. DRQ is cleared when the device is finished transferring data.
+ So this function is called after data transfer is finished.
+
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ UINTN IN TimeoutInMilliSeconds
+ used to designate the timeout for the DRQ clear.
+
+ Returns:
+ EFI_SUCCESS
+ DRQ bit clear within the time out.
+
+ EFI_TIMEOUT
+ DRQ bit not clear within the time out.
+
+
+ Notes:
+ Read Status Register will clear interrupt status.
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: TimeoutInMilliSeconds - add argument and description to function comment
+// TODO: EFI_ABORTED - add return value to function comment
+{
+ UINT32 Delay;
+ UINT8 StatusRegister;
+ UINT8 ErrorRegister;
+
+ Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
+ do {
+
+ StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
+
+ //
+ // wait for BSY == 0 and DRQ == 0
+ //
+ if ((StatusRegister & (DRQ | BSY)) == 0) {
+ break;
+ }
+
+ if ((StatusRegister & (BSY | ERR)) == ERR) {
+
+ ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
+ if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) {
+ return EFI_ABORTED;
+ }
+ }
+
+ //
+ // Stall for 30 us
+ //
+ gBS->Stall (30);
+
+ Delay--;
+
+ } while (Delay);
+
+ if (Delay == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DRQClear2 (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN TimeoutInMilliSeconds
+ )
+/*++
+ Name: DRQClear2
+
+
+ Purpose:
+ This function is used to poll for the DRQ bit clear in the Alternate
+ Status Register. DRQ is cleared when the device is finished
+ transferring data. So this function is called after data transfer
+ is finished.
+
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ UINTN IN TimeoutInMilliSeconds
+ used to designate the timeout for the DRQ clear.
+
+ Returns:
+ EFI_SUCCESS
+ DRQ bit clear within the time out.
+
+ EFI_TIMEOUT
+ DRQ bit not clear within the time out.
+
+
+ Notes:
+ Read Alternate Status Register will not clear interrupt status.
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: TimeoutInMilliSeconds - add argument and description to function comment
+// TODO: EFI_ABORTED - add return value to function comment
+{
+ UINT32 Delay;
+ UINT8 AltRegister;
+ UINT8 ErrorRegister;
+
+ Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
+ do {
+
+ AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);
+
+ //
+ // wait for BSY == 0 and DRQ == 0
+ //
+ if ((AltRegister & (DRQ | BSY)) == 0) {
+ break;
+ }
+
+ if ((AltRegister & (BSY | ERR)) == ERR) {
+
+ ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
+ if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) {
+ return EFI_ABORTED;
+ }
+ }
+
+ //
+ // Stall for 30 us
+ //
+ gBS->Stall (30);
+
+ Delay--;
+
+ } while (Delay);
+
+ if (Delay == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DRQReady (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN TimeoutInMilliSeconds
+ )
+/*++
+ Name: DRQReady
+
+
+ Purpose:
+ This function is used to poll for the DRQ bit set in the
+ Status Register.
+ DRQ is set when the device is ready to transfer data. So this function
+ is called after the command is sent to the device and before required
+ data is transferred.
+
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure,used
+ to record all the information of the IDE device.
+
+ UINTN IN TimeoutInMilliSeconds
+ used to designate the timeout for the DRQ ready.
+
+
+ Returns:
+ EFI_SUCCESS
+ DRQ bit set within the time out.
+
+ EFI_TIMEOUT
+ DRQ bit not set within the time out.
+
+ EFI_ABORTED
+ DRQ bit not set caused by the command abort.
+
+ Notes:
+ Read Status Register will clear interrupt status.
+
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: TimeoutInMilliSeconds - add argument and description to function comment
+{
+ UINT32 Delay;
+ UINT8 StatusRegister;
+ UINT8 ErrorRegister;
+
+ Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
+ do {
+ //
+ // read Status Register will clear interrupt
+ //
+ StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
+
+ //
+ // BSY==0,DRQ==1
+ //
+ if ((StatusRegister & (BSY | DRQ)) == DRQ) {
+ break;
+ }
+
+ if ((StatusRegister & (BSY | ERR)) == ERR) {
+
+ ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
+ if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) {
+ return EFI_ABORTED;
+ }
+ }
+
+ //
+ // Stall for 30 us
+ //
+ gBS->Stall (30);
+
+ Delay--;
+ } while (Delay);
+
+ if (Delay == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DRQReady2 (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN TimeoutInMilliSeconds
+ )
+/*++
+ Name: DRQReady2
+
+
+ Purpose:
+ This function is used to poll for the DRQ bit set in the
+ Alternate Status Register. DRQ is set when the device is ready to
+ transfer data. So this function is called after the command
+ is sent to the device and before required data is transferred.
+
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ UINTN IN TimeoutInMilliSeconds
+ used to designate the timeout for the DRQ ready.
+
+ Returns:
+ EFI_SUCCESS
+ DRQ bit set within the time out.
+
+ EFI_TIMEOUT
+ DRQ bit not set within the time out.
+
+ EFI_ABORTED
+ DRQ bit not set caused by the command abort.
+
+ Notes:
+ Read Alternate Status Register will not clear interrupt status.
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: TimeoutInMilliSeconds - add argument and description to function comment
+{
+ UINT32 Delay;
+ UINT8 AltRegister;
+ UINT8 ErrorRegister;
+
+ Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
+
+ do {
+ //
+ // Read Alternate Status Register will not clear interrupt status
+ //
+ AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);
+ //
+ // BSY == 0 , DRQ == 1
+ //
+ if ((AltRegister & (BSY | DRQ)) == DRQ) {
+ break;
+ }
+
+ if ((AltRegister & (BSY | ERR)) == ERR) {
+
+ ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
+ if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) {
+ return EFI_ABORTED;
+ }
+ }
+
+ //
+ // Stall for 30 us
+ //
+ gBS->Stall (30);
+
+ Delay--;
+ } while (Delay);
+
+ if (Delay == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+WaitForBSYClear (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN TimeoutInMilliSeconds
+ )
+/*++
+ Name:
+ WaitForBSYClear
+
+
+ Purpose:
+ This function is used to poll for the BSY bit clear in the
+ Status Register. BSY is clear when the device is not busy.
+ Every command must be sent after device is not busy.
+
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ UINTN IN TimeoutInMilliSeconds
+ used to designate the timeout for the DRQ ready.
+
+ Returns:
+ EFI_SUCCESS
+ BSY bit clear within the time out.
+
+ EFI_TIMEOUT
+ BSY bit not clear within the time out.
+
+
+ Notes:
+ Read Status Register will clear interrupt status.
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: TimeoutInMilliSeconds - add argument and description to function comment
+{
+ UINT32 Delay;
+ UINT8 StatusRegister;
+
+ Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
+ do {
+
+ StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
+ if ((StatusRegister & BSY) == 0x00) {
+ break;
+ }
+
+ //
+ // Stall for 30 us
+ //
+ gBS->Stall (30);
+
+ Delay--;
+
+ } while (Delay);
+
+ if (Delay == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+//
+// WaitForBSYClear2
+//
+EFI_STATUS
+WaitForBSYClear2 (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN TimeoutInMilliSeconds
+ )
+/*++
+ Name:
+ WaitForBSYClear2
+
+
+ Purpose:
+ This function is used to poll for the BSY bit clear in the
+ Alternate Status Register. BSY is clear when the device is not busy.
+ Every command must be sent after device is not busy.
+
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ UINTN IN TimeoutInMilliSeconds
+ used to designate the timeout for the DRQ ready.
+
+ Returns:
+ EFI_SUCCESS
+ BSY bit clear within the time out.
+
+ EFI_TIMEOUT
+ BSY bit not clear within the time out.
+
+
+ Notes:
+ Read Alternate Status Register will not clear interrupt status.
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: TimeoutInMilliSeconds - add argument and description to function comment
+{
+ UINT32 Delay;
+ UINT8 AltRegister;
+
+ Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
+ do {
+ AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);
+ if ((AltRegister & BSY) == 0x00) {
+ break;
+ }
+
+ gBS->Stall (30);
+
+ Delay--;
+
+ } while (Delay);
+
+ if (Delay == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//
+// DRDYReady
+//
+EFI_STATUS
+DRDYReady (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN DelayInMilliSeconds
+ )
+/*++
+ Name:
+ DRDYReady
+
+
+ Purpose:
+ This function is used to poll for the DRDY bit set in the
+ Status Register. DRDY bit is set when the device is ready
+ to accept command. Most ATA commands must be sent after
+ DRDY set except the ATAPI Packet Command.
+
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ UINTN IN TimeoutInMilliSeconds
+ used to designate the timeout for the DRQ ready.
+
+ Returns:
+ EFI_SUCCESS
+ DRDY bit set within the time out.
+
+ EFI_TIMEOUT
+ DRDY bit not set within the time out.
+
+
+ Notes:
+ Read Status Register will clear interrupt status.
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: DelayInMilliSeconds - add argument and description to function comment
+// TODO: EFI_ABORTED - add return value to function comment
+{
+ UINT32 Delay;
+ UINT8 StatusRegister;
+ UINT8 ErrorRegister;
+
+ Delay = (UINT32) (((DelayInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
+ do {
+ StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
+ //
+ // BSY == 0 , DRDY == 1
+ //
+ if ((StatusRegister & (DRDY | BSY)) == DRDY) {
+ break;
+ }
+
+ if ((StatusRegister & (BSY | ERR)) == ERR) {
+
+ ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
+ if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) {
+ return EFI_ABORTED;
+ }
+ }
+
+ gBS->Stall (15);
+
+ Delay--;
+ } while (Delay);
+
+ if (Delay == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//
+// DRDYReady2
+//
+EFI_STATUS
+DRDYReady2 (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN DelayInMilliSeconds
+ )
+/*++
+ Name:
+ DRDYReady2
+
+
+ Purpose:
+ This function is used to poll for the DRDY bit set in the
+ Alternate Status Register. DRDY bit is set when the device is ready
+ to accept command. Most ATA commands must be sent after
+ DRDY set except the ATAPI Packet Command.
+
+
+ Parameters:
+ IDE_BLK_IO_DEV IN *IdeDev
+ pointer pointing to IDE_BLK_IO_DEV data structure, used
+ to record all the information of the IDE device.
+
+ UINTN IN TimeoutInMilliSeconds
+ used to designate the timeout for the DRQ ready.
+
+ Returns:
+ EFI_SUCCESS
+ DRDY bit set within the time out.
+
+ EFI_TIMEOUT
+ DRDY bit not set within the time out.
+
+
+ Notes:
+ Read Alternate Status Register will clear interrupt status.
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: IdeDev - add argument and description to function comment
+// TODO: DelayInMilliSeconds - add argument and description to function comment
+// TODO: EFI_ABORTED - add return value to function comment
+{
+ UINT32 Delay;
+ UINT8 AltRegister;
+ UINT8 ErrorRegister;
+
+ Delay = (UINT32) (((DelayInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
+ do {
+ AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus);
+ //
+ // BSY == 0 , DRDY == 1
+ //
+ if ((AltRegister & (DRDY | BSY)) == DRDY) {
+ break;
+ }
+
+ if ((AltRegister & (BSY | ERR)) == ERR) {
+
+ ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error);
+ if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) {
+ return EFI_ABORTED;
+ }
+ }
+
+ gBS->Stall (30);
+
+ Delay--;
+ } while (Delay);
+
+ if (Delay == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//
+// SwapStringChars
+//
+VOID
+SwapStringChars (
+ IN CHAR8 *Destination,
+ IN CHAR8 *Source,
+ IN UINT32 Size
+ )
+/*++
+ Name:
+ SwapStringChars
+
+
+ Purpose:
+ This function is a helper function used to change the char order in a
+ string. It is designed specially for the PrintAtaModuleName() function.
+ After the IDE device is detected, the IDE driver gets the device module
+ name by sending ATA command called ATA Identify Command or ATAPI
+ Identify Command to the specified IDE device. The module name returned
+ is a string of ASCII characters: the first character is bit8--bit15
+ of the first word, the second character is bit0--bit7 of the first word
+ and so on. Thus the string can not be print directly before it is
+ preprocessed by this func to change the order of characters in
+ each word in the string.
+
+
+ Parameters:
+ CHAR8 IN *Destination
+ Indicates the destination string.
+
+ CHAR8 IN *Source
+ Indicates the source string.
+
+ UINT8 IN Size
+ the length of the string
+
+
+ Returns:
+ none
+
+ Notes:
+
+--*/
+// TODO: function comment is missing 'Routine Description:'
+// TODO: function comment is missing 'Arguments:'
+// TODO: Destination - add argument and description to function comment
+// TODO: Source - add argument and description to function comment
+// TODO: Size - add argument and description to function comment
+{
+ UINT32 Index;
+ CHAR8 Temp;
+
+ for (Index = 0; Index < Size; Index += 2) {
+
+ Temp = Source[Index + 1];
+ Destination[Index + 1] = Source[Index];
+ Destination[Index] = Temp;
+ }
+}
+
+//
+// ReleaseIdeResources
+//
+VOID
+ReleaseIdeResources (
+ IN IDE_BLK_IO_DEV *IdeBlkIoDevice
+ )
+/*++
+Routing Description:
+
+ Release resources of an IDE device before stopping it.
+
+Arguments:
+
+ IdeBlkIoDevice -- Standard IDE device private data structure
+
+
+Returns:
+
+ NONE
+
+---*/
+// TODO: function comment is missing 'Routine Description:'
+{
+ if (IdeBlkIoDevice == NULL) {
+ return ;
+ }
+
+ //
+ // Release all the resourses occupied by the IDE_BLK_IO_DEV
+ //
+
+ if (IdeBlkIoDevice->SenseData != NULL) {
+ gBS->FreePool (IdeBlkIoDevice->SenseData);
+ IdeBlkIoDevice->SenseData = NULL;
+ }
+
+ if (IdeBlkIoDevice->Cache != NULL) {
+ gBS->FreePool (IdeBlkIoDevice->Cache);
+ IdeBlkIoDevice->Cache = NULL;
+ }
+
+ if (IdeBlkIoDevice->pIdData != NULL) {
+ gBS->FreePool (IdeBlkIoDevice->pIdData);
+ IdeBlkIoDevice->pIdData = NULL;
+ }
+
+ if (IdeBlkIoDevice->pInquiryData != NULL) {
+ gBS->FreePool (IdeBlkIoDevice->pInquiryData);
+ IdeBlkIoDevice->pInquiryData = NULL;
+ }
+
+ if (IdeBlkIoDevice->ControllerNameTable != NULL) {
+ FreeUnicodeStringTable (IdeBlkIoDevice->ControllerNameTable);
+ IdeBlkIoDevice->ControllerNameTable = NULL;
+ }
+
+ if (IdeBlkIoDevice->IoPort != NULL) {
+ gBS->FreePool (IdeBlkIoDevice->IoPort);
+ }
+
+ if (IdeBlkIoDevice->DevicePath != NULL) {
+ gBS->FreePool (IdeBlkIoDevice->DevicePath);
+ }
+
+ gBS->FreePool (IdeBlkIoDevice);
+ IdeBlkIoDevice = NULL;
+
+ return ;
+}
+
+//
+// SetDeviceTransferMode
+//
+EFI_STATUS
+SetDeviceTransferMode (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN ATA_TRANSFER_MODE *TransferMode
+ )
+/*++
+Routing Description:
+
+ Set the calculated Best transfer mode to a detected device
+
+Arguments:
+
+ IdeDev -- Standard IDE device private data structure
+ TransferMode -- The device transfer mode to be set
+
+Returns:
+
+ Set transfer mode Command execute status
+
+---*/
+// TODO: function comment is missing 'Routine Description:'
+{
+ EFI_STATUS Status;
+ UINT8 DeviceSelect;
+ UINT8 SectorCount;
+
+ DeviceSelect = 0;
+ DeviceSelect = (UINT8) ((IdeDev->Device) << 4);
+ SectorCount = *((UINT8 *) TransferMode);
+
+ //
+ // Send SET FEATURE command (sub command 0x03) to set pio mode.
+ //
+ Status = AtaNonDataCommandIn (
+ IdeDev,
+ SET_FEATURES_CMD,
+ DeviceSelect,
+ 0x03,
+ SectorCount,
+ 0,
+ 0,
+ 0
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+AtaNonDataCommandIn (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINT8 AtaCommand,
+ IN UINT8 Device,
+ IN UINT8 Feature,
+ IN UINT8 SectorCount,
+ IN UINT8 LbaLow,
+ IN UINT8 LbaMiddle,
+ IN UINT8 LbaHigh
+ )
+/*++
+
+Routine Description:
+
+ Send ATA command into device with NON_DATA protocol
+
+Arguments:
+
+ IdeDev - Standard IDE device private data structure
+ AtaCommand - The ATA command to be sent
+ Device - The value in Device register
+ Feature - The value in Feature register
+ SectorCount - The value in SectorCount register
+ LbaLow - The value in LBA_LOW register
+ LbaMiddle - The value in LBA_MIDDLE register
+ LbaHigh - The value in LBA_HIGH register
+
+Returns:
+
+ EFI_SUCCESS - Reading succeed
+ EFI_ABORTED - Command failed
+ EFI_DEVICE_ERROR - Device status error
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT8 StatusRegister;
+
+ Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)
+ //
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ (UINT8) ((IdeDev->Device << 4) | 0xe0)
+ );
+
+ //
+ // ATA commands for ATA device must be issued when DRDY is set
+ //
+ Status = DRDYReady (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Pass parameter into device register block
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMiddle);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);
+
+ //
+ // Send command via Command Register
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);
+
+ //
+ // Wait for command completion
+ //
+ Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
+ if ((StatusRegister & ERR) == ERR) {
+ //
+ // Failed to execute command, abort operation
+ //
+ return EFI_ABORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AtaNonDataCommandInExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINT8 AtaCommand,
+ IN UINT8 Device,
+ IN UINT16 Feature,
+ IN UINT16 SectorCount,
+ IN EFI_LBA LbaAddress
+ )
+/*++
+
+Routine Description:
+
+ Send ATA Ext command into device with NON_DATA protocol
+
+Arguments:
+
+ IdeDev - Standard IDE device private data structure
+ AtaCommand - The ATA command to be sent
+ Device - The value in Device register
+ Feature - The value in Feature register
+ SectorCount - The value in SectorCount register
+ LbaAddress - The LBA address in 48-bit mode
+
+Returns:
+
+ EFI_SUCCESS - Reading succeed
+ EFI_ABORTED - Command failed
+ EFI_DEVICE_ERROR - Device status error
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT8 StatusRegister;
+ UINT8 SectorCount8;
+ UINT8 Feature8;
+ UINT8 LbaLow;
+ UINT8 LbaMid;
+ UINT8 LbaHigh;
+
+ Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility)
+ //
+ IDEWritePortB (
+ IdeDev->PciIo,
+ IdeDev->IoPort->Head,
+ (UINT8) ((IdeDev->Device << 4) | 0xe0)
+ );
+
+ //
+ // ATA commands for ATA device must be issued when DRDY is set
+ //
+ Status = DRDYReady (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Pass parameter into device register block
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device);
+
+ //
+ // Fill the feature register, which is a two-byte FIFO. Need write twice.
+ //
+ Feature8 = (UINT8) (Feature >> 8);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);
+
+ Feature8 = (UINT8) Feature;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8);
+
+ //
+ // Fill the sector count register, which is a two-byte FIFO. Need write twice.
+ //
+ SectorCount8 = (UINT8) (SectorCount >> 8);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);
+
+ SectorCount8 = (UINT8) SectorCount;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8);
+
+ //
+ // Fill the start LBA registers, which are also two-byte FIFO
+ //
+ LbaLow = (UINT8) RShiftU64 (LbaAddress, 24);
+ LbaMid = (UINT8) RShiftU64 (LbaAddress, 32);
+ LbaHigh = (UINT8) RShiftU64 (LbaAddress, 40);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);
+
+ LbaLow = (UINT8) LbaAddress;
+ LbaMid = (UINT8) RShiftU64 (LbaAddress, 8);
+ LbaHigh = (UINT8) RShiftU64 (LbaAddress, 16);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid);
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh);
+
+ //
+ // Send command via Command Register
+ //
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand);
+
+ //
+ // Wait for command completion
+ //
+ Status = WaitForBSYClear (IdeDev, ATATIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status);
+ if ((StatusRegister & ERR) == ERR) {
+ //
+ // Failed to execute command, abort operation
+ //
+ return EFI_ABORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//
+// SetDriveParameters
+//
+EFI_STATUS
+SetDriveParameters (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN ATA_DRIVE_PARMS *DriveParameters
+ )
+/*++
+Routine Description:
+
+ Set drive parameters for devices not support PACKETS command
+
+Arguments:
+
+ IdeDev -- Standard IDE device private data structure
+ DriveParameters -- The device parameters to be set into the disk
+
+Returns:
+
+ SetParameters Command execute status
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT8 DeviceSelect;
+
+ DeviceSelect = 0;
+ DeviceSelect = (UINT8) ((IdeDev->Device) << 4);
+
+ //
+ // Send Init drive parameters
+ //
+ Status = AtaPioDataIn (
+ IdeDev,
+ NULL,
+ 0,
+ INIT_DRIVE_PARAM_CMD,
+ (UINT8) (DeviceSelect + DriveParameters->Heads),
+ DriveParameters->Sector,
+ 0,
+ 0,
+ 0
+ );
+
+ //
+ // Send Set Multiple parameters
+ //
+ Status = AtaPioDataIn (
+ IdeDev,
+ NULL,
+ 0,
+ SET_MULTIPLE_MODE_CMD,
+ DeviceSelect,
+ DriveParameters->MultipleSector,
+ 0,
+ 0,
+ 0
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+EnableInterrupt (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+
+Returns:
+
+ EFI_SUCCESS - TODO: Add description for return value
+
+--*/
+{
+ UINT8 DeviceControl;
+
+ //
+ // Enable interrupt for DMA operation
+ //
+ DeviceControl = 0;
+ IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl);
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ide.h b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ide.h
new file mode 100644
index 0000000..4c43ab9
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ide.h
@@ -0,0 +1,1806 @@
+/*++
+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:
+
+ ide.h
+
+Abstract:
+
+ Header file for IDE Bus Driver, containing the helper functions'
+ entire prototype.
+
+Revision History
+
+ 2002-6: Add Atapi6 enhancement, support >120GB hard disk, including
+ Add - IDEBlkIoReadBlocksExt() func definition
+ Add - IDEBlkIoWriteBlocksExt() func definition
+
+++*/
+
+// TODO: fix comment to end with --*/
+#ifndef _IDE_H
+#define _IDE_H
+
+//
+// Helper functions Prototype
+//
+EFI_STATUS
+DeRegisterIdeDevice (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_HANDLE Handle
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Controller - TODO: add argument description
+ Handle - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EnableIdeDevice (
+ IN EFI_HANDLE Controller,
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Controller - TODO: add argument description
+ PciIo - TODO: add argument description
+ ParentDevicePath - TODO: add argument description
+ RemainingDevicePath - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+UINT8
+IDEReadPortB (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 Port
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIo - TODO: add argument description
+ Port - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+VOID
+IDEReadPortWMultiple (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 Port,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIo - TODO: add argument description
+ Port - TODO: add argument description
+ Count - TODO: add argument description
+ Buffer - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+VOID
+IDEWritePortB (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 Port,
+ IN UINT8 Data
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIo - TODO: add argument description
+ Port - TODO: add argument description
+ Data - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+VOID
+IDEWritePortW (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 Port,
+ IN UINT16 Data
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIo - TODO: add argument description
+ Port - TODO: add argument description
+ Data - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+VOID
+IDEWritePortWMultiple (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 Port,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIo - TODO: add argument description
+ Port - TODO: add argument description
+ Count - TODO: add argument description
+ Buffer - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+GetIdeRegistersBaseAddr (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ OUT IDE_REGISTERS_BASE_ADDR *IdeRegsBaseAddr
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIo - TODO: add argument description
+ IdeRegsBaseAddr - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+ReassignIdeResources (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+DiscoverIdeDevice (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+DetectIDEController (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+DRQClear (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN TimeoutInMilliSeconds
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ TimeoutInMilliSeconds - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+DRQClear2 (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN TimeoutInMilliSeconds
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ TimeoutInMilliSeconds - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+DRQReady (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN TimeoutInMilliSeconds
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ TimeoutInMilliSeconds - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+DRQReady2 (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN TimeoutInMilliSeconds
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ TimeoutInMilliSeconds - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+WaitForBSYClear (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN TimeoutInMilliSeconds
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ TimeoutInMilliSeconds - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+WaitForBSYClear2 (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN TimeoutInMilliSeconds
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ TimeoutInMilliSeconds - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+DRDYReady (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN DelayInMilliSeconds
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ DelayInMilliSeconds - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+DRDYReady2 (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINTN DelayInMilliSeconds
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ DelayInMilliSeconds - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+VOID
+SwapStringChars (
+ IN CHAR8 *Destination,
+ IN CHAR8 *Source,
+ IN UINT32 Size
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Destination - TODO: add argument description
+ Source - TODO: add argument description
+ Size - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+//
+// ATA device functions' prototype
+//
+EFI_STATUS
+ATAIdentify (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+VOID
+PrintAtaModuleName (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtaPioDataIn (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *Buffer,
+ IN UINT32 ByteCount,
+ IN UINT8 AtaCommand,
+ IN UINT8 Head,
+ IN UINT8 SectorCount,
+ IN UINT8 SectorNumber,
+ IN UINT8 CylinderLsb,
+ IN UINT8 CylinderMsb
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ Buffer - TODO: add argument description
+ ByteCount - TODO: add argument description
+ AtaCommand - TODO: add argument description
+ Head - TODO: add argument description
+ SectorCount - TODO: add argument description
+ SectorNumber - TODO: add argument description
+ CylinderLsb - TODO: add argument description
+ CylinderMsb - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtaPioDataOut (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *Buffer,
+ IN UINT32 ByteCount,
+ IN UINT8 AtaCommand,
+ IN UINT8 Head,
+ IN UINT8 SectorCount,
+ IN UINT8 SectorNumber,
+ IN UINT8 CylinderLsb,
+ IN UINT8 CylinderMsb
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ Buffer - TODO: add argument description
+ ByteCount - TODO: add argument description
+ AtaCommand - TODO: add argument description
+ Head - TODO: add argument description
+ SectorCount - TODO: add argument description
+ SectorNumber - TODO: add argument description
+ CylinderLsb - TODO: add argument description
+ CylinderMsb - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+CheckErrorStatus (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtaReadSectors (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA Lba,
+ IN UINTN NumberOfBlocks
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ DataBuffer - TODO: add argument description
+ Lba - TODO: add argument description
+ NumberOfBlocks - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtaWriteSectors (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *BufferData,
+ IN EFI_LBA Lba,
+ IN UINTN NumberOfBlocks
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ BufferData - TODO: add argument description
+ Lba - TODO: add argument description
+ NumberOfBlocks - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtaSoftReset (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtaBlkIoReadBlocks (
+ IN IDE_BLK_IO_DEV *IdeBlkIoDevice,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeBlkIoDevice - TODO: add argument description
+ MediaId - TODO: add argument description
+ LBA - TODO: add argument description
+ BufferSize - TODO: add argument description
+ Buffer - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtaBlkIoWriteBlocks (
+ IN IDE_BLK_IO_DEV *IdeBlkIoDevice,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeBlkIoDevice - TODO: add argument description
+ MediaId - TODO: add argument description
+ LBA - TODO: add argument description
+ BufferSize - TODO: add argument description
+ Buffer - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+//
+// ATAPI device functions' prototype
+//
+EFI_STATUS
+ATAPIIdentify (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtapiInquiry (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtapiPacketCommandIn (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN ATAPI_PACKET_COMMAND *Packet,
+ IN UINT16 *Buffer,
+ IN UINT32 ByteCount,
+ IN UINTN TimeOut
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ Packet - TODO: add argument description
+ Buffer - TODO: add argument description
+ ByteCount - TODO: add argument description
+ TimeOut - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtapiPacketCommandOut (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN ATAPI_PACKET_COMMAND *Packet,
+ IN UINT16 *Buffer,
+ IN UINT32 ByteCount,
+ IN UINTN TimeOut
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ Packet - TODO: add argument description
+ Buffer - TODO: add argument description
+ ByteCount - TODO: add argument description
+ TimeOut - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PioReadWriteData (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINT16 *Buffer,
+ IN UINT32 ByteCount,
+ IN BOOLEAN Read,
+ IN UINTN TimeOut
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ Buffer - TODO: add argument description
+ ByteCount - TODO: add argument description
+ Read - TODO: add argument description
+ TimeOut - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtapiTestUnitReady (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtapiRequestSense (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ OUT UINTN *SenseCounts
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ SenseCounts - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtapiReadCapacity (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtapiDetectMedia (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ OUT BOOLEAN *MediaChange
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ MediaChange - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtapiReadSectors (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *Buffer,
+ IN EFI_LBA Lba,
+ IN UINTN NumberOfBlocks
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ Buffer - TODO: add argument description
+ Lba - TODO: add argument description
+ NumberOfBlocks - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtapiWriteSectors (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *Buffer,
+ IN EFI_LBA Lba,
+ IN UINTN NumberOfBlocks
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ Buffer - TODO: add argument description
+ Lba - TODO: add argument description
+ NumberOfBlocks - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtapiSoftReset (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtapiBlkIoReadBlocks (
+ IN IDE_BLK_IO_DEV *IdeBlkIoDevice,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeBlkIoDevice - TODO: add argument description
+ MediaId - TODO: add argument description
+ LBA - TODO: add argument description
+ BufferSize - TODO: add argument description
+ Buffer - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtapiBlkIoWriteBlocks (
+ IN IDE_BLK_IO_DEV *IdeBlkIoDevice,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeBlkIoDevice - TODO: add argument description
+ MediaId - TODO: add argument description
+ LBA - TODO: add argument description
+ BufferSize - TODO: add argument description
+ Buffer - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+IsNoMedia (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ SenseData - TODO: add argument description
+ SenseCounts - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+IsMediaError (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ SenseData - TODO: add argument description
+ SenseCounts - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+IsMediaChange (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ SenseData - TODO: add argument description
+ SenseCounts - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+IsDriveReady (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts,
+ OUT BOOLEAN *NeedRetry
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ SenseData - TODO: add argument description
+ SenseCounts - TODO: add argument description
+ NeedRetry - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+HaveSenseKey (
+ IN REQUEST_SENSE_DATA *SenseData,
+ IN UINTN SenseCounts
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ SenseData - TODO: add argument description
+ SenseCounts - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+IsLS120orZipWriteProtected (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ OUT BOOLEAN *WriteProtected
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ WriteProtected - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+VOID
+ReleaseIdeResources (
+ IN IDE_BLK_IO_DEV *IdeBlkIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeBlkIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+SetDeviceTransferMode (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN ATA_TRANSFER_MODE *TransferMode
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ TransferMode - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+ReadNativeMaxAddress (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ OUT EFI_LBA *NativeMaxAddress
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ NativeMaxAddress - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+SetMaxAddress (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN EFI_LBA MaxAddress,
+ IN BOOLEAN bVolatile
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ MaxAddress - TODO: add argument description
+ bVolatile - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtaNonDataCommandIn (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINT8 AtaCommand,
+ IN UINT8 Device,
+ IN UINT8 Feature,
+ IN UINT8 SectorCount,
+ IN UINT8 LbaLow,
+ IN UINT8 LbaMiddle,
+ IN UINT8 LbaHigh
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ AtaCommand - TODO: add argument description
+ Device - TODO: add argument description
+ Feature - TODO: add argument description
+ SectorCount - TODO: add argument description
+ LbaLow - TODO: add argument description
+ LbaMiddle - TODO: add argument description
+ LbaHigh - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtaNonDataCommandInExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINT8 AtaCommand,
+ IN UINT8 Device,
+ IN UINT16 Feature,
+ IN UINT16 SectorCount,
+ IN EFI_LBA LbaAddress
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ AtaCommand - TODO: add argument description
+ Device - TODO: add argument description
+ Feature - TODO: add argument description
+ SectorCount - TODO: add argument description
+ LbaAddress - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtaReadSectorsExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ DataBuffer - TODO: add argument description
+ StartLba - TODO: add argument description
+ NumberOfBlocks - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtaWriteSectorsExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ DataBuffer - TODO: add argument description
+ StartLba - TODO: add argument description
+ NumberOfBlocks - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtaUdmaReadExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ DataBuffer - TODO: add argument description
+ StartLba - TODO: add argument description
+ NumberOfBlocks - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtaUdmaRead (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ DataBuffer - TODO: add argument description
+ StartLba - TODO: add argument description
+ NumberOfBlocks - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtaUdmaWriteExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ DataBuffer - TODO: add argument description
+ StartLba - TODO: add argument description
+ NumberOfBlocks - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtaUdmaWrite (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *DataBuffer,
+ IN EFI_LBA StartLba,
+ IN UINTN NumberOfBlocks
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ DataBuffer - TODO: add argument description
+ StartLba - TODO: add argument description
+ NumberOfBlocks - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtaCommandIssueExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINT8 AtaCommand,
+ IN UINT8 Device,
+ IN UINT16 Feature,
+ IN UINT16 SectorCount,
+ IN EFI_LBA LbaAddress
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ AtaCommand - TODO: add argument description
+ Device - TODO: add argument description
+ Feature - TODO: add argument description
+ SectorCount - TODO: add argument description
+ LbaAddress - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtaCommandIssue (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN UINT8 AtaCommand,
+ IN UINT8 Device,
+ IN UINT16 Feature,
+ IN UINT16 SectorCount,
+ IN EFI_LBA LbaAddress
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ AtaCommand - TODO: add argument description
+ Device - TODO: add argument description
+ Feature - TODO: add argument description
+ SectorCount - TODO: add argument description
+ LbaAddress - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtaAtapi6Identify (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+
+VOID
+AtaSMARTSupport (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtaPioDataInExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN OUT VOID *Buffer,
+ IN UINT32 ByteCount,
+ IN UINT8 AtaCommand,
+ IN EFI_LBA StartLba,
+ IN UINT16 SectorCount
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ Buffer - TODO: add argument description
+ ByteCount - TODO: add argument description
+ AtaCommand - TODO: add argument description
+ StartLba - TODO: add argument description
+ SectorCount - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AtaPioDataOutExt (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN VOID *Buffer,
+ IN UINT32 ByteCount,
+ IN UINT8 AtaCommand,
+ IN EFI_LBA StartLba,
+ IN UINT16 SectorCount
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ Buffer - TODO: add argument description
+ ByteCount - TODO: add argument description
+ AtaCommand - TODO: add argument description
+ StartLba - TODO: add argument description
+ SectorCount - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+SetDriveParameters (
+ IN IDE_BLK_IO_DEV *IdeDev,
+ IN ATA_DRIVE_PARMS *DriveParameters
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+ DriveParameters - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EnableInterrupt (
+ IN IDE_BLK_IO_DEV *IdeDev
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IdeDev - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.c b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.c
new file mode 100644
index 0000000..2b8f52a
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.c
@@ -0,0 +1,1400 @@
+/*++
+
+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:
+
+ idebus.c
+
+Abstract:
+
+
+Revision History
+ This module is modified from DXE\IDE module for Ide Contriller Init support
+
+--*/
+
+#include "idebus.h"
+
+#define PCI_CLASS_MASS_STORAGE 0x01
+#define PCI_SUB_CLASS_IDE 0x01
+
+
+//
+// IDE Bus Driver Binding Protocol Instance
+//
+EFI_DRIVER_BINDING_PROTOCOL gIDEBusDriverBinding = {
+ IDEBusDriverBindingSupported,
+ IDEBusDriverBindingStart,
+ IDEBusDriverBindingStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+//
+// ***********************************************************************************
+// IDEBusDriverBindingSupported
+// ***********************************************************************************
+//
+EFI_STATUS
+EFIAPI
+IDEBusDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+Routine Description:
+ Register Driver Binding protocol for this driver.
+
+Arguments:
+ This -- A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ ControllerHandle -- The handle of the controller to test.
+ RemainingDevicePath -- A pointer to the remaining portion of a device path.
+
+Returns:
+ EFI_SUCCESS - Driver loaded.
+ other - Driver not loaded.
+--*/
+// TODO: Controller - add argument and description to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_DEV_PATH *Node;
+ EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit;
+
+ if (RemainingDevicePath != NULL) {
+ Node = (EFI_DEV_PATH *) RemainingDevicePath;
+ if (Node->DevPath.Type != MESSAGING_DEVICE_PATH ||
+ Node->DevPath.SubType != MSG_ATAPI_DP ||
+ DevicePathNodeLength(&Node->DevPath) != sizeof(ATAPI_DEVICE_PATH)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ //
+ // Open the IO Abstraction(s) needed to perform the supported test
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (Status == EFI_ALREADY_STARTED) {
+ return EFI_SUCCESS;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Clsoe protocol, don't use device path protocol in the .Support() function
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ //
+ // Verify the Ide Controller Init Protocol, which installed by the
+ // IdeController module.
+ // Note 1: PciIo protocol has been opened BY_DRIVER by ide_init, so We can't
+ // open BY_DRIVER here) That's why we don't check pciio protocol
+ // Note 2: ide_init driver check ide controller's pci config space, so we dont
+ // check here any more to save code size
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiIdeControllerInitProtocolGuid,
+ (VOID **) &IdeInit,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (Status == EFI_ALREADY_STARTED) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // If protocols were opened normally, closed it
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiIdeControllerInitProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return Status;
+}
+
+//
+// ***********************************************************************************
+// IDEBusDriverBindingStart
+// ***********************************************************************************
+//
+EFI_STATUS
+EFIAPI
+IDEBusDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+ Routine Description:
+ Start this driver on Controller by detecting all disks and installing
+ BlockIo protocol on them.
+
+ Arguments:
+ This - Protocol instance pointer.
+ Controller - Handle of device to bind driver to.
+ RemainingDevicePath - Not used, always produce all possible children.
+
+ Returns:
+ EFI_SUCCESS - This driver is added to ControllerHandle.
+ EFI_ALREADY_STARTED - This driver is already running on ControllerHandle.
+ other - This driver does not support this device.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_STATUS SavedStatus;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_DEV_PATH *Node;
+ UINT8 IdeChannel;
+ UINT8 BeginningIdeChannel;
+ UINT8 EndIdeChannel;
+ UINT8 IdeDevice;
+ UINT8 BeginningIdeDevice;
+ UINT8 EndIdeDevice;
+ IDE_BLK_IO_DEV *IdeBlkIoDevice[IdeMaxChannel][IdeMaxDevice];
+ IDE_BLK_IO_DEV *IdeBlkIoDevicePtr;
+ IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr[IdeMaxChannel];
+ ATA_TRANSFER_MODE TransferMode;
+ ATA_DRIVE_PARMS DriveParameters;
+ EFI_DEV_PATH NewNode;
+ UINT8 ConfigurationOptions;
+ UINT16 CommandBlockBaseAddr;
+ UINT16 ControlBlockBaseAddr;
+ UINTN DataSize;
+ UINT32 Attributes;
+ IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData;
+
+ //
+ // Local variables declaration for IdeControllerInit support
+ //
+ EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit;
+ BOOLEAN EnumAll;
+ BOOLEAN ChannelEnabled;
+ UINT8 ChannelCount;
+ UINT8 MaxDevices;
+ EFI_IDENTIFY_DATA IdentifyData;
+ EFI_ATA_COLLECTIVE_MODE *SupportedModes;
+
+ IdeBusDriverPrivateData = NULL;
+ SupportedModes = NULL;
+
+ //
+ // Perform IdeBus initialization
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
+ return Status;
+ }
+
+ //
+ // Now open the IDE_CONTROLLER_INIT protocol. Step7.1
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiIdeControllerInitProtocolGuid,
+ (VOID **) &IdeInit,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ //
+ // The following OpenProtocol function with _GET_PROTOCOL attribute and
+ // will not return EFI_ALREADY_STARTED, so save it for now
+ //
+ SavedStatus = Status;
+
+ if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
+ DEBUG ((EFI_D_ERROR, "Open Init, Status=%x", Status));
+ //
+ // open protocol is not SUCCESS or not ALREADY_STARTED, error exit
+ //
+ goto ErrorExit;
+ }
+
+ //
+ // Save Enumall and ChannelCount. Step7.2
+ //
+ EnumAll = IdeInit->EnumAll;
+ ChannelCount = IdeInit->ChannelCount;
+
+ //
+ // Consume PCI I/O protocol. Note that the OpenProtocol with _GET_PROTOCOL
+ // attribute will not return EFI_ALREADY_STARTED
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Open PciIo, Status=%x", Status));
+ goto ErrorExit;
+ }
+
+ //
+ // We must check EFI_ALREADY_STARTED because many ATAPI devices are removable
+ //
+ if (SavedStatus != EFI_ALREADY_STARTED) {
+ IdeBusDriverPrivateData = AllocatePool (sizeof (IDE_BUS_DRIVER_PRIVATE_DATA));
+ if (IdeBusDriverPrivateData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorExit;
+ }
+
+ ZeroMem (IdeBusDriverPrivateData, sizeof (IDE_BUS_DRIVER_PRIVATE_DATA));
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Controller,
+ &gEfiCallerIdGuid,
+ IdeBusDriverPrivateData,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ } else {
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiCallerIdGuid,
+ (VOID **) &IdeBusDriverPrivateData,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ IdeBusDriverPrivateData = NULL;
+ goto ErrorExit;
+ }
+ }
+
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationEnable,
+ EFI_PCI_DEVICE_ENABLE,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ //
+ // Read the environment variable that contains the IDEBus Driver's
+ // Config options that were set by the Driver Configuration Protocol
+ //
+ DataSize = sizeof (ConfigurationOptions);
+ Status = gRT->GetVariable (
+ (CHAR16 *) L"Configuration",
+ &gEfiCallerIdGuid,
+ &Attributes,
+ &DataSize,
+ &ConfigurationOptions
+ );
+ if (EFI_ERROR (Status)) {
+ ConfigurationOptions = 0x0f;
+ }
+
+ if (EnumAll) {
+ //
+ // If IdeInit->EnumAll is TRUE, must enumerate all IDE device anyway
+ //
+ BeginningIdeChannel = IdePrimary;
+ EndIdeChannel = IdeSecondary;
+ BeginningIdeDevice = IdeMaster;
+ EndIdeDevice = IdeSlave;
+ } else if (RemainingDevicePath == NULL) {
+ //
+ // RemainingDevicePath is NULL, scan IDE bus for each device;
+ //
+ BeginningIdeChannel = IdePrimary;
+ EndIdeChannel = IdeSecondary;
+ BeginningIdeDevice = IdeMaster;
+ //
+ // default, may be redefined by IdeInit
+ //
+ EndIdeDevice = IdeSlave;
+ } else {
+ //
+ // RemainingDevicePath is not NULL, only scan the specified device.
+ //
+ Node = (EFI_DEV_PATH *) RemainingDevicePath;
+ BeginningIdeChannel = Node->Atapi.PrimarySecondary;
+ EndIdeChannel = BeginningIdeChannel;
+ BeginningIdeDevice = Node->Atapi.SlaveMaster;
+ EndIdeDevice = BeginningIdeDevice;
+ }
+
+ //
+ // Obtain IDE IO port registers' base addresses
+ //
+ Status = GetIdeRegistersBaseAddr (PciIo, IdeRegsBaseAddr);
+ if (EFI_ERROR (Status)) {
+ goto ErrorExit;
+ }
+
+ //
+ // Report status code: begin IdeBus initialization
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_PC_RESET),
+ ParentDevicePath
+ );
+
+ //
+ // Strictly follow the enumeration based on IDE_CONTROLLER_INIT protocol
+ //
+ for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) {
+
+ IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelEnumeration, IdeChannel);
+
+ //
+ // now obtain channel information fron IdeControllerInit protocol. Step9
+ //
+ Status = IdeInit->GetChannelInfo (
+ IdeInit,
+ IdeChannel,
+ &ChannelEnabled,
+ &MaxDevices
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "[GetChannel, Status=%x]", Status));
+ continue;
+ }
+
+ if (!ChannelEnabled) {
+ continue;
+ }
+
+ EndIdeDevice = (UINT8) EFI_MIN ((MaxDevices - 1), EndIdeDevice);
+
+ //
+ // Now inform the IDE Controller Init Module. Sept10
+ //
+ IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelReset, IdeChannel);
+
+ //
+ // No reset channel function implemented. Sept11
+ //
+ IdeInit->NotifyPhase (IdeInit, EfiIdeAfterChannelReset, IdeChannel);
+
+ //
+ // Step13
+ //
+ IdeInit->NotifyPhase (
+ IdeInit,
+ EfiIdeBusBeforeDevicePresenceDetection,
+ IdeChannel
+ );
+ //
+ // -- 1st inner loop --- Master/Slave ------------ Step14
+ //
+ for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) {
+ //
+ // Check whether the configuration options allow this device
+ //
+ if (!(ConfigurationOptions & (1 << (IdeChannel * 2 + IdeDevice)))) {
+ continue;
+ }
+
+ //
+ // The device has been scanned in another Start(), No need to scan it again
+ // for perf optimization.
+ //
+ if (IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice]) {
+ continue;
+ }
+
+ //
+ // create child handle for the detected device.
+ //
+ IdeBlkIoDevice[IdeChannel][IdeDevice] = AllocatePool (sizeof (IDE_BLK_IO_DEV));
+ if (IdeBlkIoDevice[IdeChannel][IdeDevice] == NULL) {
+ continue;
+ }
+
+ IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice];
+
+ ZeroMem (IdeBlkIoDevicePtr, sizeof (IDE_BLK_IO_DEV));
+
+ IdeBlkIoDevicePtr->Signature = IDE_BLK_IO_DEV_SIGNATURE;
+ IdeBlkIoDevicePtr->Channel = IdeChannel;
+ IdeBlkIoDevicePtr->Device = IdeDevice;
+
+ //
+ // initialize Block IO interface's Media pointer
+ //
+ IdeBlkIoDevicePtr->BlkIo.Media = &IdeBlkIoDevicePtr->BlkMedia;
+
+ //
+ // Initialize IDE IO port addresses, including Command Block registers
+ // and Control Block registers
+ //
+ IdeBlkIoDevicePtr->IoPort = AllocatePool (sizeof (IDE_BASE_REGISTERS));
+ if (IdeBlkIoDevicePtr->IoPort == NULL) {
+ continue;
+ }
+
+ ZeroMem (IdeBlkIoDevicePtr->IoPort, sizeof (IDE_BASE_REGISTERS));
+ CommandBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].CommandBlockBaseAddr;
+ ControlBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].ControlBlockBaseAddr;
+
+ IdeBlkIoDevicePtr->IoPort->Data = CommandBlockBaseAddr;
+ (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01);
+ IdeBlkIoDevicePtr->IoPort->SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02);
+ IdeBlkIoDevicePtr->IoPort->SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03);
+ IdeBlkIoDevicePtr->IoPort->CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04);
+ IdeBlkIoDevicePtr->IoPort->CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05);
+ IdeBlkIoDevicePtr->IoPort->Head = (UINT16) (CommandBlockBaseAddr + 0x06);
+ (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg) = (UINT16) (CommandBlockBaseAddr + 0x07);
+
+ (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Alt) = ControlBlockBaseAddr;
+ IdeBlkIoDevicePtr->IoPort->DriveAddress = (UINT16) (ControlBlockBaseAddr + 0x01);
+
+ IdeBlkIoDevicePtr->IoPort->MasterSlave = (UINT16) ((IdeDevice == IdeMaster) ? 1 : 0);
+
+ IdeBlkIoDevicePtr->PciIo = PciIo;
+ IdeBlkIoDevicePtr->IdeBusDriverPrivateData = IdeBusDriverPrivateData;
+ IdeBlkIoDevicePtr->IoPort->BusMasterBaseAddr = IdeRegsBaseAddr[IdeChannel].BusMasterBaseAddr;
+
+ //
+ // Report Status code: is about to detect IDE drive
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_PRESENCE_DETECT),
+ IdeBlkIoDevicePtr->DevicePath
+ );
+
+ //
+ // Discover device, now!
+ //
+ PERF_START (0, "DiscoverIdeDevice", "IDE", 0);
+ Status = DiscoverIdeDevice (IdeBlkIoDevicePtr);
+ PERF_END (0, "DiscoverIdeDevice", "IDE", 0);
+
+ IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice] = TRUE;
+ IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice] = FALSE;
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Set Device Path
+ //
+ ZeroMem (&NewNode, sizeof (NewNode));
+ NewNode.DevPath.Type = MESSAGING_DEVICE_PATH;
+ NewNode.DevPath.SubType = MSG_ATAPI_DP;
+ SetDevicePathNodeLength (&NewNode.DevPath, sizeof (ATAPI_DEVICE_PATH));
+
+ NewNode.Atapi.PrimarySecondary = (UINT8) IdeBlkIoDevicePtr->Channel;
+ NewNode.Atapi.SlaveMaster = (UINT8) IdeBlkIoDevicePtr->Device;
+ NewNode.Atapi.Lun = IdeBlkIoDevicePtr->Lun;
+ IdeBlkIoDevicePtr->DevicePath = AppendDevicePathNode (
+ ParentDevicePath,
+ &NewNode.DevPath
+ );
+ if (IdeBlkIoDevicePtr->DevicePath == NULL) {
+ ReleaseIdeResources (IdeBlkIoDevicePtr);
+ continue;
+ }
+
+ //
+ // Submit identify data to IDE controller init driver
+ //
+ CopyMem (&IdentifyData, IdeBlkIoDevicePtr->pIdData, sizeof (IdentifyData));
+ // IdentifyData = *IdeBlkIoDevicePtr->pIdData;
+ IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = TRUE;
+ IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, &IdentifyData);
+ } else {
+ //
+ // Device detection failed
+ //
+ IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
+ IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, NULL);
+ ReleaseIdeResources (IdeBlkIoDevicePtr);
+ IdeBlkIoDevicePtr = NULL;
+ }
+ //
+ // end of 1st inner loop ---
+ //
+ }
+ //
+ // end of 1st outer loop =========
+ //
+ }
+
+ //
+ // = 2nd outer loop == Primary/Secondary =================
+ //
+ for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) {
+
+ //
+ // -- 2nd inner loop --- Master/Slave --------
+ //
+ for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) {
+
+ if (IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice]) {
+ continue;
+ }
+
+ if (!IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice]) {
+ continue;
+ }
+
+ Status = IdeInit->CalculateMode (
+ IdeInit,
+ IdeChannel,
+ IdeDevice,
+ &SupportedModes
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "[bStStp20S=%x]", Status));
+ continue;
+ }
+
+ IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice];
+
+ //
+ // Set best supported PIO mode on this IDE device
+ //
+ if (SupportedModes->PioMode.Mode <= ATA_PIO_MODE_2) {
+ TransferMode.ModeCategory = ATA_MODE_CATEGORY_DEFAULT_PIO;
+ } else {
+ TransferMode.ModeCategory = ATA_MODE_CATEGORY_FLOW_PIO;
+ }
+
+ TransferMode.ModeNumber = (UINT8) (SupportedModes->PioMode.Mode);
+
+ if (SupportedModes->ExtModeCount == 0){
+ Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);
+
+ if (EFI_ERROR (Status)) {
+ IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
+ ReleaseIdeResources (IdeBlkIoDevicePtr);
+ IdeBlkIoDevicePtr = NULL;
+ continue;
+ }
+ }
+
+ //
+ // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
+ // be set together. Only one DMA mode can be set to a device. If setting
+ // DMA mode operation fails, we can continue moving on because we only use
+ // PIO mode at boot time. DMA modes are used by certain kind of OS booting
+ //
+ if (SupportedModes->UdmaMode.Valid) {
+
+ TransferMode.ModeCategory = ATA_MODE_CATEGORY_UDMA;
+ TransferMode.ModeNumber = (UINT8) (SupportedModes->UdmaMode.Mode);
+ Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);
+
+ if (EFI_ERROR (Status)) {
+ IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
+ ReleaseIdeResources (IdeBlkIoDevicePtr);
+ IdeBlkIoDevicePtr = NULL;
+ continue;
+ }
+
+ EnableInterrupt (IdeBlkIoDevicePtr);
+ } else if (SupportedModes->MultiWordDmaMode.Valid) {
+
+ TransferMode.ModeCategory = ATA_MODE_CATEGORY_MDMA;
+ TransferMode.ModeNumber = (UINT8) SupportedModes->MultiWordDmaMode.Mode;
+ Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode);
+
+ if (EFI_ERROR (Status)) {
+ IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE;
+ ReleaseIdeResources (IdeBlkIoDevicePtr);
+ IdeBlkIoDevicePtr = NULL;
+ continue;
+ }
+
+ EnableInterrupt (IdeBlkIoDevicePtr);
+ }
+ //
+ // Init driver parameters
+ //
+ DriveParameters.Sector = (UINT8) IdeBlkIoDevicePtr->pIdData->AtaData.sectors_per_track;
+ DriveParameters.Heads = (UINT8) (IdeBlkIoDevicePtr->pIdData->AtaData.heads - 1);
+ DriveParameters.MultipleSector = (UINT8) IdeBlkIoDevicePtr->pIdData->AtaData.multi_sector_cmd_max_sct_cnt;
+ //
+ // Set Parameters for the device:
+ // 1) Init
+ // 2) Establish the block count for READ/WRITE MULTIPLE (EXT) command
+ //
+ if ((IdeBlkIoDevicePtr->Type == IdeHardDisk) || (IdeBlkIoDevicePtr->Type == Ide48bitAddressingHardDisk)) {
+ Status = SetDriveParameters (IdeBlkIoDevicePtr, &DriveParameters);
+ }
+
+ //
+ // Record PIO mode used in private data
+ //
+ IdeBlkIoDevicePtr->PioMode = SupportedModes->PioMode.Mode;
+
+ //
+ // Set IDE controller Timing Blocks in the PCI Configuration Space
+ //
+ IdeInit->SetTiming (IdeInit, IdeChannel, IdeDevice, SupportedModes);
+
+ //
+ // Add Component Name for the IDE/ATAPI device that was discovered.
+ //
+ IdeBlkIoDevicePtr->ControllerNameTable = NULL;
+ ADD_NAME (IdeBlkIoDevicePtr);
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &IdeBlkIoDevicePtr->Handle,
+ &gEfiDevicePathProtocolGuid,
+ IdeBlkIoDevicePtr->DevicePath,
+ &gEfiBlockIoProtocolGuid,
+ &IdeBlkIoDevicePtr->BlkIo,
+ &gEfiDiskInfoProtocolGuid,
+ &IdeBlkIoDevicePtr->DiskInfo,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ ReleaseIdeResources (IdeBlkIoDevicePtr);
+ }
+
+ gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ IdeBlkIoDevicePtr->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+
+ IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice] = TRUE;
+
+ //
+ // Report status code: device eanbled!
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_ENABLE),
+ IdeBlkIoDevicePtr->DevicePath
+ );
+ //
+ // end of 2nd inner loop ----
+ //
+ }
+ //
+ // end of 2nd outer loop ==========
+ //
+ }
+
+ //
+ // All configurations done! Notify IdeController to do post initialization
+ // work such as saving IDE controller PCI settings for S3 resume
+ //
+ IdeInit->NotifyPhase (IdeInit, EfiIdeBusPhaseMaximum, 0);
+
+ if (SupportedModes != NULL) {
+ gBS->FreePool (SupportedModes);
+ }
+
+ PERF_START (0, "Finish IDE detection", "IDE", 1);
+ PERF_END (0, "Finish IDE detection", "IDE", 0);
+
+ return EFI_SUCCESS;
+
+ErrorExit:
+
+ //
+ // Report error code: controller error
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_EC_CONTROLLER_ERROR),
+ ParentDevicePath
+ );
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiIdeControllerInitProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ gBS->UninstallMultipleProtocolInterfaces (
+ Controller,
+ &gEfiCallerIdGuid,
+ IdeBusDriverPrivateData,
+ NULL
+ );
+
+ if (IdeBusDriverPrivateData != NULL) {
+ gBS->FreePool (IdeBusDriverPrivateData);
+ }
+
+ if (SupportedModes != NULL) {
+ gBS->FreePool (SupportedModes);
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return Status;
+
+}
+
+//
+// ***********************************************************************************
+// IDEBusDriverBindingStop
+// ***********************************************************************************
+//
+EFI_STATUS
+EFIAPI
+IDEBusDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+/*++
+
+ Routine Description:
+ Stop this driver on Controller Handle.
+
+ Arguments:
+ This - Protocol instance pointer.
+ DeviceHandle - Handle of device to stop driver on
+ NumberOfChildren - Not used
+ ChildHandleBuffer - Not used
+
+ Returns:
+ EFI_SUCCESS - This driver is removed DeviceHandle
+ other - This driver was not removed from this device
+
+--*/
+// TODO: Controller - add argument and description to function comment
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ BOOLEAN AllChildrenStopped;
+ UINTN Index;
+ IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData;
+
+ IdeBusDriverPrivateData = NULL;
+
+ if (NumberOfChildren == 0) {
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationDisable,
+ EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE,
+ NULL
+ );
+ }
+
+ gBS->OpenProtocol (
+ Controller,
+ &gEfiCallerIdGuid,
+ (VOID **) &IdeBusDriverPrivateData,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ gBS->UninstallMultipleProtocolInterfaces (
+ Controller,
+ &gEfiCallerIdGuid,
+ IdeBusDriverPrivateData,
+ NULL
+ );
+
+ if (IdeBusDriverPrivateData != NULL) {
+ gBS->FreePool (IdeBusDriverPrivateData);
+ }
+ //
+ // Close the bus driver
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiIdeControllerInitProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return EFI_SUCCESS;
+ }
+
+ AllChildrenStopped = TRUE;
+
+ for (Index = 0; Index < NumberOfChildren; Index++) {
+
+ Status = DeRegisterIdeDevice (This, Controller, ChildHandleBuffer[Index]);
+
+ if (EFI_ERROR (Status)) {
+ AllChildrenStopped = FALSE;
+ }
+ }
+
+ if (!AllChildrenStopped) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//
+// ***********************************************************************************
+// DeRegisterIdeDevice
+// ***********************************************************************************
+//
+EFI_STATUS
+DeRegisterIdeDevice (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_HANDLE Handle
+ )
+/*++
+
+Routine Description:
+
+ Deregister an IDE device and free resources
+
+Arguments:
+
+ This - Protocol instance pointer.
+ Controller - Ide device handle
+ Handle - Handle of device to deregister driver on
+
+Returns:
+
+ EFI_STATUS
+
+--*/
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;
+ IDE_BLK_IO_DEV *IdeBlkIoDevice;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINTN Index;
+
+ Status = gBS->OpenProtocol (
+ Handle,
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlkIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo);
+
+ //
+ // Report Status code: Device disabled
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_DISABLE),
+ IdeBlkIoDevice->DevicePath
+ );
+
+ //
+ // Close the child handle
+ //
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Handle
+ );
+
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ Handle,
+ &gEfiDevicePathProtocolGuid,
+ IdeBlkIoDevice->DevicePath,
+ &gEfiBlockIoProtocolGuid,
+ &IdeBlkIoDevice->BlkIo,
+ &gEfiDiskInfoProtocolGuid,
+ &IdeBlkIoDevice->DiskInfo,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ return Status;
+ }
+
+ //
+ // Release allocated resources
+ //
+ Index = IdeBlkIoDevice->Channel * 2 + IdeBlkIoDevice->Device;
+ IdeBlkIoDevice->IdeBusDriverPrivateData->HaveScannedDevice[Index] = FALSE;
+
+ ReleaseIdeResources (IdeBlkIoDevice);
+
+ return EFI_SUCCESS;
+}
+
+//
+// ***********************************************************************************
+// IDEBlkIoReset
+// ***********************************************************************************
+//
+EFI_STATUS
+EFIAPI
+IDEBlkIoReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: ExtendedVerification - add argument and description to function comment
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+{
+ IDE_BLK_IO_DEV *IdeBlkIoDevice;
+ EFI_STATUS Status;
+
+ IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This);
+ //
+ // Requery IDE IO resources in case of the switch of native and legacy modes
+ //
+ ReassignIdeResources (IdeBlkIoDevice);
+
+ //
+ // for ATA device, using ATA reset method
+ //
+ if (IdeBlkIoDevice->Type == IdeHardDisk) {
+ return AtaSoftReset (IdeBlkIoDevice);
+ }
+
+ if (IdeBlkIoDevice->Type == IdeUnknown) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // for ATAPI device, using ATAPI reset method
+ //
+ Status = AtapiSoftReset (IdeBlkIoDevice);
+ if (ExtendedVerification) {
+ Status = AtaSoftReset (IdeBlkIoDevice);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+IDEBlkIoReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Read data from block io device
+
+Arguments:
+
+ This - Protocol instance pointer.
+ MediaId - The media ID of the device
+ LBA - Starting LBA address to read data
+ BufferSize - The size of data to be read
+ Buffer - Caller supplied buffer to save data
+
+Returns:
+
+ read data status
+
+--*/
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+{
+ IDE_BLK_IO_DEV *IdeBlkIoDevice;
+
+ IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This);
+
+ //
+ // Requery IDE IO resources in case of the switch of native and legacy modes
+ //
+ ReassignIdeResources (IdeBlkIoDevice);
+
+ //
+ // For ATA compatible device, use ATA read block's mechanism
+ //
+ if (IdeBlkIoDevice->Type == IdeHardDisk ||
+ IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {
+ return AtaBlkIoReadBlocks (
+ IdeBlkIoDevice,
+ MediaId,
+ LBA,
+ BufferSize,
+ Buffer
+ );
+ }
+
+ if (IdeBlkIoDevice->Type == IdeUnknown) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // for ATAPI device, using ATAPI read block's mechanism
+ //
+ return AtapiBlkIoReadBlocks (
+ IdeBlkIoDevice,
+ MediaId,
+ LBA,
+ BufferSize,
+ Buffer
+ );
+
+}
+
+EFI_STATUS
+EFIAPI
+IDEBlkIoWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Write data to block io device
+
+Arguments:
+
+ This - Protocol instance pointer.
+ MediaId - The media ID of the device
+ LBA - Starting LBA address to write data
+ BufferSize - The size of data to be written
+ Buffer - Caller supplied buffer to save data
+
+Returns:
+
+ write data status
+
+--*/
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+{
+ IDE_BLK_IO_DEV *IdeBlkIoDevice;
+
+ IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This);
+ //
+ // Requery IDE IO resources in case of the switch of native and legacy modes
+ //
+ ReassignIdeResources (IdeBlkIoDevice);
+
+ //
+ // for ATA device, using ATA write block's mechanism
+ //
+ if (IdeBlkIoDevice->Type == IdeHardDisk ||
+ IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) {
+
+ return AtaBlkIoWriteBlocks (
+ IdeBlkIoDevice,
+ MediaId,
+ LBA,
+ BufferSize,
+ Buffer
+ );
+ }
+
+ if (IdeBlkIoDevice->Type == IdeUnknown) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // for ATAPI device, using ATAPI write block's mechanism
+ //
+ return AtapiBlkIoWriteBlocks (
+ IdeBlkIoDevice,
+ MediaId,
+ LBA,
+ BufferSize,
+ Buffer
+ );
+}
+
+//
+// ***********************************************************************************
+// IDEBlkIoFlushBlocks
+// ***********************************************************************************
+//
+EFI_STATUS
+EFIAPI
+IDEBlkIoFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ //
+ // return directly
+ //
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+IDEDiskInfoInquiry (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *InquiryData,
+ IN OUT UINT32 *InquiryDataSize
+ )
+/*++
+
+ Routine Description:
+ Return the results of the Inquiry command to a drive in InquiryData.
+ Data format of Inquiry data is defined by the Interface GUID.
+
+ Arguments:
+ This - Protocol instance pointer.
+ InquiryData - Results of Inquiry command to device
+ InquiryDataSize - Size of InquiryData in bytes.
+
+ Returns:
+ EFI_SUCCESS - InquiryData valid
+ EFI_NOT_FOUND - Device does not support this data class
+ EFI_DEVICE_ERROR - Error reading InquiryData from device
+ EFI_BUFFER_TOO_SMALL - IntquiryDataSize not big enough
+
+--*/
+{
+ IDE_BLK_IO_DEV *IdeBlkIoDevice;
+
+ IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This);
+
+ if (*InquiryDataSize < sizeof (INQUIRY_DATA)) {
+ *InquiryDataSize = sizeof (INQUIRY_DATA);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ if (IdeBlkIoDevice->pInquiryData == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ gBS->CopyMem (InquiryData, IdeBlkIoDevice->pInquiryData, sizeof (INQUIRY_DATA));
+ *InquiryDataSize = sizeof (INQUIRY_DATA);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+IDEDiskInfoIdentify (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *IdentifyData,
+ IN OUT UINT32 *IdentifyDataSize
+ )
+/*++
+
+ Routine Description:
+ Return the results of the Identify command to a drive in IdentifyData.
+ Data format of Identify data is defined by the Interface GUID.
+
+ Arguments:
+ This - Protocol instance pointer.
+ IdentifyData - Results of Identify command to device
+ IdentifyDataSize - Size of IdentifyData in bytes.
+
+ Returns:
+ EFI_SUCCESS - IdentifyData valid
+ EFI_NOT_FOUND - Device does not support this data class
+ EFI_DEVICE_ERROR - Error reading IdentifyData from device
+ EFI_BUFFER_TOO_SMALL - IdentifyDataSize not big enough
+
+--*/
+{
+ IDE_BLK_IO_DEV *IdeBlkIoDevice;
+
+ IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This);
+
+ if (*IdentifyDataSize < sizeof (EFI_IDENTIFY_DATA)) {
+ *IdentifyDataSize = sizeof (EFI_IDENTIFY_DATA);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ if (IdeBlkIoDevice->pIdData == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ gBS->CopyMem (IdentifyData, IdeBlkIoDevice->pIdData, sizeof (EFI_IDENTIFY_DATA));
+ *IdentifyDataSize = sizeof (EFI_IDENTIFY_DATA);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+IDEDiskInfoSenseData (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *SenseData,
+ IN OUT UINT32 *SenseDataSize,
+ OUT UINT8 *SenseDataNumber
+ )
+/*++
+
+ Routine Description:
+ Return the results of the Request Sense command to a drive in SenseData.
+ Data format of Sense data is defined by the Interface GUID.
+
+ Arguments:
+ This - Protocol instance pointer.
+ SenseData - Results of Request Sense command to device
+ SenseDataSize - Size of SenseData in bytes.
+ SenseDataNumber - Type of SenseData
+
+ Returns:
+ EFI_SUCCESS - InquiryData valid
+ EFI_NOT_FOUND - Device does not support this data class
+ EFI_DEVICE_ERROR - Error reading InquiryData from device
+ EFI_BUFFER_TOO_SMALL - SenseDataSize not big enough
+
+--*/
+{
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+EFIAPI
+IDEDiskInfoWhichIde (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ OUT UINT32 *IdeChannel,
+ OUT UINT32 *IdeDevice
+ )
+/*++
+
+ Routine Description:
+ Return the results of the Request Sense command to a drive in SenseData.
+ Data format of Sense data is defined by the Interface GUID.
+
+ Arguments:
+ This - Protocol instance pointer.
+ IdeChannel - Primary or Secondary
+ IdeDevice - Master or Slave
+
+ Returns:
+ EFI_SUCCESS - IdeChannel and IdeDevice are valid
+ EFI_UNSUPPORTED - This is not an IDE device
+
+--*/
+{
+ IDE_BLK_IO_DEV *IdeBlkIoDevice;
+
+ IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This);
+ *IdeChannel = IdeBlkIoDevice->Channel;
+ *IdeDevice = IdeBlkIoDevice->Device;
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.h b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.h
new file mode 100644
index 0000000..2e3caaf
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.h
@@ -0,0 +1,439 @@
+/*++
+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:
+
+ idebus.h
+
+Abstract:
+
+ Header file for IDE Bus Driver.
+
+Revision History
+++*/
+
+// TODO: fix comment to end with --*/
+#ifndef _IDE_BUS_H
+#define _IDE_BUS_H
+
+
+#include <IndustryStandard/Pci22.h>
+#include "idedata.h"
+
+//
+// Extra Definition to porting
+//
+#define EFI_MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+#define MAX_IDE_DEVICE 4
+#define MAX_IDE_CHANNELS 2
+#define MAX_IDE_DRIVES 2
+
+typedef struct {
+ BOOLEAN HaveScannedDevice[MAX_IDE_DEVICE];
+ BOOLEAN DeviceFound[MAX_IDE_DEVICE];
+ BOOLEAN DeviceProcessed[MAX_IDE_DEVICE];
+} IDE_BUS_DRIVER_PRIVATE_DATA;
+
+#define IDE_BLK_IO_DEV_SIGNATURE EFI_SIGNATURE_32 ('i', 'b', 'i', 'd')
+
+typedef struct {
+ UINT32 Signature;
+
+ EFI_HANDLE Handle;
+ EFI_BLOCK_IO_PROTOCOL BlkIo;
+ EFI_BLOCK_IO_MEDIA BlkMedia;
+ EFI_DISK_INFO_PROTOCOL DiskInfo;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData;
+
+ //
+ // Local Data for IDE interface goes here
+ //
+ EFI_IDE_CHANNEL Channel;
+ EFI_IDE_DEVICE Device;
+ UINT16 Lun;
+ IDE_DEVICE_TYPE Type;
+
+ IDE_BASE_REGISTERS *IoPort;
+ UINT16 AtapiError;
+
+ INQUIRY_DATA *pInquiryData;
+ EFI_IDENTIFY_DATA *pIdData;
+ ATA_PIO_MODE PioMode;
+ ATA_UDMA_MODE UDma_Mode;
+ CHAR8 ModelName[41];
+ REQUEST_SENSE_DATA *SenseData;
+ UINT8 SenseDataNumber;
+ UINT8 *Cache;
+
+ EFI_UNICODE_STRING_TABLE *ControllerNameTable;
+} IDE_BLK_IO_DEV;
+
+#include "ComponentName.h"
+
+#define IDE_BLOCK_IO_DEV_FROM_THIS(a) CR (a, IDE_BLK_IO_DEV, BlkIo, IDE_BLK_IO_DEV_SIGNATURE)
+#define IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS(a) CR (a, IDE_BLK_IO_DEV, DiskInfo, IDE_BLK_IO_DEV_SIGNATURE)
+
+//
+// Global Variables
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gIDEBusDriverBinding;
+
+#include "ide.h"
+
+//
+// Prototypes
+// Driver model protocol interface
+//
+EFI_STATUS
+EFIAPI
+IDEBusControllerDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ ImageHandle - TODO: add argument description
+ SystemTable - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+IDEBusDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Controller - TODO: add argument description
+ RemainingDevicePath - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+IDEBusDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Controller - TODO: add argument description
+ RemainingDevicePath - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+IDEBusDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Controller - TODO: add argument description
+ NumberOfChildren - TODO: add argument description
+ ChildHandleBuffer - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+//
+// Block I/O Protocol Interface
+//
+EFI_STATUS
+EFIAPI
+IDEBlkIoReset (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ ExtendedVerification - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+IDEBlkIoReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ MediaId - TODO: add argument description
+ LBA - TODO: add argument description
+ BufferSize - TODO: add argument description
+ Buffer - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+IDEBlkIoWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA LBA,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ MediaId - TODO: add argument description
+ LBA - TODO: add argument description
+ BufferSize - TODO: add argument description
+ Buffer - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+IDEBlkIoFlushBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+IDERegisterDecodeEnableorDisable (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN BOOLEAN Enable
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIo - TODO: add argument description
+ Enable - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+IDEDiskInfoInquiry (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *InquiryData,
+ IN OUT UINT32 *IntquiryDataSize
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ InquiryData - TODO: add argument description
+ IntquiryDataSize - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+IDEDiskInfoIdentify (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *IdentifyData,
+ IN OUT UINT32 *IdentifyDataSize
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ IdentifyData - TODO: add argument description
+ IdentifyDataSize - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+IDEDiskInfoSenseData (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *SenseData,
+ IN OUT UINT32 *SenseDataSize,
+ OUT UINT8 *SenseDataNumber
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ SenseData - TODO: add argument description
+ SenseDataSize - TODO: add argument description
+ SenseDataNumber - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+IDEDiskInfoWhichIde (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ OUT UINT32 *IdeChannel,
+ OUT UINT32 *IdeDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ IdeChannel - TODO: add argument description
+ IdeDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.mbd b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.mbd
new file mode 100644
index 0000000..f6e3ba1
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.mbd
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MbdHeader>
+ <BaseName>IdeBus</BaseName>
+ <Guid>69FD8E47-A161-4550-B01A-5594CEB2B2B2</Guid>
+ <Version>0</Version>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Created>2006-03-12 17:09</Created>
+ <Modified>2006-03-22 16:27</Modified>
+ </MbdHeader>
+ <Libraries>
+ <Library>UefiBootServicesTableLib</Library>
+ <Library>UefiRuntimeServicesTableLib</Library>
+ <Library>UefiMemoryLib</Library>
+ <Library>UefiLib</Library>
+ <Library>UefiDriverEntryPoint</Library>
+ <Library>UefiDriverModelLib</Library>
+ <Library>DxeReportStatusCodeLib</Library>
+ <Library>BaseDebugLibReportStatusCode</Library>
+ <Library>EdkDxePrintLib</Library>
+ <Library>BaseLib</Library>
+ <Library>DxeMemoryAllocationLib</Library>
+ <Library>UefiDevicePathLib</Library>
+ <Library>BasePerformanceLibNull</Library>
+ </Libraries>
+</ModuleBuildDescription>
diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.msa b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.msa
new file mode 100644
index 0000000..1b303c6
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.msa
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MsaHeader>
+ <BaseName>IdeBus</BaseName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <ComponentType>BS_DRIVER</ComponentType>
+ <Guid>69FD8E47-A161-4550-B01A-5594CEB2B2B2</Guid>
+ <Version>0</Version>
+ <Abstract>Component description file for PS2 keyboard module.</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Specification>0</Specification>
+ <Created>2006-03-12 17:09</Created>
+ <Updated>2006-03-22 16:27</Updated>
+ </MsaHeader>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverModelLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverEntryPoint</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">ReportStatusCodeLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">MemoryAllocationLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">PerformanceLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiBootServicesTableLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiRuntimeServicesTableLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DevicePathLib</LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>idebus.h</Filename>
+ <Filename>ide.h</Filename>
+ <Filename>idedata.h</Filename>
+ <Filename>idebus.c</Filename>
+ <Filename>ide.c</Filename>
+ <Filename>ata.c</Filename>
+ <Filename>atapi.c</Filename>
+ <Filename>ComponentName.c</Filename>
+ <Filename>ComponentName.h</Filename>
+ </SourceFiles>
+ <Includes>
+ <PackageName>MdePkg</PackageName>
+ <PackageName>EdkModulePkg</PackageName>
+ </Includes>
+ <Protocols>
+ <Protocol Usage="TO_START">DevicePath</Protocol>
+ <Protocol Usage="TO_START">PciIo</Protocol>
+ <Protocol Usage="TO_START">IdeControllerInit</Protocol>
+ <Protocol Usage="BY_START">BlockIo</Protocol>
+ <Protocol Usage="BY_START">DiskInfo</Protocol>
+ </Protocols>
+ <Variables>
+ <Variable Usage="ALWAYS_CONSUMED">
+ <String>Configuration</String>
+ <Guid>0x69fd8e47, 0xa161, 0x4550, 0xb0, 0x1a, 0x55, 0x94, 0xce, 0xb2, 0xb2, 0xb2</Guid>
+ </Variable>
+ </Variables>
+ <Guids>
+ <GuidEntry Usage="SOMETIMES_CONSUMED">
+ <C_Name>DiskInfoIde</C_Name>
+ </GuidEntry>
+ </Guids>
+ <Externs>
+ <Extern>
+ <ModuleEntryPoint></ModuleEntryPoint>
+ </Extern>
+ <Extern>
+ <DriverBinding>gIDEBusDriverBinding</DriverBinding>
+ <ComponentName>gIDEBusComponentName</ComponentName>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea>
diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebusLite.mbd b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebusLite.mbd
new file mode 100644
index 0000000..fa4bc33
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebusLite.mbd
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MbdHeader>
+ <BaseName>IdeBusLite</BaseName>
+ <Guid>69FD8E47-A161-4550-B01A-5594CEB2B2B2</Guid>
+ <Version>0</Version>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Created>2006-03-12 17:09</Created>
+ <Modified>2006-03-19 15:18</Modified>
+ </MbdHeader>
+ <Libraries>
+ <Library>UefiBootServicesTableLib</Library>
+ <Library>UefiRuntimeServicesTableLib</Library>
+ <Library>UefiMemoryLib</Library>
+ <Library>UefiLib</Library>
+ <Library>UefiDriverEntryPoint</Library>
+ <Library>UefiDriverModelLib</Library>
+ <Library>DxeReportStatusCodeLib</Library>
+ <Library>BaseDebugLibNull</Library>
+ <Library>EdkDxePrintLib</Library>
+ <Library>BaseLib</Library>
+ <Library>UefiDevicePathLib</Library>
+ <Library>BasePerformanceLibNull</Library>
+ </Libraries>
+</ModuleBuildDescription>
diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebusLite.msa b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebusLite.msa
new file mode 100644
index 0000000..71fc18d
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebusLite.msa
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MsaHeader>
+ <BaseName>IdeBusLite</BaseName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <ComponentType>BS_DRIVER</ComponentType>
+ <Guid>69FD8E47-A161-4550-B01A-5594CEB2B2B2</Guid>
+ <Version>0</Version>
+ <Abstract>Component description file for PS2 keyboard module.</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Specification>0</Specification>
+ <Created>2006-03-12 17:09</Created>
+ <Updated>2006-03-19 15:18</Updated>
+ </MsaHeader>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverModelLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverEntryPoint</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">PerformanceLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiBootServicesTableLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiRuntimeServicesTableLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DevicePathLib</LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>idebus.h</Filename>
+ <Filename>ide.h</Filename>
+ <Filename>idedata.h</Filename>
+ <Filename>idebus.c</Filename>
+ <Filename>ide.c</Filename>
+ <Filename>ata.c</Filename>
+ <Filename>atapi.c</Filename>
+ </SourceFiles>
+ <Includes>
+ <PackageName>MdePkg</PackageName>
+ <PackageName>EdkModulePkg</PackageName>
+ </Includes>
+ <Protocols>
+ <Protocol Usage="ALWAYS_CONSUMED">DevicePath</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">PciIo</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">IdeControllerInit</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">BlockIo</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">DiskInfo</Protocol>
+ </Protocols>
+ <Guids>
+ <GuidEntry Usage="ALWAYS_CONSUMED">
+ <C_Name>DiskInfoIde</C_Name>
+ </GuidEntry>
+ <GuidEntry Usage="ALWAYS_CONSUMED">
+ <C_Name>DiskInfoScsi</C_Name>
+ </GuidEntry>
+ <GuidEntry Usage="ALWAYS_CONSUMED">
+ <C_Name>DiskInfoUsb</C_Name>
+ </GuidEntry>
+ </Guids>
+ <Externs>
+ <Extern>
+ <ModuleEntryPoint></ModuleEntryPoint>
+ </Extern>
+ <Extern>
+ <DriverBinding>gIDEBusDriverBinding</DriverBinding>
+ <ComponentName>gIDEBusComponentName</ComponentName>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea>
diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idedata.h b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idedata.h
new file mode 100644
index 0000000..50b1f05
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idedata.h
@@ -0,0 +1,879 @@
+/*++
+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:
+
+ idedata.h
+
+Abstract:
+
+ Header file for IDE Bus Driver's Data Structures
+
+Revision History
+++*/
+
+// TODO: fix comment to end with --*/
+#ifndef _IDE_DATA_H
+#define _IDE_DATA_H
+
+//
+// bit definition
+//
+#define bit0 (1 << 0)
+#define bit1 (1 << 1)
+#define bit2 (1 << 2)
+#define bit3 (1 << 3)
+#define bit4 (1 << 4)
+#define bit5 (1 << 5)
+#define bit6 (1 << 6)
+#define bit7 (1 << 7)
+#define bit8 (1 << 8)
+#define bit9 (1 << 9)
+#define bit10 (1 << 10)
+#define bit11 (1 << 11)
+#define bit12 (1 << 12)
+#define bit13 (1 << 13)
+#define bit14 (1 << 14)
+#define bit15 (1 << 15)
+#define bit16 (1 << 16)
+#define bit17 (1 << 17)
+#define bit18 (1 << 18)
+#define bit19 (1 << 19)
+#define bit20 (1 << 20)
+#define bit21 (1 << 21)
+#define bit22 (1 << 22)
+#define bit23 (1 << 23)
+#define bit24 (1 << 24)
+#define bit25 (1 << 25)
+#define bit26 (1 << 26)
+#define bit27 (1 << 27)
+#define bit28 (1 << 28)
+#define bit29 (1 << 29)
+#define bit30 (1 << 30)
+#define bit31 (1 << 31)
+
+//
+// common constants
+//
+#define STALL_1_MILLI_SECOND 1000 // stall 1 ms
+#define STALL_1_SECOND 1000000 // stall 1 second
+typedef enum {
+ IdePrimary = 0,
+ IdeSecondary = 1,
+ IdeMaxChannel = 2
+} EFI_IDE_CHANNEL;
+
+typedef enum {
+ IdeMaster = 0,
+ IdeSlave = 1,
+ IdeMaxDevice = 2
+} EFI_IDE_DEVICE;
+
+typedef enum {
+ IdeMagnetic, /* ZIP Drive or LS120 Floppy Drive */
+ IdeCdRom, /* ATAPI CDROM */
+ IdeHardDisk, /* Hard Disk */
+ Ide48bitAddressingHardDisk, /* Hard Disk larger than 120GB */
+ IdeUnknown
+} IDE_DEVICE_TYPE;
+
+//
+// IDE Registers
+//
+typedef union {
+ UINT16 Command; /* when write */
+ UINT16 Status; /* when read */
+} IDE_CMD_OR_STATUS;
+
+typedef union {
+ UINT16 Error; /* when read */
+ UINT16 Feature; /* when write */
+} IDE_ERROR_OR_FEATURE;
+
+typedef union {
+ UINT16 AltStatus; /* when read */
+ UINT16 DeviceControl; /* when write */
+} IDE_AltStatus_OR_DeviceControl;
+
+//
+// IDE registers set
+//
+typedef struct {
+ UINT16 Data;
+ IDE_ERROR_OR_FEATURE Reg1;
+ UINT16 SectorCount;
+ UINT16 SectorNumber;
+ UINT16 CylinderLsb;
+ UINT16 CylinderMsb;
+ UINT16 Head;
+ IDE_CMD_OR_STATUS Reg;
+
+ IDE_AltStatus_OR_DeviceControl Alt;
+ UINT16 DriveAddress;
+
+ UINT16 MasterSlave;
+ UINT16 BusMasterBaseAddr;
+} IDE_BASE_REGISTERS;
+
+//
+// IDE registers' base addresses
+//
+typedef struct {
+ UINT16 CommandBlockBaseAddr;
+ UINT16 ControlBlockBaseAddr;
+ UINT16 BusMasterBaseAddr;
+} IDE_REGISTERS_BASE_ADDR;
+
+//
+// Bit definitions in Programming Interface byte of the Class Code field
+// in PCI IDE controller's Configuration Space
+//
+#define IDE_PRIMARY_OPERATING_MODE bit0
+#define IDE_PRIMARY_PROGRAMMABLE_INDICATOR bit1
+#define IDE_SECONDARY_OPERATING_MODE bit2
+#define IDE_SECONDARY_PROGRAMMABLE_INDICATOR bit3
+
+//
+// IDE registers bit definitions
+//
+
+//
+// Err Reg
+//
+#define BBK_ERR bit7 /* Bad block detected */
+#define UNC_ERR bit6 /* Uncorrectable Data */
+#define MC_ERR bit5 /* Media Change */
+#define IDNF_ERR bit4 /* ID Not Found */
+#define MCR_ERR bit3 /* Media Change Requested */
+#define ABRT_ERR bit2 /* Aborted Command */
+#define TK0NF_ERR bit1 /* Track 0 Not Found */
+#define AMNF_ERR bit0 /* Address Mark Not Found */
+
+//
+// Device/Head Reg
+//
+#define LBA_MODE bit6
+#define DEV bit4
+#define HS3 bit3
+#define HS2 bit2
+#define HS1 bit1
+#define HS0 bit0
+#define CHS_MODE (0)
+#define DRV0 (0)
+#define DRV1 (1)
+#define MST_DRV DRV0
+#define SLV_DRV DRV1
+
+//
+// Status Reg
+//
+#define BSY bit7 /* Controller Busy */
+#define DRDY bit6 /* Drive Ready */
+#define DWF bit5 /* Drive Write Fault */
+#define DSC bit4 /* Disk Seek Complete */
+#define DRQ bit3 /* Data Request */
+#define CORR bit2 /* Corrected Data */
+#define IDX bit1 /* Index */
+#define ERR bit0 /* Error */
+
+//
+// Device Control Reg
+//
+#define SRST bit2 /* Software Reset */
+#define IEN_L bit1 /* Interrupt Enable #*/
+
+//
+// Bus Master Reg
+//
+#define BMIC_nREAD bit3
+#define BMIC_START bit0
+#define BMIS_INTERRUPT bit2
+#define BMIS_ERROR bit1
+
+#define BMICP_OFFSET 0x00
+#define BMISP_OFFSET 0x02
+#define BMIDP_OFFSET 0x04
+#define BMICS_OFFSET 0x08
+#define BMISS_OFFSET 0x0A
+#define BMIDS_OFFSET 0x0C
+
+//
+// Time Out Value For IDE Device Polling
+//
+
+//
+// ATATIMEOUT is used for waiting time out for ATA device
+//
+
+//
+// 1 second
+//
+#define ATATIMEOUT 1000
+
+//
+// ATAPITIMEOUT is used for waiting operation
+// except read and write time out for ATAPI device
+//
+
+//
+// 1 second
+//
+#define ATAPITIMEOUT 1000
+
+//
+// ATAPILONGTIMEOUT is used for waiting read and
+// write operation timeout for ATAPI device
+//
+
+//
+// 2 seconds
+//
+#define CDROMLONGTIMEOUT 2000
+
+//
+// 5 seconds
+//
+#define ATAPILONGTIMEOUT 5000
+
+//
+// ATA Commands Code
+//
+#define ATA_INITIALIZE_DEVICE 0x91
+
+//
+// Class 1
+//
+#define IDENTIFY_DRIVE_CMD 0xec
+#define READ_BUFFER_CMD 0xe4
+#define READ_SECTORS_CMD 0x20
+#define READ_SECTORS_WITH_RETRY_CMD 0x21
+#define READ_LONG_CMD 0x22
+#define READ_LONG_WITH_RETRY_CMD 0x23
+//
+// Class 1 - Atapi6 enhanced commands
+//
+#define READ_SECTORS_EXT_CMD 0x24
+
+//
+// Class 2
+//
+#define FORMAT_TRACK_CMD 0x50
+#define WRITE_BUFFER_CMD 0xe8
+#define WRITE_SECTORS_CMD 0x30
+#define WRITE_SECTORS_WITH_RETRY_CMD 0x31
+#define WRITE_LONG_CMD 0x32
+#define WRITE_LONG_WITH_RETRY_CMD 0x33
+#define WRITE_VERIFY_CMD 0x3c
+//
+// Class 2 - Atapi6 enhanced commands
+//
+#define WRITE_SECTORS_EXT_CMD 0x34
+
+//
+// Class 3
+//
+#define ACK_MEDIA_CHANGE_CMD 0xdb
+#define BOOT_POST_BOOT_CMD 0xdc
+#define BOOT_PRE_BOOT_CMD 0xdd
+#define CHECK_POWER_MODE_CMD 0x98
+#define CHECK_POWER_MODE_CMD_ALIAS 0xe5
+#define DOOR_LOCK_CMD 0xde
+#define DOOR_UNLOCK_CMD 0xdf
+#define EXEC_DRIVE_DIAG_CMD 0x90
+#define IDLE_CMD_ALIAS 0x97
+#define IDLE_CMD 0xe3
+#define IDLE_IMMEDIATE_CMD 0x95
+#define IDLE_IMMEDIATE_CMD_ALIAS 0xe1
+#define INIT_DRIVE_PARAM_CMD 0x91
+#define RECALIBRATE_CMD 0x10 /* aliased to 1x */
+#define READ_DRIVE_STATE_CMD 0xe9
+#define SET_MULTIPLE_MODE_CMD 0xC6
+#define READ_DRIVE_STATE_CMD 0xe9
+#define READ_VERIFY_CMD 0x40
+#define READ_VERIFY_WITH_RETRY_CMD 0x41
+#define SEEK_CMD 0x70 /* aliased to 7x */
+#define SET_FEATURES_CMD 0xef
+#define STANDBY_CMD 0x96
+#define STANDBY_CMD_ALIAS 0xe2
+#define STANDBY_IMMEDIATE_CMD 0x94
+#define STANDBY_IMMEDIATE_CMD_ALIAS 0xe0
+
+//
+// Class 4
+//
+#define READ_DMA_CMD 0xc8
+#define READ_DMA_WITH_RETRY_CMD 0xc9
+#define READ_DMA_EXT_CMD 0x25
+#define WRITE_DMA_CMD 0xca
+#define WRITE_DMA_WITH_RETRY_CMD 0xcb
+#define WRITE_DMA_EXT_CMD 0x35
+
+//
+// Class 5
+//
+#define READ_MULTIPLE_CMD 0xc4
+#define REST_CMD 0xe7
+#define RESTORE_DRIVE_STATE_CMD 0xea
+#define SET_SLEEP_MODE_CMD 0x99
+#define SET_SLEEP_MODE_CMD_ALIAS 0xe6
+#define WRITE_MULTIPLE_CMD 0xc5
+#define WRITE_SAME_CMD 0xe9
+
+//
+// Class 6 - Host protected area access feature set
+//
+#define READ_NATIVE_MAX_ADDRESS_CMD 0xf8
+#define SET_MAX_ADDRESS_CMD 0xf9
+
+//
+// Class 6 - ATA/ATAPI-6 enhanced commands
+//
+#define READ_NATIVE_MAX_ADDRESS_EXT_CMD 0x27
+#define SET_MAX_ADDRESS_CMD_EXT 0x37
+
+//
+// Class 6 - SET_MAX related sub command (in feature register)
+//
+#define PARTIES_SET_MAX_ADDRESS_SUB_CMD 0x00
+#define PARTIES_SET_PASSWORD_SUB_CMD 0x01
+#define PARTIES_LOCK_SUB_CMD 0x02
+#define PARTIES_UNLOCK_SUB_CMD 0x03
+#define PARTIES_FREEZE_SUB_CMD 0x04
+
+//
+// S.M.A.R.T
+//
+#define ATA_SMART_CMD 0xb0
+#define ATA_CONSTANT_C2 0xc2
+#define ATA_CONSTANT_4F 0x4f
+#define ATA_SMART_ENABLE_OPERATION 0xd8
+#define ATA_SMART_RETURN_STATUS 0xda
+
+//
+// Error codes for Exec Drive Diag
+//
+#define DRIV_DIAG_NO_ERROR (0x01)
+#define DRIV_DIAG_FORMATTER_ERROR (0x02)
+#define DRIV_DIAG_DATA_BUFFER_ERROR (0x03)
+#define DRIV_DIAG_ECC_CKT_ERRROR (0x04)
+#define DRIV_DIAG_UP_ERROR (0x05)
+#define DRIV_DIAG_SLAVE_DRV_ERROR (0x80) /* aliased to 0x8x */
+
+//
+// Codes for Format Track
+//
+#define FORMAT_GOOD_SECTOR (0x00)
+#define FORMAT_SUSPEND_ALLOC (0x01)
+#define FORMAT_REALLOC_SECTOR (0x02)
+#define FORMAT_MARK_SECTOR_DEFECTIVE (0x03)
+
+//
+// IDE_IDENTIFY bits
+// config bits :
+//
+#define ID_CONFIG_RESERVED0 bit0
+#define ID_CONFIG_HARD_SECTORED_DRIVE bit1
+#define ID_CONFIG_SOFT_SECTORED_DRIVE bit2
+#define ID_CONFIG_NON_MFM bit3
+#define ID_CONFIG_15uS_HEAD_SWITCHING bit4
+#define ID_CONFIG_SPINDLE_MOTOR_CONTROL bit5
+#define ID_CONFIG_HARD_DRIVE bit6
+#define ID_CONFIG_CHANGEABLE_MEDIUM bit7
+#define ID_CONFIG_DATA_RATE_TO_5MHZ bit8
+#define ID_CONFIG_DATA_RATE_5_TO_10MHZ bit9
+#define ID_CONFIG_DATA_RATE_ABOVE_10MHZ bit10
+#define ID_CONFIG_MOTOR_SPEED_TOLERANCE_ABOVE_0_5_PERC bit11
+#define ID_CONFIG_DATA_CLK_OFFSET_AVAIL bit12
+#define ID_CONFIG_TRACK_OFFSET_AVAIL bit13
+#define ID_CONFIG_SPEED_TOLERANCE_GAP_NECESSARY bit14
+#define ID_CONFIG_RESERVED1 bit15
+
+#define ID_DOUBLE_WORD_IO_POSSIBLE bit01
+#define ID_LBA_SUPPORTED bit9
+#define ID_DMA_SUPPORTED bit8
+
+#define SET_FEATURE_ENABLE_8BIT_TRANSFER (0x01)
+#define SET_FEATURE_ENABLE_WRITE_CACHE (0x02)
+#define SET_FEATURE_TRANSFER_MODE (0x03)
+#define SET_FEATURE_WRITE_SAME_WRITE_SPECIFIC_AREA (0x22)
+#define SET_FEATURE_DISABLE_RETRIES (0x33)
+//
+// for Read & Write Longs
+//
+#define SET_FEATURE_VENDOR_SPEC_ECC_LENGTH (0x44)
+#define SET_FEATURE_PLACE_NO_OF_CACHE_SEGMENTS_IN_SECTOR_NO_REG (0x54)
+#define SET_FEATURE_DISABLE_READ_AHEAD (0x55)
+#define SET_FEATURE_MAINTAIN_PARAM_AFTER_RESET (0x66)
+#define SET_FEATURE_DISABLE_ECC (0x77)
+#define SET_FEATURE_DISABLE_8BIT_TRANSFER (0x81)
+#define SET_FEATURE_DISABLE_WRITE_CACHE (0x82)
+#define SET_FEATURE_ENABLE_ECC (0x88)
+#define SET_FEATURE_ENABLE_RETRIES (0x99)
+#define SET_FEATURE_ENABLE_READ_AHEAD (0xaa)
+#define SET_FEATURE_SET_SECTOR_CNT_REG_AS_NO_OF_READ_AHEAD_SECTORS (0xab)
+#define SET_FEATURE_ALLOW_REST_MODE (0xac)
+//
+// for Read & Write Longs
+//
+#define SET_FEATURE_4BYTE_ECC (0xbb)
+#define SET_FEATURE_DEFALUT_FEATURES_ON_SOFTWARE_RESET (0xcc)
+#define SET_FEATURE_WRITE_SAME_TO_WRITE_ENTIRE_MEDIUM (0xdd)
+
+#define BLOCK_TRANSFER_MODE (0x00)
+#define SINGLE_WORD_DMA_TRANSFER_MODE (0x10)
+#define MULTI_WORD_DMA_TRANSFER_MODE (0x20)
+#define TRANSFER_MODE_MASK (0x07) // 3 LSBs
+
+//
+// Drive 0 - Head 0
+//
+#define DEFAULT_DRIVE (0x00)
+#define DEFAULT_CMD (0xa0)
+//
+// default content of device control register, disable INT
+//
+#define DEFAULT_CTL (0x0a)
+#define DEFAULT_IDE_BM_IO_BASE_ADR (0xffa0)
+
+//
+// ATAPI6 related data structure definition
+//
+
+//
+// The maximum sectors count in 28 bit addressing mode
+//
+#define MAX_28BIT_ADDRESSING_CAPACITY 0xfffffff
+
+//
+// Move the IDENTIFY section to DXE\Protocol\IdeControllerInit
+//
+
+//
+// ATAPI Command
+//
+#define ATAPI_SOFT_RESET_CMD 0x08
+#define ATAPI_PACKET_CMD 0xA0
+#define PACKET_CMD 0xA0
+#define ATAPI_IDENTIFY_DEVICE_CMD 0xA1
+#define ATAPI_SERVICE_CMD 0xA2
+
+//
+// ATAPI Packet Command
+//
+#pragma pack(1)
+
+typedef struct {
+ UINT8 opcode;
+ UINT8 reserved_1;
+ UINT8 reserved_2;
+ UINT8 reserved_3;
+ UINT8 reserved_4;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 reserved_7;
+ UINT8 reserved_8;
+ UINT8 reserved_9;
+ UINT8 reserved_10;
+ UINT8 reserved_11;
+} TEST_UNIT_READY_CMD;
+
+typedef struct {
+ UINT8 opcode;
+ UINT8 reserved_1 : 4;
+ UINT8 lun : 4;
+ UINT8 page_code;
+ UINT8 reserved_3;
+ UINT8 allocation_length;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 reserved_7;
+ UINT8 reserved_8;
+ UINT8 reserved_9;
+ UINT8 reserved_10;
+ UINT8 reserved_11;
+} INQUIRY_CMD;
+
+typedef struct {
+ UINT8 opcode;
+ UINT8 reserved_1 : 4;
+ UINT8 lun : 4;
+ UINT8 reserved_2;
+ UINT8 reserved_3;
+ UINT8 allocation_length;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 reserved_7;
+ UINT8 reserved_8;
+ UINT8 reserved_9;
+ UINT8 reserved_10;
+ UINT8 reserved_11;
+} REQUEST_SENSE_CMD;
+
+typedef struct {
+ UINT8 opcode;
+ UINT8 reserved_1 : 4;
+ UINT8 lun : 4;
+ UINT8 page_code : 4;
+ UINT8 page_control : 4;
+ UINT8 reserved_3;
+ UINT8 reserved_4;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 parameter_list_length_hi;
+ UINT8 parameter_list_length_lo;
+ UINT8 reserved_9;
+ UINT8 reserved_10;
+ UINT8 reserved_11;
+} MODE_SENSE_CMD;
+
+typedef struct {
+ UINT8 opcode;
+ UINT8 reserved_1 : 5;
+ UINT8 lun : 3;
+ UINT8 Lba0;
+ UINT8 Lba1;
+ UINT8 Lba2;
+ UINT8 Lba3;
+ UINT8 reserved_6;
+ UINT8 TranLen0;
+ UINT8 TranLen1;
+ UINT8 reserved_9;
+ UINT8 reserved_10;
+ UINT8 reserved_11;
+} READ10_CMD;
+
+typedef struct {
+ UINT8 opcode;
+ UINT8 reserved_1;
+ UINT8 reserved_2;
+ UINT8 reserved_3;
+ UINT8 reserved_4;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 allocation_length_hi;
+ UINT8 allocation_length_lo;
+ UINT8 reserved_9;
+ UINT8 reserved_10;
+ UINT8 reserved_11;
+} READ_FORMAT_CAP_CMD;
+
+typedef union {
+ UINT16 Data16[6];
+ TEST_UNIT_READY_CMD TestUnitReady;
+ READ10_CMD Read10;
+ REQUEST_SENSE_CMD RequestSence;
+ INQUIRY_CMD Inquiry;
+ MODE_SENSE_CMD ModeSense;
+ READ_FORMAT_CAP_CMD ReadFormatCapacity;
+} ATAPI_PACKET_COMMAND;
+
+typedef struct {
+ UINT32 RegionBaseAddr;
+ UINT16 ByteCount;
+ UINT16 EndOfTable;
+} IDE_DMA_PRD;
+
+#define MAX_DMA_EXT_COMMAND_SECTORS 0x10000
+#define MAX_DMA_COMMAND_SECTORS 0x100
+
+#pragma pack()
+
+//
+// Packet Command Code
+//
+#define TEST_UNIT_READY 0x00
+#define REZERO 0x01
+#define REQUEST_SENSE 0x03
+#define FORMAT_UNIT 0x04
+#define REASSIGN_BLOCKS 0x07
+#define INQUIRY 0x12
+#define START_STOP_UNIT 0x1B
+#define PREVENT_ALLOW_MEDIA_REMOVAL 0x1E
+#define READ_FORMAT_CAPACITY 0x23
+#define OLD_FORMAT_UNIT 0x24
+#define READ_CAPACITY 0x25
+#define READ_10 0x28
+#define WRITE_10 0x2A
+#define SEEK 0x2B
+#define SEND_DIAGNOSTICS 0x3D
+#define WRITE_VERIFY 0x2E
+#define VERIFY 0x2F
+#define READ_DEFECT_DATA 0x37
+#define WRITE_BUFFER 0x38
+#define READ_BUFFER 0x3C
+#define READ_LONG 0x3E
+#define WRITE_LONG 0x3F
+#define MODE_SELECT 0x55
+#define MODE_SENSE 0x5A
+#define READ_12 0xA8
+#define WRITE_12 0xAA
+#define MAX_ATAPI_BYTE_COUNT (0xfffe)
+
+//
+// Sense Key
+//
+#define REQUEST_SENSE_ERROR (0x70)
+#define SK_NO_SENSE (0x0)
+#define SK_RECOVERY_ERROR (0x1)
+#define SK_NOT_READY (0x2)
+#define SK_MEDIUM_ERROR (0x3)
+#define SK_HARDWARE_ERROR (0x4)
+#define SK_ILLEGAL_REQUEST (0x5)
+#define SK_UNIT_ATTENTION (0x6)
+#define SK_DATA_PROTECT (0x7)
+#define SK_BLANK_CHECK (0x8)
+#define SK_VENDOR_SPECIFIC (0x9)
+#define SK_RESERVED_A (0xA)
+#define SK_ABORT (0xB)
+#define SK_RESERVED_C (0xC)
+#define SK_OVERFLOW (0xD)
+#define SK_MISCOMPARE (0xE)
+#define SK_RESERVED_F (0xF)
+
+//
+// Additional Sense Codes
+//
+#define ASC_NOT_READY (0x04)
+#define ASC_MEDIA_ERR1 (0x10)
+#define ASC_MEDIA_ERR2 (0x11)
+#define ASC_MEDIA_ERR3 (0x14)
+#define ASC_MEDIA_ERR4 (0x30)
+#define ASC_MEDIA_UPSIDE_DOWN (0x06)
+#define ASC_INVALID_CMD (0x20)
+#define ASC_LBA_OUT_OF_RANGE (0x21)
+#define ASC_INVALID_FIELD (0x24)
+#define ASC_WRITE_PROTECTED (0x27)
+#define ASC_MEDIA_CHANGE (0x28)
+#define ASC_RESET (0x29) /* Power On Reset or Bus Reset occurred */
+#define ASC_ILLEGAL_FIELD (0x26)
+#define ASC_NO_MEDIA (0x3A)
+#define ASC_ILLEGAL_MODE_FOR_THIS_TRACK (0x64)
+
+//
+// Additional Sense Code Qualifier
+//
+#define ASCQ_IN_PROGRESS (0x01)
+
+#define SETFEATURE TRUE
+#define CLEARFEATURE FALSE
+
+//
+// ATAPI Data structure
+//
+#pragma pack(1)
+
+typedef struct {
+ UINT8 peripheral_type;
+ UINT8 RMB;
+ UINT8 version;
+ UINT8 response_data_format;
+ UINT8 addnl_length;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 reserved_7;
+ UINT8 vendor_info[8];
+ UINT8 product_id[12];
+ UINT8 eeprom_product_code[4];
+ UINT8 firmware_rev_level[4];
+ UINT8 firmware_sub_rev_level[1];
+ UINT8 reserved_37;
+ UINT8 reserved_38;
+ UINT8 reserved_39;
+ UINT8 max_capacity_hi;
+ UINT8 max_capacity_mid;
+ UINT8 max_capacity_lo;
+ UINT8 reserved_43_95[95 - 43 + 1];
+} INQUIRY_DATA;
+
+typedef struct {
+ UINT8 peripheral_type;
+ UINT8 RMB;
+ UINT8 version;
+ UINT8 response_data_format;
+ UINT8 addnl_length;
+ UINT8 reserved_5;
+ UINT8 reserved_6;
+ UINT8 reserved_7;
+ UINT8 vendor_info[8];
+ UINT8 product_id[16];
+ UINT8 product_revision_level[4];
+ UINT8 vendor_specific[20];
+ UINT8 reserved_56_95[40];
+} CDROM_INQUIRY_DATA;
+
+typedef struct {
+ UINT8 error_code : 7;
+ UINT8 valid : 1;
+ UINT8 reserved_1;
+ UINT8 sense_key : 4;
+ UINT8 reserved_21 : 1;
+ UINT8 ILI : 1;
+ UINT8 reserved_22 : 2;
+ UINT8 vendor_specific_3;
+ UINT8 vendor_specific_4;
+ UINT8 vendor_specific_5;
+ UINT8 vendor_specific_6;
+ UINT8 addnl_sense_length; // n - 7
+ UINT8 vendor_specific_8;
+ UINT8 vendor_specific_9;
+ UINT8 vendor_specific_10;
+ UINT8 vendor_specific_11;
+ UINT8 addnl_sense_code; // mandatory
+ UINT8 addnl_sense_code_qualifier; // mandatory
+ UINT8 field_replaceable_unit_code; // optional
+ UINT8 reserved_15;
+ UINT8 reserved_16;
+ UINT8 reserved_17;
+ //
+ // Followed by additional sense bytes : FIXME
+ //
+} REQUEST_SENSE_DATA;
+
+typedef struct {
+ UINT8 LastLba3;
+ UINT8 LastLba2;
+ UINT8 LastLba1;
+ UINT8 LastLba0;
+ UINT8 BlockSize3;
+ UINT8 BlockSize2;
+ UINT8 BlockSize1;
+ UINT8 BlockSize0;
+} READ_CAPACITY_DATA;
+
+typedef struct {
+ UINT8 reserved_0;
+ UINT8 reserved_1;
+ UINT8 reserved_2;
+ UINT8 Capacity_Length;
+ UINT8 LastLba3;
+ UINT8 LastLba2;
+ UINT8 LastLba1;
+ UINT8 LastLba0;
+ UINT8 DesCode : 2;
+ UINT8 reserved_9 : 6;
+ UINT8 BlockSize2;
+ UINT8 BlockSize1;
+ UINT8 BlockSize0;
+} READ_FORMAT_CAPACITY_DATA;
+
+#pragma pack()
+
+//
+// PIO mode definition
+//
+typedef enum {
+ ATA_PIO_MODE_BELOW_2,
+ ATA_PIO_MODE_2,
+ ATA_PIO_MODE_3,
+ ATA_PIO_MODE_4
+} ATA_PIO_MODE;
+
+//
+// Multi word DMA definition
+//
+typedef enum {
+ ATA_MDMA_MODE_0,
+ ATA_MDMA_MODE_1,
+ ATA_MDMA_MODE_2
+} ATA_MDMA_MODE;
+
+//
+// UDMA mode definition
+//
+typedef enum {
+ ATA_UDMA_MODE_0,
+ ATA_UDMA_MODE_1,
+ ATA_UDMA_MODE_2,
+ ATA_UDMA_MODE_3,
+ ATA_UDMA_MODE_4,
+ ATA_UDMA_MODE_5
+} ATA_UDMA_MODE;
+
+#define ATA_MODE_CATEGORY_DEFAULT_PIO 0x00
+#define ATA_MODE_CATEGORY_FLOW_PIO 0x01
+#define ATA_MODE_CATEGORY_MDMA 0x04
+#define ATA_MODE_CATEGORY_UDMA 0x08
+
+#pragma pack(1)
+
+typedef struct {
+ UINT8 ModeNumber : 3;
+ UINT8 ModeCategory : 5;
+} ATA_TRANSFER_MODE;
+
+typedef struct {
+ UINT8 Sector;
+ UINT8 Heads;
+ UINT8 MultipleSector;
+} ATA_DRIVE_PARMS;
+
+#pragma pack()
+//
+// IORDY Sample Point field value
+//
+#define ISP_5_CLK 0
+#define ISP_4_CLK 1
+#define ISP_3_CLK 2
+#define ISP_2_CLK 3
+
+//
+// Recovery Time field value
+//
+#define RECVY_4_CLK 0
+#define RECVY_3_CLK 1
+#define RECVY_2_CLK 2
+#define RECVY_1_CLK 3
+
+//
+// Slave IDE Timing Register Enable
+//
+#define SITRE bit14
+
+//
+// DMA Timing Enable Only Select 1
+//
+#define DTE1 bit7
+
+//
+// Pre-fetch and Posting Enable Select 1
+//
+#define PPE1 bit6
+
+//
+// IORDY Sample Point Enable Select 1
+//
+#define IE1 bit5
+
+//
+// Fast Timing Bank Drive Select 1
+//
+#define TIME1 bit4
+
+//
+// DMA Timing Enable Only Select 0
+//
+#define DTE0 bit3
+
+//
+// Pre-fetch and Posting Enable Select 0
+//
+#define PPE0 bit2
+
+//
+// IOREY Sample Point Enable Select 0
+//
+#define IE0 bit1
+
+//
+// Fast Timing Bank Drive Select 0
+//
+#define TIME0 bit0
+
+#endif
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/ComponentName.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/ComponentName.c
new file mode 100644
index 0000000..ba7ec08
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/ComponentName.c
@@ -0,0 +1,133 @@
+/*++
+
+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:
+
+ ComponentName.c
+
+Abstract:
+
+--*/
+
+#include "PciBus.h"
+
+//
+// EFI Component Name Protocol
+//
+EFI_COMPONENT_NAME_PROTOCOL gPciBusComponentName = {
+ PciBusComponentNameGetDriverName,
+ PciBusComponentNameGetControllerName,
+ "eng"
+};
+
+STATIC EFI_UNICODE_STRING_TABLE mPciBusDriverNameTable[] = {
+ { "eng", (CHAR16 *) L"PCI Bus Driver" },
+ { NULL , NULL }
+};
+
+EFI_STATUS
+EFIAPI
+PciBusComponentNameGetDriverName (
+ 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,
+ gPciBusComponentName.SupportedLanguages,
+ mPciBusDriverNameTable,
+ DriverName
+ );
+}
+
+EFI_STATUS
+EFIAPI
+PciBusComponentNameGetControllerName (
+ 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.
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/ComponentName.h b/EdkModulePkg/Bus/Pci/PciBus/Dxe/ComponentName.h
new file mode 100644
index 0000000..87d44c8
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/ComponentName.h
@@ -0,0 +1,91 @@
+/*++
+
+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:
+
+ ComponentName.h
+
+Abstract:
+
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_BUS_COMPONENT_NAME_H
+#define _EFI_PCI_BUS_COMPONENT_NAME_H
+
+#ifndef EFI_SIZE_REDUCTION_APPLIED
+
+extern EFI_COMPONENT_NAME_PROTOCOL gPciBusComponentName;
+
+#endif
+
+//
+// EFI Component Name Functions
+//
+EFI_STATUS
+EFIAPI
+PciBusComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Language - TODO: add argument description
+ DriverName - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciBusComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ ControllerHandle - TODO: add argument description
+ ChildHandle - TODO: add argument description
+ Language - TODO: add argument description
+ ControllerName - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/LightPciBus.mbd b/EdkModulePkg/Bus/Pci/PciBus/Dxe/LightPciBus.mbd
new file mode 100644
index 0000000..eea4971
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/LightPciBus.mbd
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MbdHeader>
+ <BaseName>LightPciBusPciBus</BaseName>
+ <Guid>C0734D12-7927-432b-986B-A7E3A35BA005</Guid>
+ <Version>0</Version>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Created>2006-03-12 17:09</Created>
+ <Modified>2006-03-19 15:18</Modified>
+ </MbdHeader>
+ <Libraries>
+ <Library>UefiBootServicesTableLib</Library>
+ <Library>UefiMemoryLib</Library>
+ <Library>UefiLib</Library>
+ <Library>UefiDriverEntryPoint</Library>
+ <Library>UefiDriverModelLib</Library>
+ <Library>DxeReportStatusCodeLib</Library>
+ <Library>BaseDebugLibReportStatusCode</Library>
+ <Library>EdkDxePrintLib</Library>
+ <Library>BaseLib</Library>
+ <Library>UefiDevicePathLib</Library>
+ <Library>DxeMemoryAllocationLib</Library>
+ </Libraries>
+</ModuleBuildDescription>
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/LightPciBus.msa b/EdkModulePkg/Bus/Pci/PciBus/Dxe/LightPciBus.msa
new file mode 100644
index 0000000..eec5c3c
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/LightPciBus.msa
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MsaHeader>
+ <BaseName>LightPciBusPciBus</BaseName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <ComponentType>BS_DRIVER</ComponentType>
+ <Guid>C0734D12-7927-432b-986B-A7E3A35BA005</Guid>
+ <Version>0</Version>
+ <Abstract>Component description file for LightPciBus module.</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Specification>0</Specification>
+ <Created>2006-03-12 17:09</Created>
+ <Updated>2006-03-19 15:18</Updated>
+ </MsaHeader>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverModelLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverEntryPoint</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">ReportStatusCodeLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiBootServicesTableLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DevicePathLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">MemoryAllocationLib</LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>PciBus.h</Filename>
+ <Filename>PciIo.h</Filename>
+ <Filename>PciCommand.h</Filename>
+ <Filename>PciDeviceSupport.h</Filename>
+ <Filename>PciResourceSupport.h</Filename>
+ <Filename>PciEnumerator.h</Filename>
+ <Filename>PciEnumeratorSupport.h</Filename>
+ <Filename>PciOptionRomSupport.h</Filename>
+ <Filename>PciRomTable.h</Filename>
+ <Filename>PciLib.h</Filename>
+ <Filename>PciRomTable.c</Filename>
+ <Filename>PciDriverOverride.h</Filename>
+ <Filename>PciPowerManagement.h</Filename>
+ <Filename>PciPowerManagement.c</Filename>
+ <Filename>PciDriverOverride.c</Filename>
+ <Filename>PciOptionRomSupport.c</Filename>
+ <Filename>PciEnumerator.c</Filename>
+ <Filename>PciEnumeratorSupport.c</Filename>
+ <Filename>PciResourceSupport.c</Filename>
+ <Filename>PciCOmmand.c</Filename>
+ <Filename>ComponentName.c</Filename>
+ <Filename>PciDeviceSupport.c</Filename>
+ <Filename>PciHotPlugSupport.c</Filename>
+ <Filename>PciBus.c</Filename>
+ <Filename>PciIo.c</Filename>
+ <Filename>LightPciLib.c</Filename>
+ </SourceFiles>
+ <Includes>
+ <PackageName>MdePkg</PackageName>
+ <PackageName>EdkModulePkg</PackageName>
+ </Includes>
+ <Protocols>
+ <Protocol Usage="ALWAYS_CONSUMED">DevicePath</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">PciRootBridgeIo</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">Decompress</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">UgaIo</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">PciPlatform</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">PciIo</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">BusSpecificDriverOverride</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">PciHotPlugRequest</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">IncompatiblePciDeviceSupport</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">PciHotPlugInit</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">PciHostBridgeResourceAllocation</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">LoadedImage</Protocol>
+ </Protocols>
+ <Guids>
+ <GuidEntry Usage="ALWAYS_CONSUMED">
+ <C_Name>PciOptionRomTable</C_Name>
+ </GuidEntry>
+ <GuidEntry Usage="ALWAYS_CONSUMED">
+ <C_Name>PciHotplugDevice</C_Name>
+ </GuidEntry>
+ <GuidEntry Usage="ALWAYS_CONSUMED">
+ <C_Name>StatusCodeSpecificData</C_Name>
+ </GuidEntry>
+ </Guids>
+ <Externs>
+ <Extern>
+ <ModuleEntryPoint>PciBusEntryPoint</ModuleEntryPoint>
+ </Extern>
+ <Extern>
+ <DriverBinding>gPciBusDriverBinding</DriverBinding>
+ <ComponentName>gPciBusComponentName</ComponentName>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea>
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/LightPciLib.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/LightPciLib.c
new file mode 100644
index 0000000..28c8a79
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/LightPciLib.c
@@ -0,0 +1,881 @@
+/*++
+
+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:
+
+ LightPciLib.c
+
+Abstract:
+
+ Light PCI Bus Driver Lib file
+ It abstracts some functions that can be different
+ between light PCI bus driver and full PCI bus driver
+
+Revision History
+
+--*/
+
+#include "pcibus.h"
+
+//
+// Light PCI bus driver woundn't support hotplug device
+// So just return
+//
+VOID
+InstallHotPlugRequestProtocol (
+ IN EFI_STATUS *Status
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Status - add argument and description to function comment
+{
+ return ;
+}
+
+//
+// Light PCI bus driver woundn't support hotplug device
+// So just skip install this GUID
+//
+VOID
+InstallPciHotplugGuid (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+{
+ return ;
+}
+
+//
+// Light PCI bus driver woundn't support hotplug device
+// So just skip uninstall the GUID
+//
+VOID
+UninstallPciHotplugGuid (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+{
+ return ;
+}
+
+//
+// Light PCI bus driver woundn't support PCCard
+// So it needn't get the bar of CardBus
+//
+VOID
+GetBackPcCardBar (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ return ;
+}
+
+//
+// Light PCI bus driver woundn't support resource reallocation
+// So just return
+//
+EFI_STATUS
+RemoveRejectedPciDevices (
+ EFI_HANDLE RootBridgeHandle,
+ IN PCI_IO_DEVICE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ RootBridgeHandle - TODO: add argument description
+ Bridge - TODO: add argument description
+
+Returns:
+
+ EFI_SUCCESS - TODO: Add description for return value
+
+--*/
+{
+ return EFI_SUCCESS;
+}
+
+//
+// Light PCI bus driver woundn't support resource reallocation
+// Simplified the code
+//
+EFI_STATUS
+PciHostBridgeResourceAllocator (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciResAlloc - add argument and description to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_IO_DEVICE *RootBridgeDev;
+ EFI_HANDLE RootBridgeHandle;
+ VOID *AcpiConfig;
+ EFI_STATUS Status;
+ UINT64 IoBase;
+ UINT64 Mem32Base;
+ UINT64 PMem32Base;
+ UINT64 Mem64Base;
+ UINT64 PMem64Base;
+ UINT64 MaxOptionRomSize;
+ PCI_RESOURCE_NODE *IoBridge;
+ PCI_RESOURCE_NODE *Mem32Bridge;
+ PCI_RESOURCE_NODE *PMem32Bridge;
+ PCI_RESOURCE_NODE *Mem64Bridge;
+ PCI_RESOURCE_NODE *PMem64Bridge;
+ PCI_RESOURCE_NODE IoPool;
+ PCI_RESOURCE_NODE Mem32Pool;
+ PCI_RESOURCE_NODE PMem32Pool;
+ PCI_RESOURCE_NODE Mem64Pool;
+ PCI_RESOURCE_NODE PMem64Pool;
+ REPORT_STATUS_CODE_LIBRARY_DEVICE_HANDLE_EXTENDED_DATA ExtendedData;
+
+ //
+ // Initialize resource pool
+ //
+
+ InitializeResourcePool (&IoPool, PciBarTypeIo16);
+ InitializeResourcePool (&Mem32Pool, PciBarTypeMem32);
+ InitializeResourcePool (&PMem32Pool, PciBarTypePMem32);
+ InitializeResourcePool (&Mem64Pool, PciBarTypeMem64);
+ InitializeResourcePool (&PMem64Pool, PciBarTypePMem64);
+
+ RootBridgeDev = NULL;
+ RootBridgeHandle = 0;
+
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+ //
+ // Get RootBridg Device by handle
+ //
+ RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
+
+ if (RootBridgeDev == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Get host bridge handle for status report
+ //
+ ExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;
+
+ //
+ // Create the entire system resource map from the information collected by
+ // enumerator. Several resource tree was created
+ //
+
+ IoBridge = CreateResourceNode (
+ RootBridgeDev,
+ 0,
+ 0xFFF,
+ 0,
+ PciBarTypeIo16,
+ PciResUsageTypical
+ );
+
+ Mem32Bridge = CreateResourceNode (
+ RootBridgeDev,
+ 0,
+ 0xFFFFF,
+ 0,
+ PciBarTypeMem32,
+ PciResUsageTypical
+ );
+
+ PMem32Bridge = CreateResourceNode (
+ RootBridgeDev,
+ 0,
+ 0xFFFFF,
+ 0,
+ PciBarTypePMem32,
+ PciResUsageTypical
+ );
+
+ Mem64Bridge = CreateResourceNode (
+ RootBridgeDev,
+ 0,
+ 0xFFFFF,
+ 0,
+ PciBarTypeMem64,
+ PciResUsageTypical
+ );
+
+ PMem64Bridge = CreateResourceNode (
+ RootBridgeDev,
+ 0,
+ 0xFFFFF,
+ 0,
+ PciBarTypePMem64,
+ PciResUsageTypical
+ );
+
+ //
+ // Create resourcemap by going through all the devices subject to this root bridge
+ //
+ Status = CreateResourceMap (
+ RootBridgeDev,
+ IoBridge,
+ Mem32Bridge,
+ PMem32Bridge,
+ Mem64Bridge,
+ PMem64Bridge
+ );
+
+ //
+ // Get the max ROM size that the root bridge can process
+ //
+ RootBridgeDev->RomSize = Mem32Bridge->Length;
+
+ //
+ // Get Max Option Rom size for current root bridge
+ //
+ MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);
+
+ //
+ // Enlarger the mem32 resource to accomdate the option rom
+ // if the mem32 resource is not enough to hold the rom
+ //
+ if (MaxOptionRomSize > Mem32Bridge->Length) {
+
+ Mem32Bridge->Length = MaxOptionRomSize;
+ RootBridgeDev->RomSize = MaxOptionRomSize;
+
+ //
+ // Alignment should be adjusted as well
+ //
+ if (Mem32Bridge->Alignment < MaxOptionRomSize - 1) {
+ Mem32Bridge->Alignment = MaxOptionRomSize - 1;
+ }
+ }
+
+ //
+ // Based on the all the resource tree, contruct ACPI resource node to
+ // submit the resource aperture to pci host bridge protocol
+ //
+ Status = ConstructAcpiResourceRequestor (
+ RootBridgeDev,
+ IoBridge,
+ Mem32Bridge,
+ PMem32Bridge,
+ Mem64Bridge,
+ PMem64Bridge,
+ &AcpiConfig
+ );
+
+ //
+ // Insert these resource nodes into the database
+ //
+ InsertResourceNode (&IoPool, IoBridge);
+ InsertResourceNode (&Mem32Pool, Mem32Bridge);
+ InsertResourceNode (&PMem32Pool, PMem32Bridge);
+ InsertResourceNode (&Mem64Pool, Mem64Bridge);
+ InsertResourceNode (&PMem64Pool, PMem64Bridge);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Submit the resource requirement
+ //
+ Status = PciResAlloc->SubmitResources (
+ PciResAlloc,
+ RootBridgeDev->Handle,
+ AcpiConfig
+ );
+ }
+ //
+ // Free acpi resource node
+ //
+ if (AcpiConfig) {
+ gBS->FreePool (AcpiConfig);
+ }
+
+ if (EFI_ERROR (Status)) {
+ //
+ // Destroy all the resource tree
+ //
+ DestroyResourceTree (&IoPool);
+ DestroyResourceTree (&Mem32Pool);
+ DestroyResourceTree (&PMem32Pool);
+ DestroyResourceTree (&Mem64Pool);
+ DestroyResourceTree (&PMem64Pool);
+ return Status;
+ }
+ }
+ //
+ // End while
+ //
+
+ //
+ // Notify pci bus driver starts to program the resource
+ //
+ Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);
+
+ if (EFI_ERROR (Status)) {
+ //
+ // Allocation failed, then return
+ //
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Raise the EFI_IOB_PCI_RES_ALLOC status code
+ //
+ REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
+ EFI_PROGRESS_CODE,
+ EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_RES_ALLOC,
+ (VOID *) &ExtendedData,
+ sizeof (ExtendedData)
+ );
+
+ //
+ // Notify pci bus driver starts to program the resource
+ //
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);
+
+ RootBridgeDev = NULL;
+
+ RootBridgeHandle = 0;
+
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+ //
+ // Get RootBridg Device by handle
+ //
+ RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
+
+ if (RootBridgeDev == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Get acpi resource node for all the resource types
+ //
+ AcpiConfig = NULL;
+ Status = PciResAlloc->GetProposedResources (
+ PciResAlloc,
+ RootBridgeDev->Handle,
+ &AcpiConfig
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get the resource base by interpreting acpi resource node
+ //
+ //
+ GetResourceBase (
+ AcpiConfig,
+ &IoBase,
+ &Mem32Base,
+ &PMem32Base,
+ &Mem64Base,
+ &PMem64Base
+ );
+
+ //
+ // Process option rom for this root bridge
+ //
+ Status = ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize);
+
+ //
+ // Create the entire system resource map from the information collected by
+ // enumerator. Several resource tree was created
+ //
+ Status = GetResourceMap (
+ RootBridgeDev,
+ &IoBridge,
+ &Mem32Bridge,
+ &PMem32Bridge,
+ &Mem64Bridge,
+ &PMem64Bridge,
+ &IoPool,
+ &Mem32Pool,
+ &PMem32Pool,
+ &Mem64Pool,
+ &PMem64Pool
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Program IO resources
+ //
+ ProgramResource (
+ IoBase,
+ IoBridge
+ );
+
+ //
+ // Program Mem32 resources
+ //
+ ProgramResource (
+ Mem32Base,
+ Mem32Bridge
+ );
+
+ //
+ // Program PMem32 resources
+ //
+ ProgramResource (
+ PMem32Base,
+ PMem32Bridge
+ );
+
+ //
+ // Program Mem64 resources
+ //
+ ProgramResource (
+ Mem64Base,
+ Mem64Bridge
+ );
+
+ //
+ // Program PMem64 resources
+ //
+ ProgramResource (
+ PMem64Base,
+ PMem64Bridge
+ );
+
+ if (AcpiConfig != NULL) {
+ gBS->FreePool (AcpiConfig);
+ }
+ }
+
+ //
+ // Destroy all the resource tree
+ //
+ DestroyResourceTree (&IoPool);
+ DestroyResourceTree (&Mem32Pool);
+ DestroyResourceTree (&PMem32Pool);
+ DestroyResourceTree (&Mem64Pool);
+ DestroyResourceTree (&PMem64Pool);
+
+ //
+ // Notify the resource allocation phase is to end
+ //
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciScanBus (
+ IN PCI_IO_DEVICE *Bridge,
+ IN UINT8 StartBusNumber,
+ OUT UINT8 *SubBusNumber,
+ OUT UINT8 *PaddedBusRange
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to assign bus number to the given PCI bus system
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: StartBusNumber - add argument and description to function comment
+// TODO: SubBusNumber - add argument and description to function comment
+// TODO: PaddedBusRange - add argument and description to function comment
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_TYPE00 Pci;
+ UINT8 Device;
+ UINT8 Func;
+ UINT64 Address;
+ UINTN SecondBus;
+ UINT16 Register;
+ PCI_IO_DEVICE *PciDevice;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+
+ PciRootBridgeIo = Bridge->PciRootBridgeIo;
+ SecondBus = 0;
+ Register = 0;
+
+ ResetAllPpbBusReg (Bridge, StartBusNumber);
+
+ for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
+ for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
+
+ //
+ // Check to see whether a pci device is present
+ //
+ Status = PciDevicePresent (
+ PciRootBridgeIo,
+ &Pci,
+ StartBusNumber,
+ Device,
+ Func
+ );
+
+ if (!EFI_ERROR (Status) &&
+ (IS_PCI_BRIDGE (&Pci) ||
+ IS_CARDBUS_BRIDGE (&Pci))) {
+
+ //
+ // Get the bridge information
+ //
+ Status = PciSearchDevice (
+ Bridge,
+ &Pci,
+ StartBusNumber,
+ Device,
+ Func,
+ &PciDevice
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ (*SubBusNumber)++;
+
+ SecondBus = (*SubBusNumber);
+
+ Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);
+
+ Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
+
+ Status = PciRootBridgeIo->Pci.Write (
+ PciRootBridgeIo,
+ EfiPciWidthUint16,
+ Address,
+ 1,
+ &Register
+ );
+
+ //
+ // Initialize SubBusNumber to SecondBus
+ //
+ Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
+ Status = PciRootBridgeIo->Pci.Write (
+ PciRootBridgeIo,
+ EfiPciWidthUint8,
+ Address,
+ 1,
+ SubBusNumber
+ );
+ //
+ // If it is PPB, resursively search down this bridge
+ //
+ if (IS_PCI_BRIDGE (&Pci)) {
+ //
+ // Temporarily initialize SubBusNumber to maximum bus number to ensure the
+ // PCI configuration transaction to go through any PPB
+ //
+ Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
+ Register = 0xFF;
+ Status = PciRootBridgeIo->Pci.Write (
+ PciRootBridgeIo,
+ EfiPciWidthUint8,
+ Address,
+ 1,
+ &Register
+ );
+
+ PreprocessController (
+ PciDevice,
+ PciDevice->BusNumber,
+ PciDevice->DeviceNumber,
+ PciDevice->FunctionNumber,
+ EfiPciBeforeChildBusEnumeration
+ );
+
+ Status = PciScanBus (
+ PciDevice,
+ (UINT8) (SecondBus),
+ SubBusNumber,
+ PaddedBusRange
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ //
+ // Set the current maximum bus number under the PPB
+ //
+
+ Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
+
+ Status = PciRootBridgeIo->Pci.Write (
+ PciRootBridgeIo,
+ EfiPciWidthUint8,
+ Address,
+ 1,
+ SubBusNumber
+ );
+
+ }
+
+ if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
+
+ //
+ // Skip sub functions, this is not a multi function device
+ //
+
+ Func = PCI_MAX_FUNC;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+//
+// Light PCI bus driver woundn't support P2C
+// Return instead
+//
+EFI_STATUS
+PciHostBridgeP2CProcess (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciResAlloc - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ return EFI_SUCCESS;
+}
+
+//
+// Light PCI bus driver woundn't support hotplug device
+// Simplified the code
+//
+EFI_STATUS
+PciHostBridgeEnumerator (
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+ )
+/*++
+
+Routine Description:
+
+ This function is used to enumerate the entire host bridge
+ in a given platform
+
+Arguments:
+
+ PciResAlloc A pointer to the protocol to allocate resource.
+
+Returns:
+
+ None
+
+--*/
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_HANDLE RootBridgeHandle;
+ PCI_IO_DEVICE *RootBridgeDev;
+ EFI_STATUS Status;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+ UINT16 MinBus;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
+
+ InitializeHotPlugSupport ();
+
+ //
+ // Notify the bus allocation phase is about to start
+ //
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
+
+ RootBridgeHandle = NULL;
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+
+ //
+ // if a root bridge instance is found, create root bridge device for it
+ //
+
+ RootBridgeDev = CreateRootBridge (RootBridgeHandle);
+
+ if (RootBridgeDev == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Enumerate all the buses under this root bridge
+ //
+
+ Status = PciRootBridgeEnumerator (
+ PciResAlloc,
+ RootBridgeDev
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DestroyRootBridge (RootBridgeDev);
+
+ //
+ // Error proccess here
+ //
+ }
+
+ //
+ // Notify the bus allocation phase is to end
+ //
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);
+
+ //
+ // Notify the resource allocation phase is to start
+ //
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);
+
+ RootBridgeHandle = NULL;
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+
+ //
+ // if a root bridge instance is found, create root bridge device for it
+ //
+
+ RootBridgeDev = CreateRootBridge (RootBridgeHandle);
+
+ if (RootBridgeDev == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = StartManagingRootBridge (RootBridgeDev);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;
+ Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Determine root bridge attribute by calling interface of Pcihostbridge
+ // protocol
+ //
+ DetermineRootBridgeAttributes (
+ PciResAlloc,
+ RootBridgeDev
+ );
+
+ //
+ // Collect all the resource information under this root bridge
+ // A database that records all the information about pci device subject to this
+ // root bridge will then be created
+ //
+ Status = PciPciDeviceInfoCollector (
+ RootBridgeDev,
+ (UINT8) MinBus
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ InsertRootBridge (RootBridgeDev);
+
+ //
+ // Record the hostbridge handle
+ //
+ AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBus.mbd b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBus.mbd
new file mode 100644
index 0000000..41543f7
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBus.mbd
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MbdHeader>
+ <BaseName>PciBus</BaseName>
+ <Guid>93B80004-9FB3-11d4-9A3A-0090273FC14D</Guid>
+ <Version>0</Version>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Created>2006-03-12 17:09</Created>
+ <Modified>2006-03-19 15:18</Modified>
+ </MbdHeader>
+ <Libraries>
+ <Library>UefiBootServicesTableLib</Library>
+ <Library>UefiMemoryLib</Library>
+ <Library>UefiLib</Library>
+ <Library>UefiDriverEntryPoint</Library>
+ <Library>UefiDriverModelLib</Library>
+ <Library>DxeReportStatusCodeLib</Library>
+ <Library>BaseDebugLibReportStatusCode</Library>
+ <Library>EdkDxePrintLib</Library>
+ <Library>BaseLib</Library>
+ <Library>DxeMemoryAllocationLib</Library>
+ <Library>UefiDevicePathLib</Library>
+ </Libraries>
+</ModuleBuildDescription>
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBus.msa b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBus.msa
new file mode 100644
index 0000000..bf5c369
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBus.msa
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MsaHeader>
+ <BaseName>PciBus</BaseName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <ComponentType>BS_DRIVER</ComponentType>
+ <Guid>93B80004-9FB3-11d4-9A3A-0090273FC14D</Guid>
+ <Version>0</Version>
+ <Abstract>Component description file for PciBus module.</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Specification>0</Specification>
+ <Created>2006-03-12 17:09</Created>
+ <Updated>2006-03-19 15:18</Updated>
+ </MsaHeader>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverModelLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverEntryPoint</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">ReportStatusCodeLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">MemoryAllocationLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiBootServicesTableLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DevicePathLib</LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>PciBus.h</Filename>
+ <Filename>PciIo.h</Filename>
+ <Filename>PciCommand.h</Filename>
+ <Filename>PciDeviceSupport.h</Filename>
+ <Filename>PciResourceSupport.h</Filename>
+ <Filename>PciEnumerator.h</Filename>
+ <Filename>PciEnumeratorSupport.h</Filename>
+ <Filename>PciOptionRomSupport.h</Filename>
+ <Filename>PciRomTable.h</Filename>
+ <Filename>PciHotPlugSupport.h</Filename>
+ <Filename>PciLib.h</Filename>
+ <Filename>PciHotPlugSupport.c</Filename>
+ <Filename>PciRomTable.c</Filename>
+ <Filename>PciDriverOverride.h</Filename>
+ <Filename>PciPowerManagement.h</Filename>
+ <Filename>PciPowerManagement.c</Filename>
+ <Filename>PciDriverOverride.c</Filename>
+ <Filename>PciOptionRomSupport.c</Filename>
+ <Filename>PciEnumerator.c</Filename>
+ <Filename>PciEnumeratorSupport.c</Filename>
+ <Filename>PciResourceSupport.c</Filename>
+ <Filename>PciCOmmand.c</Filename>
+ <Filename>ComponentName.c</Filename>
+ <Filename>PciDeviceSupport.c</Filename>
+ <Filename>PciBus.c</Filename>
+ <Filename>PciIo.c</Filename>
+ <Filename>PciLib.c</Filename>
+ </SourceFiles>
+ <Includes>
+ <PackageName>MdePkg</PackageName>
+ <PackageName>EdkModulePkg</PackageName>
+ </Includes>
+ <Protocols>
+ <Protocol Usage="TO_START">DevicePath</Protocol>
+ <Protocol Usage="TO_START">PciRootBridgeIo</Protocol>
+ <Protocol Usage="TO_START">PciPlatform</Protocol>
+ <Protocol Usage="TO_START">IncompatiblePciDeviceSupport</Protocol>
+ <Protocol Usage="TO_START">PciHostBridgeResourceAllocation</Protocol>
+ <Protocol Usage="TO_START">PciHotPlugInit</Protocol>
+ <Protocol Usage="TO_START">Decompress</Protocol>
+ <Protocol Usage="TO_START">LoadedImage</Protocol>
+ <Protocol Usage="TO_START">UgaIo</Protocol>
+ <Protocol Usage="BY_START">PciIo</Protocol>
+ <Protocol Usage="BY_START">BusSpecificDriverOverride</Protocol>
+ <Protocol Usage="ALWAYS_PRODUCED">PciHotPlugRequest</Protocol>
+ </Protocols>
+ <SystemTables>
+ <SystemTable Usage="ALWAYS_CONSUMED">
+ <Entry>gEfiUgaIoProtocolGuid</Entry>
+ </SystemTable>
+ <SystemTable Usage="SOMETIMES_CONSUMED">
+ <Entry>gEfiPciOptionRomTableGuid</Entry>
+ </SystemTable>
+ </SystemTables>
+ <Guids>
+ <GuidEntry Usage="SOMETIMES_CONSUMED">
+ <C_Name>PciOptionRomTable</C_Name>
+ </GuidEntry>
+ <GuidEntry Usage="SOMETIMES_CONSUMED">
+ <C_Name>StatusCodeSpecificData</C_Name>
+ </GuidEntry>
+ <GuidEntry Usage="PRIVATE">
+ <C_Name>PciHotplugDevice</C_Name>
+ </GuidEntry>
+ </Guids>
+ <Externs>
+ <Extern>
+ <ModuleEntryPoint>PciBusEntryPoint</ModuleEntryPoint>
+ </Extern>
+ <Extern>
+ <DriverBinding>gPciBusDriverBinding</DriverBinding>
+ <ComponentName>gPciBusComponentName</ComponentName>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea>
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBusLite.mbd b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBusLite.mbd
new file mode 100644
index 0000000..c029652
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBusLite.mbd
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MbdHeader>
+ <BaseName>PciBusPciBusLite</BaseName>
+ <Guid>C0734D12-7927-432b-986B-A7E3A35BA005</Guid>
+ <Version>0</Version>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Created>2006-03-12 17:09</Created>
+ <Modified>2006-03-19 15:18</Modified>
+ </MbdHeader>
+ <Libraries>
+ <Library>UefiBootServicesTableLib</Library>
+ <Library>UefiMemoryLib</Library>
+ <Library>UefiLib</Library>
+ <Library>UefiDriverEntryPoint</Library>
+ <Library>UefiDriverModelLib</Library>
+ <Library>DxeReportStatusCodeLib</Library>
+ <Library>BaseDebugLibReportStatusCode</Library>
+ <Library>EdkDxePrintLib</Library>
+ <Library>BaseLib</Library>
+ <Library>UefiDevicePathLib</Library>
+ <Library>DxeMemoryAllocationLib</Library>
+ </Libraries>
+</ModuleBuildDescription>
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBusLite.msa b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBusLite.msa
new file mode 100644
index 0000000..1568b31
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBusLite.msa
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MsaHeader>
+ <BaseName>PciBusPciBusLite</BaseName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <ComponentType>BS_DRIVER</ComponentType>
+ <Guid>C0734D12-7927-432b-986B-A7E3A35BA005</Guid>
+ <Version>0</Version>
+ <Abstract>Component description file for LightPciBus module.</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Specification>0</Specification>
+ <Created>2006-03-12 17:09</Created>
+ <Updated>2006-03-19 15:18</Updated>
+ </MsaHeader>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverModelLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverEntryPoint</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">ReportStatusCodeLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiBootServicesTableLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DevicePathLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">MemoryAllocationLib</LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>PciBus.h</Filename>
+ <Filename>PciIo.h</Filename>
+ <Filename>PciCommand.h</Filename>
+ <Filename>PciDeviceSupport.h</Filename>
+ <Filename>PciResourceSupport.h</Filename>
+ <Filename>PciEnumerator.h</Filename>
+ <Filename>PciEnumeratorSupport.h</Filename>
+ <Filename>PciOptionRomSupport.h</Filename>
+ <Filename>PciRomTable.h</Filename>
+ <Filename>PciLib.h</Filename>
+ <Filename>PciRomTable.c</Filename>
+ <Filename>PciDriverOverride.h</Filename>
+ <Filename>PciPowerManagement.h</Filename>
+ <Filename>PciPowerManagement.c</Filename>
+ <Filename>PciDriverOverride.c</Filename>
+ <Filename>PciOptionRomSupport.c</Filename>
+ <Filename>PciEnumerator.c</Filename>
+ <Filename>PciEnumeratorSupport.c</Filename>
+ <Filename>PciResourceSupport.c</Filename>
+ <Filename>PciCOmmand.c</Filename>
+ <Filename>PciDeviceSupport.c</Filename>
+ <Filename>PciHotPlugSupport.c</Filename>
+ <Filename>PciBus.c</Filename>
+ <Filename>PciIo.c</Filename>
+ <Filename>LightPciLib.c</Filename>
+ </SourceFiles>
+ <Includes>
+ <PackageName>MdePkg</PackageName>
+ <PackageName>EdkModulePkg</PackageName>
+ </Includes>
+ <Protocols>
+ <Protocol Usage="ALWAYS_CONSUMED">DevicePath</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">PciRootBridgeIo</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">Decompress</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">UgaIo</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">PciPlatform</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">PciIo</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">BusSpecificDriverOverride</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">PciHotPlugRequest</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">IncompatiblePciDeviceSupport</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">PciHotPlugInit</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">PciHostBridgeResourceAllocation</Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">LoadedImage</Protocol>
+ </Protocols>
+ <Guids>
+ <GuidEntry Usage="ALWAYS_CONSUMED">
+ <C_Name>PciOptionRomTable</C_Name>
+ </GuidEntry>
+ <GuidEntry Usage="ALWAYS_CONSUMED">
+ <C_Name>PciHotplugDevice</C_Name>
+ </GuidEntry>
+ <GuidEntry Usage="ALWAYS_CONSUMED">
+ <C_Name>StatusCodeSpecificData</C_Name>
+ </GuidEntry>
+ </Guids>
+ <Externs>
+ <Extern>
+ <ModuleEntryPoint>PciBusEntryPoint</ModuleEntryPoint>
+ </Extern>
+ <Extern>
+ <DriverBinding>gPciBusDriverBinding</DriverBinding>
+ <ComponentName>gPciBusComponentName</ComponentName>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea>
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciCommand.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciCommand.c
new file mode 100644
index 0000000..9071233
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciCommand.c
@@ -0,0 +1,207 @@
+/*++
+
+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:
+
+ PciCommand.c
+
+Abstract:
+
+ PCI Bus Driver
+
+Revision History
+
+--*/
+
+#include "Pcibus.h"
+
+EFI_STATUS
+PciOperateRegister (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINT16 Command,
+ IN UINT8 Offset,
+ IN UINT8 Operation,
+ OUT UINT16 *PtrCommand
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: Command - add argument and description to function comment
+// TODO: Offset - add argument and description to function comment
+// TODO: Operation - add argument and description to function comment
+// TODO: PtrCommand - add argument and description to function comment
+{
+ UINT16 OldCommand;
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ OldCommand = 0;
+ PciIo = &PciIoDevice->PciIo;
+
+ if (Operation != EFI_SET_REGISTER) {
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ Offset,
+ 1,
+ &OldCommand
+ );
+
+ if (Operation == EFI_GET_REGISTER) {
+ *PtrCommand = OldCommand;
+ return Status;
+ }
+ }
+
+ if (Operation == EFI_ENABLE_REGISTER) {
+ OldCommand |= Command;
+ } else if (Operation == EFI_DISABLE_REGISTER) {
+ OldCommand &= ~(Command);
+ } else {
+ OldCommand = Command;
+ }
+
+ return PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ Offset,
+ 1,
+ &OldCommand
+ );
+}
+
+BOOLEAN
+PciCapabilitySupport (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+{
+
+ if (PciIoDevice->Pci.Hdr.Status & EFI_PCI_STATUS_CAPABILITY) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+EFI_STATUS
+LocateCapabilityRegBlock (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINT8 CapId,
+ IN OUT UINT8 *Offset,
+ OUT UINT8 *NextRegBlock OPTIONAL
+ )
+/*++
+
+Routine Description:
+ Locate cap reg.
+
+Arguments:
+ PciIoDevice - A pointer to the PCI_IO_DEVICE.
+ CapId - The cap ID.
+ Offset - A pointer to the offset.
+ NextRegBlock - A pointer to the next block.
+
+Returns:
+
+ None
+
+--*/
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+{
+ UINT8 CapabilityPtr;
+ UINT16 CapabilityEntry;
+ UINT8 CapabilityID;
+
+ //
+ // To check the cpability of this device supports
+ //
+ if (!PciCapabilitySupport (PciIoDevice)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (*Offset != 0) {
+ CapabilityPtr = *Offset;
+ } else {
+
+ CapabilityPtr = 0;
+ if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
+
+ PciIoDevice->PciIo.Pci.Read (
+ &PciIoDevice->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR,
+ 1,
+ &CapabilityPtr
+ );
+ } else {
+
+ PciIoDevice->PciIo.Pci.Read (
+ &PciIoDevice->PciIo,
+ EfiPciIoWidthUint8,
+ EFI_PCI_CAPABILITY_PTR,
+ 1,
+ &CapabilityPtr
+ );
+ }
+ }
+
+ while (CapabilityPtr > 0x3F) {
+ //
+ // Mask it to DWORD alignment per PCI spec
+ //
+ CapabilityPtr &= 0xFC;
+ PciIoDevice->PciIo.Pci.Read (
+ &PciIoDevice->PciIo,
+ EfiPciIoWidthUint16,
+ CapabilityPtr,
+ 1,
+ &CapabilityEntry
+ );
+
+ CapabilityID = (UINT8) CapabilityEntry;
+
+ if (CapabilityID == CapId) {
+ *Offset = CapabilityPtr;
+ if (NextRegBlock != NULL) {
+ *NextRegBlock = (UINT8) (CapabilityEntry >> 8);
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ CapabilityPtr = (UINT8) (CapabilityEntry >> 8);
+ }
+
+ return EFI_NOT_FOUND;
+}
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciCommand.h b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciCommand.h
new file mode 100644
index 0000000..56f632e
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciCommand.h
@@ -0,0 +1,134 @@
+/*++
+
+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:
+
+ PciCommand.h
+
+Abstract:
+
+ PCI Bus Driver
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_COMMAND_H
+#define _EFI_PCI_COMMAND_H
+
+#define EFI_GET_REGISTER 1
+#define EFI_SET_REGISTER 2
+#define EFI_ENABLE_REGISTER 3
+#define EFI_DISABLE_REGISTER 4
+
+EFI_STATUS
+PciOperateRegister (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINT16 Command,
+ IN UINT8 Offset,
+ IN UINT8 Operation,
+ OUT UINT16 *PtrCommand
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+ Command - TODO: add argument description
+ Offset - TODO: add argument description
+ Operation - TODO: add argument description
+ PtrCommand - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+PciCapabilitySupport (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+LocateCapabilityRegBlock (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINT8 CapId,
+ IN OUT UINT8 *Offset,
+ OUT UINT8 *NextRegBlock OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+ CapId - TODO: add argument description
+ Offset - TODO: add argument description
+ NextRegBlock - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+
+#define PciReadCommandRegister(a,b) \
+ PciOperateRegister (a,0, PCI_COMMAND_OFFSET, EFI_GET_REGISTER, b)
+
+#define PciSetCommandRegister(a,b) \
+ PciOperateRegister (a,b, PCI_COMMAND_OFFSET, EFI_SET_REGISTER, NULL)
+
+#define PciEnableCommandRegister(a,b) \
+ PciOperateRegister (a,b, PCI_COMMAND_OFFSET, EFI_ENABLE_REGISTER, NULL)
+
+#define PciDisableCommandRegister(a,b) \
+ PciOperateRegister (a,b, PCI_COMMAND_OFFSET, EFI_DISABLE_REGISTER, NULL)
+
+#define PciReadBridgeControlRegister(a,b) \
+ PciOperateRegister (a,0, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, EFI_GET_REGISTER, b)
+
+#define PciSetBridgeControlRegister(a,b) \
+ PciOperateRegister (a,b, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, EFI_SET_REGISTER, NULL)
+
+#define PciEnableBridgeControlRegister(a,b) \
+ PciOperateRegister (a,b, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, EFI_ENABLE_REGISTER, NULL)
+
+#define PciDisableBridgeControlRegister(a,b) \
+ PciOperateRegister (a,b, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, EFI_DISABLE_REGISTER, NULL)
+
+#endif
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDeviceSupport.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDeviceSupport.c
new file mode 100644
index 0000000..c24d1b5
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDeviceSupport.c
@@ -0,0 +1,1345 @@
+/*++
+
+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:
+
+ PciDeviceSupport.c
+
+Abstract:
+
+ This file provides routine to support Pci device node manipulation
+
+Revision History
+
+--*/
+
+#include "Pcibus.h"
+#include "PciDeviceSupport.h"
+
+//
+// This device structure is serviced as a header.
+// Its Next field points to the first root bridge device node
+//
+LIST_ENTRY gPciDevicePool;
+
+EFI_STATUS
+InitializePciDevicePool (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initialize the gPciDevicePool
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ InitializeListHead (&gPciDevicePool);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+InsertRootBridge (
+ PCI_IO_DEVICE *RootBridge
+ )
+/*++
+
+Routine Description:
+
+ Insert a root bridge into PCI device pool
+
+Arguments:
+
+ RootBridge - A pointer to the PCI_IO_DEVICE.
+
+Returns:
+
+ None
+
+--*/
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ InsertTailList (&gPciDevicePool, &(RootBridge->Link));
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+InsertPciDevice (
+ PCI_IO_DEVICE *Bridge,
+ PCI_IO_DEVICE *PciDeviceNode
+ )
+/*++
+
+Routine Description:
+
+ This function is used to insert a PCI device node under
+ a bridge
+
+Arguments:
+ Bridge - A pointer to the PCI_IO_DEVICE.
+ PciDeviceNode - A pointer to the PCI_IO_DEVICE.
+
+Returns:
+
+ None
+
+--*/
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ InsertTailList (&Bridge->ChildList, &(PciDeviceNode->Link));
+ PciDeviceNode->Parent = Bridge;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DestroyRootBridge (
+ IN PCI_IO_DEVICE *RootBridge
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+ RootBridge - A pointer to the PCI_IO_DEVICE.
+
+Returns:
+
+ None
+
+--*/
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ DestroyPciDeviceTree (RootBridge);
+
+ FreePciDevice (RootBridge);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FreePciDevice (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ Destroy a pci device node.
+ Also all direct or indirect allocated resource for this node will be freed.
+
+Arguments:
+
+ PciIoDevice - A pointer to the PCI_IO_DEVICE.
+
+Returns:
+
+ None
+
+--*/
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ //
+ // Assume all children have been removed underneath this device
+ //
+ if (PciIoDevice->ResourcePaddingDescriptors != NULL) {
+ gBS->FreePool (PciIoDevice->ResourcePaddingDescriptors);
+ }
+
+ if (PciIoDevice->DevicePath != NULL) {
+ gBS->FreePool (PciIoDevice->DevicePath);
+ }
+
+ gBS->FreePool (PciIoDevice);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DestroyPciDeviceTree (
+ IN PCI_IO_DEVICE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ Destroy all the pci device node under the bridge.
+ Bridge itself is not included.
+
+Arguments:
+
+ Bridge - A pointer to the PCI_IO_DEVICE.
+
+Returns:
+
+ None
+
+--*/
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ LIST_ENTRY *CurrentLink;
+ PCI_IO_DEVICE *Temp;
+
+ while (!IsListEmpty (&Bridge->ChildList)) {
+
+ CurrentLink = Bridge->ChildList.ForwardLink;
+
+ //
+ // Remove this node from the linked list
+ //
+ RemoveEntryList (CurrentLink);
+
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+ if (!IsListEmpty (&Temp->ChildList)) {
+ DestroyPciDeviceTree (Temp);
+ }
+
+ FreePciDevice (Temp);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DestroyRootBridgeByHandle (
+ EFI_HANDLE Controller
+ )
+/*++
+
+Routine Description:
+
+ Destroy all device nodes under the root bridge
+ specified by Controller.
+ The root bridge itself is also included.
+
+Arguments:
+
+ Controller - An efi handle.
+
+Returns:
+
+ None
+
+--*/
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+{
+
+ LIST_ENTRY *CurrentLink;
+ PCI_IO_DEVICE *Temp;
+
+ CurrentLink = gPciDevicePool.ForwardLink;
+
+ while (CurrentLink && CurrentLink != &gPciDevicePool) {
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+ if (Temp->Handle == Controller) {
+
+ RemoveEntryList (CurrentLink);
+
+ DestroyPciDeviceTree (Temp);
+
+ FreePciDevice (Temp);
+
+ return EFI_SUCCESS;
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+RegisterPciDevice (
+ IN EFI_HANDLE Controller,
+ IN PCI_IO_DEVICE *PciIoDevice,
+ OUT EFI_HANDLE *Handle OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ This function is used to register the PCI device to the EFI,
+ create a handle for this PCI device,then attach apporpriate protocols
+ onto the handle.
+
+Arguments:
+
+ Controller - An efi handle.
+ PciIoDevice - A pointer to the PCI_IO_DEVICE.
+ Handle - A pointer to a efi handle.
+
+Returns:
+
+ None
+
+--*/
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ VOID *PlatformOpRomBuffer;
+ UINTN PlatformOpRomSize;
+ UINT8 PciExpressCapRegOffset;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ //
+ // Install the pciio protocol, device path protocol
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &PciIoDevice->Handle,
+ &gEfiDevicePathProtocolGuid,
+ PciIoDevice->DevicePath,
+ &gEfiPciIoProtocolGuid,
+ &PciIoDevice->PciIo,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Detect if PCI Express Device
+ //
+ PciExpressCapRegOffset = 0;
+ Status = LocateCapabilityRegBlock (
+ PciIoDevice,
+ EFI_PCI_CAPABILITY_ID_PCIEXP,
+ &PciExpressCapRegOffset,
+ NULL
+ );
+ if (!EFI_ERROR (Status)) {
+ PciIoDevice->IsPciExp = TRUE;
+ }
+
+ //
+ // Force Interrupt line to zero for cards that come up randomly
+ //
+ PciIo = &(PciIoDevice->PciIo);
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);
+ //
+ // Process Platform OpRom
+ //
+ if (gPciPlatformProtocol != NULL && !PciIoDevice->AllOpRomProcessed) {
+ PciIoDevice->AllOpRomProcessed = TRUE;
+
+ Status = gPciPlatformProtocol->GetPciRom (
+ gPciPlatformProtocol,
+ PciIoDevice->Handle,
+ &PlatformOpRomBuffer,
+ &PlatformOpRomSize
+ );
+
+ if (!EFI_ERROR (Status)) {
+
+ //
+ // Have Platform OpRom
+ //
+ PciIoDevice->RomSize = PlatformOpRomSize;
+ PciIoDevice->PciIo.RomSize = PlatformOpRomSize;
+ PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
+
+ //
+ // Process Image
+ //
+ ProcessOpRomImage (PciIoDevice);
+ }
+ }
+
+ if (PciIoDevice->BusOverride) {
+ //
+ // Install BusSpecificDriverOverride Protocol
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &PciIoDevice->Handle,
+ &gEfiBusSpecificDriverOverrideProtocolGuid,
+ &PciIoDevice->PciDriverOverride,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->UninstallMultipleProtocolInterfaces (
+ &PciIoDevice->Handle,
+ &gEfiDevicePathProtocolGuid,
+ PciIoDevice->DevicePath,
+ &gEfiPciIoProtocolGuid,
+ &PciIoDevice->PciIo,
+ NULL
+ );
+
+ return Status;
+ }
+ }
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ (VOID **) &(PciIoDevice->PciRootBridgeIo),
+ gPciBusDriverBinding.DriverBindingHandle,
+ PciIoDevice->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Install Pccard Hotplug GUID for Pccard device so that
+ // to notify CardBus driver to stop the device when de-register happens
+ //
+ InstallPciHotplugGuid (PciIoDevice);
+
+ if (Handle != NULL) {
+ *Handle = PciIoDevice->Handle;
+ }
+
+ //
+ // Indicate the pci device is registered
+ //
+ PciIoDevice->Registered = TRUE;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+RemoveAllPciDeviceOnBridge (
+ EFI_HANDLE RootBridgeHandle,
+ PCI_IO_DEVICE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ This function is used to remove the whole PCI devices from the bridge.
+
+Arguments:
+
+ RootBridgeHandle - An efi handle.
+ Bridge - A pointer to the PCI_IO_DEVICE.
+
+Returns:
+
+ None
+
+--*/
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ LIST_ENTRY *CurrentLink;
+ PCI_IO_DEVICE *Temp;
+
+ while (!IsListEmpty (&Bridge->ChildList)) {
+
+ CurrentLink = Bridge->ChildList.ForwardLink;
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+ //
+ // Check if the current node has been deregistered before
+ // If it is not, then deregister it
+ //
+ if (Temp->Registered) {
+ DeRegisterPciDevice (RootBridgeHandle, Temp->Handle);
+ }
+
+ //
+ // Remove this node from the linked list
+ //
+ RemoveEntryList (CurrentLink);
+
+ if (!IsListEmpty (&Temp->ChildList)) {
+ RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp);
+ }
+
+ FreePciDevice (Temp);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DeRegisterPciDevice (
+ IN EFI_HANDLE Controller,
+ IN EFI_HANDLE Handle
+ )
+/*++
+
+Routine Description:
+
+ This function is used to de-register the PCI device from the EFI,
+ That includes un-installing PciIo protocol from the specified PCI
+ device handle.
+
+Arguments:
+
+ Controller - An efi handle.
+ Handle - An efi handle.
+
+Returns:
+
+ None
+
+--*/
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+ PCI_IO_DEVICE *Node;
+ LIST_ENTRY *CurrentLink;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+
+ Status = gBS->OpenProtocol (
+ Handle,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ gPciBusDriverBinding.DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);
+
+ //
+ // If it is already de-registered
+ //
+ if (!PciIoDevice->Registered) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // If it is PPB, first de-register its children
+ //
+
+ if (!IsListEmpty (&PciIoDevice->ChildList)) {
+
+ CurrentLink = PciIoDevice->ChildList.ForwardLink;
+
+ while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) {
+ Node = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+ Status = DeRegisterPciDevice (Controller, Node->Handle);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+ }
+ //
+ // Uninstall Pccard Hotplug GUID for Pccard device
+ //
+ UninstallPciHotplugGuid (PciIoDevice);
+
+ //
+ // Close the child handle
+ //
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ gPciBusDriverBinding.DriverBindingHandle,
+ Handle
+ );
+
+ //
+ // Un-install the device path protocol and pci io protocol
+ //
+ if (PciIoDevice->BusOverride) {
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ Handle,
+ &gEfiDevicePathProtocolGuid,
+ PciIoDevice->DevicePath,
+ &gEfiPciIoProtocolGuid,
+ &PciIoDevice->PciIo,
+ &gEfiBusSpecificDriverOverrideProtocolGuid,
+ &PciIoDevice->PciDriverOverride,
+ NULL
+ );
+ } else {
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ Handle,
+ &gEfiDevicePathProtocolGuid,
+ PciIoDevice->DevicePath,
+ &gEfiPciIoProtocolGuid,
+ &PciIoDevice->PciIo,
+ NULL
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ gBS->OpenProtocol (
+ Controller,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ (VOID **) &PciRootBridgeIo,
+ gPciBusDriverBinding.DriverBindingHandle,
+ Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ return Status;
+ }
+
+ //
+ // The Device Driver should disable this device after disconnect
+ // so the Pci Bus driver will not touch this device any more.
+ // Restore the register field to the original value
+ //
+ PciIoDevice->Registered = FALSE;
+ PciIoDevice->Handle = NULL;
+ } else {
+
+ //
+ // Handle may be closed before
+ //
+ return EFI_SUCCESS;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+StartPciDevicesOnBridge (
+ IN EFI_HANDLE Controller,
+ IN PCI_IO_DEVICE *RootBridge,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath,
+ IN OUT UINT8 *NumberOfChildren,
+ IN OUT EFI_HANDLE *ChildHandleBuffer
+ )
+/*++
+
+Routine Description:
+
+ Start to manage the PCI device on specified the root bridge or PCI-PCI Bridge
+
+Arguments:
+
+ Controller - An efi handle.
+ RootBridge - A pointer to the PCI_IO_DEVICE.
+ RemainingDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL.
+ NumberOfChildren - Children number.
+ ChildHandleBuffer - A pointer to the child handle buffer.
+
+Returns:
+
+ None
+
+--*/
+// TODO: EFI_NOT_READY - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+{
+ PCI_IO_DEVICE *Temp;
+ PCI_IO_DEVICE *PciIoDevice;
+ EFI_DEV_PATH_PTR Node;
+ EFI_DEVICE_PATH_PROTOCOL *CurrentDevicePath;
+ EFI_STATUS Status;
+ LIST_ENTRY *CurrentLink;
+ UINT64 Supports;
+
+ CurrentLink = RootBridge->ChildList.ForwardLink;
+
+ while (CurrentLink && CurrentLink != &RootBridge->ChildList) {
+
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+ if (RemainingDevicePath != NULL) {
+
+ Node.DevPath = RemainingDevicePath;
+
+ if (Node.Pci->Device != Temp->DeviceNumber ||
+ Node.Pci->Function != Temp->FunctionNumber) {
+ CurrentLink = CurrentLink->ForwardLink;
+ continue;
+ }
+
+ //
+ // Check if the device has been assigned with required resource
+ //
+ if (!Temp->Allocated) {
+ return EFI_NOT_READY;
+ }
+
+ //
+ // Check if the current node has been registered before
+ // If it is not, register it
+ //
+ if (!Temp->Registered) {
+ PciIoDevice = Temp;
+
+ Status = RegisterPciDevice (
+ Controller,
+ PciIoDevice,
+ NULL
+ );
+
+ }
+
+ if (NumberOfChildren != NULL && ChildHandleBuffer != NULL && Temp->Registered) {
+ ChildHandleBuffer[*NumberOfChildren] = Temp->Handle;
+ (*NumberOfChildren)++;
+ }
+
+ //
+ // Get the next device path
+ //
+ CurrentDevicePath = EfiNextDevicePathNode (RemainingDevicePath);
+ if (EfiIsDevicePathEnd (CurrentDevicePath)) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // If it is a PPB
+ //
+ if (!IsListEmpty (&Temp->ChildList)) {
+ Status = StartPciDevicesOnBridge (
+ Controller,
+ Temp,
+ CurrentDevicePath,
+ NumberOfChildren,
+ ChildHandleBuffer
+ );
+
+ Temp->PciIo.Attributes (
+ &(Temp->PciIo),
+ EfiPciIoAttributeOperationSupported,
+ 0,
+ &Supports
+ );
+ Supports &= EFI_PCI_DEVICE_ENABLE;
+ Temp->PciIo.Attributes (
+ &(Temp->PciIo),
+ EfiPciIoAttributeOperationEnable,
+ Supports,
+ NULL
+ );
+
+ return Status;
+ } else {
+
+ //
+ // Currently, the PCI bus driver only support PCI-PCI bridge
+ //
+ return EFI_UNSUPPORTED;
+ }
+
+ } else {
+
+ //
+ // If remaining device path is NULL,
+ // try to enable all the pci devices under this bridge
+ //
+
+ if (!Temp->Registered && Temp->Allocated) {
+
+ PciIoDevice = Temp;
+
+ Status = RegisterPciDevice (
+ Controller,
+ PciIoDevice,
+ NULL
+ );
+
+ }
+
+ if (NumberOfChildren != NULL && ChildHandleBuffer != NULL && Temp->Registered) {
+ ChildHandleBuffer[*NumberOfChildren] = Temp->Handle;
+ (*NumberOfChildren)++;
+ }
+
+ if (!IsListEmpty (&Temp->ChildList)) {
+ Status = StartPciDevicesOnBridge (
+ Controller,
+ Temp,
+ RemainingDevicePath,
+ NumberOfChildren,
+ ChildHandleBuffer
+ );
+
+ Temp->PciIo.Attributes (
+ &(Temp->PciIo),
+ EfiPciIoAttributeOperationSupported,
+ 0,
+ &Supports
+ );
+ Supports &= EFI_PCI_DEVICE_ENABLE;
+ Temp->PciIo.Attributes (
+ &(Temp->PciIo),
+ EfiPciIoAttributeOperationEnable,
+ Supports,
+ NULL
+ );
+
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ continue;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+StartPciDevices (
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+Routine Description:
+
+ Start to manage the PCI device according to RemainingDevicePath
+ If RemainingDevicePath == NULL, the PCI bus driver will start
+ to manage all the PCI devices it found previously
+
+Arguments:
+ Controller - An efi handle.
+ RemainingDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL.
+
+Returns:
+
+ None
+
+--*/
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_DEV_PATH_PTR Node;
+ PCI_IO_DEVICE *RootBridge;
+ LIST_ENTRY *CurrentLink;
+
+ if (RemainingDevicePath != NULL) {
+
+ //
+ // Check if the RemainingDevicePath is valid
+ //
+ Node.DevPath = RemainingDevicePath;
+ if ((Node.DevPath->Type != HARDWARE_DEVICE_PATH) ||
+ ((Node.DevPath->SubType != HW_PCI_DP) &&
+ (DevicePathNodeLength (Node.DevPath) != sizeof (PCI_DEVICE_PATH)))
+ ) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ CurrentLink = gPciDevicePool.ForwardLink;
+
+ while (CurrentLink && CurrentLink != &gPciDevicePool) {
+
+ RootBridge = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+ //
+ // Locate the right root bridge to start
+ //
+ if (RootBridge->Handle == Controller) {
+ StartPciDevicesOnBridge (
+ Controller,
+ RootBridge,
+ RemainingDevicePath,
+ NULL,
+ NULL
+ );
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ return EFI_SUCCESS;
+}
+
+PCI_IO_DEVICE *
+CreateRootBridge (
+ IN EFI_HANDLE RootBridgeHandle
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+ RootBridgeHandle - An efi handle.
+
+Returns:
+
+ None
+
+--*/
+{
+
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *Dev;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+
+ Dev = NULL;
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (PCI_IO_DEVICE),
+ (VOID **) &Dev
+ );
+
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ ZeroMem (Dev, sizeof (PCI_IO_DEVICE));
+ Dev->Signature = PCI_IO_DEVICE_SIGNATURE;
+ Dev->Handle = RootBridgeHandle;
+ InitializeListHead (&Dev->ChildList);
+
+ Status = gBS->OpenProtocol (
+ RootBridgeHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath,
+ gPciBusDriverBinding.DriverBindingHandle,
+ RootBridgeHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (Dev);
+ return NULL;
+ }
+
+ //
+ // Record the root bridge parent device path
+ //
+ Dev->DevicePath = DuplicateDevicePath (ParentDevicePath);
+
+ //
+ // Get the pci root bridge io protocol
+ //
+ Status = gBS->OpenProtocol (
+ RootBridgeHandle,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ (VOID **) &PciRootBridgeIo,
+ gPciBusDriverBinding.DriverBindingHandle,
+ RootBridgeHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ FreePciDevice (Dev);
+ return NULL;
+ }
+
+ Dev->PciRootBridgeIo = PciRootBridgeIo;
+
+ //
+ // Initialize the PCI I/O instance structure
+ //
+ Status = InitializePciIoInstance (Dev);
+ Status = InitializePciDriverOverrideInstance (Dev);
+
+ //
+ // Initialize reserved resource list and
+ // option rom driver list
+ //
+ InitializeListHead (&Dev->ReservedResourceList);
+ InitializeListHead (&Dev->OptionRomDriverList);
+
+ return Dev;
+}
+
+PCI_IO_DEVICE *
+GetRootBridgeByHandle (
+ EFI_HANDLE RootBridgeHandle
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+ RootBridgeHandle - An efi handle.
+
+Returns:
+
+ None
+
+--*/
+{
+ PCI_IO_DEVICE *RootBridgeDev;
+ LIST_ENTRY *CurrentLink;
+
+ CurrentLink = gPciDevicePool.ForwardLink;
+
+ while (CurrentLink && CurrentLink != &gPciDevicePool) {
+
+ RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+ if (RootBridgeDev->Handle == RootBridgeHandle) {
+ return RootBridgeDev;
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ return NULL;
+}
+
+BOOLEAN
+RootBridgeExisted (
+ IN EFI_HANDLE RootBridgeHandle
+ )
+/*++
+
+Routine Description:
+
+ This function searches if RootBridgeHandle has already existed
+ in current device pool.
+
+ If so, it means the given root bridge has been already enumerated.
+
+Arguments:
+
+ RootBridgeHandle - An efi handle.
+
+Returns:
+
+ None
+
+--*/
+{
+ PCI_IO_DEVICE *Bridge;
+
+ Bridge = GetRootBridgeByHandle (RootBridgeHandle);
+
+ if (Bridge != NULL) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOLEAN
+PciDeviceExisted (
+ IN PCI_IO_DEVICE *Bridge,
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+ Bridge - A pointer to the PCI_IO_DEVICE.
+ PciIoDevice - A pointer to the PCI_IO_DEVICE.
+
+Returns:
+
+ None
+
+--*/
+{
+
+ PCI_IO_DEVICE *Temp;
+ LIST_ENTRY *CurrentLink;
+
+ CurrentLink = Bridge->ChildList.ForwardLink;
+
+ while (CurrentLink && CurrentLink != &Bridge->ChildList) {
+
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+ if (Temp == PciIoDevice) {
+ return TRUE;
+ }
+
+ if (!IsListEmpty (&Temp->ChildList)) {
+ if (PciDeviceExisted (Temp, PciIoDevice)) {
+ return TRUE;
+ }
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ return FALSE;
+}
+
+PCI_IO_DEVICE *
+ActiveVGADeviceOnTheSameSegment (
+ IN PCI_IO_DEVICE *VgaDevice
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+ VgaDevice - A pointer to the PCI_IO_DEVICE.
+
+Returns:
+
+ None
+
+--*/
+{
+ LIST_ENTRY *CurrentLink;
+ PCI_IO_DEVICE *Temp;
+
+ CurrentLink = gPciDevicePool.ForwardLink;
+
+ while (CurrentLink && CurrentLink != &gPciDevicePool) {
+
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+ if (Temp->PciRootBridgeIo->SegmentNumber == VgaDevice->PciRootBridgeIo->SegmentNumber) {
+
+ Temp = ActiveVGADeviceOnTheRootBridge (Temp);
+
+ if (Temp != NULL) {
+ return Temp;
+ }
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ return NULL;
+}
+
+PCI_IO_DEVICE *
+ActiveVGADeviceOnTheRootBridge (
+ IN PCI_IO_DEVICE *RootBridge
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+ RootBridge - A pointer to the PCI_IO_DEVICE.
+
+Returns:
+
+ None
+
+--*/
+{
+ LIST_ENTRY *CurrentLink;
+ PCI_IO_DEVICE *Temp;
+
+ CurrentLink = RootBridge->ChildList.ForwardLink;
+
+ while (CurrentLink && CurrentLink != &RootBridge->ChildList) {
+
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+ if (IS_PCI_VGA(&Temp->Pci) &&
+ (Temp->Attributes & (EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_IO))) {
+ return Temp;
+ }
+
+ if (IS_PCI_BRIDGE (&Temp->Pci)) {
+
+ Temp = ActiveVGADeviceOnTheRootBridge (Temp);
+
+ if (Temp != NULL) {
+ return Temp;
+ }
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ return NULL;
+}
+
+EFI_STATUS
+GetHpcPciAddress (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
+ IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath,
+ OUT UINT64 *PciAddress
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+ PciRootBridgeIo - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ HpcDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCL.
+ PciAddress - A pointer to the pci address.
+
+Returns:
+
+ None
+
+--*/
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+{
+ EFI_DEVICE_PATH_PROTOCOL *CurrentDevicePath;
+ EFI_DEV_PATH_PTR Node;
+ LIST_ENTRY *CurrentLink;
+ PCI_IO_DEVICE *RootBridge;
+ EFI_STATUS Status;
+
+ CurrentDevicePath = HpcDevicePath;
+
+ //
+ // Get the remaining device path for this PCI device, if it is a PCI device
+ //
+ while (!EfiIsDevicePathEnd (CurrentDevicePath)) {
+
+ Node.DevPath = CurrentDevicePath;
+
+ //
+ // Check if it is PCI device Path?
+ //
+ if ((Node.DevPath->Type != HARDWARE_DEVICE_PATH) ||
+ ((Node.DevPath->SubType != HW_PCI_DP) &&
+ (DevicePathNodeLength (Node.DevPath) != sizeof (PCI_DEVICE_PATH)))) {
+ CurrentDevicePath = EfiNextDevicePathNode (CurrentDevicePath);
+ continue;
+ }
+
+ break;
+ }
+
+ //
+ // Check if it is not PCI device path
+ //
+ if (EfiIsDevicePathEnd (CurrentDevicePath)) {
+ return EFI_NOT_FOUND;
+ }
+
+ CurrentLink = gPciDevicePool.ForwardLink;
+
+ while (CurrentLink && CurrentLink != &gPciDevicePool) {
+
+ RootBridge = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+ //
+ // Locate the right root bridge to start
+ //
+ if (RootBridge->PciRootBridgeIo == PciRootBridgeIo) {
+ Status = GetHpcPciAddressFromRootBridge (
+ RootBridge,
+ CurrentDevicePath,
+ PciAddress
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+GetHpcPciAddressFromRootBridge (
+ IN PCI_IO_DEVICE *RootBridge,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath,
+ OUT UINT64 *PciAddress
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+ PciRootBridgeIo - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ HpcDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCL.
+ PciAddress - A pointer to the pci address.
+
+Returns:
+
+ None
+
+--*/
+// TODO: RootBridge - add argument and description to function comment
+// TODO: RemainingDevicePath - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_DEV_PATH_PTR Node;
+ PCI_IO_DEVICE *Temp;
+ EFI_DEVICE_PATH_PROTOCOL *CurrentDevicePath;
+ LIST_ENTRY *CurrentLink;
+ BOOLEAN MisMatch;
+
+ MisMatch = FALSE;
+
+ CurrentDevicePath = RemainingDevicePath;
+ Node.DevPath = CurrentDevicePath;
+ Temp = NULL;
+
+ while (!EfiIsDevicePathEnd (CurrentDevicePath)) {
+
+ CurrentLink = RootBridge->ChildList.ForwardLink;
+ Node.DevPath = CurrentDevicePath;
+
+ while (CurrentLink && CurrentLink != &RootBridge->ChildList) {
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+ if (Node.Pci->Device == Temp->DeviceNumber &&
+ Node.Pci->Function == Temp->FunctionNumber) {
+ RootBridge = Temp;
+ break;
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ //
+ // Check if we find the bridge
+ //
+ if (CurrentLink == &RootBridge->ChildList) {
+
+ MisMatch = TRUE;
+ break;
+
+ }
+
+ CurrentDevicePath = EfiNextDevicePathNode (CurrentDevicePath);
+ }
+
+ if (MisMatch) {
+
+ CurrentDevicePath = EfiNextDevicePathNode (CurrentDevicePath);
+
+ if (EfiIsDevicePathEnd (CurrentDevicePath)) {
+ *PciAddress = EFI_PCI_ADDRESS (RootBridge->BusNumber, Node.Pci->Device, Node.Pci->Function, 0);
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+ }
+
+ *PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);
+
+ return EFI_SUCCESS;
+
+}
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDeviceSupport.h b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDeviceSupport.h
new file mode 100644
index 0000000..374f4df
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDeviceSupport.h
@@ -0,0 +1,477 @@
+/*++
+
+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:
+
+ PciDeviceSupport.h
+
+Abstract:
+
+
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_DEVICE_SUPPORT_H
+#define _EFI_PCI_DEVICE_SUPPORT_H
+
+EFI_STATUS
+InitializePciDevicePool (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+InsertRootBridge (
+ PCI_IO_DEVICE *RootBridge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ RootBridge - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+InsertPciDevice (
+ PCI_IO_DEVICE *Bridge,
+ PCI_IO_DEVICE *PciDeviceNode
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ PciDeviceNode - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+DestroyRootBridge (
+ IN PCI_IO_DEVICE *RootBridge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ RootBridge - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+DestroyPciDeviceTree (
+ IN PCI_IO_DEVICE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+DestroyRootBridgeByHandle (
+ EFI_HANDLE Controller
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Controller - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+RegisterPciDevice (
+ IN EFI_HANDLE Controller,
+ IN PCI_IO_DEVICE *PciIoDevice,
+ OUT EFI_HANDLE *Handle OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Controller - TODO: add argument description
+ PciIoDevice - TODO: add argument description
+ Handle - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+RemoveAllPciDeviceOnBridge (
+ EFI_HANDLE RootBridgeHandle,
+ PCI_IO_DEVICE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ RootBridgeHandle - TODO: add argument description
+ Bridge - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+DeRegisterPciDevice (
+ IN EFI_HANDLE Controller,
+ IN EFI_HANDLE Handle
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Controller - TODO: add argument description
+ Handle - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+StartPciDevicesOnBridge (
+ IN EFI_HANDLE Controller,
+ IN PCI_IO_DEVICE *RootBridge,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath,
+ IN OUT UINT8 *NumberOfChildren,
+ IN OUT EFI_HANDLE *ChildHandleBuffer
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Controller - TODO: add argument description
+ RootBridge - TODO: add argument description
+ RemainingDevicePath - TODO: add argument description
+ NumberOfChildren - TODO: add argument description
+ ChildHandleBuffer - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+StartPciDevices (
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Controller - TODO: add argument description
+ RemainingDevicePath - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+PCI_IO_DEVICE *
+CreateRootBridge (
+ IN EFI_HANDLE RootBridgeHandle
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ RootBridgeHandle - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+PCI_IO_DEVICE *
+GetRootBridgeByHandle (
+ EFI_HANDLE RootBridgeHandle
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ RootBridgeHandle - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+RootBridgeExisted (
+ IN EFI_HANDLE RootBridgeHandle
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ RootBridgeHandle - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+PciDeviceExisted (
+ IN PCI_IO_DEVICE *Bridge,
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+PCI_IO_DEVICE *
+ActiveVGADeviceOnTheSameSegment (
+ IN PCI_IO_DEVICE *VgaDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ VgaDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+PCI_IO_DEVICE *
+ActiveVGADeviceOnTheRootBridge (
+ IN PCI_IO_DEVICE *RootBridge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ RootBridge - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+GetHpcPciAddress (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
+ IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath,
+ OUT UINT64 *PciAddress
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciRootBridgeIo - TODO: add argument description
+ HpcDevicePath - TODO: add argument description
+ PciAddress - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+GetHpcPciAddressFromRootBridge (
+ IN PCI_IO_DEVICE *RootBridge,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath,
+ OUT UINT64 *PciAddress
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ RootBridge - TODO: add argument description
+ RemainingDevicePath - TODO: add argument description
+ PciAddress - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+FreePciDevice (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDriverOverride.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDriverOverride.c
new file mode 100644
index 0000000..76c5a20
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDriverOverride.c
@@ -0,0 +1,290 @@
+/*++
+
+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:
+
+ PciDriverOverride.c
+
+Abstract:
+
+ PCI Bus Driver
+
+Revision History
+
+--*/
+
+#include "pcibus.h"
+
+EFI_STATUS
+InitializePciDriverOverrideInstance (
+ PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ Initializes a PCI Driver Override Instance
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PciIoDevice->PciDriverOverride.GetDriver = GetDriver;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+GetDriver (
+ IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *This,
+ IN OUT EFI_HANDLE *DriverImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Get a overriding driver image
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: DriverImageHandle - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+{
+ PCI_IO_DEVICE *PciIoDevice;
+ LIST_ENTRY *CurrentLink;
+ PCI_DRIVER_OVERRIDE_LIST *Node;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_DRIVER_OVERRIDE_THIS (This);
+
+ CurrentLink = PciIoDevice->OptionRomDriverList.ForwardLink;
+
+ while (CurrentLink && CurrentLink != &PciIoDevice->OptionRomDriverList) {
+
+ Node = DRIVER_OVERRIDE_FROM_LINK (CurrentLink);
+
+ if (*DriverImageHandle == NULL) {
+
+ *DriverImageHandle = Node->DriverImageHandle;
+ return EFI_SUCCESS;
+ }
+
+ if (*DriverImageHandle == Node->DriverImageHandle) {
+
+ if (CurrentLink->ForwardLink == &PciIoDevice->OptionRomDriverList ||
+ CurrentLink->ForwardLink == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Get next node
+ //
+ Node = DRIVER_OVERRIDE_FROM_LINK (CurrentLink->ForwardLink);
+ *DriverImageHandle = Node->DriverImageHandle;
+ return EFI_SUCCESS;
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ return EFI_INVALID_PARAMETER;
+}
+
+EFI_STATUS
+AddDriver (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN EFI_HANDLE DriverImageHandle
+ )
+/*++
+
+Routine Description:
+
+ Add a overriding driver image
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: DriverImageHandle - add argument and description to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ EFI_IMAGE_DOS_HEADER *DosHdr;
+ EFI_IMAGE_NT_HEADERS *PeHdr;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ PCI_DRIVER_OVERRIDE_LIST *Node;
+ EFI_DRIVER_OS_HANDOFF_HEADER *DriverOsHandoffHeader;
+ EFI_DRIVER_OS_HANDOFF_HEADER *NewDriverOsHandoffHeader;
+ EFI_DRIVER_OS_HANDOFF *DriverOsHandoff;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_HANDLE DeviceHandle;
+ UINTN NumberOfEntries;
+ UINTN Size;
+ UINTN Index;
+
+ Status = gBS->HandleProtocol (DriverImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &LoadedImage);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Node = AllocatePool (sizeof (PCI_DRIVER_OVERRIDE_LIST));
+ if (Node == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Node->Signature = DRIVER_OVERRIDE_SIGNATURE;
+ Node->DriverImageHandle = DriverImageHandle;
+
+ InsertTailList (&PciIoDevice->OptionRomDriverList, &(Node->Link));
+
+ PciIoDevice->BusOverride = TRUE;
+
+ DosHdr = (EFI_IMAGE_DOS_HEADER *) LoadedImage->ImageBase;
+ if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
+ return EFI_SUCCESS;
+ }
+
+ PeHdr = (EFI_IMAGE_NT_HEADERS *) ((UINTN) LoadedImage->ImageBase + DosHdr->e_lfanew);
+
+ if (PeHdr->FileHeader.Machine != EFI_IMAGE_MACHINE_EBC) {
+ return EFI_SUCCESS;
+ }
+
+ DriverOsHandoffHeader = NULL;
+ Status = EfiGetSystemConfigurationTable (&gEfiUgaIoProtocolGuid, (VOID **) &DriverOsHandoffHeader);
+ if (!EFI_ERROR (Status) && DriverOsHandoffHeader != NULL) {
+ for (Index = 0; Index < DriverOsHandoffHeader->NumberOfEntries; Index++) {
+ DriverOsHandoff = (EFI_DRIVER_OS_HANDOFF *)((UINTN)(DriverOsHandoffHeader) +
+ DriverOsHandoffHeader->HeaderSize +
+ Index * DriverOsHandoffHeader->SizeOfEntries);
+ DevicePath = DriverOsHandoff->DevicePath;
+ Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &DeviceHandle);
+ if (!EFI_ERROR (Status) && DeviceHandle != NULL && IsDevicePathEnd (DevicePath)) {
+ if (DeviceHandle == PciIoDevice->Handle) {
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ NumberOfEntries = DriverOsHandoffHeader->NumberOfEntries + 1;
+ } else {
+ NumberOfEntries = 1;
+ }
+
+ Status = gBS->AllocatePool (
+ EfiRuntimeServicesData,
+ sizeof (EFI_DRIVER_OS_HANDOFF_HEADER) + NumberOfEntries * sizeof (EFI_DRIVER_OS_HANDOFF),
+ (VOID **) &NewDriverOsHandoffHeader
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (DriverOsHandoffHeader == NULL) {
+ NewDriverOsHandoffHeader->Version = 0;
+ NewDriverOsHandoffHeader->HeaderSize = sizeof (EFI_DRIVER_OS_HANDOFF_HEADER);
+ NewDriverOsHandoffHeader->SizeOfEntries = sizeof (EFI_DRIVER_OS_HANDOFF);
+ NewDriverOsHandoffHeader->NumberOfEntries = (UINT32) NumberOfEntries;
+ } else {
+ gBS->CopyMem (
+ NewDriverOsHandoffHeader,
+ DriverOsHandoffHeader,
+ DriverOsHandoffHeader->HeaderSize + (NumberOfEntries - 1) * DriverOsHandoffHeader->SizeOfEntries
+ );
+ NewDriverOsHandoffHeader->NumberOfEntries = (UINT32) NumberOfEntries;
+ }
+
+ DriverOsHandoff = (EFI_DRIVER_OS_HANDOFF *)((UINTN)NewDriverOsHandoffHeader +
+ NewDriverOsHandoffHeader->HeaderSize +
+ (NumberOfEntries - 1) * NewDriverOsHandoffHeader->SizeOfEntries);
+
+ //
+ // Fill in the EFI_DRIVER_OS_HANDOFF structure
+ //
+ DriverOsHandoff->Type = EfiUgaDriverFromPciRom;
+
+ //
+ // Compute the size of the device path
+ //
+ Size = GetDevicePathSize (PciIoDevice->DevicePath);
+ if (Size == 0) {
+ DriverOsHandoff->DevicePath = NULL;
+ } else {
+
+ //
+ // Allocate space for duplicate device path
+ //
+ Status = gBS->AllocatePool (
+ EfiRuntimeServicesData,
+ Size,
+ (VOID **) &DriverOsHandoff->DevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (NewDriverOsHandoffHeader);
+ return Status;
+ }
+
+ //
+ // Make copy of device path
+ //
+ CopyMem (DriverOsHandoff->DevicePath, PciIoDevice->DevicePath, Size);
+ }
+
+ DriverOsHandoff->PciRomSize = (UINT64) PciIoDevice->PciIo.RomSize;
+ Status = gBS->AllocatePool (
+ EfiRuntimeServicesData,
+ (UINTN) DriverOsHandoff->PciRomSize,
+ (VOID **) &DriverOsHandoff->PciRomImage
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (NewDriverOsHandoffHeader);
+ return Status;
+ }
+
+ gBS->CopyMem (
+ DriverOsHandoff->PciRomImage,
+ PciIoDevice->PciIo.RomImage,
+ (UINTN) DriverOsHandoff->PciRomSize
+ );
+
+ Status = gBS->InstallConfigurationTable (&gEfiUgaIoProtocolGuid, NewDriverOsHandoffHeader);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (DriverOsHandoffHeader != NULL) {
+ gBS->FreePool (DriverOsHandoffHeader);
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDriverOverride.h b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDriverOverride.h
new file mode 100644
index 0000000..5992df9
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDriverOverride.h
@@ -0,0 +1,108 @@
+/*++
+
+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:
+
+ PciDriverOverride.h
+
+Abstract:
+
+
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_DRIVER_OVERRRIDE_H
+#define _EFI_PCI_DRIVER_OVERRRIDE_H
+
+#define DRIVER_OVERRIDE_SIGNATURE EFI_SIGNATURE_32 ('d', 'r', 'o', 'v')
+
+typedef struct {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+ EFI_HANDLE DriverImageHandle;
+} PCI_DRIVER_OVERRIDE_LIST;
+
+
+#define DRIVER_OVERRIDE_FROM_LINK(a) \
+ CR (a, PCI_DRIVER_OVERRIDE_LIST, Link, DRIVER_OVERRIDE_SIGNATURE)
+
+
+EFI_STATUS
+InitializePciDriverOverrideInstance (
+ PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AddDriver (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN EFI_HANDLE DriverImageHandle
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+ DriverImageHandle - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+GetDriver (
+ IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *This,
+ IN OUT EFI_HANDLE *DriverImageHandle
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ DriverImageHandle - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumerator.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumerator.c
new file mode 100644
index 0000000..d3566a1
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumerator.c
@@ -0,0 +1,2164 @@
+/*++
+
+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:
+
+ PciEnumerator.c
+
+Abstract:
+
+ PCI Bus Driver
+
+Revision History
+
+--*/
+
+#include "Pcibus.h"
+#include "PciEnumerator.h"
+#include "PciResourceSupport.h"
+#include "PciOptionRomSupport.h"
+
+EFI_STATUS
+PciEnumerator (
+ IN EFI_HANDLE Controller
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to enumerate entire pci bus system
+ in a given platform
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Controller - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ EFI_HANDLE HostBridgeHandle;
+ EFI_STATUS Status;
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+
+ //
+ // If PCI bus has already done the full enumeration, never do it again
+ //
+ if (!gFullEnumeration) {
+ return PciEnumeratorLight (Controller);
+ }
+
+ //
+ // If this host bridge has been already enumerated, then return successfully
+ //
+ if (RootBridgeExisted (Controller)) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Get the rootbridge Io protocol to find the host bridge handle
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ (VOID **) &PciRootBridgeIo,
+ gPciBusDriverBinding.DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get the host bridge handle
+ //
+ HostBridgeHandle = PciRootBridgeIo->ParentHandle;
+
+ //
+ // Get the pci host bridge resource allocation protocol
+ //
+ Status = gBS->OpenProtocol (
+ HostBridgeHandle,
+ &gEfiPciHostBridgeResourceAllocationProtocolGuid,
+ (VOID **) &PciResAlloc,
+ gPciBusDriverBinding.DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Notify the pci bus enumeration is about to begin
+ //
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginEnumeration);
+
+ //
+ // Start the bus allocation phase
+ //
+ Status = PciHostBridgeEnumerator (PciResAlloc);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Submit the resource request
+ //
+ Status = PciHostBridgeResourceAllocator (PciResAlloc);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Process P2C
+ //
+ Status = PciHostBridgeP2CProcess (PciResAlloc);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Process attributes for devices on this host bridge
+ //
+ Status = PciHostBridgeDeviceAttribute (PciResAlloc);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ gFullEnumeration = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciRootBridgeEnumerator (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
+ IN PCI_IO_DEVICE *RootBridgeDev
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciResAlloc - add argument and description to function comment
+// TODO: RootBridgeDev - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *pConfiguration;
+ UINT8 SubBusNumber;
+ UINT8 StartBusNumber;
+ UINT8 PaddedBusRange;
+ EFI_HANDLE RootBridgeHandle;
+
+ SubBusNumber = 0;
+ StartBusNumber = 0;
+ PaddedBusRange = 0;
+
+ //
+ // Get the root bridge handle
+ //
+ RootBridgeHandle = RootBridgeDev->Handle;
+
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_BUS_ENUM,
+ RootBridgeDev->DevicePath
+ );
+
+ //
+ // Get the Bus information
+ //
+ Status = PciResAlloc->StartBusEnumeration (
+ PciResAlloc,
+ RootBridgeHandle,
+ (VOID **) &pConfiguration
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get the bus number to start with
+ //
+ StartBusNumber = (UINT8) (pConfiguration->AddrRangeMin);
+
+ //
+ // Initialize the subordinate bus number
+ //
+ SubBusNumber = StartBusNumber;
+
+ //
+ // Assign bus number
+ //
+ Status = PciScanBus (
+ RootBridgeDev,
+ (UINT8) (pConfiguration->AddrRangeMin),
+ &SubBusNumber,
+ &PaddedBusRange
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+
+ //
+ // Assign max bus number scanned
+ //
+ pConfiguration->AddrLen = SubBusNumber - StartBusNumber + 1 + PaddedBusRange;
+
+ //
+ // Set bus number
+ //
+ Status = PciResAlloc->SetBusNumbers (
+ PciResAlloc,
+ RootBridgeHandle,
+ pConfiguration
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ProcessOptionRom (
+ IN PCI_IO_DEVICE *Bridge,
+ IN UINT64 RomBase,
+ IN UINT64 MaxLength
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to process option rom on a certain root bridge
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: RomBase - add argument and description to function comment
+// TODO: MaxLength - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ LIST_ENTRY *CurrentLink;
+ PCI_IO_DEVICE *Temp;
+ EFI_STATUS Status;
+
+ //
+ // Go through bridges to reach all devices
+ //
+ CurrentLink = Bridge->ChildList.ForwardLink;
+ while (CurrentLink && CurrentLink != &Bridge->ChildList) {
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+ if (!IsListEmpty (&Temp->ChildList)) {
+
+ //
+ // Go further to process the option rom under this bridge
+ //
+ Status = ProcessOptionRom (Temp, RomBase, MaxLength);
+ }
+
+ if (Temp->RomSize != 0 && Temp->RomSize <= MaxLength) {
+
+ //
+ // Load and process the option rom
+ //
+ Status = LoadOpRomImage (Temp, RomBase);
+ if (Status == EFI_SUCCESS) {
+ Status = ProcessOpRomImage (Temp);
+ }
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciAssignBusNumber (
+ IN PCI_IO_DEVICE *Bridge,
+ IN UINT8 StartBusNumber,
+ OUT UINT8 *SubBusNumber
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to assign bus number to the given PCI bus system
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: StartBusNumber - add argument and description to function comment
+// TODO: SubBusNumber - add argument and description to function comment
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_TYPE00 Pci;
+ UINT8 Device;
+ UINT8 Func;
+ UINT64 Address;
+ UINTN SecondBus;
+ UINT16 Register;
+ UINT8 Register8;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+
+ PciRootBridgeIo = Bridge->PciRootBridgeIo;
+
+ SecondBus = 0;
+ Register = 0;
+
+ *SubBusNumber = StartBusNumber;
+
+ //
+ // First check to see whether the parent is ppb
+ //
+ for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
+ for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
+
+ //
+ // Check to see whether a pci device is present
+ //
+
+ Status = PciDevicePresent (
+ PciRootBridgeIo,
+ &Pci,
+ StartBusNumber,
+ Device,
+ Func
+ );
+
+ if (!EFI_ERROR (Status) &&
+ (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {
+
+ //
+ // Reserved one bus for cardbus bridge
+ //
+ SecondBus = ++(*SubBusNumber);
+
+ Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);
+
+ Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
+
+ Status = PciRootBridgeIo->Pci.Write (
+ PciRootBridgeIo,
+ EfiPciWidthUint16,
+ Address,
+ 1,
+ &Register
+ );
+
+ //
+ // Initialize SubBusNumber to SecondBus
+ //
+ Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
+ Status = PciRootBridgeIo->Pci.Write (
+ PciRootBridgeIo,
+ EfiPciWidthUint8,
+ Address,
+ 1,
+ SubBusNumber
+ );
+ //
+ // If it is PPB, resursively search down this bridge
+ //
+ if (IS_PCI_BRIDGE (&Pci)) {
+
+ Register8 = 0xFF;
+ Status = PciRootBridgeIo->Pci.Write (
+ PciRootBridgeIo,
+ EfiPciWidthUint8,
+ Address,
+ 1,
+ &Register8
+ );
+
+ Status = PciAssignBusNumber (
+ Bridge,
+ (UINT8) (SecondBus),
+ SubBusNumber
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ //
+ // Set the current maximum bus number under the PPB
+ //
+
+ Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
+
+ Status = PciRootBridgeIo->Pci.Write (
+ PciRootBridgeIo,
+ EfiPciWidthUint8,
+ Address,
+ 1,
+ SubBusNumber
+ );
+
+ }
+
+ if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
+
+ //
+ // Skip sub functions, this is not a multi function device
+ //
+
+ Func = PCI_MAX_FUNC;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DetermineRootBridgeAttributes (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
+ IN PCI_IO_DEVICE *RootBridgeDev
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to determine the root bridge attribute by interfacing
+ the host bridge resource allocation protocol.
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciResAlloc - add argument and description to function comment
+// TODO: RootBridgeDev - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINT64 Attributes;
+ EFI_STATUS Status;
+ EFI_HANDLE RootBridgeHandle;
+
+ Attributes = 0;
+ RootBridgeHandle = RootBridgeDev->Handle;
+
+ //
+ // Get root bridge attribute by calling into pci host bridge resource allocation protocol
+ //
+ Status = PciResAlloc->GetAllocAttributes (
+ PciResAlloc,
+ RootBridgeHandle,
+ &Attributes
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Here is the point where PCI bus driver calls HOST bridge allocation protocol
+ // Currently we hardcoded for ea815
+ //
+
+ if (Attributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) {
+ RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED;
+ }
+
+ if (Attributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) {
+ RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;
+ }
+
+ RootBridgeDev->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;
+ RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
+ RootBridgeDev->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;
+
+ return EFI_SUCCESS;
+}
+
+UINT64
+GetMaxOptionRomSize (
+ IN PCI_IO_DEVICE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ Get Max Option Rom size on this bridge
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+{
+ LIST_ENTRY *CurrentLink;
+ PCI_IO_DEVICE *Temp;
+ UINT64 MaxOptionRomSize;
+ UINT64 TempOptionRomSize;
+
+ MaxOptionRomSize = 0;
+
+ //
+ // Go through bridges to reach all devices
+ //
+ CurrentLink = Bridge->ChildList.ForwardLink;
+ while (CurrentLink && CurrentLink != &Bridge->ChildList) {
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+ if (!IsListEmpty (&Temp->ChildList)) {
+
+ //
+ // Get max option rom size under this bridge
+ //
+ TempOptionRomSize = GetMaxOptionRomSize (Temp);
+
+ //
+ // Compare with the option rom size of the bridge
+ // Get the larger one
+ //
+ if (Temp->RomSize > TempOptionRomSize) {
+ TempOptionRomSize = Temp->RomSize;
+ }
+
+ } else {
+
+ //
+ // For devices get the rom size directly
+ //
+ TempOptionRomSize = Temp->RomSize;
+ }
+
+ //
+ // Get the largest rom size on this bridge
+ //
+ if (TempOptionRomSize > MaxOptionRomSize) {
+ MaxOptionRomSize = TempOptionRomSize;
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ return MaxOptionRomSize;
+}
+
+EFI_STATUS
+PciHostBridgeDeviceAttribute (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+ )
+/*++
+
+Routine Description:
+
+ Process attributes of devices on this host bridge
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciResAlloc - add argument and description to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_HANDLE RootBridgeHandle;
+ PCI_IO_DEVICE *RootBridgeDev;
+ EFI_STATUS Status;
+
+ RootBridgeHandle = NULL;
+
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+
+ //
+ // Get RootBridg Device by handle
+ //
+ RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
+
+ if (RootBridgeDev == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Set the attributes for devcies behind the Root Bridge
+ //
+ Status = DetermineDeviceAttribute (RootBridgeDev);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetResourceAllocationStatus (
+ VOID *AcpiConfig,
+ OUT UINT64 *IoResStatus,
+ OUT UINT64 *Mem32ResStatus,
+ OUT UINT64 *PMem32ResStatus,
+ OUT UINT64 *Mem64ResStatus,
+ OUT UINT64 *PMem64ResStatus
+ )
+/*++
+
+Routine Description:
+
+ Get resource allocation status from the ACPI pointer
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: AcpiConfig - add argument and description to function comment
+// TODO: IoResStatus - add argument and description to function comment
+// TODO: Mem32ResStatus - add argument and description to function comment
+// TODO: PMem32ResStatus - add argument and description to function comment
+// TODO: Mem64ResStatus - add argument and description to function comment
+// TODO: PMem64ResStatus - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ UINT8 *Temp;
+ UINT64 ResStatus;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ptr;
+
+ Temp = (UINT8 *) AcpiConfig;
+
+ while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+
+ ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
+ ResStatus = ptr->AddrTranslationOffset;
+
+ switch (ptr->ResType) {
+ case 0:
+ if (ptr->AddrSpaceGranularity == 32) {
+ if (ptr->SpecificFlag == 0x06) {
+ //
+ // Pmem32
+ //
+ *PMem32ResStatus = ResStatus;
+ } else {
+ //
+ // Mem32
+ //
+ *Mem32ResStatus = ResStatus;
+ }
+ }
+
+ if (ptr->AddrSpaceGranularity == 64) {
+ if (ptr->SpecificFlag == 0x06) {
+ //
+ // PMem64
+ //
+ *PMem64ResStatus = ResStatus;
+ } else {
+ //
+ // Mem64
+ //
+ *Mem64ResStatus = ResStatus;
+ }
+ }
+
+ break;
+
+ case 1:
+ //
+ // Io
+ //
+ *IoResStatus = ResStatus;
+ break;
+
+ default:
+ break;
+ }
+
+ Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+RejectPciDevice (
+ IN PCI_IO_DEVICE *PciDevice
+ )
+/*++
+
+Routine Description:
+
+ Remove a PCI device from device pool and mark its bar
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciDevice - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_ABORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_ABORTED - add return value to function comment
+{
+ PCI_IO_DEVICE *Bridge;
+ PCI_IO_DEVICE *Temp;
+ LIST_ENTRY *CurrentLink;
+
+ //
+ // Remove the padding resource from a bridge
+ //
+ if ( IS_PCI_BRIDGE(&PciDevice->Pci) && \
+ PciDevice->ResourcePaddingDescriptors ) {
+ gBS->FreePool (PciDevice->ResourcePaddingDescriptors);
+ PciDevice->ResourcePaddingDescriptors = NULL;
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Skip RB and PPB
+ //
+ if (IS_PCI_BRIDGE (&PciDevice->Pci) || (!PciDevice->Parent)) {
+ return EFI_ABORTED;
+ }
+
+ if (IS_CARDBUS_BRIDGE (&PciDevice->Pci)) {
+ //
+ // Get the root bridge device
+ //
+ Bridge = PciDevice;
+ while (Bridge->Parent) {
+ Bridge = Bridge->Parent;
+ }
+
+ RemoveAllPciDeviceOnBridge (Bridge->Handle, PciDevice);
+
+ //
+ // Mark its bar
+ //
+ InitializeP2C (PciDevice);
+ }
+
+ //
+ // Remove the device
+ //
+ Bridge = PciDevice->Parent;
+ CurrentLink = Bridge->ChildList.ForwardLink;
+ while (CurrentLink && CurrentLink != &Bridge->ChildList) {
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+ if (Temp == PciDevice) {
+ InitializePciDevice (Temp);
+ RemoveEntryList (CurrentLink);
+ FreePciDevice (Temp);
+ return EFI_SUCCESS;
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ return EFI_ABORTED;
+}
+
+BOOLEAN
+IsRejectiveDevice (
+ IN PCI_RESOURCE_NODE *PciResNode
+ )
+/*++
+
+Routine Description:
+
+ Determine whethter a PCI device can be rejected
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciResNode - add argument and description to function comment
+{
+ PCI_IO_DEVICE *Temp;
+
+ Temp = PciResNode->PciDev;
+
+ //
+ // Ensure the device is present
+ //
+ if (!Temp) {
+ return FALSE;
+ }
+
+ //
+ // PPB and RB should go ahead
+ //
+ if (IS_PCI_BRIDGE (&Temp->Pci) || (!Temp->Parent)) {
+ return TRUE;
+ }
+
+ //
+ // Skip device on Bus0
+ //
+ if ((Temp->Parent) && (Temp->BusNumber == 0)) {
+ return FALSE;
+ }
+
+ //
+ // Skip VGA
+ //
+ if (IS_PCI_VGA (&Temp->Pci)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+PCI_RESOURCE_NODE *
+GetLargerConsumerDevice (
+ IN PCI_RESOURCE_NODE *PciResNode1,
+ IN PCI_RESOURCE_NODE *PciResNode2
+ )
+/*++
+
+Routine Description:
+
+ Get the larger resource consumer
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciResNode1 - add argument and description to function comment
+// TODO: PciResNode2 - add argument and description to function comment
+{
+ if (!PciResNode2) {
+ return PciResNode1;
+ }
+
+ if ((IS_PCI_BRIDGE(&(PciResNode2->PciDev->Pci)) || !(PciResNode2->PciDev->Parent)) \
+ && (PciResNode2->ResourceUsage != PciResUsagePadding) )
+ {
+ return PciResNode1;
+ }
+
+ if (!PciResNode1) {
+ return PciResNode2;
+ }
+
+ if ((PciResNode1->Length) > (PciResNode2->Length)) {
+ return PciResNode1;
+ }
+
+ return PciResNode2;
+
+}
+
+PCI_RESOURCE_NODE *
+GetMaxResourceConsumerDevice (
+ IN PCI_RESOURCE_NODE *ResPool
+ )
+/*++
+
+Routine Description:
+
+ Get the max resource consumer in the host resource pool
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: ResPool - add argument and description to function comment
+{
+ PCI_RESOURCE_NODE *Temp;
+ LIST_ENTRY *CurrentLink;
+ PCI_RESOURCE_NODE *PciResNode;
+ PCI_RESOURCE_NODE *PPBResNode;
+
+ PciResNode = NULL;
+
+ CurrentLink = ResPool->ChildList.ForwardLink;
+ while (CurrentLink && CurrentLink != &ResPool->ChildList) {
+
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
+
+ if (!IsRejectiveDevice (Temp)) {
+ CurrentLink = CurrentLink->ForwardLink;
+ continue;
+ }
+
+ if ((IS_PCI_BRIDGE (&(Temp->PciDev->Pci)) || (!Temp->PciDev->Parent)) \
+ && (Temp->ResourceUsage != PciResUsagePadding))
+ {
+ PPBResNode = GetMaxResourceConsumerDevice (Temp);
+ PciResNode = GetLargerConsumerDevice (PciResNode, PPBResNode);
+ } else {
+ PciResNode = GetLargerConsumerDevice (PciResNode, Temp);
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ return PciResNode;
+}
+
+EFI_STATUS
+PciHostBridgeAdjustAllocation (
+ IN PCI_RESOURCE_NODE *IoPool,
+ IN PCI_RESOURCE_NODE *Mem32Pool,
+ IN PCI_RESOURCE_NODE *PMem32Pool,
+ IN PCI_RESOURCE_NODE *Mem64Pool,
+ IN PCI_RESOURCE_NODE *PMem64Pool,
+ IN UINT64 IoResStatus,
+ IN UINT64 Mem32ResStatus,
+ IN UINT64 PMem32ResStatus,
+ IN UINT64 Mem64ResStatus,
+ IN UINT64 PMem64ResStatus
+ )
+/*++
+
+Routine Description:
+
+ Adjust host bridge allocation so as to reduce resource requirement
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: IoPool - add argument and description to function comment
+// TODO: Mem32Pool - add argument and description to function comment
+// TODO: PMem32Pool - add argument and description to function comment
+// TODO: Mem64Pool - add argument and description to function comment
+// TODO: PMem64Pool - add argument and description to function comment
+// TODO: IoResStatus - add argument and description to function comment
+// TODO: Mem32ResStatus - add argument and description to function comment
+// TODO: PMem32ResStatus - add argument and description to function comment
+// TODO: Mem64ResStatus - add argument and description to function comment
+// TODO: PMem64ResStatus - add argument and description to function comment
+// TODO: EFI_ABORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_ABORTED - add return value to function comment
+{
+ BOOLEAN AllocationAjusted;
+ PCI_RESOURCE_NODE *PciResNode;
+ PCI_RESOURCE_NODE *ResPool[5];
+ PCI_IO_DEVICE *RemovedPciDev[5];
+ UINT64 ResStatus[5];
+ UINTN RemovedPciDevNum;
+ UINTN DevIndex;
+ UINTN ResType;
+ EFI_STATUS Status;
+ REPORT_STATUS_CODE_LIBRARY_RESOURCE_ALLOC_FAILURE_ERROR_DATA AllocFailExtendedData;
+
+ PciResNode = NULL;
+ ZeroMem (RemovedPciDev, 5 * sizeof (PCI_IO_DEVICE *));
+ RemovedPciDevNum = 0;
+
+ ResPool[0] = IoPool;
+ ResPool[1] = Mem32Pool;
+ ResPool[2] = PMem32Pool;
+ ResPool[3] = Mem64Pool;
+ ResPool[4] = PMem64Pool;
+
+ ResStatus[0] = IoResStatus;
+ ResStatus[1] = Mem32ResStatus;
+ ResStatus[2] = PMem32ResStatus;
+ ResStatus[3] = Mem64ResStatus;
+ ResStatus[4] = PMem64ResStatus;
+
+ AllocationAjusted = FALSE;
+
+ for (ResType = 0; ResType < 5; ResType++) {
+
+ if (ResStatus[ResType] == EFI_RESOURCE_SATISFIED) {
+ continue;
+ }
+
+ if (ResStatus[ResType] == EFI_RESOURCE_NONEXISTENT) {
+ //
+ // Hostbridge hasn't this resource type
+ //
+ return EFI_ABORTED;
+ }
+
+ //
+ // Hostbridge hasn't enough resource
+ //
+ PciResNode = GetMaxResourceConsumerDevice (ResPool[ResType]);
+ if (!PciResNode) {
+ continue;
+ }
+
+ //
+ // Check if the device has been removed before
+ //
+ for (DevIndex = 0; DevIndex < RemovedPciDevNum; DevIndex++) {
+ if (PciResNode->PciDev == RemovedPciDev[DevIndex]) {
+ continue;
+ }
+ }
+
+ //
+ // Remove the device if it isn't in the array
+ //
+ Status = RejectPciDevice (PciResNode->PciDev);
+ if (Status == EFI_SUCCESS) {
+
+ //
+ // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
+ //
+ //
+ // Have no way to get ReqRes, AllocRes & Bar here
+ //
+ ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));
+ AllocFailExtendedData.DevicePathSize = sizeof (EFI_DEVICE_PATH_PROTOCOL);
+ AllocFailExtendedData.DevicePath = (UINT8 *) PciResNode->PciDev->DevicePath;
+ AllocFailExtendedData.Bar = PciResNode->Bar;
+
+ REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
+ EFI_PROGRESS_CODE,
+ EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,
+ (VOID *) &AllocFailExtendedData,
+ sizeof (AllocFailExtendedData)
+ );
+
+ //
+ // Add it to the array and indicate at least a device has been rejected
+ //
+ RemovedPciDev[RemovedPciDevNum++] = PciResNode->PciDev;
+ AllocationAjusted = TRUE;
+ }
+ }
+ //
+ // End for
+ //
+
+ if (AllocationAjusted) {
+ return EFI_SUCCESS;
+ } else {
+ return EFI_ABORTED;
+ }
+}
+
+EFI_STATUS
+ConstructAcpiResourceRequestor (
+ IN PCI_IO_DEVICE *Bridge,
+ IN PCI_RESOURCE_NODE *IoNode,
+ IN PCI_RESOURCE_NODE *Mem32Node,
+ IN PCI_RESOURCE_NODE *PMem32Node,
+ IN PCI_RESOURCE_NODE *Mem64Node,
+ IN PCI_RESOURCE_NODE *PMem64Node,
+ OUT VOID **pConfig
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: IoNode - add argument and description to function comment
+// TODO: Mem32Node - add argument and description to function comment
+// TODO: PMem32Node - add argument and description to function comment
+// TODO: Mem64Node - add argument and description to function comment
+// TODO: PMem64Node - add argument and description to function comment
+// TODO: pConfig - add argument and description to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINT8 NumConfig;
+ UINT8 Aperture;
+ UINT8 *Configuration;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
+ EFI_ACPI_END_TAG_DESCRIPTOR *PtrEnd;
+
+ NumConfig = 0;
+ Aperture = 0;
+
+ *pConfig = NULL;
+
+ //
+ // if there is io request, add to the io aperture
+ //
+ if (ResourceRequestExisted (IoNode)) {
+ NumConfig++;
+ Aperture |= 0x01;
+ }
+
+ //
+ // if there is mem32 request, add to the mem32 aperture
+ //
+ if (ResourceRequestExisted (Mem32Node)) {
+ NumConfig++;
+ Aperture |= 0x02;
+ }
+
+ //
+ // if there is pmem32 request, add to the pmem32 aperture
+ //
+ if (ResourceRequestExisted (PMem32Node)) {
+ NumConfig++;
+ Aperture |= 0x04;
+ }
+
+ //
+ // if there is mem64 request, add to the mem64 aperture
+ //
+ if (ResourceRequestExisted (Mem64Node)) {
+ NumConfig++;
+ Aperture |= 0x08;
+ }
+
+ //
+ // if there is pmem64 request, add to the pmem64 aperture
+ //
+ if (ResourceRequestExisted (PMem64Node)) {
+ NumConfig++;
+ Aperture |= 0x10;
+ }
+
+ if (NumConfig != 0) {
+
+ //
+ // If there is at least one type of resource request,
+ // allocate a acpi resource node
+ //
+ Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
+ if (Configuration == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ZeroMem (
+ Configuration,
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
+ );
+
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
+
+ //
+ // Deal with io aperture
+ //
+ if (Aperture & 0x01) {
+ Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
+ //
+ // Io
+ //
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
+ //
+ // non ISA range
+ //
+ Ptr->SpecificFlag = 1;
+ Ptr->AddrLen = IoNode->Length;
+ Ptr->AddrRangeMax = IoNode->Alignment;
+
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
+ }
+ //
+ // Deal with mem32 aperture
+ //
+ if (Aperture & 0x02) {
+ Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
+ //
+ // Mem
+ //
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ //
+ // Nonprefechable
+ //
+ Ptr->SpecificFlag = 0;
+ //
+ // 32 bit
+ //
+ Ptr->AddrSpaceGranularity = 32;
+ Ptr->AddrLen = Mem32Node->Length;
+ Ptr->AddrRangeMax = Mem32Node->Alignment;
+
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
+ }
+
+ //
+ // Deal with Pmem32 aperture
+ //
+ if (Aperture & 0x04) {
+ Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
+ //
+ // Mem
+ //
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ //
+ // prefechable
+ //
+ Ptr->SpecificFlag = 0x6;
+ //
+ // 32 bit
+ //
+ Ptr->AddrSpaceGranularity = 32;
+ Ptr->AddrLen = PMem32Node->Length;
+ Ptr->AddrRangeMax = PMem32Node->Alignment;
+
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
+ }
+ //
+ // Deal with mem64 aperture
+ //
+ if (Aperture & 0x08) {
+ Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
+ //
+ // Mem
+ //
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ //
+ // nonprefechable
+ //
+ Ptr->SpecificFlag = 0;
+ //
+ // 64 bit
+ //
+ Ptr->AddrSpaceGranularity = 64;
+ Ptr->AddrLen = Mem64Node->Length;
+ Ptr->AddrRangeMax = Mem64Node->Alignment;
+
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
+ }
+ //
+ // Deal with Pmem64 aperture
+ //
+ if (Aperture & 0x10) {
+ Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
+ //
+ // Mem
+ //
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ //
+ // prefechable
+ //
+ Ptr->SpecificFlag = 0x06;
+ //
+ // 64 bit
+ //
+ Ptr->AddrSpaceGranularity = 64;
+ Ptr->AddrLen = PMem64Node->Length;
+ Ptr->AddrRangeMax = PMem64Node->Alignment;
+
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (Configuration + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
+ }
+
+ //
+ // put the checksum
+ //
+ PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) ((UINT8 *) Ptr);
+
+ PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
+ PtrEnd->Checksum = 0;
+
+ } else {
+
+ //
+ // If there is no resource request
+ //
+ Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
+ if (Configuration == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ZeroMem (Configuration, sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
+
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (Configuration);
+ Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+
+ PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Configuration + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
+ PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
+ PtrEnd->Checksum = 0;
+ }
+
+ *pConfig = Configuration;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetResourceBase (
+ IN VOID *pConfig,
+ OUT UINT64 *IoBase,
+ OUT UINT64 *Mem32Base,
+ OUT UINT64 *PMem32Base,
+ OUT UINT64 *Mem64Base,
+ OUT UINT64 *PMem64Base
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: pConfig - add argument and description to function comment
+// TODO: IoBase - add argument and description to function comment
+// TODO: Mem32Base - add argument and description to function comment
+// TODO: PMem32Base - add argument and description to function comment
+// TODO: Mem64Base - add argument and description to function comment
+// TODO: PMem64Base - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINT8 *Temp;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
+ UINT64 ResStatus;
+
+ *IoBase = 0xFFFFFFFFFFFFFFFFULL;
+ *Mem32Base = 0xFFFFFFFFFFFFFFFFULL;
+ *PMem32Base = 0xFFFFFFFFFFFFFFFFULL;
+ *Mem64Base = 0xFFFFFFFFFFFFFFFFULL;
+ *PMem64Base = 0xFFFFFFFFFFFFFFFFULL;
+
+ Temp = (UINT8 *) pConfig;
+
+ while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
+ ResStatus = Ptr->AddrTranslationOffset;
+
+ if (ResStatus == EFI_RESOURCE_SATISFIED) {
+
+ switch (Ptr->ResType) {
+
+ //
+ // Memory type aperture
+ //
+ case 0:
+
+ //
+ // Check to see the granularity
+ //
+ if (Ptr->AddrSpaceGranularity == 32) {
+ if (Ptr->SpecificFlag & 0x06) {
+ *PMem32Base = Ptr->AddrRangeMin;
+ } else {
+ *Mem32Base = Ptr->AddrRangeMin;
+ }
+ }
+
+ if (Ptr->AddrSpaceGranularity == 64) {
+ if (Ptr->SpecificFlag & 0x06) {
+ *PMem64Base = Ptr->AddrRangeMin;
+ } else {
+ *Mem64Base = Ptr->AddrRangeMin;
+ }
+ }
+ break;
+
+ case 1:
+
+ //
+ // Io type aperture
+ //
+ *IoBase = Ptr->AddrRangeMin;
+ break;
+
+ default:
+ break;
+
+ }
+ //
+ // End switch
+ //
+ }
+ //
+ // End for
+ //
+ Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciBridgeEnumerator (
+ IN PCI_IO_DEVICE *BridgeDev
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: BridgeDev - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINT8 SubBusNumber;
+ UINT8 StartBusNumber;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status;
+
+ SubBusNumber = 0;
+ StartBusNumber = 0;
+ PciIo = &(BridgeDev->PciIo);
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x19, 1, &StartBusNumber);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PciAssignBusNumber (
+ BridgeDev,
+ StartBusNumber,
+ &SubBusNumber
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PciPciDeviceInfoCollector (BridgeDev, StartBusNumber);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PciBridgeResourceAllocator (BridgeDev);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = DetermineDeviceAttribute (BridgeDev);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+PciBridgeResourceAllocator (
+ IN PCI_IO_DEVICE *Bridge
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_RESOURCE_NODE *IoBridge;
+ PCI_RESOURCE_NODE *Mem32Bridge;
+ PCI_RESOURCE_NODE *PMem32Bridge;
+ PCI_RESOURCE_NODE *Mem64Bridge;
+ PCI_RESOURCE_NODE *PMem64Bridge;
+ UINT64 IoBase;
+ UINT64 Mem32Base;
+ UINT64 PMem32Base;
+ UINT64 Mem64Base;
+ UINT64 PMem64Base;
+ EFI_STATUS Status;
+
+ IoBridge = CreateResourceNode (
+ Bridge,
+ 0,
+ 0xFFF,
+ 0,
+ PciBarTypeIo16,
+ PciResUsageTypical
+ );
+
+ Mem32Bridge = CreateResourceNode (
+ Bridge,
+ 0,
+ 0xFFFFF,
+ 0,
+ PciBarTypeMem32,
+ PciResUsageTypical
+ );
+
+ PMem32Bridge = CreateResourceNode (
+ Bridge,
+ 0,
+ 0xFFFFF,
+ 0,
+ PciBarTypePMem32,
+ PciResUsageTypical
+ );
+
+ Mem64Bridge = CreateResourceNode (
+ Bridge,
+ 0,
+ 0xFFFFF,
+ 0,
+ PciBarTypeMem64,
+ PciResUsageTypical
+ );
+
+ PMem64Bridge = CreateResourceNode (
+ Bridge,
+ 0,
+ 0xFFFFF,
+ 0,
+ PciBarTypePMem64,
+ PciResUsageTypical
+ );
+
+ //
+ // Create resourcemap by going through all the devices subject to this root bridge
+ //
+ Status = CreateResourceMap (
+ Bridge,
+ IoBridge,
+ Mem32Bridge,
+ PMem32Bridge,
+ Mem64Bridge,
+ PMem64Bridge
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = GetResourceBaseFromBridge (
+ Bridge,
+ &IoBase,
+ &Mem32Base,
+ &PMem32Base,
+ &Mem64Base,
+ &PMem64Base
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Program IO resources
+ //
+ ProgramResource (
+ IoBase,
+ IoBridge
+ );
+
+ //
+ // Program Mem32 resources
+ //
+ ProgramResource (
+ Mem32Base,
+ Mem32Bridge
+ );
+
+ //
+ // Program PMem32 resources
+ //
+ ProgramResource (
+ PMem32Base,
+ PMem32Bridge
+ );
+
+ //
+ // Program Mem64 resources
+ //
+ ProgramResource (
+ Mem64Base,
+ Mem64Bridge
+ );
+
+ //
+ // Program PMem64 resources
+ //
+ ProgramResource (
+ PMem64Base,
+ PMem64Bridge
+ );
+
+ DestroyResourceTree (IoBridge);
+ DestroyResourceTree (Mem32Bridge);
+ DestroyResourceTree (PMem32Bridge);
+ DestroyResourceTree (PMem64Bridge);
+ DestroyResourceTree (Mem64Bridge);
+
+ gBS->FreePool (IoBridge);
+ gBS->FreePool (Mem32Bridge);
+ gBS->FreePool (PMem32Bridge);
+ gBS->FreePool (PMem64Bridge);
+ gBS->FreePool (Mem64Bridge);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetResourceBaseFromBridge (
+ IN PCI_IO_DEVICE *Bridge,
+ OUT UINT64 *IoBase,
+ OUT UINT64 *Mem32Base,
+ OUT UINT64 *PMem32Base,
+ OUT UINT64 *Mem64Base,
+ OUT UINT64 *PMem64Base
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: IoBase - add argument and description to function comment
+// TODO: Mem32Base - add argument and description to function comment
+// TODO: PMem32Base - add argument and description to function comment
+// TODO: Mem64Base - add argument and description to function comment
+// TODO: PMem64Base - add argument and description to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ if (!Bridge->Allocated) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *IoBase = gAllOne;
+ *Mem32Base = gAllOne;
+ *PMem32Base = gAllOne;
+ *Mem64Base = gAllOne;
+ *PMem64Base = gAllOne;
+
+ if (IS_PCI_BRIDGE (&Bridge->Pci)) {
+
+ if (Bridge->PciBar[PPB_IO_RANGE].Length) {
+ *IoBase = Bridge->PciBar[PPB_IO_RANGE].BaseAddress;
+ }
+
+ if (Bridge->PciBar[PPB_MEM32_RANGE].Length) {
+ *Mem32Base = Bridge->PciBar[PPB_MEM32_RANGE].BaseAddress;
+ }
+
+ if (Bridge->PciBar[PPB_PMEM32_RANGE].Length) {
+ *PMem32Base = Bridge->PciBar[PPB_PMEM32_RANGE].BaseAddress;
+ }
+
+ if (Bridge->PciBar[PPB_PMEM64_RANGE].Length) {
+ *PMem64Base = Bridge->PciBar[PPB_PMEM64_RANGE].BaseAddress;
+ } else {
+ *PMem64Base = gAllOne;
+ }
+
+ }
+
+ if (IS_CARDBUS_BRIDGE (&Bridge->Pci)) {
+ if (Bridge->PciBar[P2C_IO_1].Length) {
+ *IoBase = Bridge->PciBar[P2C_IO_1].BaseAddress;
+ } else {
+ if (Bridge->PciBar[P2C_IO_2].Length) {
+ *IoBase = Bridge->PciBar[P2C_IO_2].BaseAddress;
+ }
+ }
+
+ if (Bridge->PciBar[P2C_MEM_1].Length) {
+ if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypePMem32) {
+ *PMem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;
+ }
+
+ if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypeMem32) {
+ *Mem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;
+ }
+ }
+
+ if (Bridge->PciBar[P2C_MEM_2].Length) {
+ if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypePMem32) {
+ *PMem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;
+ }
+
+ if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypeMem32) {
+ *Mem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+NotifyPhase (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciResAlloc - add argument and description to function comment
+// TODO: Phase - add argument and description to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_HANDLE HostBridgeHandle;
+ EFI_HANDLE RootBridgeHandle;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+ EFI_STATUS Status;
+
+ HostBridgeHandle = NULL;
+ RootBridgeHandle = NULL;
+ if (gPciPlatformProtocol != NULL) {
+ //
+ // Get Host Bridge Handle.
+ //
+ PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);
+
+ //
+ // Get the rootbridge Io protocol to find the host bridge handle
+ //
+ Status = gBS->HandleProtocol (
+ RootBridgeHandle,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ (VOID **) &PciRootBridgeIo
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ HostBridgeHandle = PciRootBridgeIo->ParentHandle;
+
+ //
+ // Call PlatformPci::PhaseNotify() if the protocol is present.
+ //
+ gPciPlatformProtocol->PhaseNotify (
+ gPciPlatformProtocol,
+ HostBridgeHandle,
+ Phase,
+ ChipsetEntry
+ );
+ }
+
+ Status = PciResAlloc->NotifyPhase (
+ PciResAlloc,
+ Phase
+ );
+
+ if (gPciPlatformProtocol != NULL) {
+ //
+ // Call PlatformPci::PhaseNotify() if the protocol is present.
+ //
+ gPciPlatformProtocol->PhaseNotify (
+ gPciPlatformProtocol,
+ HostBridgeHandle,
+ Phase,
+ ChipsetExit
+ );
+
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PreprocessController (
+ IN PCI_IO_DEVICE *Bridge,
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Func,
+ IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: Bus - add argument and description to function comment
+// TODO: Device - add argument and description to function comment
+// TODO: Func - add argument and description to function comment
+// TODO: Phase - add argument and description to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS RootBridgePciAddress;
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc;
+ EFI_HANDLE RootBridgeHandle;
+ EFI_HANDLE HostBridgeHandle;
+ EFI_STATUS Status;
+
+ //
+ // Get the host bridge handle
+ //
+ HostBridgeHandle = Bridge->PciRootBridgeIo->ParentHandle;
+
+ //
+ // Get the pci host bridge resource allocation protocol
+ //
+ Status = gBS->OpenProtocol (
+ HostBridgeHandle,
+ &gEfiPciHostBridgeResourceAllocationProtocolGuid,
+ (VOID **) &PciResAlloc,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get Root Brige Handle
+ //
+ while (Bridge->Parent) {
+ Bridge = Bridge->Parent;
+ }
+
+ RootBridgeHandle = Bridge->Handle;
+
+ RootBridgePciAddress.Register = 0;
+ RootBridgePciAddress.Function = Func;
+ RootBridgePciAddress.Device = Device;
+ RootBridgePciAddress.Bus = Bus;
+ RootBridgePciAddress.ExtendedRegister = 0;
+
+ if (gPciPlatformProtocol != NULL) {
+ //
+ // Call PlatformPci::PrepController() if the protocol is present.
+ //
+ gPciPlatformProtocol->PlatformPrepController (
+ gPciPlatformProtocol,
+ HostBridgeHandle,
+ RootBridgeHandle,
+ RootBridgePciAddress,
+ Phase,
+ ChipsetEntry
+ );
+ }
+
+ Status = PciResAlloc->PreprocessController (
+ PciResAlloc,
+ RootBridgeHandle,
+ RootBridgePciAddress,
+ Phase
+ );
+
+ if (gPciPlatformProtocol != NULL) {
+ //
+ // Call PlatformPci::PrepController() if the protocol is present.
+ //
+ gPciPlatformProtocol->PlatformPrepController (
+ gPciPlatformProtocol,
+ HostBridgeHandle,
+ RootBridgeHandle,
+ RootBridgePciAddress,
+ Phase,
+ ChipsetExit
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PciHotPlugRequestNotify (
+ IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL * This,
+ IN EFI_PCI_HOTPLUG_OPERATION Operation,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL,
+ IN OUT UINT8 *NumberOfChildren,
+ IN OUT EFI_HANDLE * ChildHandleBuffer
+ )
+/*++
+
+Routine Description:
+
+ Hot plug request notify.
+
+Arguments:
+
+ This - A pointer to the hot plug request protocol.
+ Operation - The operation.
+ Controller - A pointer to the controller.
+ RemainningDevicePath - A pointer to the device path.
+ NumberOfChildren - A the number of child handle in the ChildHandleBuffer.
+ ChildHandleBuffer - A pointer to the array contain the child handle.
+
+Returns:
+
+ Status code.
+
+--*/
+// TODO: RemainingDevicePath - add argument and description to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_IO_DEVICE *Bridge;
+ PCI_IO_DEVICE *Temp;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINTN Index;
+ EFI_HANDLE RootBridgeHandle;
+ EFI_STATUS Status;
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ gPciBusDriverBinding.DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Bridge = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);
+
+ //
+ // Get root bridge handle
+ //
+ Temp = Bridge;
+ while (Temp->Parent) {
+ Temp = Temp->Parent;
+ }
+
+ RootBridgeHandle = Temp->Handle;
+
+ if (Operation == EfiPciHotPlugRequestAdd) {
+
+ if (NumberOfChildren != NULL) {
+ *NumberOfChildren = 0;
+ }
+
+ if (IsListEmpty (&Bridge->ChildList)) {
+
+ Status = PciBridgeEnumerator (Bridge);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ Status = StartPciDevicesOnBridge (
+ RootBridgeHandle,
+ Bridge,
+ RemainingDevicePath,
+ NumberOfChildren,
+ ChildHandleBuffer
+ );
+
+ return EFI_SUCCESS;
+ }
+
+ if (Operation == EfiPciHotplugRequestRemove) {
+
+ if (*NumberOfChildren == 0) {
+ //
+ // Remove all devices on the bridge
+ //
+ Status = RemoveAllPciDeviceOnBridge (RootBridgeHandle, Bridge);
+ return Status;
+
+ }
+
+ for (Index = 0; Index < *NumberOfChildren; Index++) {
+ //
+ // De register all the pci device
+ //
+ Status = DeRegisterPciDevice (RootBridgeHandle, ChildHandleBuffer[Index]);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ }
+ //
+ // End for
+ //
+ return EFI_SUCCESS;
+ }
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+SearchHostBridgeHandle (
+ IN EFI_HANDLE RootBridgeHandle
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: RootBridgeHandle - add argument and description to function comment
+{
+ EFI_HANDLE HostBridgeHandle;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+ UINTN Index;
+ EFI_STATUS Status;
+
+ //
+ // Get the rootbridge Io protocol to find the host bridge handle
+ //
+ Status = gBS->OpenProtocol (
+ RootBridgeHandle,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ (VOID **) &PciRootBridgeIo,
+ gPciBusDriverBinding.DriverBindingHandle,
+ RootBridgeHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ HostBridgeHandle = PciRootBridgeIo->ParentHandle;
+ for (Index = 0; Index < gPciHostBridgeNumber; Index++) {
+ if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+EFI_STATUS
+AddHostBridgeEnumerator (
+ IN EFI_HANDLE HostBridgeHandle
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: HostBridgeHandle - add argument and description to function comment
+// TODO: EFI_ABORTED - add return value to function comment
+// TODO: EFI_ABORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINTN Index;
+
+ if (!HostBridgeHandle) {
+ return EFI_ABORTED;
+ }
+
+ for (Index = 0; Index < gPciHostBridgeNumber; Index++) {
+ if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {
+ return EFI_ABORTED;
+ }
+ }
+
+ if (Index < PCI_MAX_HOST_BRIDGE_NUM) {
+ gPciHostBrigeHandles[Index] = HostBridgeHandle;
+ gPciHostBridgeNumber++;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumerator.h b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumerator.h
new file mode 100644
index 0000000..e7667d5
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumerator.h
@@ -0,0 +1,628 @@
+/*++
+
+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:
+
+ PciEnumerator.h
+
+Abstract:
+
+ PCI Bus Driver
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_ENUMERATOR_H
+#define _EFI_PCI_ENUMERATOR_H
+
+#include "PciResourceSupport.h"
+
+EFI_STATUS
+PciEnumerator (
+ IN EFI_HANDLE Controller
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Controller - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciRootBridgeEnumerator (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
+ IN PCI_IO_DEVICE *RootBridgeDev
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciResAlloc - TODO: add argument description
+ RootBridgeDev - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+ProcessOptionRom (
+ IN PCI_IO_DEVICE *Bridge,
+ IN UINT64 RomBase,
+ IN UINT64 MaxLength
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ RomBase - TODO: add argument description
+ MaxLength - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciAssignBusNumber (
+ IN PCI_IO_DEVICE *Bridge,
+ IN UINT8 StartBusNumber,
+ OUT UINT8 *SubBusNumber
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ StartBusNumber - TODO: add argument description
+ SubBusNumber - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+DetermineRootBridgeAttributes (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
+ IN PCI_IO_DEVICE *RootBridgeDev
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciResAlloc - TODO: add argument description
+ RootBridgeDev - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+UINT64
+GetMaxOptionRomSize (
+ IN PCI_IO_DEVICE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciHostBridgeDeviceAttribute (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciResAlloc - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+GetResourceAllocationStatus (
+ VOID *AcpiConfig,
+ OUT UINT64 *IoResStatus,
+ OUT UINT64 *Mem32ResStatus,
+ OUT UINT64 *PMem32ResStatus,
+ OUT UINT64 *Mem64ResStatus,
+ OUT UINT64 *PMem64ResStatus
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AcpiConfig - TODO: add argument description
+ IoResStatus - TODO: add argument description
+ Mem32ResStatus - TODO: add argument description
+ PMem32ResStatus - TODO: add argument description
+ Mem64ResStatus - TODO: add argument description
+ PMem64ResStatus - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+RejectPciDevice (
+ IN PCI_IO_DEVICE *PciDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+IsRejectiveDevice (
+ IN PCI_RESOURCE_NODE *PciResNode
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciResNode - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+PCI_RESOURCE_NODE *
+GetLargerConsumerDevice (
+ IN PCI_RESOURCE_NODE *PciResNode1,
+ IN PCI_RESOURCE_NODE *PciResNode2
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciResNode1 - TODO: add argument description
+ PciResNode2 - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+PCI_RESOURCE_NODE *
+GetMaxResourceConsumerDevice (
+ IN PCI_RESOURCE_NODE *ResPool
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ ResPool - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciHostBridgeAdjustAllocation (
+ IN PCI_RESOURCE_NODE *IoPool,
+ IN PCI_RESOURCE_NODE *Mem32Pool,
+ IN PCI_RESOURCE_NODE *PMem32Pool,
+ IN PCI_RESOURCE_NODE *Mem64Pool,
+ IN PCI_RESOURCE_NODE *PMem64Pool,
+ IN UINT64 IoResStatus,
+ IN UINT64 Mem32ResStatus,
+ IN UINT64 PMem32ResStatus,
+ IN UINT64 Mem64ResStatus,
+ IN UINT64 PMem64ResStatus
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ IoPool - TODO: add argument description
+ Mem32Pool - TODO: add argument description
+ PMem32Pool - TODO: add argument description
+ Mem64Pool - TODO: add argument description
+ PMem64Pool - TODO: add argument description
+ IoResStatus - TODO: add argument description
+ Mem32ResStatus - TODO: add argument description
+ PMem32ResStatus - TODO: add argument description
+ Mem64ResStatus - TODO: add argument description
+ PMem64ResStatus - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+ConstructAcpiResourceRequestor (
+ IN PCI_IO_DEVICE *Bridge,
+ IN PCI_RESOURCE_NODE *IoNode,
+ IN PCI_RESOURCE_NODE *Mem32Node,
+ IN PCI_RESOURCE_NODE *PMem32Node,
+ IN PCI_RESOURCE_NODE *Mem64Node,
+ IN PCI_RESOURCE_NODE *PMem64Node,
+ OUT VOID **pConfig
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ IoNode - TODO: add argument description
+ Mem32Node - TODO: add argument description
+ PMem32Node - TODO: add argument description
+ Mem64Node - TODO: add argument description
+ PMem64Node - TODO: add argument description
+ pConfig - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+GetResourceBase (
+ IN VOID *pConfig,
+ OUT UINT64 *IoBase,
+ OUT UINT64 *Mem32Base,
+ OUT UINT64 *PMem32Base,
+ OUT UINT64 *Mem64Base,
+ OUT UINT64 *PMem64Base
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ pConfig - TODO: add argument description
+ IoBase - TODO: add argument description
+ Mem32Base - TODO: add argument description
+ PMem32Base - TODO: add argument description
+ Mem64Base - TODO: add argument description
+ PMem64Base - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciBridgeEnumerator (
+ IN PCI_IO_DEVICE *BridgeDev
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ BridgeDev - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciBridgeResourceAllocator (
+ IN PCI_IO_DEVICE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+GetResourceBaseFromBridge (
+ IN PCI_IO_DEVICE *Bridge,
+ OUT UINT64 *IoBase,
+ OUT UINT64 *Mem32Base,
+ OUT UINT64 *PMem32Base,
+ OUT UINT64 *Mem64Base,
+ OUT UINT64 *PMem64Base
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ IoBase - TODO: add argument description
+ Mem32Base - TODO: add argument description
+ PMem32Base - TODO: add argument description
+ Mem64Base - TODO: add argument description
+ PMem64Base - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciHostBridgeP2CProcess (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciResAlloc - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+NotifyPhase (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciResAlloc - TODO: add argument description
+ Phase - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PreprocessController (
+ IN PCI_IO_DEVICE *Bridge,
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Func,
+ IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ Bus - TODO: add argument description
+ Device - TODO: add argument description
+ Func - TODO: add argument description
+ Phase - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciHotPlugRequestNotify (
+ IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL * This,
+ IN EFI_PCI_HOTPLUG_OPERATION Operation,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL,
+ IN OUT UINT8 *NumberOfChildren,
+ IN OUT EFI_HANDLE * ChildHandleBuffer
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Operation - TODO: add argument description
+ Controller - TODO: add argument description
+ RemainingDevicePath - TODO: add argument description
+ NumberOfChildren - TODO: add argument description
+ ChildHandleBuffer - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+SearchHostBridgeHandle (
+ IN EFI_HANDLE RootBridgeHandle
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ RootBridgeHandle - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AddHostBridgeEnumerator (
+ IN EFI_HANDLE HostBridgeHandle
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ HostBridgeHandle - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumeratorSupport.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumeratorSupport.c
new file mode 100644
index 0000000..2c54897
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumeratorSupport.c
@@ -0,0 +1,2261 @@
+/*++
+
+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:
+
+ PciEnumeratorSupport.c
+
+Abstract:
+
+ PCI Bus Driver
+
+Revision History
+
+--*/
+
+#include "Pcibus.h"
+#include "PciEnumeratorSupport.h"
+#include "PciCommand.h"
+#include "PciIo.h"
+
+EFI_STATUS
+PciDevicePresent (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
+ PCI_TYPE00 *Pci,
+ UINT8 Bus,
+ UINT8 Device,
+ UINT8 Func
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to check whether the pci device is present
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciRootBridgeIo - add argument and description to function comment
+// TODO: Pci - add argument and description to function comment
+// TODO: Bus - add argument and description to function comment
+// TODO: Device - add argument and description to function comment
+// TODO: Func - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+{
+ UINT64 Address;
+ EFI_STATUS Status;
+
+ //
+ // Create PCI address map in terms of Bus, Device and Func
+ //
+ Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);
+
+ //
+ // Read the Vendor Id register
+ //
+ Status = PciRootBridgeIo->Pci.Read (
+ PciRootBridgeIo,
+ EfiPciWidthUint32,
+ Address,
+ 1,
+ Pci
+ );
+
+ if (!EFI_ERROR (Status) && (Pci->Hdr).VendorId != 0xffff) {
+
+ //
+ // Read the entire config header for the device
+ //
+
+ Status = PciRootBridgeIo->Pci.Read (
+ PciRootBridgeIo,
+ EfiPciWidthUint32,
+ Address,
+ sizeof (PCI_TYPE00) / sizeof (UINT32),
+ Pci
+ );
+
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+PciPciDeviceInfoCollector (
+ IN PCI_IO_DEVICE *Bridge,
+ UINT8 StartBusNumber
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: StartBusNumber - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_TYPE00 Pci;
+ UINT8 Device;
+ UINT8 Func;
+ UINT8 SecBus;
+ PCI_IO_DEVICE *PciIoDevice;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ Status = EFI_SUCCESS;
+ SecBus = 0;
+
+ for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
+
+ for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
+
+ //
+ // Check to see whether PCI device is present
+ //
+
+ Status = PciDevicePresent (
+ Bridge->PciRootBridgeIo,
+ &Pci,
+ (UINT8) StartBusNumber,
+ (UINT8) Device,
+ (UINT8) Func
+ );
+
+ if (!EFI_ERROR (Status)) {
+
+ //
+ // Call back to host bridge function
+ //
+ PreprocessController (Bridge, (UINT8) StartBusNumber, Device, Func, EfiPciBeforeResourceCollection);
+
+ //
+ // Collect all the information about the PCI device discovered
+ //
+ Status = PciSearchDevice (
+ Bridge,
+ &Pci,
+ (UINT8) StartBusNumber,
+ Device,
+ Func,
+ &PciIoDevice
+ );
+
+ //
+ // Recursively scan PCI busses on the other side of PCI-PCI bridges
+ //
+ //
+
+ if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {
+
+ //
+ // If it is PPB, we need to get the secondary bus to continue the enumeration
+ //
+ PciIo = &(PciIoDevice->PciIo);
+
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x19, 1, &SecBus);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get resource padding for PPB
+ //
+ GetResourcePaddingPpb (PciIoDevice);
+
+ //
+ // Deep enumerate the next level bus
+ //
+ Status = PciPciDeviceInfoCollector (
+ PciIoDevice,
+ (UINT8) (SecBus)
+ );
+
+ }
+
+ if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
+
+ //
+ // Skip sub functions, this is not a multi function device
+ //
+ Func = PCI_MAX_FUNC;
+ }
+ }
+
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciSearchDevice (
+ IN PCI_IO_DEVICE *Bridge,
+ IN PCI_TYPE00 *Pci,
+ IN UINT8 Bus,
+ IN UINT8 Device,
+ IN UINT8 Func,
+ OUT PCI_IO_DEVICE **PciDevice
+ )
+/*++
+
+Routine Description:
+
+ Search required device.
+
+Arguments:
+
+ Bridge - A pointer to the PCI_IO_DEVICE.
+ Pci - A pointer to the PCI_TYPE00.
+ Bus - Bus number.
+ Device - Device number.
+ Func - Function number.
+ PciDevice - The Required pci device.
+
+Returns:
+
+ Status code.
+
+--*/
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciIoDevice = NULL;
+
+ if (!IS_PCI_BRIDGE (Pci)) {
+
+ if (IS_CARDBUS_BRIDGE (Pci)) {
+ PciIoDevice = GatherP2CInfo (
+ Bridge,
+ Pci,
+ Bus,
+ Device,
+ Func
+ );
+ if (gFullEnumeration) {
+ InitializeP2C (PciIoDevice);
+ }
+ } else {
+
+ //
+ // Create private data for Pci Device
+ //
+ PciIoDevice = GatherDeviceInfo (
+ Bridge,
+ Pci,
+ Bus,
+ Device,
+ Func
+ );
+
+ }
+
+ } else {
+
+ //
+ // Create private data for PPB
+ //
+ PciIoDevice = GatherPpbInfo (
+ Bridge,
+ Pci,
+ Bus,
+ Device,
+ Func
+ );
+
+ //
+ // Special initialization for PPB including making the PPB quiet
+ //
+ if (gFullEnumeration) {
+ InitializePpb (PciIoDevice);
+ }
+ }
+
+ if (!PciIoDevice) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Update the bar information for this PCI device so as to support some specific device
+ //
+ UpdatePciInfo (PciIoDevice);
+
+ if (PciIoDevice->DevicePath == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Detect this function has option rom
+ //
+ if (gFullEnumeration) {
+
+ if (!IS_CARDBUS_BRIDGE (Pci)) {
+
+ GetOpRomInfo (PciIoDevice);
+
+ }
+
+ ResetPowerManagementFeature (PciIoDevice);
+
+ }
+
+ //
+ // Insert it into a global tree for future reference
+ //
+ InsertPciDevice (Bridge, PciIoDevice);
+
+ //
+ // Determine PCI device attributes
+ //
+
+ if (PciDevice != NULL) {
+ *PciDevice = PciIoDevice;
+ }
+
+ return EFI_SUCCESS;
+}
+
+PCI_IO_DEVICE *
+GatherDeviceInfo (
+ IN PCI_IO_DEVICE *Bridge,
+ IN PCI_TYPE00 *Pci,
+ UINT8 Bus,
+ UINT8 Device,
+ UINT8 Func
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: Pci - add argument and description to function comment
+// TODO: Bus - add argument and description to function comment
+// TODO: Device - add argument and description to function comment
+// TODO: Func - add argument and description to function comment
+{
+ UINTN Offset;
+ UINTN BarIndex;
+ PCI_IO_DEVICE *PciIoDevice;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+
+ PciRootBridgeIo = Bridge->PciRootBridgeIo;
+ PciIoDevice = CreatePciIoDevice (
+ PciRootBridgeIo,
+ Pci,
+ Bus,
+ Device,
+ Func
+ );
+
+ if (!PciIoDevice) {
+ return NULL;
+ }
+
+ //
+ // Create a device path for this PCI device and store it into its private data
+ //
+ CreatePciDevicePath (
+ Bridge->DevicePath,
+ PciIoDevice
+ );
+
+ //
+ // If it is a full enumeration, disconnect the device in advance
+ //
+ if (gFullEnumeration) {
+
+ PciSetCommandRegister (PciIoDevice, 0);
+
+ }
+
+ //
+ // Start to parse the bars
+ //
+ for (Offset = 0x10, BarIndex = 0; Offset <= 0x24; BarIndex++) {
+ Offset = PciParseBar (PciIoDevice, Offset, BarIndex);
+ }
+
+ return PciIoDevice;
+}
+
+PCI_IO_DEVICE *
+GatherPpbInfo (
+ IN PCI_IO_DEVICE *Bridge,
+ IN PCI_TYPE00 *Pci,
+ UINT8 Bus,
+ UINT8 Device,
+ UINT8 Func
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: Pci - add argument and description to function comment
+// TODO: Bus - add argument and description to function comment
+// TODO: Device - add argument and description to function comment
+// TODO: Func - add argument and description to function comment
+{
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+ PCI_IO_DEVICE *PciIoDevice;
+ EFI_STATUS Status;
+ UINT32 Value;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT8 Temp;
+
+ PciRootBridgeIo = Bridge->PciRootBridgeIo;
+ PciIoDevice = CreatePciIoDevice (
+ PciRootBridgeIo,
+ Pci,
+ Bus,
+ Device,
+ Func
+ );
+
+ if (!PciIoDevice) {
+ return NULL;
+ }
+
+ //
+ // Create a device path for this PCI device and store it into its private data
+ //
+ CreatePciDevicePath (
+ Bridge->DevicePath,
+ PciIoDevice
+ );
+
+ if (gFullEnumeration) {
+ PciSetCommandRegister (PciIoDevice, 0);
+
+ //
+ // Initalize the bridge control register
+ //
+ PciSetBridgeControlRegister (PciIoDevice, 0);
+
+ }
+
+ //
+ // PPB can have two BARs
+ //
+ if (PciParseBar (PciIoDevice, 0x10, PPB_BAR_0) == 0x14) {
+ //
+ // Not 64-bit bar
+ //
+ PciParseBar (PciIoDevice, 0x14, PPB_BAR_1);
+ }
+
+ PciIo = &PciIoDevice->PciIo;
+
+ //
+ // Test whether it support 32 decode or not
+ //
+ PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
+ PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);
+
+ if (Value) {
+ if (Value & 0x01) {
+ PciIoDevice->Decodes |= EFI_BRIDGE_IO32_DECODE_SUPPORTED;
+ } else {
+ PciIoDevice->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;
+ }
+ }
+
+ Status = BarExisted (
+ PciIoDevice,
+ 0x24,
+ NULL,
+ NULL
+ );
+
+ //
+ // test if it supports 64 memory or not
+ //
+ if (!EFI_ERROR (Status)) {
+
+ Status = BarExisted (
+ PciIoDevice,
+ 0x28,
+ NULL,
+ NULL
+ );
+
+ if (!EFI_ERROR (Status)) {
+ PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
+ PciIoDevice->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;
+ } else {
+ PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
+ }
+ }
+
+ //
+ // Memory 32 code is required for ppb
+ //
+ PciIoDevice->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;
+
+ GetResourcePaddingPpb (PciIoDevice);
+
+ return PciIoDevice;
+}
+
+PCI_IO_DEVICE *
+GatherP2CInfo (
+ IN PCI_IO_DEVICE *Bridge,
+ IN PCI_TYPE00 *Pci,
+ UINT8 Bus,
+ UINT8 Device,
+ UINT8 Func
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: Pci - add argument and description to function comment
+// TODO: Bus - add argument and description to function comment
+// TODO: Device - add argument and description to function comment
+// TODO: Func - add argument and description to function comment
+{
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciRootBridgeIo = Bridge->PciRootBridgeIo;
+ PciIoDevice = CreatePciIoDevice (
+ PciRootBridgeIo,
+ Pci,
+ Bus,
+ Device,
+ Func
+ );
+
+ if (!PciIoDevice) {
+ return NULL;
+ }
+
+ //
+ // Create a device path for this PCI device and store it into its private data
+ //
+ CreatePciDevicePath (
+ Bridge->DevicePath,
+ PciIoDevice
+ );
+
+ if (gFullEnumeration) {
+ PciSetCommandRegister (PciIoDevice, 0);
+
+ //
+ // Initalize the bridge control register
+ //
+ PciSetBridgeControlRegister (PciIoDevice, 0);
+
+ }
+ //
+ // P2C only has one bar that is in 0x10
+ //
+ PciParseBar (PciIoDevice, 0x10, P2C_BAR_0);
+
+ //
+ // Read PciBar information from the bar register
+ //
+ GetBackPcCardBar (PciIoDevice);
+ PciIoDevice->Decodes = EFI_BRIDGE_MEM32_DECODE_SUPPORTED |
+ EFI_BRIDGE_PMEM32_DECODE_SUPPORTED |
+ EFI_BRIDGE_IO32_DECODE_SUPPORTED;
+
+ return PciIoDevice;
+}
+
+EFI_DEVICE_PATH_PROTOCOL *
+CreatePciDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: ParentDevicePath - add argument and description to function comment
+// TODO: PciIoDevice - add argument and description to function comment
+{
+
+ PCI_DEVICE_PATH PciNode;
+
+ //
+ // Create PCI device path
+ //
+ PciNode.Header.Type = HARDWARE_DEVICE_PATH;
+ PciNode.Header.SubType = HW_PCI_DP;
+ SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));
+
+ PciNode.Device = PciIoDevice->DeviceNumber;
+ PciNode.Function = PciIoDevice->FunctionNumber;
+ PciIoDevice->DevicePath = AppendDevicePathNode (ParentDevicePath, &PciNode.Header);
+
+ return PciIoDevice->DevicePath;
+}
+
+EFI_STATUS
+BarExisted (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINTN Offset,
+ OUT UINT32 *BarLengthValue,
+ OUT UINT32 *OriginalBarValue
+ )
+/*++
+
+Routine Description:
+
+ Check the bar is existed or not.
+
+Arguments:
+
+ PciIoDevice - A pointer to the PCI_IO_DEVICE.
+ Offset - The offset.
+ BarLengthValue - The bar length value.
+ OriginalBarValue - The original bar value.
+
+Returns:
+
+ EFI_NOT_FOUND - The bar don't exist.
+ EFI_SUCCESS - The bar exist.
+
+--*/
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT32 OriginalValue;
+ UINT32 Value;
+ EFI_TPL OldTpl;
+
+ PciIo = &PciIoDevice->PciIo;
+
+ //
+ // Preserve the original value
+ //
+
+ PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);
+
+ //
+ // Raise TPL to high level to disable timer interrupt while the BAR is probed
+ //
+ OldTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL);
+
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &gAllOne);
+ PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &Value);
+
+ //
+ // Write back the original value
+ //
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);
+
+ //
+ // Restore TPL to its original level
+ //
+ gBS->RestoreTPL (OldTpl);
+
+ if (BarLengthValue != NULL) {
+ *BarLengthValue = Value;
+ }
+
+ if (OriginalBarValue != NULL) {
+ *OriginalBarValue = OriginalValue;
+ }
+
+ if (Value == 0) {
+ return EFI_NOT_FOUND;
+ } else {
+ return EFI_SUCCESS;
+ }
+}
+
+EFI_STATUS
+PciTestSupportedAttribute (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINT16 *Command,
+ IN UINT16 *BridgeControl,
+ IN UINT16 *OldCommand,
+ IN UINT16 *OldBridgeControl
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: Command - add argument and description to function comment
+// TODO: BridgeControl - add argument and description to function comment
+// TODO: OldCommand - add argument and description to function comment
+// TODO: OldBridgeControl - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_TPL OldTpl;
+
+ //
+ // Preserve the original value
+ //
+ PciReadCommandRegister (PciIoDevice, OldCommand);
+
+ //
+ // Raise TPL to high level to disable timer interrupt while the BAR is probed
+ //
+ OldTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL);
+
+ PciSetCommandRegister (PciIoDevice, *Command);
+ PciReadCommandRegister (PciIoDevice, Command);
+
+ //
+ // Write back the original value
+ //
+ PciSetCommandRegister (PciIoDevice, *OldCommand);
+
+ //
+ // Restore TPL to its original level
+ //
+ gBS->RestoreTPL (OldTpl);
+
+ if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
+
+ //
+ // Preserve the original value
+ //
+ PciReadBridgeControlRegister (PciIoDevice, OldBridgeControl);
+
+ //
+ // Raise TPL to high level to disable timer interrupt while the BAR is probed
+ //
+ OldTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL);
+
+ PciSetBridgeControlRegister (PciIoDevice, *BridgeControl);
+ PciReadBridgeControlRegister (PciIoDevice, BridgeControl);
+
+ //
+ // Write back the original value
+ //
+ PciSetBridgeControlRegister (PciIoDevice, *OldBridgeControl);
+
+ //
+ // Restore TPL to its original level
+ //
+ gBS->RestoreTPL (OldTpl);
+
+ } else {
+ *OldBridgeControl = 0;
+ *BridgeControl = 0;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciSetDeviceAttribute (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINT16 Command,
+ IN UINT16 BridgeControl,
+ IN UINTN Option
+ )
+/*++
+
+ Routine Description:
+ Set the supported or current attributes of a PCI device
+
+ Arguments:
+ PciIoDevice - Structure pointer for PCI device.
+ Command - Command register value.
+ BridgeControl - Bridge control value for PPB or P2C.
+ Option - Make a choice of EFI_SET_SUPPORTS or EFI_SET_ATTRIBUTES.
+
+ Returns:
+
+--*/
+
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+
+Returns:
+
+ EFI_SUCCESS Always success
+
+
+--*/
+{
+ UINT64 Attributes;
+
+ Attributes = 0;
+
+ if (Command & EFI_PCI_COMMAND_IO_SPACE) {
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_IO;
+ }
+
+ if (Command & EFI_PCI_COMMAND_MEMORY_SPACE) {
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY;
+ }
+
+ if (Command & EFI_PCI_COMMAND_BUS_MASTER) {
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;
+ }
+
+ if (Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) {
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
+ }
+
+ if (BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) {
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;
+ }
+
+ if (BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) {
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
+ }
+
+ if (Option == EFI_SET_SUPPORTS) {
+
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE |
+ EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED |
+ EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE |
+ EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE |
+ EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM |
+ EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
+
+ if (Attributes & EFI_PCI_IO_ATTRIBUTE_IO) {
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;
+ }
+
+ if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
+ //
+ // For bridge, it should support IDE attributes
+ //
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;
+ } else {
+
+ if (IS_PCI_IDE (&PciIoDevice->Pci)) {
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;
+ }
+
+ if (IS_PCI_VGA (&PciIoDevice->Pci)) {
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;
+ Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;
+ }
+ }
+
+ PciIoDevice->Supports = Attributes;
+ PciIoDevice->Supports &= ( (PciIoDevice->Parent->Supports) | \
+ EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | \
+ EFI_PCI_IO_ATTRIBUTE_BUS_MASTER );
+
+ } else {
+ PciIoDevice->Attributes = Attributes;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetFastBackToBackSupport (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINT8 StatusIndex
+ )
+/*++
+
+Routine Description:
+
+ Determine if the device can support Fast Back to Back attribute
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: StatusIndex - add argument and description to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status;
+ UINT32 StatusRegister;
+
+ //
+ // Read the status register
+ //
+ PciIo = &PciIoDevice->PciIo;
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, StatusIndex, 1, &StatusRegister);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Check the Fast B2B bit
+ //
+ if (StatusRegister & EFI_PCI_FAST_BACK_TO_BACK_CAPABLE) {
+ return EFI_SUCCESS;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+}
+
+EFI_STATUS
+ProcessOptionRomLight (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ Process the option ROM for all the children of the specified parent PCI device.
+ It can only be used after the first full Option ROM process.
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_IO_DEVICE *Temp;
+ LIST_ENTRY *CurrentLink;
+
+ //
+ // For RootBridge, PPB , P2C, go recursively to traverse all its children
+ //
+ CurrentLink = PciIoDevice->ChildList.ForwardLink;
+ while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) {
+
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+ if (!IsListEmpty (&Temp->ChildList)) {
+ ProcessOptionRomLight (Temp);
+ }
+
+ PciRomGetImageMapping (Temp);
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DetermineDeviceAttribute (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ Determine the related attributes of all devices under a Root Bridge
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINT16 Command;
+ UINT16 BridgeControl;
+ UINT16 OldCommand;
+ UINT16 OldBridgeControl;
+ BOOLEAN FastB2BSupport;
+
+ /*
+ UINT8 IdePI;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ */
+ PCI_IO_DEVICE *Temp;
+ LIST_ENTRY *CurrentLink;
+ EFI_STATUS Status;
+
+ //
+ // For Root Bridge, just copy it by RootBridgeIo proctocol
+ // so as to keep consistent with the actual attribute
+ //
+ if (!PciIoDevice->Parent) {
+ Status = PciIoDevice->PciRootBridgeIo->GetAttributes (
+ PciIoDevice->PciRootBridgeIo,
+ &PciIoDevice->Supports,
+ &PciIoDevice->Attributes
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ } else {
+
+ //
+ // Set the attributes to be checked for common PCI devices and PPB or P2C
+ // Since some devices only support part of them, it is better to set the
+ // attribute according to its command or bridge control register
+ //
+ Command = EFI_PCI_COMMAND_IO_SPACE |
+ EFI_PCI_COMMAND_MEMORY_SPACE |
+ EFI_PCI_COMMAND_BUS_MASTER |
+ EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
+
+ BridgeControl = EFI_PCI_BRIDGE_CONTROL_ISA | EFI_PCI_BRIDGE_CONTROL_VGA;
+
+ //
+ // Test whether the device can support attributes above
+ //
+ PciTestSupportedAttribute (PciIoDevice, &Command, &BridgeControl, &OldCommand, &OldBridgeControl);
+
+ //
+ // Set the supported attributes for specified PCI device
+ //
+ PciSetDeviceAttribute (PciIoDevice, Command, BridgeControl, EFI_SET_SUPPORTS);
+
+ //
+ // Set the current attributes for specified PCI device
+ //
+ PciSetDeviceAttribute (PciIoDevice, OldCommand, OldBridgeControl, EFI_SET_ATTRIBUTES);
+
+ //
+ // Enable other supported attributes but not defined in PCI_IO_PROTOCOL
+ //
+ PciEnableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE);
+
+ //
+ // Enable IDE native mode
+ //
+ /*
+ if (IS_PCI_IDE(&PciIoDevice->Pci)) {
+
+ PciIo = &PciIoDevice->PciIo;
+
+ PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0x09,
+ 1,
+ &IdePI
+ );
+
+ //
+ // Set native mode if it can be supported
+ //
+ IdePI |= (((IdePI & 0x0F) >> 1) & 0x05);
+
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0x09,
+ 1,
+ &IdePI
+ );
+
+ }
+ */
+ }
+
+ FastB2BSupport = TRUE;
+
+ //
+ // P2C can not support FB2B on the secondary side
+ //
+ if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
+ FastB2BSupport = FALSE;
+ }
+
+ //
+ // For RootBridge, PPB , P2C, go recursively to traverse all its children
+ //
+ CurrentLink = PciIoDevice->ChildList.ForwardLink;
+ while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) {
+
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+ Status = DetermineDeviceAttribute (Temp);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Detect Fast Bact to Bact support for the device under the bridge
+ //
+ Status = GetFastBackToBackSupport (Temp, PCI_PRIMARY_STATUS_OFFSET);
+ if (FastB2BSupport && EFI_ERROR (Status)) {
+ FastB2BSupport = FALSE;
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+ //
+ // Set or clear Fast Back to Back bit for the whole bridge
+ //
+ if (!IsListEmpty (&PciIoDevice->ChildList)) {
+
+ if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
+
+ Status = GetFastBackToBackSupport (PciIoDevice, PCI_BRIDGE_STATUS_REGISTER_OFFSET);
+
+ if (EFI_ERROR (Status) || (!FastB2BSupport)) {
+ FastB2BSupport = FALSE;
+ PciDisableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);
+ } else {
+ PciEnableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);
+ }
+ }
+
+ CurrentLink = PciIoDevice->ChildList.ForwardLink;
+ while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) {
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+ if (FastB2BSupport) {
+ PciEnableCommandRegister (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);
+ } else {
+ PciDisableCommandRegister (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+ }
+ //
+ // End for IsListEmpty
+ //
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+UpdatePciInfo (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to update the bar information for those incompatible PCI device
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+{
+ EFI_STATUS Status;
+ UINTN BarIndex;
+ UINTN BarEndIndex;
+ BOOLEAN SetFlag;
+ VOID *Configuration;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
+
+ Configuration = NULL;
+
+ //
+ // It can only be supported after the Incompatible PCI Device
+ // Support Protocol has been installed
+ //
+ if (gEfiIncompatiblePciDeviceSupport == NULL) {
+
+ Status = gBS->LocateProtocol (
+ &gEfiIncompatiblePciDeviceSupportProtocolGuid,
+ NULL,
+ (VOID **) &gEfiIncompatiblePciDeviceSupport
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ //
+ // Check whether the device belongs to incompatible devices or not
+ // If it is , then get its special requirement in the ACPI table
+ //
+ Status = gEfiIncompatiblePciDeviceSupport->CheckDevice (
+ gEfiIncompatiblePciDeviceSupport,
+ PciIoDevice->Pci.Hdr.VendorId,
+ PciIoDevice->Pci.Hdr.DeviceId,
+ PciIoDevice->Pci.Hdr.RevisionID,
+ PciIoDevice->Pci.Device.SubsystemVendorID,
+ PciIoDevice->Pci.Device.SubsystemID,
+ &Configuration
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Update PCI device information from the ACPI table
+ //
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
+
+ while (Ptr->Desc != ACPI_END_TAG_DESCRIPTOR) {
+
+ if (Ptr->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+ //
+ // The format is not support
+ //
+ break;
+ }
+
+ BarIndex = (UINTN) Ptr->AddrTranslationOffset;
+ BarEndIndex = BarIndex;
+
+ //
+ // Update all the bars in the device
+ //
+ if (BarIndex == PCI_BAR_ALL) {
+ BarIndex = 0;
+ BarEndIndex = PCI_MAX_BAR - 1;
+ }
+
+ if (BarIndex >= PCI_MAX_BAR) {
+ Ptr++;
+ continue;
+ }
+
+ for (; BarIndex <= BarEndIndex; BarIndex++) {
+ SetFlag = FALSE;
+ switch (Ptr->ResType) {
+ case ACPI_ADDRESS_SPACE_TYPE_MEM:
+
+ //
+ // Make sure the bar is memory type
+ //
+ if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeMem)) {
+ SetFlag = TRUE;
+ }
+ break;
+
+ case ACPI_ADDRESS_SPACE_TYPE_IO:
+
+ //
+ // Make sure the bar is IO type
+ //
+ if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeIo)) {
+ SetFlag = TRUE;
+ }
+ break;
+ }
+
+ if (SetFlag) {
+
+ //
+ // Update the new alignment for the device
+ //
+ SetNewAlign (&(PciIoDevice->PciBar[BarIndex].Alignment), Ptr->AddrRangeMax);
+
+ //
+ // Update the new length for the device
+ //
+ if (Ptr->AddrLen != PCI_BAR_NOCHANGE) {
+ PciIoDevice->PciBar[BarIndex].Length = Ptr->AddrLen;
+ }
+ }
+ }
+
+ Ptr++;
+ }
+
+ gBS->FreePool (Configuration);
+ return Status;
+
+}
+
+VOID
+SetNewAlign (
+ IN UINT64 *Alignment,
+ IN UINT64 NewAlignment
+ )
+/*++
+
+Routine Description:
+
+ This routine will update the alignment with the new alignment
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Alignment - add argument and description to function comment
+// TODO: NewAlignment - add argument and description to function comment
+{
+ UINT64 OldAlignment;
+ UINTN ShiftBit;
+
+ //
+ // The new alignment is the same as the original,
+ // so skip it
+ //
+ if (NewAlignment == PCI_BAR_OLD_ALIGN) {
+ return ;
+ }
+ //
+ // Check the validity of the parameter
+ //
+ if (NewAlignment != PCI_BAR_EVEN_ALIGN &&
+ NewAlignment != PCI_BAR_SQUAD_ALIGN &&
+ NewAlignment != PCI_BAR_DQUAD_ALIGN ) {
+ *Alignment = NewAlignment;
+ return ;
+ }
+
+ OldAlignment = (*Alignment) + 1;
+ ShiftBit = 0;
+
+ //
+ // Get the first non-zero hex value of the length
+ //
+ while ((OldAlignment & 0x0F) == 0x00) {
+ OldAlignment = RShiftU64 (OldAlignment, 4);
+ ShiftBit += 4;
+ }
+
+ //
+ // Adjust the alignment to even, quad or double quad boundary
+ //
+ if (NewAlignment == PCI_BAR_EVEN_ALIGN) {
+ if (OldAlignment & 0x01) {
+ OldAlignment = OldAlignment + 2 - (OldAlignment & 0x01);
+ }
+ } else if (NewAlignment == PCI_BAR_SQUAD_ALIGN) {
+ if (OldAlignment & 0x03) {
+ OldAlignment = OldAlignment + 4 - (OldAlignment & 0x03);
+ }
+ } else if (NewAlignment == PCI_BAR_DQUAD_ALIGN) {
+ if (OldAlignment & 0x07) {
+ OldAlignment = OldAlignment + 8 - (OldAlignment & 0x07);
+ }
+ }
+
+ //
+ // Update the old value
+ //
+ NewAlignment = LShiftU64 (OldAlignment, ShiftBit) - 1;
+ *Alignment = NewAlignment;
+
+ return ;
+}
+
+UINTN
+PciParseBar (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINTN Offset,
+ IN UINTN BarIndex
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: Offset - add argument and description to function comment
+// TODO: BarIndex - add argument and description to function comment
+{
+ UINT32 Value;
+ UINT64 BarValue64;
+ UINT32 OriginalValue;
+ UINT32 Mask;
+ UINT32 Data;
+ UINT8 Index;
+ EFI_STATUS Status;
+
+ OriginalValue = 0;
+ Value = 0;
+ BarValue64 = 0;
+
+ Status = BarExisted (
+ PciIoDevice,
+ Offset,
+ &Value,
+ &OriginalValue
+ );
+
+ if (EFI_ERROR (Status)) {
+ PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
+ PciIoDevice->PciBar[BarIndex].Length = 0;
+ PciIoDevice->PciBar[BarIndex].Alignment = 0;
+
+ //
+ // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway
+ //
+ PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;
+ return Offset + 4;
+ }
+
+ PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;
+ if (Value & 0x01) {
+ //
+ // Device I/Os
+ //
+ Mask = 0xfffffffc;
+
+ if (Value & 0xFFFF0000) {
+ //
+ // It is a IO32 bar
+ //
+ PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo32;
+ PciIoDevice->PciBar[BarIndex].Length = ((~(Value & Mask)) + 1);
+ PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
+
+ } else {
+ //
+ // It is a IO16 bar
+ //
+ PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo16;
+ PciIoDevice->PciBar[BarIndex].Length = 0x0000FFFF & ((~(Value & Mask)) + 1);
+ PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
+
+ }
+ //
+ // Workaround. Some platforms inplement IO bar with 0 length
+ // Need to treat it as no-bar
+ //
+ if (PciIoDevice->PciBar[BarIndex].Length == 0) {
+ PciIoDevice->PciBar[BarIndex].BarType = 0;
+ }
+
+ PciIoDevice->PciBar[BarIndex].Prefetchable = FALSE;
+ PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;
+
+ } else {
+
+ Mask = 0xfffffff0;
+
+ PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;
+
+ switch (Value & 0x07) {
+
+ //
+ //memory space; anywhere in 32 bit address space
+ //
+ case 0x00:
+ if (Value & 0x08) {
+ PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;
+ } else {
+ PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;
+ }
+
+ PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;
+ PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
+
+ break;
+
+ //
+ // memory space; anywhere in 64 bit address space
+ //
+ case 0x04:
+ if (Value & 0x08) {
+ PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64;
+ } else {
+ PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64;
+ }
+
+ //
+ // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
+ // is regarded as an extension for the first bar. As a result
+ // the sizing will be conducted on combined 64 bit value
+ // Here just store the masked first 32bit value for future size
+ // calculation
+ //
+ PciIoDevice->PciBar[BarIndex].Length = Value & Mask;
+ PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
+
+ //
+ // Increment the offset to point to next DWORD
+ //
+ Offset += 4;
+
+ Status = BarExisted (
+ PciIoDevice,
+ Offset,
+ &Value,
+ &OriginalValue
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Offset + 4;
+ }
+
+ //
+ // Fix the length to support some spefic 64 bit BAR
+ //
+ Data = Value;
+ Index = 0;
+ for (Data = Value; Data != 0; Data >>= 1) {
+ Index ++;
+ }
+ Value |= ((UINT32)(-1) << Index);
+
+ //
+ // Calculate the size of 64bit bar
+ //
+ PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);
+
+ PciIoDevice->PciBar[BarIndex].Length = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);
+ PciIoDevice->PciBar[BarIndex].Length = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1;
+ PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
+
+ break;
+
+ //
+ // reserved
+ //
+ default:
+ PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
+ PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1;
+ PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;
+
+ break;
+ }
+ }
+
+ //
+ // Check the length again so as to keep compatible with some special bars
+ //
+ if (PciIoDevice->PciBar[BarIndex].Length == 0) {
+ PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown;
+ PciIoDevice->PciBar[BarIndex].BaseAddress = 0;
+ PciIoDevice->PciBar[BarIndex].Alignment = 0;
+ }
+
+ //
+ // Increment number of bar
+ //
+ return Offset + 4;
+}
+
+EFI_STATUS
+InitializePciDevice (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to initialize the bar of a PCI device
+ It can be called typically when a device is going to be rejected
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT8 Offset;
+
+ PciIo = &(PciIoDevice->PciIo);
+
+ //
+ // Put all the resource apertures
+ // Resource base is set to all ones so as to indicate its resource
+ // has not been alloacted
+ //
+ for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) {
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllOne);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+InitializePpb (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ PciIo = &(PciIoDevice->PciIo);
+
+ //
+ // Put all the resource apertures including IO16
+ // Io32, pMem32, pMem64 to quiescent state
+ // Resource base all ones, Resource limit all zeros
+ //
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero);
+
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne);
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero);
+
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne);
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero);
+
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne);
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero);
+
+ //
+ // don't support use io32 as for now
+ //
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne);
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero);
+
+ //
+ // Force Interrupt line to zero for cards that come up randomly
+ //
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+InitializeP2C (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ PciIo = &(PciIoDevice->PciIo);
+
+ //
+ // Put all the resource apertures including IO16
+ // Io32, pMem32, pMem64 to quiescent state(
+ // Resource base all ones, Resource limit all zeros
+ //
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne);
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero);
+
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne);
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero);
+
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne);
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero);
+
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne);
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero);
+
+ //
+ // Force Interrupt line to zero for cards that come up randomly
+ //
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);
+ return EFI_SUCCESS;
+}
+
+PCI_IO_DEVICE *
+CreatePciIoDevice (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
+ IN PCI_TYPE00 *Pci,
+ UINT8 Bus,
+ UINT8 Device,
+ UINT8 Func
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciRootBridgeIo - add argument and description to function comment
+// TODO: Pci - add argument and description to function comment
+// TODO: Bus - add argument and description to function comment
+// TODO: Device - add argument and description to function comment
+// TODO: Func - add argument and description to function comment
+{
+
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciIoDevice = NULL;
+
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (PCI_IO_DEVICE),
+ (VOID **) &PciIoDevice
+ );
+
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ ZeroMem (PciIoDevice, sizeof (PCI_IO_DEVICE));
+
+ PciIoDevice->Signature = PCI_IO_DEVICE_SIGNATURE;
+ PciIoDevice->Handle = NULL;
+ PciIoDevice->PciRootBridgeIo = PciRootBridgeIo;
+ PciIoDevice->DevicePath = NULL;
+ PciIoDevice->BusNumber = Bus;
+ PciIoDevice->DeviceNumber = Device;
+ PciIoDevice->FunctionNumber = Func;
+ PciIoDevice->Decodes = 0;
+ if (gFullEnumeration) {
+ PciIoDevice->Allocated = FALSE;
+ } else {
+ PciIoDevice->Allocated = TRUE;
+ }
+
+ PciIoDevice->Registered = FALSE;
+ PciIoDevice->Attributes = 0;
+ PciIoDevice->Supports = 0;
+ PciIoDevice->BusOverride = FALSE;
+ PciIoDevice->AllOpRomProcessed = FALSE;
+
+ PciIoDevice->IsPciExp = FALSE;
+
+ CopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01));
+
+ //
+ // Initialize the PCI I/O instance structure
+ //
+
+ Status = InitializePciIoInstance (PciIoDevice);
+ Status = InitializePciDriverOverrideInstance (PciIoDevice);
+
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (PciIoDevice);
+ return NULL;
+ }
+
+ //
+ // Initialize the reserved resource list
+ //
+ InitializeListHead (&PciIoDevice->ReservedResourceList);
+
+ //
+ // Initialize the driver list
+ //
+ InitializeListHead (&PciIoDevice->OptionRomDriverList);
+
+ //
+ // Initialize the child list
+ //
+ InitializeListHead (&PciIoDevice->ChildList);
+
+ return PciIoDevice;
+}
+
+EFI_STATUS
+PciEnumeratorLight (
+ IN EFI_HANDLE Controller
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to enumerate entire pci bus system
+ in a given platform
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Controller - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ EFI_STATUS Status;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+ PCI_IO_DEVICE *RootBridgeDev;
+ UINT16 MinBus;
+ UINT16 MaxBus;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
+
+ MinBus = 0;
+ MaxBus = PCI_MAX_BUS;
+ Descriptors = NULL;
+
+ //
+ // If this host bridge has been already enumerated, then return successfully
+ //
+ if (RootBridgeExisted (Controller)) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Open pci root bridge io protocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ (VOID **) &PciRootBridgeIo,
+ gPciBusDriverBinding.DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
+ return Status;
+ }
+
+ Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ while (PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL) == EFI_SUCCESS) {
+
+ //
+ // Create a device node for root bridge device with a NULL host bridge controller handle
+ //
+ RootBridgeDev = CreateRootBridge (Controller);
+
+ if (!RootBridgeDev) {
+ Descriptors++;
+ continue;
+ }
+
+ //
+ // Record the root bridge io protocol
+ //
+ RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;
+
+ Status = PciPciDeviceInfoCollector (
+ RootBridgeDev,
+ (UINT8) MinBus
+ );
+
+ if (!EFI_ERROR (Status)) {
+
+ //
+ // Remove those PCI devices which are rejected when full enumeration
+ //
+ RemoveRejectedPciDevices (RootBridgeDev->Handle, RootBridgeDev);
+
+ //
+ // Process option rom light
+ //
+ ProcessOptionRomLight (RootBridgeDev);
+
+ //
+ // Determine attributes for all devices under this root bridge
+ //
+ DetermineDeviceAttribute (RootBridgeDev);
+
+ //
+ // If successfully, insert the node into device pool
+ //
+ InsertRootBridge (RootBridgeDev);
+ } else {
+
+ //
+ // If unsuccessly, destroy the entire node
+ //
+ DestroyRootBridge (RootBridgeDev);
+ }
+
+ Descriptors++;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciGetBusRange (
+ IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors,
+ OUT UINT16 *MinBus,
+ OUT UINT16 *MaxBus,
+ OUT UINT16 *BusRange
+ )
+/*++
+
+Routine Description:
+
+ Get the bus range.
+
+Arguments:
+
+ Descriptors - A pointer to the address space descriptor.
+ MinBus - The min bus.
+ MaxBus - The max bus.
+ BusRange - The bus range.
+
+Returns:
+
+ Status Code.
+
+--*/
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+{
+
+ while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) {
+ if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
+ if (MinBus != NULL) {
+ *MinBus = (UINT16) (*Descriptors)->AddrRangeMin;
+ }
+
+ if (MaxBus != NULL) {
+ *MaxBus = (UINT16) (*Descriptors)->AddrRangeMax;
+ }
+
+ if (BusRange != NULL) {
+ *BusRange = (UINT16) (*Descriptors)->AddrLen;
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ (*Descriptors)++;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+StartManagingRootBridge (
+ IN PCI_IO_DEVICE *RootBridgeDev
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: RootBridgeDev - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_HANDLE RootBridgeHandle;
+ EFI_STATUS Status;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+
+ //
+ // Get the root bridge handle
+ //
+ RootBridgeHandle = RootBridgeDev->Handle;
+ PciRootBridgeIo = NULL;
+
+ //
+ // Get the pci root bridge io protocol
+ //
+ Status = gBS->OpenProtocol (
+ RootBridgeHandle,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ (VOID **) &PciRootBridgeIo,
+ gPciBusDriverBinding.DriverBindingHandle,
+ RootBridgeHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
+ return Status;
+ }
+
+ //
+ // Store the PciRootBridgeIo protocol into root bridge private data
+ //
+ RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;
+
+ return EFI_SUCCESS;
+
+}
+
+BOOLEAN
+IsPciDeviceRejected (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ This routine can be used to check whether a PCI device should be rejected when light enumeration
+
+Arguments:
+
+Returns:
+
+ TRUE This device should be rejected
+ FALSE This device shouldn't be rejected
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ UINT32 TestValue;
+ UINT32 OldValue;
+ UINT32 Mask;
+ UINT8 BarOffset;
+
+ //
+ // PPB should be skip!
+ //
+ if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
+ return FALSE;
+ }
+
+ if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
+ //
+ // Only test base registers for P2C
+ //
+ for (BarOffset = 0x1C; BarOffset <= 0x38; BarOffset += 2 * sizeof (UINT32)) {
+
+ Mask = (BarOffset < 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC;
+ Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ TestValue = TestValue & Mask;
+ if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
+ //
+ // The bar isn't programed, so it should be rejected
+ //
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+ }
+
+ for (BarOffset = 0x14; BarOffset <= 0x24; BarOffset += sizeof (UINT32)) {
+ //
+ // Test PCI devices
+ //
+ Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ if (TestValue & 0x01) {
+
+ //
+ // IO Bar
+ //
+
+ Mask = 0xFFFFFFFC;
+ TestValue = TestValue & Mask;
+ if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
+ return TRUE;
+ }
+
+ } else {
+
+ //
+ // Mem Bar
+ //
+
+ Mask = 0xFFFFFFF0;
+ TestValue = TestValue & Mask;
+
+ if ((TestValue & 0x07) == 0x04) {
+
+ //
+ // Mem64 or PMem64
+ //
+ BarOffset += sizeof (UINT32);
+ if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
+
+ //
+ // Test its high 32-Bit BAR
+ //
+
+ Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);
+ if (TestValue == OldValue) {
+ return TRUE;
+ }
+ }
+
+ } else {
+
+ //
+ // Mem32 or PMem32
+ //
+ if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {
+ return TRUE;
+ }
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+EFI_STATUS
+ResetAllPpbBusReg (
+ IN PCI_IO_DEVICE *Bridge,
+ IN UINT8 StartBusNumber
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ StartBusNumber - TODO: add argument description
+
+Returns:
+
+ EFI_SUCCESS - TODO: Add description for return value
+
+--*/
+{
+ EFI_STATUS Status;
+ PCI_TYPE00 Pci;
+ UINT8 Device;
+ UINT32 Register;
+ UINT8 Func;
+ UINT64 Address;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+
+ PciRootBridgeIo = Bridge->PciRootBridgeIo;
+
+ for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
+ for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
+
+ //
+ // Check to see whether a pci device is present
+ //
+ Status = PciDevicePresent (
+ PciRootBridgeIo,
+ &Pci,
+ StartBusNumber,
+ Device,
+ Func
+ );
+
+ if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci))) {
+ Register = 0;
+ Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
+ Status = PciRootBridgeIo->Pci.Read (
+ PciRootBridgeIo,
+ EfiPciWidthUint32,
+ Address,
+ 1,
+ &Register
+ );
+ //
+ // Reset register 18h, 19h, 1Ah on PCI Bridge
+ //
+ Register &= 0xFF000000;
+ Status = PciRootBridgeIo->Pci.Write (
+ PciRootBridgeIo,
+ EfiPciWidthUint32,
+ Address,
+ 1,
+ &Register
+ );
+ }
+
+ if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
+ //
+ // Skip sub functions, this is not a multi function device
+ //
+ Func = PCI_MAX_FUNC;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumeratorSupport.h b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumeratorSupport.h
new file mode 100644
index 0000000..41d6efb
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumeratorSupport.h
@@ -0,0 +1,598 @@
+/*++
+
+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:
+
+ PciEnumeratorSupport.h
+
+Abstract:
+
+ PCI Bus Driver
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_ENUMERATOR_SUPPORT_H
+#define _EFI_PCI_ENUMERATOR_SUPPORT_H
+
+EFI_STATUS
+PciDevicePresent (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
+ PCI_TYPE00 *Pci,
+ UINT8 Bus,
+ UINT8 Device,
+ UINT8 Func
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciRootBridgeIo - TODO: add argument description
+ Pci - TODO: add argument description
+ Bus - TODO: add argument description
+ Device - TODO: add argument description
+ Func - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciPciDeviceInfoCollector (
+ IN PCI_IO_DEVICE *Bridge,
+ UINT8 StartBusNumber
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ StartBusNumber - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciSearchDevice (
+ IN PCI_IO_DEVICE *Bridge,
+ PCI_TYPE00 *Pci,
+ UINT8 Bus,
+ UINT8 Device,
+ UINT8 Func,
+ PCI_IO_DEVICE **PciDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ Pci - TODO: add argument description
+ Bus - TODO: add argument description
+ Device - TODO: add argument description
+ Func - TODO: add argument description
+ PciDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+PCI_IO_DEVICE *
+GatherDeviceInfo (
+ IN PCI_IO_DEVICE *Bridge,
+ IN PCI_TYPE00 *Pci,
+ UINT8 Bus,
+ UINT8 Device,
+ UINT8 Func
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ Pci - TODO: add argument description
+ Bus - TODO: add argument description
+ Device - TODO: add argument description
+ Func - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+PCI_IO_DEVICE *
+GatherPpbInfo (
+ IN PCI_IO_DEVICE *Bridge,
+ IN PCI_TYPE00 *Pci,
+ UINT8 Bus,
+ UINT8 Device,
+ UINT8 Func
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ Pci - TODO: add argument description
+ Bus - TODO: add argument description
+ Device - TODO: add argument description
+ Func - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+PCI_IO_DEVICE *
+GatherP2CInfo (
+ IN PCI_IO_DEVICE *Bridge,
+ IN PCI_TYPE00 *Pci,
+ UINT8 Bus,
+ UINT8 Device,
+ UINT8 Func
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ Pci - TODO: add argument description
+ Bus - TODO: add argument description
+ Device - TODO: add argument description
+ Func - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_DEVICE_PATH_PROTOCOL *
+CreatePciDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ ParentDevicePath - TODO: add argument description
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+BarExisted (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINTN Offset,
+ OUT UINT32 *BarLengthValue,
+ OUT UINT32 *OriginalBarValue
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+ Offset - TODO: add argument description
+ BarLengthValue - TODO: add argument description
+ OriginalBarValue - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciTestSupportedAttribute (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINT16 *Command,
+ IN UINT16 *BridgeControl,
+ IN UINT16 *OldCommand,
+ IN UINT16 *OldBridgeControl
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+ Command - TODO: add argument description
+ BridgeControl - TODO: add argument description
+ OldCommand - TODO: add argument description
+ OldBridgeControl - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciSetDeviceAttribute (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINT16 Command,
+ IN UINT16 BridgeControl,
+ IN UINTN Option
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+ Command - TODO: add argument description
+ BridgeControl - TODO: add argument description
+ Option - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+GetFastBackToBackSupport (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINT8 StatusIndex
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+ StatusIndex - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+DetermineDeviceAttribute (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+UpdatePciInfo (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+VOID
+SetNewAlign (
+ IN UINT64 *Alignment,
+ IN UINT64 NewAlignment
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Alignment - TODO: add argument description
+ NewAlignment - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+UINTN
+PciParseBar (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINTN Offset,
+ IN UINTN BarIndex
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+ Offset - TODO: add argument description
+ BarIndex - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+InitializePciDevice (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+InitializePpb (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+InitializeP2C (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+PCI_IO_DEVICE *
+CreatePciIoDevice (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
+ IN PCI_TYPE00 *Pci,
+ UINT8 Bus,
+ UINT8 Device,
+ UINT8 Func
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciRootBridgeIo - TODO: add argument description
+ Pci - TODO: add argument description
+ Bus - TODO: add argument description
+ Device - TODO: add argument description
+ Func - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciEnumeratorLight (
+ IN EFI_HANDLE Controller
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Controller - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciGetBusRange (
+ IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors,
+ OUT UINT16 *MinBus,
+ OUT UINT16 *MaxBus,
+ OUT UINT16 *BusRange
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Descriptors - TODO: add argument description
+ MinBus - TODO: add argument description
+ MaxBus - TODO: add argument description
+ BusRange - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+StartManagingRootBridge (
+ IN PCI_IO_DEVICE *RootBridgeDev
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ RootBridgeDev - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+IsPciDeviceRejected (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciHotPlugSupport.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciHotPlugSupport.c
new file mode 100644
index 0000000..4ebf9a7
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciHotPlugSupport.c
@@ -0,0 +1,462 @@
+/*++
+
+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:
+
+ PciHotPlugSupport.c
+
+Abstract:
+
+
+
+Revision History
+
+--*/
+
+#include "Pcibus.h"
+#include "PciHotPlugSupport.h"
+
+EFI_PCI_HOT_PLUG_INIT_PROTOCOL *gPciHotPlugInit;
+EFI_HPC_LOCATION *gPciRootHpcPool;
+UINTN gPciRootHpcCount;
+ROOT_HPC_DATA *gPciRootHpcData;
+
+VOID
+EFIAPI
+PciHPCInitialized (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Event - add argument and description to function comment
+// TODO: Context - add argument and description to function comment
+{
+ ROOT_HPC_DATA *HpcData;
+
+ HpcData = (ROOT_HPC_DATA *) Context;
+ HpcData->Initialized = TRUE;
+
+}
+
+BOOLEAN
+EfiCompareDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: DevicePath1 - add argument and description to function comment
+// TODO: DevicePath2 - add argument and description to function comment
+{
+ UINTN Size1;
+ UINTN Size2;
+
+ Size1 = GetDevicePathSize (DevicePath1);
+ Size2 = GetDevicePathSize (DevicePath2);
+
+ if (Size1 != Size2) {
+ return FALSE;
+ }
+
+ if (CompareMem (DevicePath1, DevicePath2, Size1)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+EFI_STATUS
+InitializeHotPlugSupport (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ EFI_HPC_LOCATION *HpcList;
+ UINTN HpcCount;
+
+ //
+ // Locate the PciHotPlugInit Protocol
+ // If it doesn't exist, that means there is no
+ // hot plug controller supported on the platform
+ // the PCI Bus driver is running on. HotPlug Support
+ // is an optional feature, so absence of the protocol
+ // won't incur the penalty
+ //
+ gPciHotPlugInit = NULL;
+ gPciRootHpcPool = NULL;
+ gPciRootHpcCount = 0;
+ gPciRootHpcData = NULL;
+
+ Status = gBS->LocateProtocol (
+ &gEfiPciHotPlugInitProtocolGuid,
+ NULL,
+ (VOID **) &gPciHotPlugInit
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = gPciHotPlugInit->GetRootHpcList (
+ gPciHotPlugInit,
+ &HpcCount,
+ &HpcList
+ );
+
+ if (!EFI_ERROR (Status)) {
+
+ gPciRootHpcPool = HpcList;
+ gPciRootHpcCount = HpcCount;
+ gPciRootHpcData = AllocateZeroPool (sizeof (ROOT_HPC_DATA) * gPciRootHpcCount);
+ if (gPciRootHpcData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+IsRootPciHotPlugBus (
+ IN EFI_DEVICE_PATH_PROTOCOL *HpbDevicePath,
+ OUT UINTN *HpIndex
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+ HpcDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL.
+ HpIndex - A pointer to the Index.
+
+Returns:
+
+ None
+
+--*/
+// TODO: HpbDevicePath - add argument and description to function comment
+{
+ UINTN Index;
+
+ for (Index = 0; Index < gPciRootHpcCount; Index++) {
+
+ if (EfiCompareDevicePath (gPciRootHpcPool[Index].HpbDevicePath, HpbDevicePath)) {
+
+ if (HpIndex != NULL) {
+ *HpIndex = Index;
+ }
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+BOOLEAN
+IsRootPciHotPlugController (
+ IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath,
+ OUT UINTN *HpIndex
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+ HpcDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL.
+ HpIndex - A pointer to the Index.
+
+Returns:
+
+ None
+
+--*/
+{
+ UINTN Index;
+
+ for (Index = 0; Index < gPciRootHpcCount; Index++) {
+
+ if (EfiCompareDevicePath (gPciRootHpcPool[Index].HpcDevicePath, HpcDevicePath)) {
+
+ if (HpIndex != NULL) {
+ *HpIndex = Index;
+ }
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+EFI_STATUS
+CreateEventForHpc (
+ IN UINTN HpIndex,
+ OUT EFI_EVENT *Event
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: HpIndex - add argument and description to function comment
+// TODO: Event - add argument and description to function comment
+{
+ EFI_STATUS Status;
+
+ Status = gBS->CreateEvent (
+ EFI_EVENT_NOTIFY_SIGNAL,
+ EFI_TPL_CALLBACK,
+ PciHPCInitialized,
+ gPciRootHpcData + HpIndex,
+ &((gPciRootHpcData + HpIndex)->Event)
+ );
+
+ if (!EFI_ERROR (Status)) {
+ *Event = (gPciRootHpcData + HpIndex)->Event;
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+AllRootHPCInitialized (
+ IN UINTN TimeoutInMilliSeconds
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: TimeoutInMilliSeconds - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_TIMEOUT - add return value to function comment
+{
+ UINT32 Delay;
+ UINTN Index;
+
+ Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1);
+ do {
+
+ for (Index = 0; Index < gPciRootHpcCount; Index++) {
+
+ if (!gPciRootHpcData[Index].Initialized) {
+ break;
+ }
+ }
+
+ if (Index == gPciRootHpcCount) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Stall for 30 us
+ //
+ gBS->Stall (30);
+
+ Delay--;
+
+ } while (Delay);
+
+ return EFI_TIMEOUT;
+}
+
+EFI_STATUS
+IsSHPC (
+ PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+{
+
+ EFI_STATUS Status;
+ UINT8 Offset;
+
+ if (!PciIoDevice) {
+ return EFI_NOT_FOUND;
+ }
+
+ Offset = 0;
+ Status = LocateCapabilityRegBlock (
+ PciIoDevice,
+ EFI_PCI_CAPABILITY_ID_HOTPLUG,
+ &Offset,
+ NULL
+ );
+
+ //
+ // If the PPB has the hot plug controller build-in,
+ // then return TRUE;
+ //
+ if (!EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+GetResourcePaddingForHpb (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+{
+ EFI_STATUS Status;
+ EFI_HPC_STATE State;
+ UINT64 PciAddress;
+ EFI_HPC_PADDING_ATTRIBUTES Attributes;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
+
+ Status = IsPciHotPlugBus (PciIoDevice);
+
+ if (!EFI_ERROR (Status)) {
+ PciAddress = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0);
+ Status = gPciHotPlugInit->GetResourcePadding (
+ gPciHotPlugInit,
+ PciIoDevice->DevicePath,
+ PciAddress,
+ &State,
+ (VOID **) &Descriptors,
+ &Attributes
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if ((State & EFI_HPC_STATE_ENABLED) && (State & EFI_HPC_STATE_INITIALIZED)) {
+ PciIoDevice->ResourcePaddingDescriptors = Descriptors;
+ PciIoDevice->PaddingAttributes = Attributes;
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+IsPciHotPlugBus (
+ PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+{
+ BOOLEAN Result;
+ EFI_STATUS Status;
+
+ Status = IsSHPC (PciIoDevice);
+
+ //
+ // If the PPB has the hot plug controller build-in,
+ // then return TRUE;
+ //
+ if (!EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Otherwise, see if it is a Root HPC
+ //
+ Result = IsRootPciHotPlugBus (PciIoDevice->DevicePath, NULL);
+
+ if (Result) {
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciHotPlugSupport.h b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciHotPlugSupport.h
new file mode 100644
index 0000000..df49eba
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciHotPlugSupport.h
@@ -0,0 +1,269 @@
+/*++
+
+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:
+
+ PciHotPlugSupport.h
+
+Abstract:
+
+
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_HOT_PLUG_SUPPORT_H
+#define _EFI_PCI_HOT_PLUG_SUPPORT_H
+
+//
+// stall 1 ms
+//
+#define STALL_1_MILLI_SECOND 1000
+
+//
+// stall 1 second
+//
+#define STALL_1_SECOND 1000000
+
+typedef struct {
+ EFI_EVENT Event;
+ BOOLEAN Initialized;
+ VOID *Padding;
+} ROOT_HPC_DATA;
+
+extern EFI_PCI_HOT_PLUG_INIT_PROTOCOL *gPciHotPlugInit;
+extern EFI_HPC_LOCATION *gPciRootHpcPool;
+extern UINTN gPciRootHpcCount;
+extern ROOT_HPC_DATA *gPciRootHpcData;
+
+VOID
+EFIAPI
+PciHPCInitialized (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Event - TODO: add argument description
+ Context - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+EfiCompareDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ DevicePath1 - TODO: add argument description
+ DevicePath2 - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+InitializeHotPlugSupport (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+IsPciHotPlugBus (
+ PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+IsRootPciHotPlugBus (
+ IN EFI_DEVICE_PATH_PROTOCOL *HpbDevicePath,
+ OUT UINTN *HpIndex
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ HpbDevicePath - TODO: add argument description
+ HpIndex - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+IsRootPciHotPlugController (
+ IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath,
+ OUT UINTN *HpIndex
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ HpcDevicePath - TODO: add argument description
+ HpIndex - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+CreateEventForHpc (
+ IN UINTN HpIndex,
+ OUT EFI_EVENT *Event
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ HpIndex - TODO: add argument description
+ Event - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+AllRootHPCInitialized (
+ IN UINTN TimeoutInMilliSeconds
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ TimeoutInMilliSeconds - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+IsSHPC (
+ PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+GetResourcePaddingForHpb (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciIo.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciIo.c
new file mode 100644
index 0000000..4f1737f
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciIo.c
@@ -0,0 +1,1964 @@
+/*++
+
+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:
+
+ PciIo.c
+
+Abstract:
+
+ PCI I/O Abstraction Driver
+
+Revision History
+
+--*/
+
+#include "Pcibus.h"
+
+//
+// Internal use only
+//
+STATIC
+EFI_STATUS
+ReportErrorStatusCode (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN EFI_STATUS_CODE_VALUE Code
+ );
+
+//
+// PCI I/O Support Function Prototypes
+//
+//
+//
+// Pci Io Protocol Interface
+//
+static EFI_PCI_IO_PROTOCOL PciIoInterface = {
+ PciIoPollMem,
+ PciIoPollIo,
+ {
+ PciIoMemRead,
+ PciIoMemWrite
+ },
+ {
+ PciIoIoRead,
+ PciIoIoWrite
+ },
+ {
+ PciIoConfigRead,
+ PciIoConfigWrite
+ },
+ PciIoCopyMem,
+ PciIoMap,
+ PciIoUnmap,
+ PciIoAllocateBuffer,
+ PciIoFreeBuffer,
+ PciIoFlush,
+ PciIoGetLocation,
+ PciIoAttributes,
+ PciIoGetBarAttributes,
+ PciIoSetBarAttributes,
+ 0,
+ NULL
+};
+
+STATIC
+EFI_STATUS
+ReportErrorStatusCode (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN EFI_STATUS_CODE_VALUE Code
+ )
+/*++
+
+Routine Description:
+
+ report a error Status code of PCI bus driver controller
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: Code - add argument and description to function comment
+{
+ return REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,
+ Code,
+ PciIoDevice->DevicePath
+ );
+}
+
+EFI_STATUS
+InitializePciIoInstance (
+ PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ Initializes a PCI I/O Instance
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ CopyMem (&PciIoDevice->PciIo, &PciIoInterface, sizeof (EFI_PCI_IO_PROTOCOL));
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciIoVerifyBarAccess (
+ PCI_IO_DEVICE *PciIoDevice,
+ UINT8 BarIndex,
+ PCI_BAR_TYPE Type,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINTN Count,
+ UINT64 *Offset
+ )
+/*++
+
+Routine Description:
+
+ Verifies access to a PCI Base Address Register (BAR)
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: BarIndex - add argument and description to function comment
+// TODO: Type - add argument and description to function comment
+// TODO: Width - add argument and description to function comment
+// TODO: Count - add argument and description to function comment
+// TODO: Offset - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BarIndex == EFI_PCI_IO_PASS_THROUGH_BAR) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // BarIndex 0-5 is legal
+ //
+ if (BarIndex >= PCI_MAX_BAR) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!CheckBarType (PciIoDevice, BarIndex, Type)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX
+ // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX
+ //
+ if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
+ Count = 1;
+ }
+
+ Width &= 0x03;
+
+ if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PciIoDevice->PciBar[BarIndex].Length) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Offset = *Offset + PciIoDevice->PciBar[BarIndex].BaseAddress;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciIoVerifyConfigAccess (
+ PCI_IO_DEVICE *PciIoDevice,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINTN Count,
+ IN UINT64 *Offset
+ )
+/*++
+
+Routine Description:
+
+ Verifies access to a PCI Config Header
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: Width - add argument and description to function comment
+// TODO: Count - add argument and description to function comment
+// TODO: Offset - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINT64 ExtendOffset;
+
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX
+ //
+ Width &= 0x03;
+
+ if (PciIoDevice->IsPciExp) {
+ if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PCI_EXP_MAX_CONFIG_OFFSET) {
+ return EFI_UNSUPPORTED;
+ }
+
+ ExtendOffset = LShiftU64 (*Offset, 32);
+ *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0);
+ *Offset = (*Offset) | ExtendOffset;
+
+ } else {
+ if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PCI_MAX_CONFIG_OFFSET) {
+ return EFI_UNSUPPORTED;
+ }
+
+ *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, *Offset);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoPollMem (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+/*++
+
+Routine Description:
+
+ Poll PCI Memmory
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Width - add argument and description to function comment
+// TODO: BarIndex - add argument and description to function comment
+// TODO: Offset - add argument and description to function comment
+// TODO: Mask - add argument and description to function comment
+// TODO: Value - add argument and description to function comment
+// TODO: Delay - add argument and description to function comment
+// TODO: Result - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, 1, &Offset);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (Width > EfiPciIoWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = PciIoDevice->PciRootBridgeIo->PollMem (
+ PciIoDevice->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Offset,
+ Mask,
+ Value,
+ Delay,
+ Result
+ );
+
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoPollIo (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+/*++
+
+Routine Description:
+
+ Poll PCI IO
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Width - add argument and description to function comment
+// TODO: BarIndex - add argument and description to function comment
+// TODO: Offset - add argument and description to function comment
+// TODO: Mask - add argument and description to function comment
+// TODO: Value - add argument and description to function comment
+// TODO: Delay - add argument and description to function comment
+// TODO: Result - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, 1, &Offset);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (Width > EfiPciIoWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = PciIoDevice->PciRootBridgeIo->PollIo (
+ PciIoDevice->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Offset,
+ Mask,
+ Value,
+ Delay,
+ Result
+ );
+
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoMemRead (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Performs a PCI Memory Read Cycle
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Width - add argument and description to function comment
+// TODO: BarIndex - add argument and description to function comment
+// TODO: Offset - add argument and description to function comment
+// TODO: Count - add argument and description to function comment
+// TODO: Buffer - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = PciIoDevice->PciRootBridgeIo->Mem.Read (
+ PciIoDevice->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Offset,
+ Count,
+ Buffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoMemWrite (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Performs a PCI Memory Write Cycle
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Width - add argument and description to function comment
+// TODO: BarIndex - add argument and description to function comment
+// TODO: Offset - add argument and description to function comment
+// TODO: Count - add argument and description to function comment
+// TODO: Buffer - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = PciIoDevice->PciRootBridgeIo->Mem.Write (
+ PciIoDevice->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Offset,
+ Count,
+ Buffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoIoRead (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Performs a PCI I/O Read Cycle
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Width - add argument and description to function comment
+// TODO: BarIndex - add argument and description to function comment
+// TODO: Offset - add argument and description to function comment
+// TODO: Count - add argument and description to function comment
+// TODO: Buffer - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = PciIoDevice->PciRootBridgeIo->Io.Read (
+ PciIoDevice->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Offset,
+ Count,
+ Buffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoIoWrite (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Performs a PCI I/O Write Cycle
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Width - add argument and description to function comment
+// TODO: BarIndex - add argument and description to function comment
+// TODO: Offset - add argument and description to function comment
+// TODO: Count - add argument and description to function comment
+// TODO: Buffer - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = PciIoDevice->PciRootBridgeIo->Io.Write (
+ PciIoDevice->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Offset,
+ Count,
+ Buffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoConfigRead (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT32 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Performs a PCI Configuration Read Cycle
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Width - add argument and description to function comment
+// TODO: Offset - add argument and description to function comment
+// TODO: Count - add argument and description to function comment
+// TODO: Buffer - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+ UINT64 Address;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ Address = Offset;
+ Status = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PciIoDevice->PciRootBridgeIo->Pci.Read (
+ PciIoDevice->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Address,
+ Count,
+ Buffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoConfigWrite (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT32 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Performs a PCI Configuration Write Cycle
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Width - add argument and description to function comment
+// TODO: Offset - add argument and description to function comment
+// TODO: Count - add argument and description to function comment
+// TODO: Buffer - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+ UINT64 Address;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ Address = Offset;
+ Status = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PciIoDevice->PciRootBridgeIo->Pci.Write (
+ PciIoDevice->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ Address,
+ Count,
+ Buffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoCopyMem (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 DestBarIndex,
+ IN UINT64 DestOffset,
+ IN UINT8 SrcBarIndex,
+ IN UINT64 SrcOffset,
+ IN UINTN Count
+ )
+/*++
+
+Routine Description:
+
+ Copy PCI Memory
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Width - add argument and description to function comment
+// TODO: DestBarIndex - add argument and description to function comment
+// TODO: DestOffset - add argument and description to function comment
+// TODO: SrcBarIndex - add argument and description to function comment
+// TODO: SrcOffset - add argument and description to function comment
+// TODO: Count - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ if (Width < 0 || Width >= EfiPciIoWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width == EfiPciIoWidthFifoUint8 ||
+ Width == EfiPciIoWidthFifoUint16 ||
+ Width == EfiPciIoWidthFifoUint32 ||
+ Width == EfiPciIoWidthFifoUint64 ||
+ Width == EfiPciIoWidthFillUint8 ||
+ Width == EfiPciIoWidthFillUint16 ||
+ Width == EfiPciIoWidthFillUint32 ||
+ Width == EfiPciIoWidthFillUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = PciIoVerifyBarAccess (PciIoDevice, DestBarIndex, PciBarTypeMem, Width, Count, &DestOffset);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = PciIoVerifyBarAccess (PciIoDevice, SrcBarIndex, PciBarTypeMem, Width, Count, &SrcOffset);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = PciIoDevice->PciRootBridgeIo->CopyMem (
+ PciIoDevice->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,
+ DestOffset,
+ SrcOffset,
+ Count
+ );
+
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoMap (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ )
+/*++
+
+Routine Description:
+
+ Maps a memory region for DMA
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Operation - add argument and description to function comment
+// TODO: HostAddress - add argument and description to function comment
+// TODO: NumberOfBytes - add argument and description to function comment
+// TODO: DeviceAddress - add argument and description to function comment
+// TODO: Mapping - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ if (Operation < 0 || Operation >= EfiPciIoOperationMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) {
+ Operation = Operation + EfiPciOperationBusMasterRead64;
+ }
+
+ Status = PciIoDevice->PciRootBridgeIo->Map (
+ PciIoDevice->PciRootBridgeIo,
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,
+ HostAddress,
+ NumberOfBytes,
+ DeviceAddress,
+ Mapping
+ );
+
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoUnmap (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ )
+/*++
+
+Routine Description:
+
+ Unmaps a memory region for DMA
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Mapping - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ Status = PciIoDevice->PciRootBridgeIo->Unmap (
+ PciIoDevice->PciRootBridgeIo,
+ Mapping
+ );
+
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoAllocateBuffer (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ )
+/*++
+
+Routine Description:
+
+ Allocates a common buffer for DMA
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Type - add argument and description to function comment
+// TODO: MemoryType - add argument and description to function comment
+// TODO: Pages - add argument and description to function comment
+// TODO: HostAddress - add argument and description to function comment
+// TODO: Attributes - add argument and description to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+
+ if (Attributes &
+ (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED))) {
+ return EFI_UNSUPPORTED;
+ }
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ if (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) {
+ Attributes |= EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
+ }
+
+ Status = PciIoDevice->PciRootBridgeIo->AllocateBuffer (
+ PciIoDevice->PciRootBridgeIo,
+ Type,
+ MemoryType,
+ Pages,
+ HostAddress,
+ Attributes
+ );
+
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoFreeBuffer (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ IN VOID *HostAddress
+ )
+/*++
+
+Routine Description:
+
+ Frees a common buffer
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Pages - add argument and description to function comment
+// TODO: HostAddress - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ Status = PciIoDevice->PciRootBridgeIo->FreeBuffer (
+ PciIoDevice->PciRootBridgeIo,
+ Pages,
+ HostAddress
+ );
+
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoFlush (
+ IN EFI_PCI_IO_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+
+ Flushes a DMA buffer
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ Status = PciIoDevice->PciRootBridgeIo->Flush (
+ PciIoDevice->PciRootBridgeIo
+ );
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoGetLocation (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ OUT UINTN *Segment,
+ OUT UINTN *Bus,
+ OUT UINTN *Device,
+ OUT UINTN *Function
+ )
+/*++
+
+Routine Description:
+
+ Gets a PCI device's current bus number, device number, and function number.
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Segment - add argument and description to function comment
+// TODO: Bus - add argument and description to function comment
+// TODO: Device - add argument and description to function comment
+// TODO: Function - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_IO_DEVICE *PciIoDevice;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ if (Segment == NULL || Bus == NULL || Device == NULL || Function == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Segment = PciIoDevice->PciRootBridgeIo->SegmentNumber;
+ *Bus = PciIoDevice->BusNumber;
+ *Device = PciIoDevice->DeviceNumber;
+ *Function = PciIoDevice->FunctionNumber;
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+CheckBarType (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ UINT8 BarIndex,
+ PCI_BAR_TYPE BarType
+ )
+/*++
+
+Routine Description:
+
+ Sets a PCI controllers attributes on a resource range
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: BarIndex - add argument and description to function comment
+// TODO: BarType - add argument and description to function comment
+{
+ switch (BarType) {
+
+ case PciBarTypeMem:
+
+ if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem32 &&
+ PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem32 &&
+ PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem64 &&
+ PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem64 ) {
+ return FALSE;
+ }
+
+ return TRUE;
+
+ case PciBarTypeIo:
+ if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo32 &&
+ PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo16){
+ return FALSE;
+ }
+
+ return TRUE;
+
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+EFI_STATUS
+ModifyRootBridgeAttributes (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINT64 Attributes,
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
+ )
+/*++
+
+Routine Description:
+
+ Set new attributes to a Root Bridge
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: Attributes - add argument and description to function comment
+// TODO: Operation - add argument and description to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINT64 PciRootBridgeSupports;
+ UINT64 PciRootBridgeAttributes;
+ UINT64 NewPciRootBridgeAttributes;
+ EFI_STATUS Status;
+
+ //
+ // Get the current attributes of this PCI device's PCI Root Bridge
+ //
+ Status = PciIoDevice->PciRootBridgeIo->GetAttributes (
+ PciIoDevice->PciRootBridgeIo,
+ &PciRootBridgeSupports,
+ &PciRootBridgeAttributes
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Record the new attribute of the Root Bridge
+ //
+ if (Operation == EfiPciIoAttributeOperationEnable) {
+ NewPciRootBridgeAttributes = PciRootBridgeAttributes | Attributes;
+ } else {
+ NewPciRootBridgeAttributes = PciRootBridgeAttributes & (~Attributes);
+ }
+
+ //
+ // Call the PCI Root Bridge to attempt to modify the attributes
+ //
+ if (NewPciRootBridgeAttributes ^ PciRootBridgeAttributes) {
+
+ Status = PciIoDevice->PciRootBridgeIo->SetAttributes (
+ PciIoDevice->PciRootBridgeIo,
+ NewPciRootBridgeAttributes,
+ NULL,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // The PCI Root Bridge could not modify the attributes, so return the error.
+ //
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ //
+ // Also update the attributes for this Root Bridge structure
+ //
+ PciIoDevice->Attributes = NewPciRootBridgeAttributes;
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+SupportPaletteSnoopAttributes (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
+ )
+/*++
+
+Routine Description:
+
+ Check whether this device can be enable/disable to snoop
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: Operation - add argument and description to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_IO_DEVICE *Temp;
+ UINT16 VGACommand;
+
+ //
+ // Snoop attribute can be only modified by GFX
+ //
+ if (!IS_PCI_GFX (&PciIoDevice->Pci)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Get the boot VGA on the same segement
+ //
+ Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);
+
+ if (!Temp) {
+ //
+ // If there is no VGA device on the segement, set
+ // this graphics card to decode the palette range
+ //
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Check these two agents are on the same path
+ //
+ if (!PciDevicesOnTheSamePath (Temp, PciIoDevice)) {
+ //
+ // they are not on the same path, so snoop can be enabled or disabled
+ //
+ return EFI_SUCCESS;
+ }
+ //
+ // Check if they are on the same bus
+ //
+ if (Temp->Parent == PciIoDevice->Parent) {
+
+ PciReadCommandRegister (Temp, &VGACommand);
+
+ //
+ // If they are on the same bus, either one can
+ // be set to snoop, the other set to decode
+ //
+ if (VGACommand & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) {
+ //
+ // VGA has set to snoop, so GFX can be only set to disable snoop
+ //
+ if (Operation == EfiPciIoAttributeOperationEnable) {
+ return EFI_UNSUPPORTED;
+ }
+ } else {
+ //
+ // VGA has disabled to snoop, so GFX can be only enabled
+ //
+ if (Operation == EfiPciIoAttributeOperationDisable) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ //
+ // If they are on the same path but on the different bus
+ // The first agent is set to snoop, the second one set to
+ // decode
+ //
+
+ if (Temp->BusNumber > PciIoDevice->BusNumber) {
+ //
+ // GFX should be set to decode
+ //
+ if (Operation == EfiPciIoAttributeOperationDisable) {
+ PciEnableCommandRegister (Temp, EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);
+ Temp->Attributes |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+ } else {
+ //
+ // GFX should be set to snoop
+ //
+ if (Operation == EfiPciIoAttributeOperationEnable) {
+ PciDisableCommandRegister (Temp, EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);
+ Temp->Attributes &= (~EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoAttributes (
+ IN EFI_PCI_IO_PROTOCOL * This,
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
+ IN UINT64 Attributes,
+ OUT UINT64 *Result OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Operation - add argument and description to function comment
+// TODO: Attributes - add argument and description to function comment
+// TODO: Result - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+{
+ EFI_STATUS Status;
+
+ PCI_IO_DEVICE *PciIoDevice;
+ PCI_IO_DEVICE *UpStreamBridge;
+ PCI_IO_DEVICE *Temp;
+
+ UINT64 Supports;
+ UINT64 UpStreamAttributes;
+ UINT16 BridgeControl;
+ UINT16 Command;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ switch (Operation) {
+ case EfiPciIoAttributeOperationGet:
+ if (Result == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Result = PciIoDevice->Attributes;
+ return EFI_SUCCESS;
+
+ case EfiPciIoAttributeOperationSupported:
+ if (Result == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Result = PciIoDevice->Supports;
+ return EFI_SUCCESS;
+
+ case EfiPciIoAttributeOperationSet:
+ Status = PciIoDevice->PciIo.Attributes (
+ &(PciIoDevice->PciIo),
+ EfiPciIoAttributeOperationEnable,
+ Attributes,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = PciIoDevice->PciIo.Attributes (
+ &(PciIoDevice->PciIo),
+ EfiPciIoAttributeOperationDisable,
+ (~Attributes) & (PciIoDevice->Supports),
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+
+ case EfiPciIoAttributeOperationEnable:
+ case EfiPciIoAttributeOperationDisable:
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Just a trick for ENABLE attribute
+ //
+ if ((Attributes & EFI_PCI_DEVICE_ENABLE) == EFI_PCI_DEVICE_ENABLE) {
+ Attributes &= (PciIoDevice->Supports);
+
+ //
+ // Raise the EFI_P_PC_ENABLE Status code
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_IO_BUS_PCI | EFI_P_PC_ENABLE,
+ PciIoDevice->DevicePath
+ );
+ }
+
+ //
+ // If no attributes can be supported, then return.
+ // Otherwise, set the attributes that it can support.
+ //
+ Supports = (PciIoDevice->Supports) & Attributes;
+ if (Supports != Attributes) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // For Root Bridge, just call RootBridgeIo to set attributes;
+ //
+ if (!PciIoDevice->Parent) {
+ Status = ModifyRootBridgeAttributes (PciIoDevice, Attributes, Operation);
+ return Status;
+ }
+
+ Command = 0;
+ BridgeControl = 0;
+
+ //
+ // For PPB & P2C, set relevant attribute bits
+ //
+ if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {
+
+ if (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) {
+ BridgeControl |= EFI_PCI_BRIDGE_CONTROL_VGA;
+ }
+
+ if (Attributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) {
+ BridgeControl |= EFI_PCI_BRIDGE_CONTROL_ISA;
+ }
+
+ if (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) {
+ Command |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;
+ }
+
+ } else {
+ //
+ // Do with the attributes on VGA
+ //
+ if ((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) ||
+ (IS_PCI_VGA(&PciIoDevice->Pci) &&
+ ((Attributes & EFI_PCI_IO_ATTRIBUTE_IO) ||
+ (Attributes & EFI_PCI_IO_ATTRIBUTE_MEMORY)))) {
+ //
+ // Check if a VGA has been enabled before enabling a new one
+ //
+ if (Operation == EfiPciIoAttributeOperationEnable) {
+ //
+ // Check if there have been an active VGA device on the same segment
+ //
+ Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);
+ if (Temp && Temp != PciIoDevice) {
+ //
+ // An active VGA has been detected, so can not enable another
+ //
+ return EFI_UNSUPPORTED;
+ }
+ }
+ }
+
+ //
+ // Do with the attributes on GFX
+ //
+ if (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) {
+
+ if (Operation == EfiPciIoAttributeOperationEnable) {
+ //
+ // Check if snoop can be enabled in current configuration
+ //
+ Status = SupportPaletteSnoopAttributes (PciIoDevice, Operation);
+
+ if (EFI_ERROR (Status)) {
+
+ //
+ // Enable operation is forbidden, so mask the bit in attributes
+ // so as to keep consistent with the actual Status
+ //
+ // Attributes &= (~EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO);
+ //
+ //
+ //
+ return EFI_UNSUPPORTED;
+
+ }
+ }
+
+ //
+ // It can be supported, so get ready to set the bit
+ //
+ Command |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;
+ }
+ }
+
+ if (Attributes & EFI_PCI_IO_ATTRIBUTE_IO) {
+ Command |= EFI_PCI_COMMAND_IO_SPACE;
+ }
+
+ if (Attributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) {
+ Command |= EFI_PCI_COMMAND_MEMORY_SPACE;
+ }
+
+ if (Attributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) {
+ Command |= EFI_PCI_COMMAND_BUS_MASTER;
+ }
+ //
+ // The upstream bridge should be also set to revelant attribute
+ // expect for IO, Mem and BusMaster
+ //
+ UpStreamAttributes = Attributes &
+ (~(EFI_PCI_IO_ATTRIBUTE_IO |
+ EFI_PCI_IO_ATTRIBUTE_MEMORY |
+ EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
+ )
+ );
+ UpStreamBridge = PciIoDevice->Parent;
+
+ if (Operation == EfiPciIoAttributeOperationEnable) {
+ //
+ // Enable relevant attributes to command register and bridge control register
+ //
+ Status = PciEnableCommandRegister (PciIoDevice, Command);
+ if (BridgeControl) {
+ Status = PciEnableBridgeControlRegister (PciIoDevice, BridgeControl);
+ }
+
+ PciIoDevice->Attributes |= Attributes;
+
+ //
+ // Enable attributes of the upstream bridge
+ //
+ Status = UpStreamBridge->PciIo.Attributes (
+ &(UpStreamBridge->PciIo),
+ EfiPciIoAttributeOperationEnable,
+ UpStreamAttributes,
+ NULL
+ );
+ } else {
+
+ //
+ // Disable relevant attributes to command register and bridge control register
+ //
+ Status = PciDisableCommandRegister (PciIoDevice, Command);
+ if (BridgeControl) {
+ Status = PciDisableBridgeControlRegister (PciIoDevice, BridgeControl);
+ }
+
+ PciIoDevice->Attributes &= (~Attributes);
+ Status = EFI_SUCCESS;
+
+ }
+
+ if (EFI_ERROR (Status)) {
+ ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoGetBarAttributes (
+ IN EFI_PCI_IO_PROTOCOL * This,
+ IN UINT8 BarIndex,
+ OUT UINT64 *Supports, OPTIONAL
+ OUT VOID **Resources OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: BarIndex - add argument and description to function comment
+// TODO: Supports - add argument and description to function comment
+// TODO: Resources - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ UINT8 *Configuration;
+ UINT8 NumConfig;
+ PCI_IO_DEVICE *PciIoDevice;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
+ EFI_ACPI_END_TAG_DESCRIPTOR *PtrEnd;
+
+ NumConfig = 0;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ if (Supports == NULL && Resources == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BarIndex >= PCI_MAX_BAR) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // This driver does not support modifications to the WRITE_COMBINE or
+ // CACHED attributes for BAR ranges.
+ //
+ if (Supports != NULL) {
+ *Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;
+ }
+
+ if (Resources != NULL) {
+
+ if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeUnknown) {
+ NumConfig = 1;
+ }
+
+ Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
+ if (Configuration == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ZeroMem (
+ Configuration,
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
+ );
+
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
+
+ if (NumConfig == 1) {
+ Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
+
+ Ptr->AddrRangeMin = PciIoDevice->PciBar[BarIndex].BaseAddress;
+ Ptr->AddrLen = PciIoDevice->PciBar[BarIndex].Length;
+ Ptr->AddrRangeMax = PciIoDevice->PciBar[BarIndex].Alignment;
+
+ switch (PciIoDevice->PciBar[BarIndex].BarType) {
+ case PciBarTypeIo16:
+ case PciBarTypeIo32:
+ //
+ // Io
+ //
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
+ break;
+
+ case PciBarTypeMem32:
+ //
+ // Mem
+ //
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ //
+ // 32 bit
+ //
+ Ptr->AddrSpaceGranularity = 32;
+ break;
+
+ case PciBarTypePMem32:
+ //
+ // Mem
+ //
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ //
+ // prefechable
+ //
+ Ptr->SpecificFlag = 0x6;
+ //
+ // 32 bit
+ //
+ Ptr->AddrSpaceGranularity = 32;
+ break;
+
+ case PciBarTypeMem64:
+ //
+ // Mem
+ //
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ //
+ // 64 bit
+ //
+ Ptr->AddrSpaceGranularity = 64;
+ break;
+
+ case PciBarTypePMem64:
+ //
+ // Mem
+ //
+ Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ //
+ // prefechable
+ //
+ Ptr->SpecificFlag = 0x6;
+ //
+ // 64 bit
+ //
+ Ptr->AddrSpaceGranularity = 64;
+ break;
+
+ default:
+ break;
+ }
+
+ Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
+ }
+
+ //
+ // put the checksum
+ //
+ PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) ((UINT8 *) Ptr);
+ PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
+ PtrEnd->Checksum = 0;
+
+ *Resources = Configuration;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PciIoSetBarAttributes (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN UINT8 BarIndex,
+ IN OUT UINT64 *Offset,
+ IN OUT UINT64 *Length
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Attributes - add argument and description to function comment
+// TODO: BarIndex - add argument and description to function comment
+// TODO: Offset - add argument and description to function comment
+// TODO: Length - add argument and description to function comment
+// TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_IO_DEVICE *PciIoDevice;
+ UINT64 NonRelativeOffset;
+ UINT64 Supports;
+
+ PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
+
+ //
+ // Make sure Offset and Length are not NULL
+ //
+ if (Offset == NULL || Length == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // This driver does not support setting the WRITE_COMBINE or the CACHED attributes.
+ // If Attributes is not 0, then return EFI_UNSUPPORTED.
+ //
+ Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;
+
+ if (Attributes != (Attributes & Supports)) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Attributes must be supported. Make sure the BAR range describd by BarIndex, Offset, and
+ // Length are valid for this PCI device.
+ //
+ NonRelativeOffset = *Offset;
+ Status = PciIoVerifyBarAccess (
+ PciIoDevice,
+ BarIndex,
+ PciBarTypeMem,
+ EfiPciIoWidthUint8,
+ (UINT32) *Length,
+ &NonRelativeOffset
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+UpStreamBridgesAttributes (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
+ IN UINT64 Attributes
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: Operation - add argument and description to function comment
+// TODO: Attributes - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_IO_DEVICE *Parent;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ Parent = PciIoDevice->Parent;
+
+ while (Parent && IS_PCI_BRIDGE (&Parent->Pci)) {
+
+ //
+ // Get the PciIo Protocol
+ //
+ PciIo = &Parent->PciIo;
+
+ PciIo->Attributes (PciIo, Operation, Attributes, NULL);
+
+ Parent = Parent->Parent;
+ }
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+PciDevicesOnTheSamePath (
+ IN PCI_IO_DEVICE *PciDevice1,
+ IN PCI_IO_DEVICE *PciDevice2
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciDevice1 - add argument and description to function comment
+// TODO: PciDevice2 - add argument and description to function comment
+{
+
+ if (PciDevice1->Parent == PciDevice2->Parent) {
+ return TRUE;
+ }
+
+ if (PciDevice1->BusNumber > PciDevice2->BusNumber) {
+ return PciDeviceExisted (PciDevice1->Parent, PciDevice2);
+ }
+
+ return PciDeviceExisted (PciDevice2->Parent, PciDevice1);
+}
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciIo.h b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciIo.h
new file mode 100644
index 0000000..5733f59
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciIo.h
@@ -0,0 +1,773 @@
+/*++
+
+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:
+
+ PciIo.h
+
+Abstract:
+
+ PCI Bus Driver
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_IO_PROTOCOL_H
+#define _EFI_PCI_IO_PROTOCOL_H
+
+EFI_STATUS
+InitializePciIoInstance (
+ PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciIoVerifyBarAccess (
+ PCI_IO_DEVICE *PciIoDevice,
+ UINT8 BarIndex,
+ PCI_BAR_TYPE Type,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINTN Count,
+ UINT64 *Offset
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+ BarIndex - TODO: add argument description
+ Type - TODO: add argument description
+ Width - TODO: add argument description
+ Count - TODO: add argument description
+ Offset - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciIoVerifyConfigAccess (
+ PCI_IO_DEVICE *PciIoDevice,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINTN Count,
+ IN UINT64 *Offset
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+ Width - TODO: add argument description
+ Count - TODO: add argument description
+ Offset - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoPollMem (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Width - TODO: add argument description
+ BarIndex - TODO: add argument description
+ Offset - TODO: add argument description
+ Mask - TODO: add argument description
+ Value - TODO: add argument description
+ Delay - TODO: add argument description
+ Result - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoPollIo (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Width - TODO: add argument description
+ BarIndex - TODO: add argument description
+ Offset - TODO: add argument description
+ Mask - TODO: add argument description
+ Value - TODO: add argument description
+ Delay - TODO: add argument description
+ Result - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoMemRead (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Width - TODO: add argument description
+ BarIndex - TODO: add argument description
+ Offset - TODO: add argument description
+ Count - TODO: add argument description
+ Buffer - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoMemWrite (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Width - TODO: add argument description
+ BarIndex - TODO: add argument description
+ Offset - TODO: add argument description
+ Count - TODO: add argument description
+ Buffer - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoIoRead (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Width - TODO: add argument description
+ BarIndex - TODO: add argument description
+ Offset - TODO: add argument description
+ Count - TODO: add argument description
+ Buffer - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoIoWrite (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 BarIndex,
+ IN UINT64 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Width - TODO: add argument description
+ BarIndex - TODO: add argument description
+ Offset - TODO: add argument description
+ Count - TODO: add argument description
+ Buffer - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoConfigRead (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT32 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Width - TODO: add argument description
+ Offset - TODO: add argument description
+ Count - TODO: add argument description
+ Buffer - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoConfigWrite (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT32 Offset,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Width - TODO: add argument description
+ Offset - TODO: add argument description
+ Count - TODO: add argument description
+ Buffer - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoCopyMem (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_WIDTH Width,
+ IN UINT8 DestBarIndex,
+ IN UINT64 DestOffset,
+ IN UINT8 SrcBarIndex,
+ IN UINT64 SrcOffset,
+ IN UINTN Count
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Width - TODO: add argument description
+ DestBarIndex - TODO: add argument description
+ DestOffset - TODO: add argument description
+ SrcBarIndex - TODO: add argument description
+ SrcOffset - TODO: add argument description
+ Count - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoMap (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_PCI_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Operation - TODO: add argument description
+ HostAddress - TODO: add argument description
+ NumberOfBytes - TODO: add argument description
+ DeviceAddress - TODO: add argument description
+ Mapping - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoUnmap (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Mapping - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoAllocateBuffer (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Type - TODO: add argument description
+ MemoryType - TODO: add argument description
+ Pages - TODO: add argument description
+ HostAddress - TODO: add argument description
+ Attributes - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoFreeBuffer (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ IN VOID *HostAddress
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Pages - TODO: add argument description
+ HostAddress - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoFlush (
+ IN EFI_PCI_IO_PROTOCOL *This
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoGetLocation (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ OUT UINTN *Segment,
+ OUT UINTN *Bus,
+ OUT UINTN *Device,
+ OUT UINTN *Function
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Segment - TODO: add argument description
+ Bus - TODO: add argument description
+ Device - TODO: add argument description
+ Function - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+CheckBarType (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ UINT8 BarIndex,
+ PCI_BAR_TYPE BarType
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+ BarIndex - TODO: add argument description
+ BarType - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+ModifyRootBridgeAttributes (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN UINT64 Attributes,
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+ Attributes - TODO: add argument description
+ Operation - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+SupportPaletteSnoopAttributes (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+ Operation - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoAttributes (
+ IN EFI_PCI_IO_PROTOCOL * This,
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
+ IN UINT64 Attributes,
+ OUT UINT64 *Result OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Operation - TODO: add argument description
+ Attributes - TODO: add argument description
+ Result - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoGetBarAttributes (
+ IN EFI_PCI_IO_PROTOCOL * This,
+ IN UINT8 BarIndex,
+ OUT UINT64 *Supports, OPTIONAL
+ OUT VOID **Resources OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ BarIndex - TODO: add argument description
+ Supports - TODO: add argument description
+ Resources - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+EFIAPI
+PciIoSetBarAttributes (
+ IN EFI_PCI_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN UINT8 BarIndex,
+ IN OUT UINT64 *Offset,
+ IN OUT UINT64 *Length
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ Attributes - TODO: add argument description
+ BarIndex - TODO: add argument description
+ Offset - TODO: add argument description
+ Length - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+UpStreamBridgesAttributes (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation,
+ IN UINT64 Attributes
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+ Operation - TODO: add argument description
+ Attributes - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+PciDevicesOnTheSamePath (
+ IN PCI_IO_DEVICE *PciDevice1,
+ IN PCI_IO_DEVICE *PciDevice2
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciDevice1 - TODO: add argument description
+ PciDevice2 - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciLib.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciLib.c
new file mode 100644
index 0000000..11a0c29
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciLib.c
@@ -0,0 +1,1398 @@
+/*++
+
+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:
+
+ PciLib.c
+
+Abstract:
+
+ PCI Bus Driver Lib file
+ It abstracts some functions that can be different
+ between light PCI bus driver and full PCI bus driver
+
+Revision History
+
+--*/
+
+#include "pcibus.h"
+
+EFI_PCI_HOTPLUG_REQUEST_PROTOCOL gPciHotPlugRequest = {
+ PciHotPlugRequestNotify
+};
+
+
+VOID
+InstallHotPlugRequestProtocol (
+ IN EFI_STATUS *Status
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+ Status - A pointer to the status.
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_HANDLE Handle;
+
+ Handle = NULL;
+ *Status = gBS->InstallProtocolInterface (
+ &Handle,
+ &gEfiPciHotPlugRequestProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &gPciHotPlugRequest
+ );
+}
+
+VOID
+InstallPciHotplugGuid (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+ PciIoDevice - A pointer to the PCI_IO_DEVICE.
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+
+ if (IS_CARDBUS_BRIDGE (&PciIoDevice->Parent->Pci)) {
+
+ Status = gBS->InstallProtocolInterface (
+ &PciIoDevice->Handle,
+ &gEfiPciHotplugDeviceGuid,
+ EFI_NATIVE_INTERFACE,
+ NULL
+ );
+ }
+}
+
+VOID
+UninstallPciHotplugGuid (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+ PciIoDevice - A pointer to the PCI_IO_DEVICE.
+
+Returns:
+
+ None
+
+--*/
+{
+ EFI_STATUS Status;
+
+ Status = gBS->OpenProtocol (
+ PciIoDevice->Handle,
+ &gEfiPciHotplugDeviceGuid,
+ NULL,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // This may triger CardBus driver to stop for
+ // Pccard devices opened the GUID via BY_DRIVER
+ //
+ Status = gBS->UninstallProtocolInterface (
+ PciIoDevice->Handle,
+ &gEfiPciHotplugDeviceGuid,
+ NULL
+ );
+ }
+}
+
+VOID
+GetBackPcCardBar (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+ PciIoDevice - A pointer to the PCI_IO_DEVICE.
+
+Returns:
+
+ None
+
+--*/
+{
+ UINT32 Address;
+
+ //
+ // Read PciBar information from the bar register
+ //
+ if (!gFullEnumeration) {
+
+ Address = 0;
+ PciIoDevice->PciIo.Pci.Read (
+ &(PciIoDevice->PciIo),
+ EfiPciIoWidthUint32,
+ 0x1c,
+ 1,
+ &Address
+ );
+
+ (PciIoDevice->PciBar)[P2C_MEM_1].BaseAddress = (UINT64) (Address);
+ (PciIoDevice->PciBar)[P2C_MEM_1].Length = 0x2000000;
+ (PciIoDevice->PciBar)[P2C_MEM_1].BarType = PciBarTypeMem32;
+
+ Address = 0;
+ PciIoDevice->PciIo.Pci.Read (
+ &(PciIoDevice->PciIo),
+ EfiPciIoWidthUint32,
+ 0x20,
+ 1,
+ &Address
+ );
+ (PciIoDevice->PciBar)[P2C_MEM_2].BaseAddress = (UINT64) (Address);
+ (PciIoDevice->PciBar)[P2C_MEM_2].Length = 0x2000000;
+ (PciIoDevice->PciBar)[P2C_MEM_2].BarType = PciBarTypePMem32;
+
+ Address = 0;
+ PciIoDevice->PciIo.Pci.Read (
+ &(PciIoDevice->PciIo),
+ EfiPciIoWidthUint32,
+ 0x2c,
+ 1,
+ &Address
+ );
+ (PciIoDevice->PciBar)[P2C_IO_1].BaseAddress = (UINT64) (Address);
+ (PciIoDevice->PciBar)[P2C_IO_1].Length = 0x100;
+ (PciIoDevice->PciBar)[P2C_IO_1].BarType = PciBarTypeIo16;
+
+ Address = 0;
+ PciIoDevice->PciIo.Pci.Read (
+ &(PciIoDevice->PciIo),
+ EfiPciIoWidthUint32,
+ 0x34,
+ 1,
+ &Address
+ );
+ (PciIoDevice->PciBar)[P2C_IO_2].BaseAddress = (UINT64) (Address);
+ (PciIoDevice->PciBar)[P2C_IO_2].Length = 0x100;
+ (PciIoDevice->PciBar)[P2C_IO_2].BarType = PciBarTypeIo16;
+
+ }
+
+ if (gPciHotPlugInit != NULL) {
+ GetResourcePaddingForHpb (PciIoDevice);
+ }
+}
+
+EFI_STATUS
+RemoveRejectedPciDevices (
+ EFI_HANDLE RootBridgeHandle,
+ IN PCI_IO_DEVICE *Bridge
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+ RootBridgeHandle - An efi handle.
+ Bridge - An pointer to the PCI_IO_DEVICE.
+
+Returns:
+
+ None
+
+--*/
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_IO_DEVICE *Temp;
+ LIST_ENTRY *CurrentLink;
+ LIST_ENTRY *LastLink;
+
+ CurrentLink = Bridge->ChildList.ForwardLink;
+
+ while (CurrentLink && CurrentLink != &Bridge->ChildList) {
+
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+ if (IS_PCI_BRIDGE (&Temp->Pci)) {
+ //
+ // Remove rejected devices recusively
+ //
+ RemoveRejectedPciDevices (RootBridgeHandle, Temp);
+ } else {
+ //
+ // Skip rejection for all PPBs, while detect rejection for others
+ //
+ if (IsPciDeviceRejected (Temp)) {
+
+ //
+ // For P2C, remove all devices on it
+ //
+
+ if (!IsListEmpty (&Temp->ChildList)) {
+ RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp);
+ }
+
+ //
+ // Finally remove itself
+ //
+
+ LastLink = CurrentLink->BackLink;
+ RemoveEntryList (CurrentLink);
+ FreePciDevice (Temp);
+
+ CurrentLink = LastLink;
+ }
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciHostBridgeResourceAllocator (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+ )
+/*++
+
+Routine Description:
+
+ Host brige resource allocator.
+
+Arguments:
+
+ PciResAlloc - A pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
+
+Returns:
+
+ EFI Status.
+
+--*/
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_IO_DEVICE *RootBridgeDev;
+ EFI_HANDLE RootBridgeHandle;
+ VOID *AcpiConfig;
+ EFI_STATUS Status;
+ UINT64 IoBase;
+ UINT64 Mem32Base;
+ UINT64 PMem32Base;
+ UINT64 Mem64Base;
+ UINT64 PMem64Base;
+ UINT64 IoResStatus;
+ UINT64 Mem32ResStatus;
+ UINT64 PMem32ResStatus;
+ UINT64 Mem64ResStatus;
+ UINT64 PMem64ResStatus;
+ UINT64 MaxOptionRomSize;
+ PCI_RESOURCE_NODE *IoBridge;
+ PCI_RESOURCE_NODE *Mem32Bridge;
+ PCI_RESOURCE_NODE *PMem32Bridge;
+ PCI_RESOURCE_NODE *Mem64Bridge;
+ PCI_RESOURCE_NODE *PMem64Bridge;
+ PCI_RESOURCE_NODE IoPool;
+ PCI_RESOURCE_NODE Mem32Pool;
+ PCI_RESOURCE_NODE PMem32Pool;
+ PCI_RESOURCE_NODE Mem64Pool;
+ PCI_RESOURCE_NODE PMem64Pool;
+ BOOLEAN ReAllocate;
+ REPORT_STATUS_CODE_LIBRARY_DEVICE_HANDLE_EXTENDED_DATA HandleExtendedData;
+ REPORT_STATUS_CODE_LIBRARY_RESOURCE_ALLOC_FAILURE_ERROR_DATA AllocFailExtendedData;
+
+ //
+ // Reallocate flag
+ //
+ ReAllocate = FALSE;
+
+ //
+ // It will try several times if the resource allocation fails
+ //
+ while (TRUE) {
+
+ //
+ // Initialize resource pool
+ //
+ InitializeResourcePool (&IoPool, PciBarTypeIo16);
+ InitializeResourcePool (&Mem32Pool, PciBarTypeMem32);
+ InitializeResourcePool (&PMem32Pool, PciBarTypePMem32);
+ InitializeResourcePool (&Mem64Pool, PciBarTypeMem64);
+ InitializeResourcePool (&PMem64Pool, PciBarTypePMem64);
+
+ RootBridgeDev = NULL;
+ RootBridgeHandle = 0;
+
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+
+ //
+ // Get RootBridg Device by handle
+ //
+ RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
+
+ if (RootBridgeDev == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Create the entire system resource map from the information collected by
+ // enumerator. Several resource tree was created
+ //
+
+ IoBridge = CreateResourceNode (
+ RootBridgeDev,
+ 0,
+ 0xFFF,
+ 0,
+ PciBarTypeIo16,
+ PciResUsageTypical
+ );
+
+ Mem32Bridge = CreateResourceNode (
+ RootBridgeDev,
+ 0,
+ 0xFFFFF,
+ 0,
+ PciBarTypeMem32,
+ PciResUsageTypical
+ );
+
+ PMem32Bridge = CreateResourceNode (
+ RootBridgeDev,
+ 0,
+ 0xFFFFF,
+ 0,
+ PciBarTypePMem32,
+ PciResUsageTypical
+ );
+
+ Mem64Bridge = CreateResourceNode (
+ RootBridgeDev,
+ 0,
+ 0xFFFFF,
+ 0,
+ PciBarTypeMem64,
+ PciResUsageTypical
+ );
+
+ PMem64Bridge = CreateResourceNode (
+ RootBridgeDev,
+ 0,
+ 0xFFFFF,
+ 0,
+ PciBarTypePMem64,
+ PciResUsageTypical
+ );
+
+ //
+ // Create resourcemap by going through all the devices subject to this root bridge
+ //
+ Status = CreateResourceMap (
+ RootBridgeDev,
+ IoBridge,
+ Mem32Bridge,
+ PMem32Bridge,
+ Mem64Bridge,
+ PMem64Bridge
+ );
+
+ //
+ // Get the max ROM size that the root bridge can process
+ //
+ RootBridgeDev->RomSize = Mem32Bridge->Length;
+
+ //
+ // Skip to enlarge the resource request during realloction
+ //
+ if (!ReAllocate) {
+ //
+ // Get Max Option Rom size for current root bridge
+ //
+ MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);
+
+ //
+ // Enlarger the mem32 resource to accomdate the option rom
+ // if the mem32 resource is not enough to hold the rom
+ //
+ if (MaxOptionRomSize > Mem32Bridge->Length) {
+
+ Mem32Bridge->Length = MaxOptionRomSize;
+ RootBridgeDev->RomSize = MaxOptionRomSize;
+
+ //
+ // Alignment should be adjusted as well
+ //
+ if (Mem32Bridge->Alignment < MaxOptionRomSize - 1) {
+ Mem32Bridge->Alignment = MaxOptionRomSize - 1;
+ }
+ }
+ }
+
+ //
+ // Based on the all the resource tree, contruct ACPI resource node to
+ // submit the resource aperture to pci host bridge protocol
+ //
+ Status = ConstructAcpiResourceRequestor (
+ RootBridgeDev,
+ IoBridge,
+ Mem32Bridge,
+ PMem32Bridge,
+ Mem64Bridge,
+ PMem64Bridge,
+ &AcpiConfig
+ );
+
+ //
+ // Insert these resource nodes into the database
+ //
+ InsertResourceNode (&IoPool, IoBridge);
+ InsertResourceNode (&Mem32Pool, Mem32Bridge);
+ InsertResourceNode (&PMem32Pool, PMem32Bridge);
+ InsertResourceNode (&Mem64Pool, Mem64Bridge);
+ InsertResourceNode (&PMem64Pool, PMem64Bridge);
+
+ if (Status == EFI_SUCCESS) {
+ //
+ // Submit the resource requirement
+ //
+ Status = PciResAlloc->SubmitResources (
+ PciResAlloc,
+ RootBridgeDev->Handle,
+ AcpiConfig
+ );
+ }
+
+ //
+ // Free acpi resource node
+ //
+ if (AcpiConfig != NULL) {
+ gBS->FreePool (AcpiConfig);
+ }
+
+ if (EFI_ERROR (Status)) {
+ //
+ // Destroy all the resource tree
+ //
+ DestroyResourceTree (&IoPool);
+ DestroyResourceTree (&Mem32Pool);
+ DestroyResourceTree (&PMem32Pool);
+ DestroyResourceTree (&Mem64Pool);
+ DestroyResourceTree (&PMem64Pool);
+ return Status;
+ }
+ }
+
+ //
+ // Notify pci bus driver starts to program the resource
+ //
+
+ Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Allocation succeed, then continue the following
+ //
+ break;
+ }
+
+ //
+ // If the resource allocation is unsuccessful, free resources on bridge
+ //
+
+ RootBridgeDev = NULL;
+ RootBridgeHandle = 0;
+
+ IoResStatus = EFI_RESOURCE_SATISFIED;
+ Mem32ResStatus = EFI_RESOURCE_SATISFIED;
+ PMem32ResStatus = EFI_RESOURCE_SATISFIED;
+ Mem64ResStatus = EFI_RESOURCE_SATISFIED;
+ PMem64ResStatus = EFI_RESOURCE_SATISFIED;
+
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+ //
+ // Get RootBridg Device by handle
+ //
+ RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
+ if (RootBridgeDev == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Get host bridge handle for status report
+ //
+ HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;
+
+ //
+ // Get acpi resource node for all the resource types
+ //
+ AcpiConfig = NULL;
+
+ Status = PciResAlloc->GetProposedResources (
+ PciResAlloc,
+ RootBridgeDev->Handle,
+ &AcpiConfig
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (AcpiConfig != NULL) {
+ //
+ // Adjust resource allocation policy for each RB
+ //
+ GetResourceAllocationStatus (
+ AcpiConfig,
+ &IoResStatus,
+ &Mem32ResStatus,
+ &PMem32ResStatus,
+ &Mem64ResStatus,
+ &PMem64ResStatus
+ );
+ gBS->FreePool (AcpiConfig);
+ }
+ }
+ //
+ // End while
+ //
+
+ //
+ // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
+ //
+ //
+ // It is very difficult to follow the spec here
+ // Device path , Bar index can not be get here
+ //
+ ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));
+
+ REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
+ EFI_PROGRESS_CODE,
+ EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,
+ (VOID *) &AllocFailExtendedData,
+ sizeof (AllocFailExtendedData)
+ );
+
+ Status = PciHostBridgeAdjustAllocation (
+ &IoPool,
+ &Mem32Pool,
+ &PMem32Pool,
+ &Mem64Pool,
+ &PMem64Pool,
+ IoResStatus,
+ Mem32ResStatus,
+ PMem32ResStatus,
+ Mem64ResStatus,
+ PMem64ResStatus
+ );
+
+ //
+ // Destroy all the resource tree
+ //
+ DestroyResourceTree (&IoPool);
+ DestroyResourceTree (&Mem32Pool);
+ DestroyResourceTree (&PMem32Pool);
+ DestroyResourceTree (&Mem64Pool);
+ DestroyResourceTree (&PMem64Pool);
+
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeFreeResources);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ReAllocate = TRUE;
+
+ }
+ //
+ // End main while
+ //
+
+ //
+ // Raise the EFI_IOB_PCI_RES_ALLOC status code
+ //
+ REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
+ EFI_PROGRESS_CODE,
+ EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_RES_ALLOC,
+ (VOID *) &HandleExtendedData,
+ sizeof (HandleExtendedData)
+ );
+
+ //
+ // Notify pci bus driver starts to program the resource
+ //
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);
+
+ RootBridgeDev = NULL;
+
+ RootBridgeHandle = 0;
+
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+
+ //
+ // Get RootBridg Device by handle
+ //
+ RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
+
+ if (RootBridgeDev == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Get acpi resource node for all the resource types
+ //
+ AcpiConfig = NULL;
+ Status = PciResAlloc->GetProposedResources (
+ PciResAlloc,
+ RootBridgeDev->Handle,
+ &AcpiConfig
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get the resource base by interpreting acpi resource node
+ //
+ //
+ GetResourceBase (
+ AcpiConfig,
+ &IoBase,
+ &Mem32Base,
+ &PMem32Base,
+ &Mem64Base,
+ &PMem64Base
+ );
+
+ //
+ // Process option rom for this root bridge
+ //
+ Status = ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize);
+
+ //
+ // Create the entire system resource map from the information collected by
+ // enumerator. Several resource tree was created
+ //
+ Status = GetResourceMap (
+ RootBridgeDev,
+ &IoBridge,
+ &Mem32Bridge,
+ &PMem32Bridge,
+ &Mem64Bridge,
+ &PMem64Bridge,
+ &IoPool,
+ &Mem32Pool,
+ &PMem32Pool,
+ &Mem64Pool,
+ &PMem64Pool
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Program IO resources
+ //
+ ProgramResource (
+ IoBase,
+ IoBridge
+ );
+
+ //
+ // Program Mem32 resources
+ //
+ ProgramResource (
+ Mem32Base,
+ Mem32Bridge
+ );
+
+ //
+ // Program PMem32 resources
+ //
+ ProgramResource (
+ PMem32Base,
+ PMem32Bridge
+ );
+
+ //
+ // Program Mem64 resources
+ //
+ ProgramResource (
+ Mem64Base,
+ Mem64Bridge
+ );
+
+ //
+ // Program PMem64 resources
+ //
+ ProgramResource (
+ PMem64Base,
+ PMem64Bridge
+ );
+
+ if (AcpiConfig != NULL) {
+ gBS->FreePool (AcpiConfig);
+ }
+ }
+
+ //
+ // Destroy all the resource tree
+ //
+ DestroyResourceTree (&IoPool);
+ DestroyResourceTree (&Mem32Pool);
+ DestroyResourceTree (&PMem32Pool);
+ DestroyResourceTree (&Mem64Pool);
+ DestroyResourceTree (&PMem64Pool);
+
+ //
+ // Notify the resource allocation phase is to end
+ //
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciScanBus (
+ IN PCI_IO_DEVICE *Bridge,
+ IN UINT8 StartBusNumber,
+ OUT UINT8 *SubBusNumber,
+ OUT UINT8 *PaddedBusRange
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to assign bus number to the given PCI bus system
+
+Arguments:
+
+ Bridge - A pointer to the PCI_IO_DEVICE structure.
+ StartBusNumber - The start bus number.
+ SubBusNumber - A pointer to the sub bus number.
+ PaddedBusRange - A pointer to the padded bus range.
+
+Returns:
+
+ None
+
+--*/
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ PCI_TYPE00 Pci;
+ UINT8 Device;
+ UINT8 Func;
+ UINT64 Address;
+ UINTN SecondBus;
+ UINT16 Register;
+ UINTN HpIndex;
+ PCI_IO_DEVICE *PciDevice;
+ EFI_EVENT Event;
+ EFI_HPC_STATE State;
+ UINT64 PciAddress;
+ EFI_HPC_PADDING_ATTRIBUTES Attributes;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
+ UINT16 BusRange;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+ BOOLEAN BusPadding;
+
+ PciRootBridgeIo = Bridge->PciRootBridgeIo;
+ SecondBus = 0;
+ Register = 0;
+ State = 0;
+ Attributes = 0;
+ BusRange = 0;
+
+ ResetAllPpbBusReg (Bridge, StartBusNumber);
+
+ for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
+ for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
+
+ //
+ // Check to see whether a pci device is present
+ //
+ Status = PciDevicePresent (
+ PciRootBridgeIo,
+ &Pci,
+ StartBusNumber,
+ Device,
+ Func
+ );
+
+ if (EFI_ERROR (Status)) {
+ if (Func == 0) {
+ //
+ // Skip sub functions, this is not a multi function device
+ //
+ Func = PCI_MAX_FUNC;
+ }
+
+ continue;
+ }
+
+ //
+ // Get the PCI device information
+ //
+ Status = PciSearchDevice (
+ Bridge,
+ &Pci,
+ StartBusNumber,
+ Device,
+ Func,
+ &PciDevice
+ );
+
+ ASSERT (!EFI_ERROR (Status));
+
+ PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);
+
+ if (!IS_PCI_BRIDGE (&Pci)) {
+ //
+ // PCI bridges will be called later
+ // Here just need for PCI device or PCI to cardbus controller
+ // EfiPciBeforeChildBusEnumeration for PCI Device Node
+ //
+ PreprocessController (
+ PciDevice,
+ PciDevice->BusNumber,
+ PciDevice->DeviceNumber,
+ PciDevice->FunctionNumber,
+ EfiPciBeforeChildBusEnumeration
+ );
+ }
+
+ //
+ // For Pci Hotplug controller devcie only
+ //
+ if (gPciHotPlugInit != NULL) {
+ //
+ // Check if it is a Hotplug PCI controller
+ //
+ if (IsRootPciHotPlugController (PciDevice->DevicePath, &HpIndex)) {
+
+ if (!gPciRootHpcData[HpIndex].Initialized) {
+
+ Status = CreateEventForHpc (HpIndex, &Event);
+
+ ASSERT (!EFI_ERROR (Status));
+
+ Status = gPciHotPlugInit->InitializeRootHpc (
+ gPciHotPlugInit,
+ gPciRootHpcPool[HpIndex].HpcDevicePath,
+ PciAddress,
+ Event,
+ &State
+ );
+
+ PreprocessController (
+ PciDevice,
+ PciDevice->BusNumber,
+ PciDevice->DeviceNumber,
+ PciDevice->FunctionNumber,
+ EfiPciBeforeChildBusEnumeration
+ );
+ continue;
+ }
+ }
+ }
+
+ if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) {
+ //
+ // For PPB
+ // Get the bridge information
+ //
+ BusPadding = FALSE;
+ if (gPciHotPlugInit != NULL) {
+
+ if (IsRootPciHotPlugBus (PciDevice->DevicePath, &HpIndex)) {
+
+ //
+ // If it is initialized, get the padded bus range
+ //
+ Status = gPciHotPlugInit->GetResourcePadding (
+ gPciHotPlugInit,
+ gPciRootHpcPool[HpIndex].HpbDevicePath,
+ PciAddress,
+ &State,
+ (VOID **) &Descriptors,
+ &Attributes
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ BusRange = 0;
+ Status = PciGetBusRange (
+ &Descriptors,
+ NULL,
+ NULL,
+ &BusRange
+ );
+
+ gBS->FreePool (Descriptors);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ BusPadding = TRUE;
+ }
+ }
+
+ (*SubBusNumber)++;
+ SecondBus = *SubBusNumber;
+
+ Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);
+ Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
+
+ Status = PciRootBridgeIo->Pci.Write (
+ PciRootBridgeIo,
+ EfiPciWidthUint16,
+ Address,
+ 1,
+ &Register
+ );
+
+
+ //
+ // If it is PPB, resursively search down this bridge
+ //
+ if (IS_PCI_BRIDGE (&Pci)) {
+
+ //
+ // Initialize SubBusNumber to Maximum bus number
+ //
+ Register = 0xFF;
+ Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
+ Status = PciRootBridgeIo->Pci.Write (
+ PciRootBridgeIo,
+ EfiPciWidthUint8,
+ Address,
+ 1,
+ &Register
+ );
+
+ //
+ // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige
+ //
+ PreprocessController (
+ PciDevice,
+ PciDevice->BusNumber,
+ PciDevice->DeviceNumber,
+ PciDevice->FunctionNumber,
+ EfiPciBeforeChildBusEnumeration
+ );
+
+ Status = PciScanBus (
+ PciDevice,
+ (UINT8) (SecondBus),
+ SubBusNumber,
+ PaddedBusRange
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ }
+
+ if (BusPadding) {
+ //
+ // Ensure the device is enabled and initialized
+ //
+ if ((Attributes == EfiPaddingPciRootBridge) &&
+ (State & EFI_HPC_STATE_ENABLED) &&
+ (State & EFI_HPC_STATE_INITIALIZED) ) {
+ *PaddedBusRange = (UINT8) ((UINT8) (BusRange) +*PaddedBusRange);
+ } else {
+ *SubBusNumber = (UINT8) ((UINT8) (BusRange) +*SubBusNumber);
+ }
+ }
+
+ //
+ // Set the current maximum bus number under the PPB
+ //
+ Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
+
+ Status = PciRootBridgeIo->Pci.Write (
+ PciRootBridgeIo,
+ EfiPciWidthUint8,
+ Address,
+ 1,
+ SubBusNumber
+ );
+ }
+
+ if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
+
+ //
+ // Skip sub functions, this is not a multi function device
+ //
+ Func = PCI_MAX_FUNC;
+ }
+
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciRootBridgeP2CProcess (
+ IN PCI_IO_DEVICE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ Process Option Rom on this host bridge
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ LIST_ENTRY *CurrentLink;
+ PCI_IO_DEVICE *Temp;
+ EFI_HPC_STATE State;
+ UINT64 PciAddress;
+ EFI_STATUS Status;
+
+ CurrentLink = Bridge->ChildList.ForwardLink;
+
+ while (CurrentLink && CurrentLink != &Bridge->ChildList) {
+
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+ if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {
+
+ if (gPciHotPlugInit && Temp->Allocated) {
+
+ //
+ // Raise the EFI_IOB_PCI_HPC_INIT status code
+ //
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+ EFI_PROGRESS_CODE,
+ EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_HPC_INIT,
+ Temp->DevicePath
+ );
+
+ PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);
+ Status = gPciHotPlugInit->InitializeRootHpc (
+ gPciHotPlugInit,
+ Temp->DevicePath,
+ PciAddress,
+ NULL,
+ &State
+ );
+
+ if (!EFI_ERROR (Status)) {
+ Status = PciBridgeEnumerator (Temp);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ continue;
+
+ }
+ }
+
+ if (!IsListEmpty (&Temp->ChildList)) {
+ Status = PciRootBridgeP2CProcess (Temp);
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciHostBridgeP2CProcess (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciResAlloc - add argument and description to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_HANDLE RootBridgeHandle;
+ PCI_IO_DEVICE *RootBridgeDev;
+ EFI_STATUS Status;
+
+ RootBridgeHandle = NULL;
+
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+
+ //
+ // Get RootBridg Device by handle
+ //
+ RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
+
+ if (RootBridgeDev == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = PciRootBridgeP2CProcess (RootBridgeDev);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciHostBridgeEnumerator (
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+ )
+/*++
+
+Routine Description:
+
+ This function is used to enumerate the entire host bridge
+ in a given platform
+
+Arguments:
+
+ PciResAlloc - A pointer to the resource allocate protocol.
+
+Returns:
+
+ None
+
+--*/
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_HANDLE RootBridgeHandle;
+ PCI_IO_DEVICE *RootBridgeDev;
+ EFI_STATUS Status;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+ UINT16 MinBus;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
+
+ InitializeHotPlugSupport ();
+
+ //
+ // Notify the bus allocation phase is about to start
+ //
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
+
+ RootBridgeHandle = NULL;
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+
+ //
+ // if a root bridge instance is found, create root bridge device for it
+ //
+
+ RootBridgeDev = CreateRootBridge (RootBridgeHandle);
+
+ if (RootBridgeDev == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Enumerate all the buses under this root bridge
+ //
+
+ Status = PciRootBridgeEnumerator (
+ PciResAlloc,
+ RootBridgeDev
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DestroyRootBridge (RootBridgeDev);
+
+ //
+ // Error proccess here
+ //
+ }
+
+ //
+ // Notify the bus allocation phase is finished for the first time
+ //
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);
+
+
+ if (gPciHotPlugInit != NULL) {
+ //
+ // Wait for all HPC initialized
+ //
+ Status = AllRootHPCInitialized (STALL_1_SECOND * 15);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Notify the bus allocation phase is about to start for the 2nd time
+ //
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
+
+ RootBridgeHandle = NULL;
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+
+ //
+ // if a root bridge instance is found, create root bridge device for it
+ //
+
+ RootBridgeDev = CreateRootBridge (RootBridgeHandle);
+
+ if (RootBridgeDev == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Enumerate all the buses under this root bridge
+ //
+
+ Status = PciRootBridgeEnumerator (
+ PciResAlloc,
+ RootBridgeDev
+ );
+
+ DestroyRootBridge (RootBridgeDev);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Notify the bus allocation phase is to end
+ //
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);
+ }
+
+ //
+ // Notify the resource allocation phase is to start
+ //
+ NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);
+
+ RootBridgeHandle = NULL;
+ while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
+
+ //
+ // if a root bridge instance is found, create root bridge device for it
+ //
+
+ RootBridgeDev = CreateRootBridge (RootBridgeHandle);
+
+ if (RootBridgeDev == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = StartManagingRootBridge (RootBridgeDev);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;
+ Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Determine root bridge attribute by calling interface of Pcihostbridge
+ // protocol
+ //
+ DetermineRootBridgeAttributes (
+ PciResAlloc,
+ RootBridgeDev
+ );
+
+ //
+ // Collect all the resource information under this root bridge
+ // A database that records all the information about pci device subject to this
+ // root bridge will then be created
+ //
+ Status = PciPciDeviceInfoCollector (
+ RootBridgeDev,
+ (UINT8) MinBus
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ InsertRootBridge (RootBridgeDev);
+
+ //
+ // Record the hostbridge handle
+ //
+ AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciLib.h b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciLib.h
new file mode 100644
index 0000000..1e89445
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciLib.h
@@ -0,0 +1,247 @@
+/*++
+
+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:
+
+ PciLib.h
+
+Abstract:
+
+ PCI Bus Driver Lib header file
+ It abstracts some functions that can be different
+ between light PCI bus driver and full PCI bus driver
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_LIB_H
+#define _EFI_PCI_LIB_H
+
+VOID
+InstallHotPlugRequestProtocol (
+ IN EFI_STATUS *Status
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Status - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+VOID
+InstallPciHotplugGuid (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+VOID
+UninstallPciHotplugGuid (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+VOID
+GetBackPcCardBar (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+RemoveRejectedPciDevices (
+ EFI_HANDLE RootBridgeHandle,
+ IN PCI_IO_DEVICE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ RootBridgeHandle - TODO: add argument description
+ Bridge - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciHostBridgeResourceAllocator (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciResAlloc - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciScanBus (
+ IN PCI_IO_DEVICE *Bridge,
+ IN UINT8 StartBusNumber,
+ OUT UINT8 *SubBusNumber,
+ OUT UINT8 *PaddedBusRange
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ StartBusNumber - TODO: add argument description
+ SubBusNumber - TODO: add argument description
+ PaddedBusRange - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciRootBridgeP2CProcess (
+ IN PCI_IO_DEVICE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciHostBridgeP2CProcess (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciResAlloc - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciHostBridgeEnumerator (
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciResAlloc - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciOptionRomSupport.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciOptionRomSupport.c
new file mode 100644
index 0000000..324ad62
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciOptionRomSupport.c
@@ -0,0 +1,543 @@
+/*++
+
+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:
+
+ PciOptionRomSupport.c
+
+Abstract:
+
+ PCI Bus Driver
+
+Revision History
+
+--*/
+
+#include "PciBus.h"
+#include "PciResourceSupport.h"
+
+EFI_STATUS
+GetOpRomInfo (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINT8 RomBarIndex;
+ UINT32 AllOnes;
+ UINT64 Address;
+ EFI_STATUS Status;
+ UINT8 Bus;
+ UINT8 Device;
+ UINT8 Function;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+
+ Bus = PciIoDevice->BusNumber;
+ Device = PciIoDevice->DeviceNumber;
+ Function = PciIoDevice->FunctionNumber;
+
+ PciRootBridgeIo = PciIoDevice->PciRootBridgeIo;
+
+ //
+ // offset is 48 if is not ppb
+ //
+
+ //
+ // 0x30
+ //
+ RomBarIndex = PCI_DEVICE_ROMBAR;
+
+ if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
+ //
+ // if is ppb
+ //
+
+ //
+ // 0x38
+ //
+ RomBarIndex = PCI_BRIDGE_ROMBAR;
+ }
+ //
+ // the bit0 is 0 to prevent the enabling of the Rom address decoder
+ //
+ AllOnes = 0xfffffffe;
+ Address = EFI_PCI_ADDRESS (Bus, Device, Function, RomBarIndex);
+
+ Status = PciRootBridgeIo->Pci.Write (
+ PciRootBridgeIo,
+ EfiPciWidthUint32,
+ Address,
+ 1,
+ &AllOnes
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // read back
+ //
+ Status = PciRootBridgeIo->Pci.Read (
+ PciRootBridgeIo,
+ EfiPciWidthUint32,
+ Address,
+ 1,
+ &AllOnes
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ AllOnes &= 0xFFFFFFFC;
+ if ((AllOnes == 0) || (AllOnes == 0xFFFFFFFC)) {
+ return EFI_NOT_FOUND;
+ }
+
+ PciIoDevice->RomSize = (UINT64) ((~AllOnes) + 1);
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+LoadOpRomImage (
+ IN PCI_IO_DEVICE *PciDevice,
+ IN UINT64 RomBase
+ )
+/*++
+
+Routine Description:
+
+ Load option rom image for specified PCI device
+
+Arguments:
+
+Returns:
+
+--*/
+// TODO: PciDevice - add argument and description to function comment
+// TODO: RomBase - add argument and description to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+{
+ UINT8 RomBarIndex;
+ UINT8 Indicator;
+ UINT16 OffsetPcir;
+ UINT32 RomBarOffset;
+ UINT32 RomBar;
+ UINT64 Temp;
+ EFI_STATUS retStatus;
+ BOOLEAN FirstCheck;
+ UINT8 *Image;
+ PCI_EXPANSION_ROM_HEADER *RomHeader;
+ PCI_DATA_STRUCTURE *RomPcir;
+ UINT64 RomSize;
+ UINT64 RomImageSize;
+ UINT8 *RomInMemory;
+
+ RomSize = PciDevice->RomSize;
+
+ Indicator = 0;
+ RomImageSize = 0;
+ RomInMemory = NULL;
+ Temp = 0;
+
+ //
+ // Get the RomBarIndex
+ //
+
+ //
+ // 0x30
+ //
+ RomBarIndex = PCI_DEVICE_ROMBAR;
+ if (IS_PCI_BRIDGE (&(PciDevice->Pci))) {
+ //
+ // if is ppb
+ //
+
+ //
+ // 0x38
+ //
+ RomBarIndex = PCI_BRIDGE_ROMBAR;
+ }
+ //
+ // Allocate memory for Rom header and PCIR
+ //
+ RomHeader = AllocatePool (sizeof (PCI_EXPANSION_ROM_HEADER));
+ if (RomHeader == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ RomPcir = AllocatePool (sizeof (PCI_DATA_STRUCTURE));
+ if (RomPcir == NULL) {
+ gBS->FreePool (RomHeader);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ RomBar = (UINT32) RomBase;
+
+ //
+ // Enable RomBar
+ //
+ RomDecode (PciDevice, RomBarIndex, RomBar, TRUE);
+
+ RomBarOffset = RomBar;
+ retStatus = EFI_NOT_FOUND;
+ FirstCheck = TRUE;
+
+ do {
+ PciDevice->PciRootBridgeIo->Mem.Read (
+ PciDevice->PciRootBridgeIo,
+ EfiPciWidthUint8,
+ RomBarOffset,
+ sizeof (PCI_EXPANSION_ROM_HEADER),
+ (UINT8 *) RomHeader
+ );
+
+ if (RomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
+ RomBarOffset = RomBarOffset + 512;
+ if (FirstCheck) {
+ break;
+ } else {
+ RomImageSize = RomImageSize + 512;
+ continue;
+ }
+ }
+
+ FirstCheck = FALSE;
+ OffsetPcir = RomHeader->PcirOffset;
+ PciDevice->PciRootBridgeIo->Mem.Read (
+ PciDevice->PciRootBridgeIo,
+ EfiPciWidthUint8,
+ RomBarOffset + OffsetPcir,
+ sizeof (PCI_DATA_STRUCTURE),
+ (UINT8 *) RomPcir
+ );
+ Indicator = RomPcir->Indicator;
+ RomImageSize = RomImageSize + RomPcir->ImageLength * 512;
+ RomBarOffset = RomBarOffset + RomPcir->ImageLength * 512;
+ } while (((Indicator & 0x80) == 0x00) && ((RomBarOffset - RomBar) < RomSize));
+
+ if (RomImageSize > 0) {
+ retStatus = EFI_SUCCESS;
+ Image = AllocatePool ((UINT32) RomImageSize);
+ if (Image == NULL) {
+ RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);
+ gBS->FreePool (RomHeader);
+ gBS->FreePool (RomPcir);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Copy Rom image into memory
+ //
+ PciDevice->PciRootBridgeIo->Mem.Read (
+ PciDevice->PciRootBridgeIo,
+ EfiPciWidthUint8,
+ RomBar,
+ (UINT32) RomImageSize,
+ Image
+ );
+ RomInMemory = Image;
+ }
+
+ RomDecode (PciDevice, RomBarIndex, RomBar, FALSE);
+
+ PciDevice->PciIo.RomSize = RomImageSize;
+ PciDevice->PciIo.RomImage = RomInMemory;
+
+ PciRomAddImageMapping (
+ NULL,
+ PciDevice->PciRootBridgeIo->SegmentNumber,
+ PciDevice->BusNumber,
+ PciDevice->DeviceNumber,
+ PciDevice->FunctionNumber,
+ (UINT64) (UINTN) PciDevice->PciIo.RomImage,
+ PciDevice->PciIo.RomSize
+ );
+
+ //
+ // Free allocated memory
+ //
+ gBS->FreePool (RomHeader);
+ gBS->FreePool (RomPcir);
+
+ return retStatus;
+}
+
+EFI_STATUS
+RomDecode (
+ IN PCI_IO_DEVICE *PciDevice,
+ IN UINT8 RomBarIndex,
+ IN UINT32 RomBar,
+ IN BOOLEAN Enable
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+// TODO: PciDevice - add argument and description to function comment
+// TODO: RomBarIndex - add argument and description to function comment
+// TODO: RomBar - add argument and description to function comment
+// TODO: Enable - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINT32 Value32;
+ UINT32 Offset;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ PciIo = &PciDevice->PciIo;
+ if (Enable) {
+ //
+ // Clear all bars
+ //
+ for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) {
+ PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllZero);
+ }
+
+ //
+ // set the Rom base address: now is hardcode
+ // enable its decoder
+ //
+ Value32 = RomBar | 0x1;
+ PciIo->Pci.Write (
+ PciIo,
+ (EFI_PCI_IO_PROTOCOL_WIDTH) EfiPciWidthUint32,
+ RomBarIndex,
+ 1,
+ &Value32
+ );
+
+ //
+ // Programe all upstream bridge
+ //
+ ProgrameUpstreamBridgeForRom(PciDevice, RomBar, TRUE);
+
+ //
+ // Setting the memory space bit in the function's command register
+ //
+ PciEnableCommandRegister(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE);
+
+ } else {
+
+ //
+ // disable command register decode to memory
+ //
+ PciDisableCommandRegister(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE);
+
+ //
+ // Destroy the programmed bar in all the upstream bridge.
+ //
+ ProgrameUpstreamBridgeForRom(PciDevice, RomBar, FALSE);
+
+ //
+ // disable rom decode
+ //
+ Value32 = 0xFFFFFFFE;
+ PciIo->Pci.Write (
+ PciIo,
+ (EFI_PCI_IO_PROTOCOL_WIDTH) EfiPciWidthUint32,
+ RomBarIndex,
+ 1,
+ &Value32
+ );
+
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+ProcessOpRomImage (
+ PCI_IO_DEVICE *PciDevice
+ )
+/*++
+
+Routine Description:
+
+ Process the oprom image.
+
+Arguments:
+ PciDevice A pointer to a pci device.
+
+Returns:
+
+ EFI Status.
+
+--*/
+{
+ UINT8 Indicator;
+ UINT32 ImageSize;
+ UINT16 ImageOffset;
+ VOID *RomBar;
+ UINT8 *RomBarOffset;
+ EFI_HANDLE ImageHandle;
+ EFI_STATUS Status;
+ EFI_STATUS retStatus;
+ BOOLEAN FirstCheck;
+ BOOLEAN SkipImage;
+ UINT32 DestinationSize;
+ UINT32 ScratchSize;
+ UINT8 *Scratch;
+ VOID *ImageBuffer;
+ VOID *DecompressedImageBuffer;
+ UINT32 ImageLength;
+ EFI_DECOMPRESS_PROTOCOL *Decompress;
+ EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;
+ PCI_DATA_STRUCTURE *Pcir;
+
+ Indicator = 0;
+
+ //
+ // Get the Address of the Rom image
+ //
+ RomBar = PciDevice->PciIo.RomImage;
+ RomBarOffset = (UINT8 *) RomBar;
+ retStatus = EFI_NOT_FOUND;
+ FirstCheck = TRUE;
+
+ do {
+ EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset;
+ if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
+ RomBarOffset = RomBarOffset + 512;
+ if (FirstCheck) {
+ break;
+ } else {
+ continue;
+ }
+ }
+
+ FirstCheck = FALSE;
+ Pcir = (PCI_DATA_STRUCTURE *) (RomBarOffset + EfiRomHeader->PcirOffset);
+ ImageSize = (UINT32) (Pcir->ImageLength * 512);
+ Indicator = Pcir->Indicator;
+
+ if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&
+ (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE)) {
+
+ if ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
+ (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)) {
+
+ ImageOffset = EfiRomHeader->EfiImageHeaderOffset;
+ ImageSize = (UINT32) (EfiRomHeader->InitializationSize * 512);
+
+ ImageBuffer = (VOID *) (RomBarOffset + ImageOffset);
+ ImageLength = ImageSize - (UINT32)ImageOffset;
+ DecompressedImageBuffer = NULL;
+
+ //
+ // decompress here if needed
+ //
+ SkipImage = FALSE;
+ if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
+ SkipImage = TRUE;
+ }
+
+ if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
+ Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);
+ if (EFI_ERROR (Status)) {
+ SkipImage = TRUE;
+ } else {
+ SkipImage = TRUE;
+ Status = Decompress->GetInfo (
+ Decompress,
+ ImageBuffer,
+ ImageLength,
+ &DestinationSize,
+ &ScratchSize
+ );
+ if (!EFI_ERROR (Status)) {
+ DecompressedImageBuffer = NULL;
+ DecompressedImageBuffer = AllocatePool (DestinationSize);
+ if (DecompressedImageBuffer != NULL) {
+ Scratch = AllocatePool (ScratchSize);
+ if (Scratch != NULL) {
+ Status = Decompress->Decompress (
+ Decompress,
+ ImageBuffer,
+ ImageLength,
+ DecompressedImageBuffer,
+ DestinationSize,
+ Scratch,
+ ScratchSize
+ );
+ if (!EFI_ERROR (Status)) {
+ ImageBuffer = DecompressedImageBuffer;
+ ImageLength = DestinationSize;
+ SkipImage = FALSE;
+ }
+
+ gBS->FreePool (Scratch);
+ }
+ }
+ }
+ }
+ }
+
+ if (!SkipImage) {
+ //
+ // load image and start image
+ //
+ Status = gBS->LoadImage (
+ FALSE,
+ gPciBusDriverBinding.DriverBindingHandle,
+ PciDevice->Handle,
+ ImageBuffer,
+ ImageLength,
+ &ImageHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->StartImage (ImageHandle, NULL, NULL);
+ if (!EFI_ERROR (Status)) {
+ AddDriver (PciDevice, ImageHandle);
+ PciRomAddImageMapping (
+ ImageHandle,
+ PciDevice->PciRootBridgeIo->SegmentNumber,
+ PciDevice->BusNumber,
+ PciDevice->DeviceNumber,
+ PciDevice->FunctionNumber,
+ (UINT64) (UINTN) PciDevice->PciIo.RomImage,
+ PciDevice->PciIo.RomSize
+ );
+ retStatus = EFI_SUCCESS;
+ }
+ }
+ }
+
+ RomBarOffset = RomBarOffset + ImageSize;
+ } else {
+ RomBarOffset = RomBarOffset + ImageSize;
+ }
+ } else {
+ RomBarOffset = RomBarOffset + ImageSize;
+ }
+
+ } while (((Indicator & 0x80) == 0x00) && ((UINTN) (RomBarOffset - (UINT8 *) RomBar) < PciDevice->RomSize));
+
+ return retStatus;
+
+}
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciOptionRomSupport.h b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciOptionRomSupport.h
new file mode 100644
index 0000000..2bb11bf
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciOptionRomSupport.h
@@ -0,0 +1,119 @@
+/*++
+
+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:
+
+ PciOptionRomSupport.h
+
+Abstract:
+
+ PCI Bus Driver
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_OP_ROM_SUPPORT_H
+#define _EFI_PCI_OP_ROM_SUPPORT_H
+
+EFI_STATUS
+GetOpRomInfo (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+LoadOpRomImage (
+ IN PCI_IO_DEVICE *PciDevice,
+ IN UINT64 RomBase
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciDevice - TODO: add argument description
+ RomBase - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+RomDecode (
+ IN PCI_IO_DEVICE *PciDevice,
+ IN UINT8 RomBarIndex,
+ IN UINT32 RomBar,
+ IN BOOLEAN Enable
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciDevice - TODO: add argument description
+ RomBarIndex - TODO: add argument description
+ RomBar - TODO: add argument description
+ Enable - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+ProcessOpRomImage (
+ PCI_IO_DEVICE *PciDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciPowerManagement.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciPowerManagement.c
new file mode 100644
index 0000000..1760c39
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciPowerManagement.c
@@ -0,0 +1,83 @@
+/*++
+
+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:
+
+ PciPowerManagement.c
+
+Abstract:
+
+ PCI Bus Driver
+
+Revision History
+
+--*/
+
+#include "Pcibus.h"
+
+EFI_STATUS
+ResetPowerManagementFeature (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ This function is intended to turn off PWE assertion and
+ put the device to D0 state if the device supports
+ PCI Power Management.
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ UINT8 PowerManagementRegBlock;
+ UINT16 PMCSR;
+
+ PowerManagementRegBlock = 0;
+
+ Status = LocateCapabilityRegBlock (
+ PciIoDevice,
+ EFI_PCI_CAPABILITY_ID_PMI,
+ &PowerManagementRegBlock,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Turn off the PWE assertion and put the device into D0 State
+ //
+ PMCSR = 0x8000;
+
+ //
+ // Write PMCSR
+ //
+ PciIoDevice->PciIo.Pci.Write (
+ &PciIoDevice->PciIo,
+ EfiPciIoWidthUint16,
+ PowerManagementRegBlock + 4,
+ 1,
+ &PMCSR
+ );
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciPowerManagement.h b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciPowerManagement.h
new file mode 100644
index 0000000..f33f7ab
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciPowerManagement.h
@@ -0,0 +1,48 @@
+/*++
+
+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:
+
+ PciPowerManagement.h
+
+Abstract:
+
+ PCI Bus Driver
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_POWER_MANAGEMENT_H
+#define _EFI_PCI_POWER_MANAGEMENT_H
+
+EFI_STATUS
+ResetPowerManagementFeature (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciResourceSupport.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciResourceSupport.c
new file mode 100644
index 0000000..8f89e89
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciResourceSupport.c
@@ -0,0 +1,2276 @@
+/*++
+
+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:
+
+ PciResourceSupport.c
+
+Abstract:
+
+ PCI Bus Driver
+
+Revision History
+
+--*/
+
+#include "PciBus.h"
+#include "PciResourceSupport.h"
+#include "PciCommand.h"
+
+EFI_STATUS
+SkipVGAAperture (
+ OUT UINT64 *Start,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:
+
+ The function is used to skip VGA range
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Start - add argument and description to function comment
+// TODO: Length - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINT64 Original;
+ UINT64 Mask;
+ UINT64 StartOffset;
+ UINT64 LimitOffset;
+
+ //
+ // For legacy VGA, bit 10 to bit 15 is not decoded
+ //
+ Mask = 0x3FF;
+
+ Original = *Start;
+ StartOffset = Original & Mask;
+ LimitOffset = ((*Start) + Length - 1) & Mask;
+ if (LimitOffset >= VGABASE1) {
+ *Start = *Start - StartOffset + VGALIMIT2 + 1;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SkipIsaAliasAperture (
+ OUT UINT64 *Start,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:
+
+ This function is used to skip ISA aliasing aperture
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Start - add argument and description to function comment
+// TODO: Length - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ UINT64 Original;
+ UINT64 Mask;
+ UINT64 StartOffset;
+ UINT64 LimitOffset;
+
+ //
+ // For legacy ISA, bit 10 to bit 15 is not decoded
+ //
+ Mask = 0x3FF;
+
+ Original = *Start;
+ StartOffset = Original & Mask;
+ LimitOffset = ((*Start) + Length - 1) & Mask;
+
+ if (LimitOffset >= ISABASE) {
+ *Start = *Start - StartOffset + ISALIMIT + 1;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+InsertResourceNode (
+ PCI_RESOURCE_NODE *Bridge,
+ PCI_RESOURCE_NODE *ResNode
+ )
+/*++
+
+Routine Description:
+
+ This function inserts a resource node into the resource list.
+ The resource list is sorted in descend order.
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: ResNode - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ LIST_ENTRY *CurrentLink;
+ PCI_RESOURCE_NODE *Temp;
+ UINT64 ResNodeAlignRest;
+ UINT64 TempAlignRest;
+
+ InsertHeadList (&Bridge->ChildList, &ResNode->Link);
+
+ CurrentLink = Bridge->ChildList.ForwardLink->ForwardLink;
+ while (CurrentLink != &Bridge->ChildList) {
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
+
+ if (ResNode->Alignment > Temp->Alignment) {
+ break;
+ } else if (ResNode->Alignment == Temp->Alignment) {
+ ResNodeAlignRest = ResNode->Length & ResNode->Alignment;
+ TempAlignRest = Temp->Length & Temp->Alignment;
+ if ((ResNodeAlignRest == 0) || (ResNodeAlignRest >= TempAlignRest)) {
+ break;
+ }
+ }
+
+ SwapListEntries (&ResNode->Link, CurrentLink);
+
+ CurrentLink = ResNode->Link.ForwardLink;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+MergeResourceTree (
+ PCI_RESOURCE_NODE *Dst,
+ PCI_RESOURCE_NODE *Res,
+ BOOLEAN TypeMerge
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to merge two different resource tree in need of
+ resoure degradation. For example, if a upstream PPB doesn't support,
+ prefetchable memory decoding, the PCI bus driver will choose to call this function
+ to merge prefectchable memory resource list into normal memory list.
+
+ If the TypeMerge is TRUE, Res resource type is changed to the type of destination resource
+ type.
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Dst - add argument and description to function comment
+// TODO: Res - add argument and description to function comment
+// TODO: TypeMerge - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ LIST_ENTRY *CurrentLink;
+ PCI_RESOURCE_NODE *Temp;
+
+ while (!IsListEmpty (&Res->ChildList)) {
+ CurrentLink = Res->ChildList.ForwardLink;
+
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
+
+ if (TypeMerge) {
+ Temp->ResType = Dst->ResType;
+ }
+
+ RemoveEntryList (CurrentLink);
+ InsertResourceNode (Dst, Temp);
+
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CalculateApertureIo16 (
+ IN PCI_RESOURCE_NODE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ This function is used to calculate the IO16 aperture
+ for a bridge.
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ UINT64 Aperture;
+ LIST_ENTRY *CurrentLink;
+ PCI_RESOURCE_NODE *Node;
+ UINT64 offset;
+
+ //
+ // Always assume there is ISA device and VGA device on the platform
+ // will be customized later
+ //
+ Aperture = 0;
+
+ if (!Bridge) {
+ return EFI_SUCCESS;
+ }
+
+ CurrentLink = Bridge->ChildList.ForwardLink;
+
+ //
+ // Assume the bridge is aligned
+ //
+ while (CurrentLink != &Bridge->ChildList) {
+
+ Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
+
+ //
+ // Consider the aperture alignment
+ //
+ offset = Aperture & (Node->Alignment);
+
+ if (offset) {
+
+ Aperture = Aperture + (Node->Alignment + 1) - offset;
+
+ }
+
+ //
+ // IsaEnable and VGAEnable can not be implemented now.
+ // If both of them are enabled, then the IO resource would
+ // become too limited to meet the requirement of most of devices.
+ //
+
+ Node->Offset = Aperture;
+
+ //
+ // Increment aperture by the length of node
+ //
+ Aperture += Node->Length;
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ //
+ // At last, adjust the aperture with the bridge's
+ // alignment
+ //
+ offset = Aperture & (Bridge->Alignment);
+
+ if (offset) {
+ Aperture = Aperture + (Bridge->Alignment + 1) - offset;
+ }
+
+ Bridge->Length = Aperture;
+ //
+ // At last, adjust the bridge's alignment to the first child's alignment
+ // if the bridge has at least one child
+ //
+ CurrentLink = Bridge->ChildList.ForwardLink;
+ if (CurrentLink != &Bridge->ChildList) {
+ Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
+ if (Node->Alignment > Bridge->Alignment) {
+ Bridge->Alignment = Node->Alignment;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CalculateResourceAperture (
+ IN PCI_RESOURCE_NODE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ This function is used to calculate the resource aperture
+ for a given bridge device
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINT64 Aperture;
+ LIST_ENTRY *CurrentLink;
+ PCI_RESOURCE_NODE *Node;
+
+ UINT64 offset;
+
+ Aperture = 0;
+
+ if (!Bridge) {
+ return EFI_SUCCESS;
+ }
+
+ if (Bridge->ResType == PciBarTypeIo16) {
+ return CalculateApertureIo16 (Bridge);
+ }
+
+ CurrentLink = Bridge->ChildList.ForwardLink;
+
+ //
+ // Assume the bridge is aligned
+ //
+ while (CurrentLink != &Bridge->ChildList) {
+
+ Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
+
+ //
+ // Apply padding resource if available
+ //
+
+ offset = Aperture & (Node->Alignment);
+
+ if (offset) {
+
+ Aperture = Aperture + (Node->Alignment + 1) - offset;
+
+ }
+
+ //
+ // Recode current aperture as a offset
+ // this offset will be used in future real allocation
+ //
+ Node->Offset = Aperture;
+
+ //
+ // Increment aperture by the length of node
+ //
+ Aperture += Node->Length;
+
+ //
+ // Consider the aperture alignment
+ //
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ //
+ // At last, adjust the aperture with the bridge's
+ // alignment
+ //
+ offset = Aperture & (Bridge->Alignment);
+ if (offset) {
+ Aperture = Aperture + (Bridge->Alignment + 1) - offset;
+ }
+
+ //
+ // If the bridge has already padded the resource and the
+ // amount of padded resource is larger, then keep the
+ // padded resource
+ //
+ if (Bridge->Length < Aperture) {
+ Bridge->Length = Aperture;
+ }
+
+ //
+ // At last, adjust the bridge's alignment to the first child's alignment
+ // if the bridge has at least one child
+ //
+ CurrentLink = Bridge->ChildList.ForwardLink;
+ if (CurrentLink != &Bridge->ChildList) {
+ Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
+ if (Node->Alignment > Bridge->Alignment) {
+ Bridge->Alignment = Node->Alignment;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetResourceFromDevice (
+ PCI_IO_DEVICE *PciDev,
+ PCI_RESOURCE_NODE *IoNode,
+ PCI_RESOURCE_NODE *Mem32Node,
+ PCI_RESOURCE_NODE *PMem32Node,
+ PCI_RESOURCE_NODE *Mem64Node,
+ PCI_RESOURCE_NODE *PMem64Node
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciDev - add argument and description to function comment
+// TODO: IoNode - add argument and description to function comment
+// TODO: Mem32Node - add argument and description to function comment
+// TODO: PMem32Node - add argument and description to function comment
+// TODO: Mem64Node - add argument and description to function comment
+// TODO: PMem64Node - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ UINT8 Index;
+ PCI_RESOURCE_NODE *Node;
+ BOOLEAN ResourceRequested;
+
+ Node = NULL;
+ ResourceRequested = FALSE;
+
+ for (Index = 0; Index < PCI_MAX_BAR; Index++) {
+
+ switch ((PciDev->PciBar)[Index].BarType) {
+
+ case PciBarTypeMem32:
+
+ Node = CreateResourceNode (
+ PciDev,
+ (PciDev->PciBar)[Index].Length,
+ (PciDev->PciBar)[Index].Alignment,
+ Index,
+ PciBarTypeMem32,
+ PciResUsageTypical
+ );
+
+ InsertResourceNode (
+ Mem32Node,
+ Node
+ );
+
+ ResourceRequested = TRUE;
+ break;
+
+ case PciBarTypeMem64:
+
+ Node = CreateResourceNode (
+ PciDev,
+ (PciDev->PciBar)[Index].Length,
+ (PciDev->PciBar)[Index].Alignment,
+ Index,
+ PciBarTypeMem64,
+ PciResUsageTypical
+ );
+
+ InsertResourceNode (
+ Mem64Node,
+ Node
+ );
+
+ ResourceRequested = TRUE;
+ break;
+
+ case PciBarTypePMem64:
+
+ Node = CreateResourceNode (
+ PciDev,
+ (PciDev->PciBar)[Index].Length,
+ (PciDev->PciBar)[Index].Alignment,
+ Index,
+ PciBarTypePMem64,
+ PciResUsageTypical
+ );
+
+ InsertResourceNode (
+ PMem64Node,
+ Node
+ );
+
+ ResourceRequested = TRUE;
+ break;
+
+ case PciBarTypePMem32:
+
+ Node = CreateResourceNode (
+ PciDev,
+ (PciDev->PciBar)[Index].Length,
+ (PciDev->PciBar)[Index].Alignment,
+ Index,
+ PciBarTypePMem32,
+ PciResUsageTypical
+ );
+
+ InsertResourceNode (
+ PMem32Node,
+ Node
+ );
+ ResourceRequested = TRUE;
+ break;
+
+ case PciBarTypeIo16:
+ case PciBarTypeIo32:
+
+ Node = CreateResourceNode (
+ PciDev,
+ (PciDev->PciBar)[Index].Length,
+ (PciDev->PciBar)[Index].Alignment,
+ Index,
+ PciBarTypeIo16,
+ PciResUsageTypical
+ );
+
+ InsertResourceNode (
+ IoNode,
+ Node
+ );
+ ResourceRequested = TRUE;
+ break;
+
+ case PciBarTypeUnknown:
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ //
+ // If there is no resource requested from this device,
+ // then we indicate this device has been allocated naturally.
+ //
+ if (!ResourceRequested) {
+ PciDev->Allocated = TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+PCI_RESOURCE_NODE *
+CreateResourceNode (
+ IN PCI_IO_DEVICE *PciDev,
+ IN UINT64 Length,
+ IN UINT64 Alignment,
+ IN UINT8 Bar,
+ IN PCI_BAR_TYPE ResType,
+ IN PCI_RESOURCE_USAGE ResUsage
+ )
+/*++
+
+Routine Description:
+
+ This function is used to create a resource node
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciDev - add argument and description to function comment
+// TODO: Length - add argument and description to function comment
+// TODO: Alignment - add argument and description to function comment
+// TODO: Bar - add argument and description to function comment
+// TODO: ResType - add argument and description to function comment
+// TODO: ResUsage - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ PCI_RESOURCE_NODE *Node;
+
+ Status = 0;
+ Node = NULL;
+
+ Node = AllocatePool (sizeof (PCI_RESOURCE_NODE));
+ if (Node == NULL) {
+ return NULL;
+ }
+
+ ZeroMem (Node, sizeof (PCI_RESOURCE_NODE));
+
+ Node->Signature = PCI_RESOURCE_SIGNATURE;
+ Node->PciDev = PciDev;
+ Node->Length = Length;
+ Node->Alignment = Alignment;
+ Node->Bar = Bar;
+ Node->ResType = ResType;
+ Node->Reserved = FALSE;
+ Node->ResourceUsage = ResUsage;
+ InitializeListHead (&Node->ChildList);
+ return Node;
+}
+
+EFI_STATUS
+CreateResourceMap (
+ IN PCI_IO_DEVICE *Bridge,
+ IN PCI_RESOURCE_NODE *IoNode,
+ IN PCI_RESOURCE_NODE *Mem32Node,
+ IN PCI_RESOURCE_NODE *PMem32Node,
+ IN PCI_RESOURCE_NODE *Mem64Node,
+ IN PCI_RESOURCE_NODE *PMem64Node
+ )
+/*++
+
+Routine Description:
+
+ This routine is used to extract resource request from
+ device node list.
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: IoNode - add argument and description to function comment
+// TODO: Mem32Node - add argument and description to function comment
+// TODO: PMem32Node - add argument and description to function comment
+// TODO: Mem64Node - add argument and description to function comment
+// TODO: PMem64Node - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_IO_DEVICE *Temp;
+ EFI_STATUS Status;
+ PCI_RESOURCE_NODE *IoBridge;
+ PCI_RESOURCE_NODE *Mem32Bridge;
+ PCI_RESOURCE_NODE *PMem32Bridge;
+ PCI_RESOURCE_NODE *Mem64Bridge;
+ PCI_RESOURCE_NODE *PMem64Bridge;
+ LIST_ENTRY *CurrentLink;
+
+ CurrentLink = Bridge->ChildList.ForwardLink;
+
+ while (CurrentLink && CurrentLink != &Bridge->ChildList) {
+
+ Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+ //
+ // Create resource nodes for this device by scanning the
+ // Bar array in the device private data
+ // If the upstream bridge doesn't support this device,
+ // no any resource node will be created for this device
+ //
+ GetResourceFromDevice (
+ Temp,
+ IoNode,
+ Mem32Node,
+ PMem32Node,
+ Mem64Node,
+ PMem64Node
+ );
+
+ if (IS_PCI_BRIDGE (&Temp->Pci)) {
+
+ //
+ // If the device has children, create a bridge resource node for this PPB
+ // Note: For PPB, memory aperture is aligned with 1MB and IO aperture
+ // is aligned with 4KB
+ // This device is typically a bridge device like PPB and P2C
+ //
+ IoBridge = CreateResourceNode (
+ Temp,
+ 0,
+ 0xFFF,
+ PPB_IO_RANGE,
+ PciBarTypeIo16,
+ PciResUsageTypical
+ ); //0x1000 aligned
+
+ Mem32Bridge = CreateResourceNode (
+ Temp,
+ 0,
+ 0xFFFFF,
+ PPB_MEM32_RANGE,
+ PciBarTypeMem32,
+ PciResUsageTypical
+ );
+
+ PMem32Bridge = CreateResourceNode (
+ Temp,
+ 0,
+ 0xFFFFF,
+ PPB_PMEM32_RANGE,
+ PciBarTypePMem32,
+ PciResUsageTypical
+ );
+
+ Mem64Bridge = CreateResourceNode (
+ Temp,
+ 0,
+ 0xFFFFF,
+ PPB_MEM64_RANGE,
+ PciBarTypeMem64,
+ PciResUsageTypical
+ );
+
+ PMem64Bridge = CreateResourceNode (
+ Temp,
+ 0,
+ 0xFFFFF,
+ PPB_PMEM64_RANGE,
+ PciBarTypePMem64,
+ PciResUsageTypical
+ );
+
+ //
+ // Recursively create resouce map on this bridge
+ //
+ Status = CreateResourceMap (
+ Temp,
+ IoBridge,
+ Mem32Bridge,
+ PMem32Bridge,
+ Mem64Bridge,
+ PMem64Bridge
+ );
+
+ if (ResourceRequestExisted (IoBridge)) {
+ InsertResourceNode (
+ IoNode,
+ IoBridge
+ );
+ } else {
+ gBS->FreePool (IoBridge);
+ IoBridge = NULL;
+ }
+
+ //
+ // If there is node under this resource bridge,
+ // then calculate bridge's aperture of this type
+ // and insert it into the respective resource tree.
+ // If no, delete this resource bridge
+ //
+ if (ResourceRequestExisted (Mem32Bridge)) {
+ InsertResourceNode (
+ Mem32Node,
+ Mem32Bridge
+ );
+ } else {
+ gBS->FreePool (Mem32Bridge);
+ Mem32Bridge = NULL;
+ }
+
+ //
+ // If there is node under this resource bridge,
+ // then calculate bridge's aperture of this type
+ // and insert it into the respective resource tree.
+ // If no, delete this resource bridge
+ //
+ if (ResourceRequestExisted (PMem32Bridge)) {
+ InsertResourceNode (
+ PMem32Node,
+ PMem32Bridge
+ );
+ } else {
+ gBS->FreePool (PMem32Bridge);
+ PMem32Bridge = NULL;
+ }
+
+ //
+ // If there is node under this resource bridge,
+ // then calculate bridge's aperture of this type
+ // and insert it into the respective resource tree.
+ // If no, delete this resource bridge
+ //
+ if (ResourceRequestExisted (Mem64Bridge)) {
+ InsertResourceNode (
+ Mem64Node,
+ Mem64Bridge
+ );
+ } else {
+ gBS->FreePool (Mem64Bridge);
+ Mem64Bridge = NULL;
+ }
+
+ //
+ // If there is node under this resource bridge,
+ // then calculate bridge's aperture of this type
+ // and insert it into the respective resource tree.
+ // If no, delete this resource bridge
+ //
+ if (ResourceRequestExisted (PMem64Bridge)) {
+ InsertResourceNode (
+ PMem64Node,
+ PMem64Bridge
+ );
+ } else {
+ gBS->FreePool (PMem64Bridge);
+ PMem64Bridge = NULL;
+ }
+
+ }
+
+ //
+ // If it is P2C, apply hard coded resource padding
+ //
+ //
+ if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {
+ ResourcePaddingForCardBusBridge (
+ Temp,
+ IoNode,
+ Mem32Node,
+ PMem32Node,
+ Mem64Node,
+ PMem64Node
+ );
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+ //
+ //
+ // To do some platform specific resource padding ...
+ //
+ Status = ResourcePaddingPolicy (
+ Bridge,
+ IoNode,
+ Mem32Node,
+ PMem32Node,
+ Mem64Node,
+ PMem64Node
+ );
+
+ //
+ // Degrade resource if necessary
+ //
+ DegradeResource (
+ Bridge,
+ Mem32Node,
+ PMem32Node,
+ Mem64Node,
+ PMem64Node
+ );
+
+ //
+ // Calculate resource aperture for this bridge device
+ //
+ CalculateResourceAperture (Mem32Node);
+ CalculateResourceAperture (PMem32Node);
+ CalculateResourceAperture (Mem64Node);
+ CalculateResourceAperture (PMem64Node);
+ CalculateResourceAperture (IoNode);
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+ResourcePaddingPolicy (
+ PCI_IO_DEVICE *PciDev,
+ PCI_RESOURCE_NODE *IoNode,
+ PCI_RESOURCE_NODE *Mem32Node,
+ PCI_RESOURCE_NODE *PMem32Node,
+ PCI_RESOURCE_NODE *Mem64Node,
+ PCI_RESOURCE_NODE *PMem64Node
+ )
+/*++
+
+Routine Description:
+
+ This function is used to do the resource padding for a specific platform
+
+Arguments:
+
+ PciDev - A pointer to the PCI_IO_DEVICE structrue.
+ IoNode - A pointer to the PCI_RESOURCE_NODE structrue.
+ Mem32Node - A pointer to the PCI_RESOURCE_NODE structrue.
+ PMem32Node - A pointer to the PCI_RESOURCE_NODE structrue.
+ Mem64Node - A pointer to the PCI_RESOURCE_NODE structrue.
+ PMem64Node - A pointer to the PCI_RESOURCE_NODE structrue.
+
+Returns:
+ Status code
+
+ None
+
+--*/
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ //
+ // Create padding resource node
+ //
+ if (PciDev->ResourcePaddingDescriptors != NULL) {
+ ApplyResourcePadding (
+ PciDev,
+ IoNode,
+ Mem32Node,
+ PMem32Node,
+ Mem64Node,
+ PMem64Node
+ );
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+DegradeResource (
+ IN PCI_IO_DEVICE *Bridge,
+ IN PCI_RESOURCE_NODE *Mem32Node,
+ IN PCI_RESOURCE_NODE *PMem32Node,
+ IN PCI_RESOURCE_NODE *Mem64Node,
+ IN PCI_RESOURCE_NODE *PMem64Node
+ )
+/*++
+
+Routine Description:
+
+ This function is used to degrade resource if the upstream bridge
+ doesn't support certain resource. Degradation path is
+ PMEM64 -> MEM64 -> MEM32
+ PMEM64 -> PMEM32 -> MEM32
+ IO32 -> IO16
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: Mem32Node - add argument and description to function comment
+// TODO: PMem32Node - add argument and description to function comment
+// TODO: Mem64Node - add argument and description to function comment
+// TODO: PMem64Node - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ //
+ // If bridge doesn't support Prefetchable
+ // memory64, degrade it to Mem64
+ //
+ if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM64_DECODE_SUPPORTED)) {
+ MergeResourceTree (
+ PMem32Node,
+ PMem64Node,
+ TRUE
+ );
+ } else {
+ //
+ // if no PMem32 request, still keep PMem64. Otherwise degrade to PMem32
+ //
+ if (PMem32Node != NULL) {
+ MergeResourceTree (
+ PMem32Node,
+ PMem64Node,
+ TRUE
+ );
+ }
+ }
+
+
+ //
+ // If bridge doesn't support Mem64
+ // degrade it to mem32
+ //
+ if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_MEM64_DECODE_SUPPORTED)) {
+ MergeResourceTree (
+ Mem32Node,
+ Mem64Node,
+ TRUE
+ );
+ }
+
+ //
+ // If bridge doesn't support Pmem32
+ // degrade it to mem32
+ //
+ if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM32_DECODE_SUPPORTED)) {
+ MergeResourceTree (
+ Mem32Node,
+ PMem32Node,
+ TRUE
+ );
+ }
+
+ //
+ // if bridge supports combined Pmem Mem decoding
+ // merge these two type of resource
+ //
+ if (BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED)) {
+ MergeResourceTree (
+ Mem32Node,
+ PMem32Node,
+ FALSE
+ );
+
+ MergeResourceTree (
+ Mem64Node,
+ PMem64Node,
+ FALSE
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+BridgeSupportResourceDecode (
+ IN PCI_IO_DEVICE *Bridge,
+ IN UINT32 Decode
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ Decode - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ /*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+ if ((Bridge->Decodes) & Decode) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+EFI_STATUS
+ProgramResource (
+ IN UINT64 Base,
+ IN PCI_RESOURCE_NODE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ This function is used to program the resource allocated
+ for each resource node
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Base - add argument and description to function comment
+// TODO: Bridge - add argument and description to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ LIST_ENTRY *CurrentLink;
+ PCI_RESOURCE_NODE *Node;
+ EFI_STATUS Status;
+
+ if (Base == gAllOne) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CurrentLink = Bridge->ChildList.ForwardLink;
+
+ while (CurrentLink != &Bridge->ChildList) {
+
+ Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
+
+ if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci))) {
+
+ if (IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {
+ ProgramP2C (Base, Node);
+ } else {
+ ProgramBar (Base, Node);
+ }
+ } else {
+ Status = ProgramResource (Base + Node->Offset, Node);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ProgramPpbApperture (Base, Node);
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ProgramBar (
+ IN UINT64 Base,
+ IN PCI_RESOURCE_NODE *Node
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Base - add argument and description to function comment
+// TODO: Node - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT64 Address;
+ UINT32 Address32;
+
+ Address = 0;
+ PciIo = &(Node->PciDev->PciIo);
+
+ Address = Base + Node->Offset;
+
+ //
+ // Indicate pci bus driver has allocated
+ // resource for this device
+ // It might be a temporary solution here since
+ // pci device could have multiple bar
+ //
+ Node->PciDev->Allocated = TRUE;
+
+ switch ((Node->PciDev->PciBar[Node->Bar]).BarType) {
+
+ case PciBarTypeIo16:
+ case PciBarTypeIo32:
+ case PciBarTypeMem32:
+ case PciBarTypePMem32:
+
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ (Node->PciDev->PciBar[Node->Bar]).Offset,
+ 1,
+ &Address
+ );
+
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+
+ break;
+
+ case PciBarTypeMem64:
+ case PciBarTypePMem64:
+
+ Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);
+
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ (Node->PciDev->PciBar[Node->Bar]).Offset,
+ 1,
+ &Address32
+ );
+
+ Address32 = (UINT32) RShiftU64 (Address, 32);
+
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ (UINT8) ((Node->PciDev->PciBar[Node->Bar]).Offset + 4),
+ 1,
+ &Address32
+ );
+
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+
+ break;
+
+ default:
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ProgramPpbApperture (
+ IN UINT64 Base,
+ IN PCI_RESOURCE_NODE *Node
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Base - add argument and description to function comment
+// TODO: Node - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT64 Address;
+ UINT32 Address32;
+
+ Address = 0;
+ //
+ // if no device south of this PPB, return anyway
+ // Apperture is set default in the initialization code
+ //
+ if (Node->Length == 0 || Node->ResourceUsage == PciResUsagePadding) {
+ //
+ // For padding resource node, just ignore when programming
+ //
+ return EFI_SUCCESS;
+ }
+
+ PciIo = &(Node->PciDev->PciIo);
+ Address = Base + Node->Offset;
+
+ //
+ // Indicate the PPB resource has been allocated
+ //
+ Node->PciDev->Allocated = TRUE;
+
+ switch (Node->Bar) {
+
+ case PPB_BAR_0:
+ case PPB_BAR_1:
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ (Node->PciDev->PciBar[Node->Bar]).Offset,
+ 1,
+ &Address
+ );
+
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
+
+ break;
+
+ case PPB_IO_RANGE:
+
+ Address32 = ((UINT32) (Address)) >> 8;
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0x1C,
+ 1,
+ &Address32
+ );
+
+ Address32 >>= 8;
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0x30,
+ 1,
+ &Address32
+ );
+
+ Address32 = (UINT32) (Address + Node->Length - 1);
+ Address32 = ((UINT32) (Address32)) >> 8;
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0x1D,
+ 1,
+ &Address32
+ );
+
+ Address32 >>= 8;
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0x32,
+ 1,
+ &Address32
+ );
+
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
+ break;
+
+ case PPB_MEM32_RANGE:
+
+ Address32 = ((UINT32) (Address)) >> 16;
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0x20,
+ 1,
+ &Address32
+ );
+
+ Address32 = (UINT32) (Address + Node->Length - 1);
+ Address32 = ((UINT32) (Address32)) >> 16;
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0x22,
+ 1,
+ &Address32
+ );
+
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
+ break;
+
+ case PPB_PMEM32_RANGE:
+ case PPB_PMEM64_RANGE:
+
+ Address32 = ((UINT32) (Address)) >> 16;
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0x24,
+ 1,
+ &Address32
+ );
+
+ Address32 = (UINT32) (Address + Node->Length - 1);
+ Address32 = ((UINT32) (Address32)) >> 16;
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0x26,
+ 1,
+ &Address32
+ );
+
+ Address32 = (UINT32) RShiftU64 (Address, 32);
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0x28,
+ 1,
+ &Address32
+ );
+
+ Address32 = (UINT32) RShiftU64 ((Address + Node->Length - 1), 32);
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0x2C,
+ 1,
+ &Address32
+ );
+
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
+ break;
+
+ default:
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ProgrameUpstreamBridgeForRom (
+ IN PCI_IO_DEVICE *PciDevice,
+ IN UINT32 OptionRomBase,
+ IN BOOLEAN Enable
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+// TODO: PciDevice - add argument and description to function comment
+// TODO: OptionRomBase - add argument and description to function comment
+// TODO: Enable - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_IO_DEVICE *Parent;
+ PCI_RESOURCE_NODE Node;
+ //
+ // For root bridge, just return.
+ //
+ Parent = PciDevice->Parent;
+ ZeroMem (&Node, sizeof (Node));
+ while (Parent) {
+ if (!IS_PCI_BRIDGE (&Parent->Pci)) {
+ break;
+ }
+
+ Node.PciDev = Parent;
+ Node.Length = PciDevice->RomSize;
+ Node.Alignment = 0;
+ Node.Bar = PPB_MEM32_RANGE;
+ Node.ResType = PciBarTypeMem32;
+ Node.Offset = 0;
+
+ //
+ // Program PPB to only open a single <= 16<MB apperture
+ //
+ if (Enable) {
+ ProgramPpbApperture (OptionRomBase, &Node);
+ PciEnableCommandRegister (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);
+ } else {
+ InitializePpb (Parent);
+ PciDisableCommandRegister (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);
+ }
+
+ Parent = Parent->Parent;
+ }
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+ResourceRequestExisted (
+ IN PCI_RESOURCE_NODE *Bridge
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+ Bridge - A pointer to the PCI_RESOURCE_NODE.
+
+Returns:
+
+ None
+
+--*/
+{
+ if (Bridge != NULL) {
+ if (!IsListEmpty (&Bridge->ChildList) || Bridge->Length != 0) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+EFI_STATUS
+InitializeResourcePool (
+ PCI_RESOURCE_NODE *ResourcePool,
+ PCI_BAR_TYPE ResourceType
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: ResourcePool - add argument and description to function comment
+// TODO: ResourceType - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ ZeroMem (ResourcePool, sizeof (PCI_RESOURCE_NODE));
+ ResourcePool->ResType = ResourceType;
+ ResourcePool->Signature = PCI_RESOURCE_SIGNATURE;
+ InitializeListHead (&ResourcePool->ChildList);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetResourceMap (
+ PCI_IO_DEVICE *PciDev,
+ PCI_RESOURCE_NODE **IoBridge,
+ PCI_RESOURCE_NODE **Mem32Bridge,
+ PCI_RESOURCE_NODE **PMem32Bridge,
+ PCI_RESOURCE_NODE **Mem64Bridge,
+ PCI_RESOURCE_NODE **PMem64Bridge,
+ PCI_RESOURCE_NODE *IoPool,
+ PCI_RESOURCE_NODE *Mem32Pool,
+ PCI_RESOURCE_NODE *PMem32Pool,
+ PCI_RESOURCE_NODE *Mem64Pool,
+ PCI_RESOURCE_NODE *PMem64Pool
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciDev - add argument and description to function comment
+// TODO: IoBridge - add argument and description to function comment
+// TODO: Mem32Bridge - add argument and description to function comment
+// TODO: PMem32Bridge - add argument and description to function comment
+// TODO: Mem64Bridge - add argument and description to function comment
+// TODO: PMem64Bridge - add argument and description to function comment
+// TODO: IoPool - add argument and description to function comment
+// TODO: Mem32Pool - add argument and description to function comment
+// TODO: PMem32Pool - add argument and description to function comment
+// TODO: Mem64Pool - add argument and description to function comment
+// TODO: PMem64Pool - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+
+ PCI_RESOURCE_NODE *Temp;
+ LIST_ENTRY *CurrentLink;
+
+ CurrentLink = IoPool->ChildList.ForwardLink;
+
+ //
+ // Get Io resource map
+ //
+ while (CurrentLink != &IoPool->ChildList) {
+
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
+
+ if (Temp->PciDev == PciDev) {
+ *IoBridge = Temp;
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ //
+ // Get Mem32 resource map
+ //
+ CurrentLink = Mem32Pool->ChildList.ForwardLink;
+
+ while (CurrentLink != &Mem32Pool->ChildList) {
+
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
+
+ if (Temp->PciDev == PciDev) {
+ *Mem32Bridge = Temp;
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ //
+ // Get Pmem32 resource map
+ //
+ CurrentLink = PMem32Pool->ChildList.ForwardLink;
+
+ while (CurrentLink != &PMem32Pool->ChildList) {
+
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
+
+ if (Temp->PciDev == PciDev) {
+ *PMem32Bridge = Temp;
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ //
+ // Get Mem64 resource map
+ //
+ CurrentLink = Mem64Pool->ChildList.ForwardLink;
+
+ while (CurrentLink != &Mem64Pool->ChildList) {
+
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
+
+ if (Temp->PciDev == PciDev) {
+ *Mem64Bridge = Temp;
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ //
+ // Get Pmem64 resource map
+ //
+ CurrentLink = PMem64Pool->ChildList.ForwardLink;
+
+ while (CurrentLink != &PMem64Pool->ChildList) {
+
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
+
+ if (Temp->PciDev == PciDev) {
+ *PMem64Bridge = Temp;
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DestroyResourceTree (
+ IN PCI_RESOURCE_NODE *Bridge
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Bridge - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_RESOURCE_NODE *Temp;
+ LIST_ENTRY *CurrentLink;
+
+ while (!IsListEmpty (&Bridge->ChildList)) {
+
+ CurrentLink = Bridge->ChildList.ForwardLink;
+
+ Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
+
+ RemoveEntryList (CurrentLink);
+
+ if (IS_PCI_BRIDGE (&(Temp->PciDev->Pci))) {
+ DestroyResourceTree (Temp);
+ }
+
+ gBS->FreePool (Temp);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+RecordReservedResource (
+ IN UINT64 Base,
+ IN UINT64 Length,
+ IN PCI_BAR_TYPE ResType,
+ IN PCI_IO_DEVICE *Bridge
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Base - add argument and description to function comment
+// TODO: Length - add argument and description to function comment
+// TODO: ResType - add argument and description to function comment
+// TODO: Bridge - add argument and description to function comment
+// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_RESERVED_RESOURCE_LIST *ReservedNode;
+
+ ReservedNode = AllocatePool (sizeof (PCI_RESERVED_RESOURCE_LIST));
+ if (ReservedNode == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ReservedNode->Signature = RESERVED_RESOURCE_SIGNATURE;
+ ReservedNode->Node.Base = Base;
+ ReservedNode->Node.Length = Length;
+ ReservedNode->Node.ResType = ResType;
+
+ InsertTailList (&Bridge->ReservedResourceList, &(ReservedNode->Link));
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ResourcePaddingForCardBusBridge (
+ PCI_IO_DEVICE *PciDev,
+ PCI_RESOURCE_NODE *IoNode,
+ PCI_RESOURCE_NODE *Mem32Node,
+ PCI_RESOURCE_NODE *PMem32Node,
+ PCI_RESOURCE_NODE *Mem64Node,
+ PCI_RESOURCE_NODE *PMem64Node
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciDev - add argument and description to function comment
+// TODO: IoNode - add argument and description to function comment
+// TODO: Mem32Node - add argument and description to function comment
+// TODO: PMem32Node - add argument and description to function comment
+// TODO: Mem64Node - add argument and description to function comment
+// TODO: PMem64Node - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ PCI_RESOURCE_NODE *Node;
+
+ Node = NULL;
+
+ //
+ // Memory Base/Limit Register 0
+ // Bar 1 denodes memory range 0
+ //
+ Node = CreateResourceNode (
+ PciDev,
+ 0x2000000,
+ 0x1ffffff,
+ 1,
+ PciBarTypeMem32,
+ PciResUsagePadding
+ );
+
+ InsertResourceNode (
+ Mem32Node,
+ Node
+ );
+
+ //
+ // Memory Base/Limit Register 1
+ // Bar 2 denodes memory range1
+ //
+ Node = CreateResourceNode (
+ PciDev,
+ 0x2000000,
+ 0x1ffffff,
+ 2,
+ PciBarTypePMem32,
+ PciResUsagePadding
+ );
+
+ InsertResourceNode (
+ PMem32Node,
+ Node
+ );
+
+ //
+ // Io Base/Limit
+ // Bar 3 denodes io range 0
+ //
+ Node = CreateResourceNode (
+ PciDev,
+ 0x100,
+ 0xff,
+ 3,
+ PciBarTypeIo16,
+ PciResUsagePadding
+ );
+
+ InsertResourceNode (
+ IoNode,
+ Node
+ );
+
+ //
+ // Io Base/Limit
+ // Bar 4 denodes io range 0
+ //
+ Node = CreateResourceNode (
+ PciDev,
+ 0x100,
+ 0xff,
+ 4,
+ PciBarTypeIo16,
+ PciResUsagePadding
+ );
+
+ InsertResourceNode (
+ IoNode,
+ Node
+ );
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ProgramP2C (
+ IN UINT64 Base,
+ IN PCI_RESOURCE_NODE *Node
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: Base - add argument and description to function comment
+// TODO: Node - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT64 Address;
+ UINT64 TempAddress;
+ UINT16 BridgeControl;
+
+ Address = 0;
+ PciIo = &(Node->PciDev->PciIo);
+
+ Address = Base + Node->Offset;
+
+ //
+ // Indicate pci bus driver has allocated
+ // resource for this device
+ // It might be a temporary solution here since
+ // pci device could have multiple bar
+ //
+ Node->PciDev->Allocated = TRUE;
+
+ switch (Node->Bar) {
+
+ case P2C_BAR_0:
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ (Node->PciDev->PciBar[Node->Bar]).Offset,
+ 1,
+ &Address
+ );
+
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
+ break;
+
+ case P2C_MEM_1:
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0x1c,
+ 1,
+ &Address
+ );
+
+ TempAddress = Address + Node->Length - 1;
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0x20,
+ 1,
+ &TempAddress
+ );
+
+ if (Node->ResType == PciBarTypeMem32) {
+
+ //
+ // Set non-prefetchable bit
+ //
+ PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0x3e,
+ 1,
+ &BridgeControl
+ );
+
+ BridgeControl &= 0xfeff;
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0x3e,
+ 1,
+ &BridgeControl
+ );
+
+ } else {
+
+ //
+ // Set pre-fetchable bit
+ //
+ PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0x3e,
+ 1,
+ &BridgeControl
+ );
+
+ BridgeControl |= 0x0100;
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0x3e,
+ 1,
+ &BridgeControl
+ );
+ }
+
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
+ Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
+
+ break;
+
+ case P2C_MEM_2:
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0x24,
+ 1,
+ &Address
+ );
+
+ TempAddress = Address + Node->Length - 1;
+
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0x28,
+ 1,
+ &TempAddress
+ );
+
+ if (Node->ResType == PciBarTypeMem32) {
+
+ //
+ // Set non-prefetchable bit
+ //
+ PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0x3e,
+ 1,
+ &BridgeControl
+ );
+
+ BridgeControl &= 0xfdff;
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0x3e,
+ 1,
+ &BridgeControl
+ );
+ } else {
+
+ //
+ // Set pre-fetchable bit
+ //
+ PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0x3e,
+ 1,
+ &BridgeControl
+ );
+
+ BridgeControl |= 0x0200;
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ 0x3e,
+ 1,
+ &BridgeControl
+ );
+ }
+
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
+ Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
+ break;
+
+ case P2C_IO_1:
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0x2c,
+ 1,
+ &Address
+ );
+ TempAddress = Address + Node->Length - 1;
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0x30,
+ 1,
+ &TempAddress
+ );
+
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
+ Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
+
+ break;
+
+ case P2C_IO_2:
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0x34,
+ 1,
+ &Address
+ );
+
+ TempAddress = Address + Node->Length - 1;
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0x38,
+ 1,
+ &TempAddress
+ );
+
+ Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
+ Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
+ Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
+ break;
+
+ default:
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ApplyResourcePadding (
+ PCI_IO_DEVICE *PciDev,
+ PCI_RESOURCE_NODE *IoNode,
+ PCI_RESOURCE_NODE *Mem32Node,
+ PCI_RESOURCE_NODE *PMem32Node,
+ PCI_RESOURCE_NODE *Mem64Node,
+ PCI_RESOURCE_NODE *PMem64Node
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+ None
+
+--*/
+// TODO: PciDev - add argument and description to function comment
+// TODO: IoNode - add argument and description to function comment
+// TODO: Mem32Node - add argument and description to function comment
+// TODO: PMem32Node - add argument and description to function comment
+// TODO: Mem64Node - add argument and description to function comment
+// TODO: PMem64Node - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
+ PCI_RESOURCE_NODE *Node;
+ UINT8 DummyBarIndex;
+
+ DummyBarIndex = 0;
+ Ptr = PciDev->ResourcePaddingDescriptors;
+
+ while (((EFI_ACPI_END_TAG_DESCRIPTOR *) Ptr)->Desc != ACPI_END_TAG_DESCRIPTOR) {
+
+ if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) {
+ if (Ptr->AddrLen != 0) {
+
+ Node = CreateResourceNode (
+ PciDev,
+ Ptr->AddrLen,
+ Ptr->AddrRangeMax,
+ DummyBarIndex,
+ PciBarTypeIo16,
+ PciResUsagePadding
+ );
+ InsertResourceNode (
+ IoNode,
+ Node
+ );
+ }
+
+ Ptr++;
+ continue;
+ }
+
+ if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
+
+ if (Ptr->AddrSpaceGranularity == 32) {
+
+ //
+ // prefechable
+ //
+ if (Ptr->SpecificFlag == 0x6) {
+ if (Ptr->AddrLen) {
+ Node = CreateResourceNode (
+ PciDev,
+ Ptr->AddrLen,
+ Ptr->AddrRangeMax,
+ DummyBarIndex,
+ PciBarTypePMem32,
+ PciResUsagePadding
+ );
+ InsertResourceNode (
+ PMem32Node,
+ Node
+ );
+ }
+
+ Ptr++;
+ continue;
+ }
+
+ //
+ // Non-prefechable
+ //
+ if (Ptr->SpecificFlag == 0) {
+ if (Ptr->AddrLen) {
+ Node = CreateResourceNode (
+ PciDev,
+ Ptr->AddrLen,
+ Ptr->AddrRangeMax,
+ DummyBarIndex,
+ PciBarTypeMem32,
+ PciResUsagePadding
+ );
+ InsertResourceNode (
+ Mem32Node,
+ Node
+ );
+ }
+
+ Ptr++;
+ continue;
+ }
+ }
+
+ if (Ptr->AddrSpaceGranularity == 64) {
+
+ //
+ // prefechable
+ //
+ if (Ptr->SpecificFlag == 0x6) {
+ if (Ptr->AddrLen) {
+ Node = CreateResourceNode (
+ PciDev,
+ Ptr->AddrLen,
+ Ptr->AddrRangeMax,
+ DummyBarIndex,
+ PciBarTypePMem64,
+ PciResUsagePadding
+ );
+ InsertResourceNode (
+ PMem64Node,
+ Node
+ );
+ }
+
+ Ptr++;
+ continue;
+ }
+
+ //
+ // Non-prefechable
+ //
+ if (Ptr->SpecificFlag == 0) {
+ if (Ptr->AddrLen) {
+ Node = CreateResourceNode (
+ PciDev,
+ Ptr->AddrLen,
+ Ptr->AddrRangeMax,
+ DummyBarIndex,
+ PciBarTypeMem64,
+ PciResUsagePadding
+ );
+ InsertResourceNode (
+ Mem64Node,
+ Node
+ );
+ }
+
+ Ptr++;
+ continue;
+ }
+ }
+ }
+
+ Ptr++;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//
+// Light PCI bus driver woundn't support hotplug root device
+// So no need to pad resource for them
+//
+VOID
+GetResourcePaddingPpb (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ Get resource.
+
+Arguments:
+
+ PciIoDevice A pointer to a pci device.
+
+Returns:
+
+ None
+
+--*/
+{
+ if (gPciHotPlugInit) {
+ if (PciIoDevice->ResourcePaddingDescriptors == NULL) {
+ GetResourcePaddingForHpb (PciIoDevice);
+ }
+ }
+}
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciResourceSupport.h b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciResourceSupport.h
new file mode 100644
index 0000000..61ec29f
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciResourceSupport.h
@@ -0,0 +1,740 @@
+/*++
+
+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:
+
+ PciResourceSupport.h
+
+Abstract:
+
+
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_RESOURCE_SUPPORT_H
+#define _EFI_PCI_RESOURCE_SUPPORT_H
+
+#define RESERVED_RESOURCE_SIGNATURE EFI_SIGNATURE_32 ('r', 's', 'v', 'd')
+
+typedef struct {
+ UINT64 Base;
+ UINT64 Length;
+ PCI_BAR_TYPE ResType;
+} PCI_RESERVED_RESOURCE_NODE;
+
+typedef struct {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+ PCI_RESERVED_RESOURCE_NODE Node;
+} PCI_RESERVED_RESOURCE_LIST;
+
+#define RESOURCED_LIST_FROM_NODE(a) \
+ CR (a, PCI_RESERVED_RESOURCE_LIST, Node, RESERVED_RESOURCE_SIGNATURE)
+
+#define RESOURCED_LIST_FROM_LINK(a) \
+ CR (a, PCI_RESERVED_RESOURCE_LIST, Link, RESERVED_RESOURCE_SIGNATURE)
+
+typedef enum {
+ PciResUsageTypical = 0,
+ PciResUsagePadding,
+ PciResUsageOptionRomProcessing
+} PCI_RESOURCE_USAGE;
+
+#define PCI_RESOURCE_SIGNATURE EFI_SIGNATURE_32 ('p', 'c', 'r', 'c')
+
+typedef struct {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+ LIST_ENTRY ChildList;
+ PCI_IO_DEVICE *PciDev;
+ UINT64 Alignment;
+ UINT64 Offset;
+ UINT8 Bar;
+ PCI_BAR_TYPE ResType;
+ UINT64 Length;
+ BOOLEAN Reserved;
+ PCI_RESOURCE_USAGE ResourceUsage;
+} PCI_RESOURCE_NODE;
+
+#define RESOURCE_NODE_FROM_LINK(a) \
+ CR (a, PCI_RESOURCE_NODE, Link, PCI_RESOURCE_SIGNATURE)
+
+EFI_STATUS
+SkipVGAAperture (
+ OUT UINT64 *Start,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Start - TODO: add argument description
+ Length - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+SkipIsaAliasAperture (
+ OUT UINT64 *Start,
+ IN UINT64 Length
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Start - TODO: add argument description
+ Length - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+InsertResourceNode (
+ PCI_RESOURCE_NODE *Bridge,
+ PCI_RESOURCE_NODE *ResNode
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ ResNode - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+MergeResourceTree (
+ PCI_RESOURCE_NODE *Dst,
+ PCI_RESOURCE_NODE *Res,
+ BOOLEAN TypeMerge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Dst - TODO: add argument description
+ Res - TODO: add argument description
+ TypeMerge - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+CalculateApertureIo16 (
+ IN PCI_RESOURCE_NODE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+CalculateResourceAperture (
+ IN PCI_RESOURCE_NODE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+GetResourceFromDevice (
+ PCI_IO_DEVICE *PciDev,
+ PCI_RESOURCE_NODE *IoNode,
+ PCI_RESOURCE_NODE *Mem32Node,
+ PCI_RESOURCE_NODE *PMem32Node,
+ PCI_RESOURCE_NODE *Mem64Node,
+ PCI_RESOURCE_NODE *PMem64Node
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciDev - TODO: add argument description
+ IoNode - TODO: add argument description
+ Mem32Node - TODO: add argument description
+ PMem32Node - TODO: add argument description
+ Mem64Node - TODO: add argument description
+ PMem64Node - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+PCI_RESOURCE_NODE *
+CreateResourceNode (
+ IN PCI_IO_DEVICE *PciDev,
+ IN UINT64 Length,
+ IN UINT64 Alignment,
+ IN UINT8 Bar,
+ IN PCI_BAR_TYPE ResType,
+ IN PCI_RESOURCE_USAGE ResUsage
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciDev - TODO: add argument description
+ Length - TODO: add argument description
+ Alignment - TODO: add argument description
+ Bar - TODO: add argument description
+ ResType - TODO: add argument description
+ ResUsage - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+CreateResourceMap (
+ IN PCI_IO_DEVICE *Bridge,
+ IN PCI_RESOURCE_NODE *IoNode,
+ IN PCI_RESOURCE_NODE *Mem32Node,
+ IN PCI_RESOURCE_NODE *PMem32Node,
+ IN PCI_RESOURCE_NODE *Mem64Node,
+ IN PCI_RESOURCE_NODE *PMem64Node
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ IoNode - TODO: add argument description
+ Mem32Node - TODO: add argument description
+ PMem32Node - TODO: add argument description
+ Mem64Node - TODO: add argument description
+ PMem64Node - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+ResourcePaddingPolicy (
+ PCI_IO_DEVICE *PciDev,
+ PCI_RESOURCE_NODE *IoNode,
+ PCI_RESOURCE_NODE *Mem32Node,
+ PCI_RESOURCE_NODE *PMem32Node,
+ PCI_RESOURCE_NODE *Mem64Node,
+ PCI_RESOURCE_NODE *PMem64Node
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciDev - TODO: add argument description
+ IoNode - TODO: add argument description
+ Mem32Node - TODO: add argument description
+ PMem32Node - TODO: add argument description
+ Mem64Node - TODO: add argument description
+ PMem64Node - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+DegradeResource (
+ IN PCI_IO_DEVICE *Bridge,
+ IN PCI_RESOURCE_NODE *Mem32Node,
+ IN PCI_RESOURCE_NODE *PMem32Node,
+ IN PCI_RESOURCE_NODE *Mem64Node,
+ IN PCI_RESOURCE_NODE *PMem64Node
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ Mem32Node - TODO: add argument description
+ PMem32Node - TODO: add argument description
+ Mem64Node - TODO: add argument description
+ PMem64Node - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+BridgeSupportResourceDecode (
+ IN PCI_IO_DEVICE *Bridge,
+ IN UINT32 Decode
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+ Decode - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+ProgramResource (
+ IN UINT64 Base,
+ IN PCI_RESOURCE_NODE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Base - TODO: add argument description
+ Bridge - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+ProgramBar (
+ IN UINT64 Base,
+ IN PCI_RESOURCE_NODE *Node
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Base - TODO: add argument description
+ Node - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+ProgramPpbApperture (
+ IN UINT64 Base,
+ IN PCI_RESOURCE_NODE *Node
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Base - TODO: add argument description
+ Node - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+ProgrameUpstreamBridgeForRom (
+ IN PCI_IO_DEVICE *PciDevice,
+ IN UINT32 OptionRomBase,
+ IN BOOLEAN Enable
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciDevice - TODO: add argument description
+ OptionRomBase - TODO: add argument description
+ Enable - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+BOOLEAN
+ResourceRequestExisted (
+ IN PCI_RESOURCE_NODE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+InitializeResourcePool (
+ PCI_RESOURCE_NODE *ResourcePool,
+ PCI_BAR_TYPE ResourceType
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ ResourcePool - TODO: add argument description
+ ResourceType - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+GetResourceMap (
+ PCI_IO_DEVICE *PciDev,
+ PCI_RESOURCE_NODE **IoBridge,
+ PCI_RESOURCE_NODE **Mem32Bridge,
+ PCI_RESOURCE_NODE **PMem32Bridge,
+ PCI_RESOURCE_NODE **Mem64Bridge,
+ PCI_RESOURCE_NODE **PMem64Bridge,
+ PCI_RESOURCE_NODE *IoPool,
+ PCI_RESOURCE_NODE *Mem32Pool,
+ PCI_RESOURCE_NODE *PMem32Pool,
+ PCI_RESOURCE_NODE *Mem64Pool,
+ PCI_RESOURCE_NODE *PMem64Pool
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciDev - TODO: add argument description
+ IoBridge - TODO: add argument description
+ Mem32Bridge - TODO: add argument description
+ PMem32Bridge - TODO: add argument description
+ Mem64Bridge - TODO: add argument description
+ PMem64Bridge - TODO: add argument description
+ IoPool - TODO: add argument description
+ Mem32Pool - TODO: add argument description
+ PMem32Pool - TODO: add argument description
+ Mem64Pool - TODO: add argument description
+ PMem64Pool - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+DestroyResourceTree (
+ IN PCI_RESOURCE_NODE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Bridge - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+RecordReservedResource (
+ IN UINT64 Base,
+ IN UINT64 Length,
+ IN PCI_BAR_TYPE ResType,
+ IN PCI_IO_DEVICE *Bridge
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Base - TODO: add argument description
+ Length - TODO: add argument description
+ ResType - TODO: add argument description
+ Bridge - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+ResourcePaddingForCardBusBridge (
+ PCI_IO_DEVICE *PciDev,
+ PCI_RESOURCE_NODE *IoNode,
+ PCI_RESOURCE_NODE *Mem32Node,
+ PCI_RESOURCE_NODE *PMem32Node,
+ PCI_RESOURCE_NODE *Mem64Node,
+ PCI_RESOURCE_NODE *PMem64Node
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciDev - TODO: add argument description
+ IoNode - TODO: add argument description
+ Mem32Node - TODO: add argument description
+ PMem32Node - TODO: add argument description
+ Mem64Node - TODO: add argument description
+ PMem64Node - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+ProgramP2C (
+ IN UINT64 Base,
+ IN PCI_RESOURCE_NODE *Node
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ Base - TODO: add argument description
+ Node - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+ApplyResourcePadding (
+ PCI_IO_DEVICE *PciDev,
+ PCI_RESOURCE_NODE *IoNode,
+ PCI_RESOURCE_NODE *Mem32Node,
+ PCI_RESOURCE_NODE *PMem32Node,
+ PCI_RESOURCE_NODE *Mem64Node,
+ PCI_RESOURCE_NODE *PMem64Node
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciDev - TODO: add argument description
+ IoNode - TODO: add argument description
+ Mem32Node - TODO: add argument description
+ PMem32Node - TODO: add argument description
+ Mem64Node - TODO: add argument description
+ PMem64Node - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+VOID
+GetResourcePaddingPpb (
+ IN PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+ResetAllPpbBusReg (
+ IN PCI_IO_DEVICE *Bridge,
+ IN UINT8 StartBusNumber
+ )
+/*++
+
+Routine Description:
+
+ Reset bus register
+
+Arguments:
+
+ Bridge - a pointer to the PCI_IO_DEVICE
+ StartBusNumber - the number of bus
+
+Returns:
+
+ None
+
+--*/
+;
+
+#endif
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciRomTable.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciRomTable.c
new file mode 100644
index 0000000..a1e16a0
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciRomTable.c
@@ -0,0 +1,457 @@
+/*++
+
+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:
+
+ PciRomTable.c
+
+Abstract:
+
+ Option Rom Support for PCI Bus Driver
+
+Revision History
+
+--*/
+
+#include "pcibus.h"
+#include "PciRomTable.h"
+
+typedef struct {
+ EFI_HANDLE ImageHandle;
+ UINTN Seg;
+ UINT8 Bus;
+ UINT8 Dev;
+ UINT8 Func;
+ UINT64 RomAddress;
+ UINT64 RomLength;
+} EFI_PCI_ROM_IMAGE_MAPPING;
+
+static UINTN mNumberOfPciRomImages = 0;
+static UINTN mMaxNumberOfPciRomImages = 0;
+static EFI_PCI_ROM_IMAGE_MAPPING *mRomImageTable = NULL;
+
+VOID
+PciRomAddImageMapping (
+ IN EFI_HANDLE ImageHandle,
+ IN UINTN Seg,
+ IN UINT8 Bus,
+ IN UINT8 Dev,
+ IN UINT8 Func,
+ IN UINT64 RomAddress,
+ IN UINT64 RomLength
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ ImageHandle - TODO: add argument description
+ Seg - TODO: add argument description
+ Bus - TODO: add argument description
+ Dev - TODO: add argument description
+ Func - TODO: add argument description
+ RomAddress - TODO: add argument description
+ RomLength - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ EFI_PCI_ROM_IMAGE_MAPPING *TempMapping;
+
+ if (mNumberOfPciRomImages >= mMaxNumberOfPciRomImages) {
+
+ mMaxNumberOfPciRomImages += 0x20;
+
+ TempMapping = NULL;
+ TempMapping = AllocatePool (mMaxNumberOfPciRomImages * sizeof (EFI_PCI_ROM_IMAGE_MAPPING));
+ if (TempMapping == NULL) {
+ return ;
+ }
+
+ CopyMem (TempMapping, mRomImageTable, mNumberOfPciRomImages * sizeof (EFI_PCI_ROM_IMAGE_MAPPING));
+
+ if (mRomImageTable != NULL) {
+ gBS->FreePool (mRomImageTable);
+ }
+
+ mRomImageTable = TempMapping;
+ }
+
+ mRomImageTable[mNumberOfPciRomImages].ImageHandle = ImageHandle;
+ mRomImageTable[mNumberOfPciRomImages].Seg = Seg;
+ mRomImageTable[mNumberOfPciRomImages].Bus = Bus;
+ mRomImageTable[mNumberOfPciRomImages].Dev = Dev;
+ mRomImageTable[mNumberOfPciRomImages].Func = Func;
+ mRomImageTable[mNumberOfPciRomImages].RomAddress = RomAddress;
+ mRomImageTable[mNumberOfPciRomImages].RomLength = RomLength;
+ mNumberOfPciRomImages++;
+}
+
+VOID
+HexToString (
+ CHAR16 *String,
+ UINTN Value,
+ UINTN Digits
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ String - TODO: add argument description
+ Value - TODO: add argument description
+ Digits - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ for (; Digits > 0; Digits--, String++) {
+ *String = (CHAR16) ((Value >> (4 * (Digits - 1))) & 0x0f);
+ if (*String > 9) {
+ (*String) += ('A' - 10);
+ } else {
+ (*String) += '0';
+ }
+ }
+}
+EFI_STATUS
+PciRomLoadEfiDriversFromRomImage (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_PCI_OPTION_ROM_DESCRIPTOR *PciOptionRomDescriptor
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: PciOptionRomDescriptor - add argument and description to function comment
+{
+ VOID *RomBar;
+ UINTN RomSize;
+ CHAR16 *FileName;
+ EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;
+ PCI_DATA_STRUCTURE *Pcir;
+ UINTN ImageIndex;
+ UINTN RomBarOffset;
+ UINT32 ImageSize;
+ UINT16 ImageOffset;
+ EFI_HANDLE ImageHandle;
+ EFI_STATUS Status;
+ EFI_STATUS retStatus;
+ EFI_DEVICE_PATH_PROTOCOL *FilePath;
+ BOOLEAN SkipImage;
+ UINT32 DestinationSize;
+ UINT32 ScratchSize;
+ UINT8 *Scratch;
+ VOID *ImageBuffer;
+ VOID *DecompressedImageBuffer;
+ UINT32 ImageLength;
+ EFI_DECOMPRESS_PROTOCOL *Decompress;
+
+ RomBar = (VOID *) (UINTN) PciOptionRomDescriptor->RomAddress;
+ RomSize = (UINTN) PciOptionRomDescriptor->RomLength;
+ FileName = L"PciRom Seg=00000000 Bus=00 Dev=00 Func=00 Image=0000";
+
+ HexToString (&FileName[11], PciOptionRomDescriptor->Seg, 8);
+ HexToString (&FileName[24], PciOptionRomDescriptor->Bus, 2);
+ HexToString (&FileName[31], PciOptionRomDescriptor->Dev, 2);
+ HexToString (&FileName[39], PciOptionRomDescriptor->Func, 2);
+
+ ImageIndex = 0;
+ retStatus = EFI_NOT_FOUND;
+ RomBarOffset = (UINTN) RomBar;
+
+ do {
+
+ EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (UINTN) RomBarOffset;
+
+ if (EfiRomHeader->Signature != 0xaa55) {
+ return retStatus;
+ }
+
+ Pcir = (PCI_DATA_STRUCTURE *) (UINTN) (RomBarOffset + EfiRomHeader->PcirOffset);
+ ImageSize = Pcir->ImageLength * 512;
+
+ if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&
+ (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) ) {
+
+ if ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
+ (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) ) {
+
+ ImageOffset = EfiRomHeader->EfiImageHeaderOffset;
+ ImageSize = EfiRomHeader->InitializationSize * 512;
+
+ ImageBuffer = (VOID *) (UINTN) (RomBarOffset + ImageOffset);
+ ImageLength = ImageSize - ImageOffset;
+ DecompressedImageBuffer = NULL;
+
+ //
+ // decompress here if needed
+ //
+ SkipImage = FALSE;
+ if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
+ SkipImage = TRUE;
+ }
+
+ if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
+ Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress);
+ if (EFI_ERROR (Status)) {
+ SkipImage = TRUE;
+ } else {
+ SkipImage = TRUE;
+ Status = Decompress->GetInfo (
+ Decompress,
+ ImageBuffer,
+ ImageLength,
+ &DestinationSize,
+ &ScratchSize
+ );
+ if (!EFI_ERROR (Status)) {
+ DecompressedImageBuffer = NULL;
+ DecompressedImageBuffer = AllocatePool (DestinationSize);
+ if (DecompressedImageBuffer != NULL) {
+ Scratch = AllocatePool (ScratchSize);
+ if (Scratch != NULL) {
+ Status = Decompress->Decompress (
+ Decompress,
+ ImageBuffer,
+ ImageLength,
+ DecompressedImageBuffer,
+ DestinationSize,
+ Scratch,
+ ScratchSize
+ );
+ if (!EFI_ERROR (Status)) {
+ ImageBuffer = DecompressedImageBuffer;
+ ImageLength = DestinationSize;
+ SkipImage = FALSE;
+ }
+
+ gBS->FreePool (Scratch);
+ }
+ }
+ }
+ }
+ }
+
+ if (!SkipImage) {
+
+ //
+ // load image and start image
+ //
+
+ HexToString (&FileName[48], ImageIndex, 4);
+ FilePath = FileDevicePath (NULL, FileName);
+
+ Status = gBS->LoadImage (
+ FALSE,
+ This->ImageHandle,
+ FilePath,
+ ImageBuffer,
+ ImageLength,
+ &ImageHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->StartImage (ImageHandle, NULL, NULL);
+ if (!EFI_ERROR (Status)) {
+ PciRomAddImageMapping (
+ ImageHandle,
+ PciOptionRomDescriptor->Seg,
+ PciOptionRomDescriptor->Bus,
+ PciOptionRomDescriptor->Dev,
+ PciOptionRomDescriptor->Func,
+ PciOptionRomDescriptor->RomAddress,
+ PciOptionRomDescriptor->RomLength
+ );
+ retStatus = Status;
+ }
+ }
+ }
+
+ if (DecompressedImageBuffer != NULL) {
+ gBS->FreePool (DecompressedImageBuffer);
+ }
+
+ }
+ }
+
+ RomBarOffset = RomBarOffset + ImageSize;
+ ImageIndex++;
+ } while (((Pcir->Indicator & 0x80) == 0x00) && ((RomBarOffset - (UINTN) RomBar) < RomSize));
+
+ return retStatus;
+}
+
+EFI_STATUS
+PciRomLoadEfiDriversFromOptionRomTable (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: PciRootBridgeIo - add argument and description to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+{
+ EFI_STATUS Status;
+ EFI_PCI_OPTION_ROM_TABLE *PciOptionRomTable;
+ EFI_PCI_OPTION_ROM_DESCRIPTOR *PciOptionRomDescriptor;
+ UINTN Index;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
+ UINT16 MinBus;
+ UINT16 MaxBus;
+
+ Status = EfiGetSystemConfigurationTable (&gEfiPciOptionRomTableGuid, (VOID **) &PciOptionRomTable);
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = EFI_NOT_FOUND;
+
+ for (Index = 0; Index < PciOptionRomTable->PciOptionRomCount; Index++) {
+ PciOptionRomDescriptor = &PciOptionRomTable->PciOptionRomDescriptors[Index];
+ if (!PciOptionRomDescriptor->DontLoadEfiRom) {
+ if (PciOptionRomDescriptor->Seg == PciRootBridgeIo->SegmentNumber) {
+ Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL);
+ if ((MinBus <= PciOptionRomDescriptor->Bus) && (PciOptionRomDescriptor->Bus <= MaxBus)) {
+ Status = PciRomLoadEfiDriversFromRomImage (This, PciOptionRomDescriptor);
+ PciOptionRomDescriptor->DontLoadEfiRom |= 2;
+ }
+ }
+ }
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+PciRomGetRomResourceFromPciOptionRomTable (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
+ PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: PciRootBridgeIo - add argument and description to function comment
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_NOT_FOUND - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ EFI_PCI_OPTION_ROM_TABLE *PciOptionRomTable;
+ EFI_PCI_OPTION_ROM_DESCRIPTOR *PciOptionRomDescriptor;
+ UINTN Index;
+
+ Status = EfiGetSystemConfigurationTable (&gEfiPciOptionRomTableGuid, (VOID **) &PciOptionRomTable);
+ if (EFI_ERROR (Status)) {
+ return EFI_NOT_FOUND;
+ }
+
+ for (Index = 0; Index < PciOptionRomTable->PciOptionRomCount; Index++) {
+ PciOptionRomDescriptor = &PciOptionRomTable->PciOptionRomDescriptors[Index];
+ if (PciOptionRomDescriptor->Seg == PciRootBridgeIo->SegmentNumber &&
+ PciOptionRomDescriptor->Bus == PciIoDevice->BusNumber &&
+ PciOptionRomDescriptor->Dev == PciIoDevice->DeviceNumber &&
+ PciOptionRomDescriptor->Func == PciIoDevice->FunctionNumber ) {
+
+ PciIoDevice->PciIo.RomImage = (VOID *) (UINTN) PciOptionRomDescriptor->RomAddress;
+ PciIoDevice->PciIo.RomSize = (UINTN) PciOptionRomDescriptor->RomLength;
+ }
+ }
+
+ for (Index = 0; Index < mNumberOfPciRomImages; Index++) {
+ if (mRomImageTable[Index].Seg == PciRootBridgeIo->SegmentNumber &&
+ mRomImageTable[Index].Bus == PciIoDevice->BusNumber &&
+ mRomImageTable[Index].Dev == PciIoDevice->DeviceNumber &&
+ mRomImageTable[Index].Func == PciIoDevice->FunctionNumber ) {
+
+ AddDriver (PciIoDevice, mRomImageTable[Index].ImageHandle);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PciRomGetImageMapping (
+ PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+// TODO: PciIoDevice - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+ UINTN Index;
+
+ PciRootBridgeIo = PciIoDevice->PciRootBridgeIo;
+
+ for (Index = 0; Index < mNumberOfPciRomImages; Index++) {
+ if (mRomImageTable[Index].Seg == PciRootBridgeIo->SegmentNumber &&
+ mRomImageTable[Index].Bus == PciIoDevice->BusNumber &&
+ mRomImageTable[Index].Dev == PciIoDevice->DeviceNumber &&
+ mRomImageTable[Index].Func == PciIoDevice->FunctionNumber ) {
+
+ if (mRomImageTable[Index].ImageHandle != NULL) {
+ AddDriver (PciIoDevice, mRomImageTable[Index].ImageHandle);
+ } else {
+ PciIoDevice->PciIo.RomImage = (VOID *) (UINTN) mRomImageTable[Index].RomAddress;
+ PciIoDevice->PciIo.RomSize = (UINTN) mRomImageTable[Index].RomLength;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciRomTable.h b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciRomTable.h
new file mode 100644
index 0000000..bb20c70
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciRomTable.h
@@ -0,0 +1,107 @@
+/*++
+
+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:
+
+ PciRomTable.h
+
+Abstract:
+
+ Option Rom Support for PCI Bus Driver
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_ROM_TABLE_H
+#define _EFI_PCI_ROM_TABLE_H
+
+VOID
+PciRomAddImageMapping (
+ IN EFI_HANDLE ImageHandle,
+ IN UINTN Seg,
+ IN UINT8 Bus,
+ IN UINT8 Dev,
+ IN UINT8 Func,
+ IN UINT64 RomAddress,
+ IN UINT64 RomLength
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ ImageHandle - TODO: add argument description
+ Seg - TODO: add argument description
+ Bus - TODO: add argument description
+ Dev - TODO: add argument description
+ Func - TODO: add argument description
+ RomAddress - TODO: add argument description
+ RomLength - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+
+EFI_STATUS
+PciRomGetRomResourceFromPciOptionRomTable (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
+ PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ This - TODO: add argument description
+ PciRootBridgeIo - TODO: add argument description
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+PciRomGetImageMapping (
+ PCI_IO_DEVICE *PciIoDevice
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ PciIoDevice - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/build.xml b/EdkModulePkg/Bus/Pci/PciBus/Dxe/build.xml
new file mode 100644
index 0000000..ee051c7
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/build.xml
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- 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.-->
+<project basedir="." default="PciBus"><!--Apply external ANT tasks-->
+ <taskdef resource="GenBuild.tasks"/>
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+ <property environment="env"/>
+ <property name="WORKSPACE_DIR" value="${env.WORKSPACE}"/>
+ <import file="${WORKSPACE_DIR}\Tools\Conf\BuildMacro.xml"/><!--MODULE_RELATIVE PATH is relative to PACKAGE_DIR-->
+ <property name="MODULE_RELATIVE_PATH" value="Bus\Pci\PciBus\Dxe"/>
+ <property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
+ <property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
+ <target name="PciBus">
+ <GenBuild baseName="PciBus" mbdFilename="${MODULE_DIR}\PciBus.mbd" msaFilename="${MODULE_DIR}\PciBus.msa"/>
+ </target>
+ <target name="LightPciBusPciBus">
+ <GenBuild baseName="LightPciBusPciBus" mbdFilename="${MODULE_DIR}\LightPciBus.mbd" msaFilename="${MODULE_DIR}\LightPciBus.msa"/>
+ </target>
+ <target name="PciBusPciBusLite">
+ <GenBuild baseName="PciBusPciBusLite" mbdFilename="${MODULE_DIR}\PciBusLite.mbd" msaFilename="${MODULE_DIR}\PciBusLite.msa"/>
+ </target>
+ <target depends="PciBus_clean" name="clean"/>
+ <target depends="PciBus_cleanall" name="cleanall"/>
+ <target name="PciBus_clean">
+ <OutputDirSetup baseName="PciBus" mbdFilename="${MODULE_DIR}\PciBus.mbd" msaFilename="${MODULE_DIR}\PciBus.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\PciBus_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\PciBus_build.xml" target="clean"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
+ </target>
+ <target name="LightPciBusPciBus_clean">
+ <OutputDirSetup baseName="LightPciBusPciBus" mbdFilename="${MODULE_DIR}\LightPciBus.mbd" msaFilename="${MODULE_DIR}\LightPciBus.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\LightPciBusPciBus_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\LightPciBusPciBus_build.xml" target="clean"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
+ </target>
+ <target name="PciBusPciBusLite_clean">
+ <OutputDirSetup baseName="PciBusPciBusLite" mbdFilename="${MODULE_DIR}\PciBusLite.mbd" msaFilename="${MODULE_DIR}\PciBusLite.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\PciBusPciBusLite_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\PciBusPciBusLite_build.xml" target="clean"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
+ </target>
+ <target name="PciBus_cleanall">
+ <OutputDirSetup baseName="PciBus" mbdFilename="${MODULE_DIR}\PciBus.mbd" msaFilename="${MODULE_DIR}\PciBus.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\PciBus_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\PciBus_build.xml" target="cleanall"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}"/>
+ <delete dir="${DEST_DIR_DEBUG}"/>
+ <delete>
+ <fileset dir="${BIN_DIR}" includes="**PciBus*"/>
+ </delete>
+ </target>
+ <target name="LightPciBusPciBus_cleanall">
+ <OutputDirSetup baseName="LightPciBusPciBus" mbdFilename="${MODULE_DIR}\LightPciBus.mbd" msaFilename="${MODULE_DIR}\LightPciBus.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\LightPciBusPciBus_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\LightPciBusPciBus_build.xml" target="cleanall"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}"/>
+ <delete dir="${DEST_DIR_DEBUG}"/>
+ <delete>
+ <fileset dir="${BIN_DIR}" includes="**LightPciBusPciBus*"/>
+ </delete>
+ </target>
+ <target name="PciBusPciBusLite_cleanall">
+ <OutputDirSetup baseName="PciBusPciBusLite" mbdFilename="${MODULE_DIR}\PciBusLite.mbd" msaFilename="${MODULE_DIR}\PciBusLite.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\PciBusPciBusLite_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\PciBusPciBusLite_build.xml" target="cleanall"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}"/>
+ <delete dir="${DEST_DIR_DEBUG}"/>
+ <delete>
+ <fileset dir="${BIN_DIR}" includes="**PciBusPciBusLite*"/>
+ </delete>
+ </target>
+</project> \ No newline at end of file
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/pcibus.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/pcibus.c
new file mode 100644
index 0000000..16a3301
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/pcibus.c
@@ -0,0 +1,375 @@
+/*++
+
+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:
+
+ PciBus.c
+
+Abstract:
+
+ PCI Bus Driver
+
+Revision History
+
+--*/
+
+#include "PciBus.h"
+
+//
+// PCI Bus Support Function Prototypes
+//
+
+EFI_STATUS
+EFIAPI
+PciBusEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+EFI_STATUS
+EFIAPI
+PciBusDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+EFIAPI
+PciBusDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+EFIAPI
+PciBusDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+//
+// PCI Bus Driver Global Variables
+//
+
+EFI_DRIVER_BINDING_PROTOCOL gPciBusDriverBinding = {
+ PciBusDriverBindingSupported,
+ PciBusDriverBindingStart,
+ PciBusDriverBindingStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL *gEfiIncompatiblePciDeviceSupport = NULL;
+EFI_HANDLE gPciHostBrigeHandles[PCI_MAX_HOST_BRIDGE_NUM];
+UINTN gPciHostBridgeNumber;
+BOOLEAN gFullEnumeration;
+UINT64 gAllOne = 0xFFFFFFFFFFFFFFFFULL;
+UINT64 gAllZero = 0;
+
+EFI_PCI_PLATFORM_PROTOCOL *gPciPlatformProtocol;
+
+//
+// PCI Bus Driver Support Functions
+//
+EFI_STATUS
+EFIAPI
+PciBusEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ Initialize the global variables
+ publish the driver binding protocol
+
+Arguments:
+
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_DEVICE_ERROR
+
+--*/
+// TODO: ImageHandle - add argument and description to function comment
+// TODO: SystemTable - add argument and description to function comment
+{
+ EFI_STATUS Status;
+
+ InitializePciDevicePool ();
+
+ gFullEnumeration = TRUE;
+
+ gPciHostBridgeNumber = 0;
+
+ InstallHotPlugRequestProtocol (&Status);
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+PciBusDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+Routine Description:
+
+ Check to see if pci bus driver supports the given controller
+
+Arguments:
+
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Controller - add argument and description to function comment
+// TODO: RemainingDevicePath - add argument and description to function comment
+// TODO: EFI_UNSUPPORTED - add return value to function comment
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+ EFI_DEV_PATH_PTR Node;
+
+ if (RemainingDevicePath != NULL) {
+ Node.DevPath = RemainingDevicePath;
+ if (Node.DevPath->Type != HARDWARE_DEVICE_PATH ||
+ Node.DevPath->SubType != HW_PCI_DP ||
+ DevicePathNodeLength(Node.DevPath) != sizeof(PCI_DEVICE_PATH)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+ //
+ // Open the IO Abstraction(s) needed to perform the supported test
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (Status == EFI_ALREADY_STARTED) {
+ return EFI_SUCCESS;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ (VOID **) &PciRootBridgeIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (Status == EFI_ALREADY_STARTED) {
+ return EFI_SUCCESS;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PciBusDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+Routine Description:
+
+ Start to management the controller passed in
+
+Arguments:
+
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+
+Returns:
+
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Controller - add argument and description to function comment
+// TODO: RemainingDevicePath - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol (
+ &gEfiIncompatiblePciDeviceSupportProtocolGuid,
+ NULL,
+ (VOID **) &gEfiIncompatiblePciDeviceSupport
+ );
+
+ //
+ // If PCI Platform protocol is available, get it now.
+ // If the platform implements this, it must be installed before BDS phase
+ //
+ gPciPlatformProtocol = NULL;
+ gBS->LocateProtocol (
+ &gEfiPciPlatformProtocolGuid,
+ NULL,
+ (VOID **) &gPciPlatformProtocol
+ );
+
+ gFullEnumeration = (BOOLEAN) ((SearchHostBridgeHandle (Controller) ? FALSE : TRUE));
+
+ //
+ // Enumerate the entire host bridge
+ // After enumeration, a database that records all the device information will be created
+ //
+ //
+ Status = PciEnumerator (Controller);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Enable PCI device specified by remaining device path. BDS or other driver can call the
+ // start more than once.
+ //
+
+ StartPciDevices (Controller, RemainingDevicePath);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+PciBusDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+/*++
+
+Routine Description:
+
+ Stop one or more children created at start of pci bus driver
+ if all the the children get closed, close the protocol
+
+Arguments:
+
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+
+Returns:
+
+
+--*/
+// TODO: This - add argument and description to function comment
+// TODO: Controller - add argument and description to function comment
+// TODO: NumberOfChildren - add argument and description to function comment
+// TODO: ChildHandleBuffer - add argument and description to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+// TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ BOOLEAN AllChildrenStopped;
+
+ if (NumberOfChildren == 0) {
+ //
+ // Close the bus driver
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ DestroyRootBridgeByHandle (
+ Controller
+ );
+
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Stop all the children
+ //
+
+ AllChildrenStopped = TRUE;
+
+ for (Index = 0; Index < NumberOfChildren; Index++) {
+
+ //
+ // De register all the pci device
+ //
+ Status = DeRegisterPciDevice (Controller, ChildHandleBuffer[Index]);
+
+ if (EFI_ERROR (Status)) {
+ AllChildrenStopped = FALSE;
+ }
+ }
+
+ if (!AllChildrenStopped) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/pcibus.h b/EdkModulePkg/Bus/Pci/PciBus/Dxe/pcibus.h
new file mode 100644
index 0000000..170a4e2
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/pcibus.h
@@ -0,0 +1,243 @@
+/*++
+
+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:
+
+ PciBus.h
+
+Abstract:
+
+ PCI Bus Driver
+
+Revision History
+
+--*/
+
+#ifndef _EFI_PCI_BUS_H
+#define _EFI_PCI_BUS_H
+
+
+#include <IndustryStandard/Pci22.h>
+#include <IndustryStandard/Acpi.h>
+#include "ComponentName.h"
+
+//
+// Driver Produced Protocol Prototypes
+//
+
+#define VGABASE1 0x3B0
+#define VGALIMIT1 0x3BB
+
+#define VGABASE2 0x3C0
+#define VGALIMIT2 0x3DF
+
+#define ISABASE 0x100
+#define ISALIMIT 0x3FF
+
+typedef enum {
+ PciBarTypeUnknown = 0,
+ PciBarTypeIo16,
+ PciBarTypeIo32,
+ PciBarTypeMem32,
+ PciBarTypePMem32,
+ PciBarTypeMem64,
+ PciBarTypePMem64,
+ PciBarTypeIo,
+ PciBarTypeMem,
+ PciBarTypeMaxType
+} PCI_BAR_TYPE;
+
+typedef struct {
+ UINT64 BaseAddress;
+ UINT64 Length;
+ UINT64 Alignment;
+ PCI_BAR_TYPE BarType;
+ BOOLEAN Prefetchable;
+ UINT8 MemType;
+ UINT8 Offset;
+} PCI_BAR;
+
+#define PPB_BAR_0 0
+#define PPB_BAR_1 1
+#define PPB_IO_RANGE 2
+#define PPB_MEM32_RANGE 3
+#define PPB_PMEM32_RANGE 4
+#define PPB_PMEM64_RANGE 5
+#define PPB_MEM64_RANGE 0xFF
+
+#define P2C_BAR_0 0
+#define P2C_MEM_1 1
+#define P2C_MEM_2 2
+#define P2C_IO_1 3
+#define P2C_IO_2 4
+
+#define PCI_IO_DEVICE_SIGNATURE EFI_SIGNATURE_32 ('p', 'c', 'i', 'o')
+
+#define EFI_BRIDGE_IO32_DECODE_SUPPORTED 0x0001
+#define EFI_BRIDGE_PMEM32_DECODE_SUPPORTED 0x0002
+#define EFI_BRIDGE_PMEM64_DECODE_SUPPORTED 0x0004
+#define EFI_BRIDGE_IO16_DECODE_SUPPORTED 0x0008
+#define EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED 0x0010
+#define EFI_BRIDGE_MEM64_DECODE_SUPPORTED 0x0020
+#define EFI_BRIDGE_MEM32_DECODE_SUPPORTED 0x0040
+
+#define PCI_MAX_HOST_BRIDGE_NUM 0x0010
+//
+// Define resource status constant
+//
+#define EFI_RESOURCE_NONEXISTENT 0xFFFFFFFFFFFFFFFFULL
+#define EFI_RESOURCE_LESS 0xFFFFFFFFFFFFFFFEULL
+#define EFI_RESOURCE_SATISFIED 0x0000000000000000ULL
+
+//
+// Define option for attribute
+//
+#define EFI_SET_SUPPORTS 0
+#define EFI_SET_ATTRIBUTES 1
+
+typedef struct _PCI_IO_DEVICE {
+ UINT32 Signature;
+ EFI_HANDLE Handle;
+ EFI_PCI_IO_PROTOCOL PciIo;
+ LIST_ENTRY Link;
+
+ EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL PciDriverOverride;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+
+ //
+ // PCI configuration space header type
+ //
+ PCI_TYPE00 Pci;
+
+ //
+ // Bus number, Device number, Function number
+ //
+ UINT8 BusNumber;
+ UINT8 DeviceNumber;
+ UINT8 FunctionNumber;
+
+ //
+ // BAR for this PCI Device
+ //
+ PCI_BAR PciBar[PCI_MAX_BAR];
+
+ //
+ // The bridge device this pci device is subject to
+ //
+ struct _PCI_IO_DEVICE *Parent;
+
+ //
+ // A linked list for children Pci Device if it is bridge device
+ //
+ LIST_ENTRY ChildList;
+
+ //
+ // TURE if the PCI bus driver creates the handle for this PCI device
+ //
+ BOOLEAN Registered;
+
+ //
+ // TRUE if the PCI bus driver successfully allocates the resource required by
+ // this PCI device
+ //
+ BOOLEAN Allocated;
+
+ //
+ // The attribute this PCI device currently set
+ //
+ UINT64 Attributes;
+
+ //
+ // The attributes this PCI device actually supports
+ //
+ UINT64 Supports;
+
+ //
+ // The resource decode the bridge supports
+ //
+ UINT32 Decodes;
+
+ //
+ // The OptionRom Size
+ //
+ UINT64 RomSize;
+
+ //
+ // The OptionRom Size
+ //
+ UINT64 RomBase;
+
+ //
+ // TRUE if all OpROM (in device or in platform specific position) have been processed
+ //
+ BOOLEAN AllOpRomProcessed;
+
+ //
+ // TRUE if there is any EFI driver in the OptionRom
+ //
+ BOOLEAN BusOverride;
+
+ //
+ // A list tracking reserved resource on a bridge device
+ //
+ LIST_ENTRY ReservedResourceList;
+
+ //
+ // A list tracking image handle of platform specific overriding driver
+ //
+ LIST_ENTRY OptionRomDriverList;
+
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ResourcePaddingDescriptors;
+ EFI_HPC_PADDING_ATTRIBUTES PaddingAttributes;
+
+ BOOLEAN IsPciExp;
+
+} PCI_IO_DEVICE;
+
+
+#define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \
+ CR (a, PCI_IO_DEVICE, PciIo, PCI_IO_DEVICE_SIGNATURE)
+
+#define PCI_IO_DEVICE_FROM_PCI_DRIVER_OVERRIDE_THIS(a) \
+ CR (a, PCI_IO_DEVICE, PciDriverOverride, PCI_IO_DEVICE_SIGNATURE)
+
+#define PCI_IO_DEVICE_FROM_LINK(a) \
+ CR (a, PCI_IO_DEVICE, Link, PCI_IO_DEVICE_SIGNATURE)
+
+//
+// Global Variables
+//
+extern EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL *gEfiIncompatiblePciDeviceSupport;
+extern EFI_DRIVER_BINDING_PROTOCOL gPciBusDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gPciBusComponentName;
+extern LIST_ENTRY gPciDevicePool;
+extern BOOLEAN gFullEnumeration;
+extern UINTN gPciHostBridgeNumber;
+extern EFI_HANDLE gPciHostBrigeHandles[PCI_MAX_HOST_BRIDGE_NUM];
+extern UINT64 gAllOne;
+extern UINT64 gAllZero;
+
+extern EFI_PCI_PLATFORM_PROTOCOL *gPciPlatformProtocol;
+
+#include "PciIo.h"
+#include "PciCommand.h"
+#include "PciDeviceSupport.h"
+#include "PciEnumerator.h"
+#include "PciEnumeratorSupport.h"
+#include "PciDriverOverride.h"
+#include "PciRomTable.h"
+#include "PciOptionRomSupport.h"
+#include "PciPowerManagement.h"
+#include "PciHotPlugSupport.h"
+#include "PciLib.h"
+
+#endif
diff --git a/EdkModulePkg/Bus/Pci/Uhci/Dxe/ComponentName.c b/EdkModulePkg/Bus/Pci/Uhci/Dxe/ComponentName.c
new file mode 100644
index 0000000..71d9339
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/Uhci/Dxe/ComponentName.c
@@ -0,0 +1,189 @@
+/*++
+
+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:
+
+ ComponentName.c
+
+Abstract:
+
+--*/
+
+#include "uhci.h"
+
+//
+// EFI Component Name Functions
+//
+EFI_STATUS
+EFIAPI
+UhciComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+EFI_STATUS
+EFIAPI
+UhciComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle, OPTIONAL
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+//
+// EFI Component Name Protocol
+//
+EFI_COMPONENT_NAME_PROTOCOL gUhciComponentName = {
+ UhciComponentNameGetDriverName,
+ UhciComponentNameGetControllerName,
+ "eng"
+};
+
+static EFI_UNICODE_STRING_TABLE mUhciDriverNameTable[] = {
+ { "eng", (CHAR16 *) L"Usb Uhci Driver" },
+ { NULL , NULL }
+};
+
+EFI_STATUS
+EFIAPI
+UhciComponentNameGetDriverName (
+ 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,
+ gUhciComponentName.SupportedLanguages,
+ mUhciDriverNameTable,
+ DriverName
+ );
+}
+
+EFI_STATUS
+EFIAPI
+UhciComponentNameGetControllerName (
+ 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;
+ USB_HC_DEV *UhciDev;
+ EFI_USB_HC_PROTOCOL *UsbHc;
+
+ //
+ // This is a device driver, so ChildHandle must be NULL.
+ //
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Get the device context
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiUsbHcProtocolGuid,
+ (VOID **) &UsbHc,
+ gUhciDriverBinding.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ UhciDev = USB_HC_DEV_FROM_THIS (UsbHc);
+
+ return LookupUnicodeString (
+ Language,
+ gUhciComponentName.SupportedLanguages,
+ UhciDev->ControllerNameTable,
+ ControllerName
+ );
+
+}
diff --git a/EdkModulePkg/Bus/Pci/Uhci/Dxe/Uhci.mbd b/EdkModulePkg/Bus/Pci/Uhci/Dxe/Uhci.mbd
new file mode 100644
index 0000000..76d35e7
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/Uhci/Dxe/Uhci.mbd
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MbdHeader>
+ <BaseName>Uhci</BaseName>
+ <Guid>2FB92EFA-2EE0-4bae-9EB6-7464125E1EF7</Guid>
+ <Version>0</Version>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Created>2006-03-12 17:09</Created>
+ <Modified>2006-03-19 15:18</Modified>
+ </MbdHeader>
+ <Libraries>
+ <Library>UefiBootServicesTableLib</Library>
+ <Library>UefiMemoryLib</Library>
+ <Library>UefiLib</Library>
+ <Library>UefiDriverEntryPoint</Library>
+ <Library>UefiDriverModelLib</Library>
+ <Library>DxeReportStatusCodeLib</Library>
+ <Library>BaseDebugLibReportStatusCode</Library>
+ <Library>EdkDxePrintLib</Library>
+ <Library>BaseLib</Library>
+ <Library>DxeMemoryAllocationLib</Library>
+ </Libraries>
+</ModuleBuildDescription>
diff --git a/EdkModulePkg/Bus/Pci/Uhci/Dxe/Uhci.msa b/EdkModulePkg/Bus/Pci/Uhci/Dxe/Uhci.msa
new file mode 100644
index 0000000..9e91154
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/Uhci/Dxe/Uhci.msa
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MsaHeader>
+ <BaseName>Uhci</BaseName>
+ <ModuleType>UEFI_DRIVER</ModuleType>
+ <ComponentType>BS_DRIVER</ComponentType>
+ <Guid>2FB92EFA-2EE0-4bae-9EB6-7464125E1EF7</Guid>
+ <Version>0</Version>
+ <Abstract>Component description file for Uhci module</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Specification>0</Specification>
+ <Created>2006-03-12 17:09</Created>
+ <Updated>2006-03-19 15:18</Updated>
+ </MsaHeader>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverModelLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverEntryPoint</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">MemoryAllocationLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiBootServicesTableLib</LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>uhci.c</Filename>
+ <Filename>uhchlp.c</Filename>
+ <Filename>ComponentName.c</Filename>
+ <Filename>uhci.h</Filename>
+ </SourceFiles>
+ <Includes>
+ <PackageName>MdePkg</PackageName>
+ </Includes>
+ <Protocols>
+ <Protocol Usage="TO_START">PciIo</Protocol>
+ <Protocol Usage="BY_START">UsbHc</Protocol>
+ </Protocols>
+ <Externs>
+ <Extern>
+ <ModuleEntryPoint></ModuleEntryPoint>
+ </Extern>
+ <Extern>
+ <DriverBinding>gUhciDriverBinding</DriverBinding>
+ <ComponentName>gUhciComponentName</ComponentName>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea>
diff --git a/EdkModulePkg/Bus/Pci/Uhci/Dxe/build.xml b/EdkModulePkg/Bus/Pci/Uhci/Dxe/build.xml
new file mode 100644
index 0000000..37bb3c3
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/Uhci/Dxe/build.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- 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.-->
+<project basedir="." default="Uhci"><!--Apply external ANT tasks-->
+ <taskdef resource="GenBuild.tasks"/>
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+ <property environment="env"/>
+ <property name="WORKSPACE_DIR" value="${env.WORKSPACE}"/>
+ <import file="${WORKSPACE_DIR}\Tools\Conf\BuildMacro.xml"/><!--MODULE_RELATIVE PATH is relative to PACKAGE_DIR-->
+ <property name="MODULE_RELATIVE_PATH" value="Bus\Pci\Uhci\Dxe"/>
+ <property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
+ <property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
+ <target name="Uhci">
+ <GenBuild baseName="Uhci" mbdFilename="${MODULE_DIR}\Uhci.mbd" msaFilename="${MODULE_DIR}\Uhci.msa"/>
+ </target>
+ <target depends="Uhci_clean" name="clean"/>
+ <target depends="Uhci_cleanall" name="cleanall"/>
+ <target name="Uhci_clean">
+ <OutputDirSetup baseName="Uhci" mbdFilename="${MODULE_DIR}\Uhci.mbd" msaFilename="${MODULE_DIR}\Uhci.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\Uhci_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\Uhci_build.xml" target="clean"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
+ </target>
+ <target name="Uhci_cleanall">
+ <OutputDirSetup baseName="Uhci" mbdFilename="${MODULE_DIR}\Uhci.mbd" msaFilename="${MODULE_DIR}\Uhci.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\Uhci_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\Uhci_build.xml" target="cleanall"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}"/>
+ <delete dir="${DEST_DIR_DEBUG}"/>
+ <delete>
+ <fileset dir="${BIN_DIR}" includes="**Uhci*"/>
+ </delete>
+ </target>
+</project> \ No newline at end of file
diff --git a/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhchlp.c b/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhchlp.c
new file mode 100644
index 0000000..62d58ee
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhchlp.c
@@ -0,0 +1,4237 @@
+/*++
+
+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:
+
+ UhcHlp.c
+
+Abstract:
+
+
+Revision History
+--*/
+
+#include "uhci.h"
+
+EFI_STATUS
+USBReadPortW (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 PortOffset,
+ IN OUT UINT16 *Data
+ )
+/*++
+
+Routine Description:
+
+ USBReadPort Word
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ PortOffset - Port offset
+ Data - Data to reutrn
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ //
+ // Perform 16bit Read in PCI IO Space
+ //
+ return PciIo->Io.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ USB_BAR_INDEX,
+ (UINT64) PortOffset,
+ 1,
+ Data
+ );
+}
+
+EFI_STATUS
+USBReadPortDW (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 PortOffset,
+ IN OUT UINT32 *Data
+ )
+/*++
+
+Routine Description:
+
+ USBReadPort DWord
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ PortOffset - Port offset
+ Data - Data to reutrn
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ //
+ // Perform 32bit Read in PCI IO Space
+ //
+ return PciIo->Io.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ USB_BAR_INDEX,
+ (UINT64) PortOffset,
+ 1,
+ Data
+ );
+}
+
+EFI_STATUS
+USBWritePortW (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 PortOffset,
+ IN UINT16 Data
+ )
+/*++
+
+Routine Description:
+
+ USB Write Port Word
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ PortOffset - Port offset
+ Data - Data to write
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ //
+ // Perform 16bit Write in PCI IO Space
+ //
+ return PciIo->Io.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ USB_BAR_INDEX,
+ (UINT64) PortOffset,
+ 1,
+ &Data
+ );
+}
+
+EFI_STATUS
+USBWritePortDW (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 PortOffset,
+ IN UINT32 Data
+ )
+/*++
+
+Routine Description:
+
+ USB Write Port DWord
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ PortOffset - Port offset
+ Data - Data to write
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ //
+ // Perform 32bit Write in PCI IO Space
+ //
+ return PciIo->Io.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ USB_BAR_INDEX,
+ (UINT64) PortOffset,
+ 1,
+ &Data
+ );
+}
+//
+// USB register-base helper functions
+//
+EFI_STATUS
+WriteUHCCommandReg (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 CmdAddrOffset,
+ IN UINT16 UsbCmd
+ )
+/*++
+
+Routine Description:
+
+ Write UHCI Command Register
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ CmdAddrOffset - Command address offset
+ UsbCmd - Data to write
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ //
+ // Write to UHC's Command Register
+ //
+ return USBWritePortW (PciIo, CmdAddrOffset, UsbCmd);
+}
+
+EFI_STATUS
+ReadUHCCommandReg (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 CmdAddrOffset,
+ IN OUT UINT16 *Data
+ )
+/*++
+
+Routine Description:
+
+ Read UHCI Command Register
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ CmdAddrOffset - Command address offset
+ Data - Data to return
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ //
+ // Read from UHC's Command Register
+ //
+ return USBReadPortW (PciIo, CmdAddrOffset, Data);
+}
+
+EFI_STATUS
+WriteUHCStatusReg (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 StatusAddrOffset,
+ IN UINT16 UsbSts
+ )
+/*++
+
+Routine Description:
+
+ Write UHCI Staus Register
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ StatusAddrOffset - Status address offset
+ UsbSts - Data to write
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ //
+ // Write to UHC's Status Register
+ //
+ return USBWritePortW (PciIo, StatusAddrOffset, UsbSts);
+}
+
+EFI_STATUS
+ReadUHCStatusReg (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 StatusAddrOffset,
+ IN OUT UINT16 *Data
+ )
+/*++
+
+Routine Description:
+
+ Read UHCI Staus Register
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ StatusAddrOffset - Status address offset
+ UsbSts - Data to return
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ //
+ // Read from UHC's Status Register
+ //
+ return USBReadPortW (PciIo, StatusAddrOffset, Data);
+}
+
+
+EFI_STATUS
+ClearStatusReg (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 StatusAddrOffset
+ )
+/*++
+
+Routine Description:
+
+ Clear the content of UHC's Status Register
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ StatusAddrOffset - Status address offset
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+
+ return WriteUHCStatusReg (PciIo, StatusAddrOffset, 0x003F);
+}
+
+EFI_STATUS
+ReadUHCFrameNumberReg (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 FrameNumAddrOffset,
+ IN OUT UINT16 *Data
+ )
+/*++
+
+Routine Description:
+
+ Read from UHC's Frame Number Register
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ FrameNumAddrOffset - Frame number register offset
+ Data - Data to return
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+
+ return USBReadPortW (PciIo, FrameNumAddrOffset, Data);
+}
+
+EFI_STATUS
+WriteUHCFrameListBaseReg (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 FlBaseAddrOffset,
+ IN UINT32 UsbFrameListBaseAddr
+ )
+/*++
+
+Routine Description:
+
+ Write to UHC's Frame List Base Register
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ FlBaseAddrOffset - Frame Base address register
+ UsbFrameListBaseAddr - Address to write
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+
+ return USBWritePortDW (PciIo, FlBaseAddrOffset, UsbFrameListBaseAddr);
+}
+
+EFI_STATUS
+ReadRootPortReg (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 PortAddrOffset,
+ IN OUT UINT16 *Data
+ )
+/*++
+
+Routine Description:
+
+ Read from UHC's Root Port Register
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ PortAddrOffset - Port Addrress Offset,
+ Data - Data to return
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+
+ return USBReadPortW (PciIo, PortAddrOffset, Data);
+}
+
+EFI_STATUS
+WriteRootPortReg (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 PortAddrOffset,
+ IN UINT16 ControlBits
+ )
+/*++
+
+Routine Description:
+
+ Write to UHC's Root Port Register
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ PortAddrOffset - Port Addrress Offset,
+ ControlBits - Data to write
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+
+ return USBWritePortW (PciIo, PortAddrOffset, ControlBits);
+}
+
+
+
+EFI_STATUS
+WaitForUHCHalt (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 StatusRegAddr,
+ IN UINTN Timeout
+ )
+/*++
+
+Routine Description:
+
+ Wait until UHCI halt or timeout
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ StatusRegAddr - Status Register Address
+ Timeout - Time out value in us
+
+Returns:
+
+ EFI_DEVICE_ERROR - Unable to read the status register
+ EFI_TIMEOUT - Time out
+ EFI_SUCCESS - Success
+
+--*/
+{
+ UINTN Delay;
+ EFI_STATUS Status;
+ UINT16 HcStatus;
+
+ //
+ // Timeout is in us unit
+ //
+ Delay = (Timeout / 50) + 1;
+ do {
+ Status = ReadUHCStatusReg (PciIo, StatusRegAddr, &HcStatus);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ((HcStatus & USBSTS_HCH) == USBSTS_HCH) {
+ break;
+ }
+ //
+ // Stall for 50 us
+ //
+ gBS->Stall (50);
+
+ } while (Delay--);
+
+ if (Delay == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+IsStatusOK (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 StatusRegAddr
+ )
+/*++
+
+Routine Description:
+
+ Judge whether the host controller operates well
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ StatusRegAddr - Status register address
+
+Returns:
+
+ TRUE - Status is good
+ FALSE - Status is bad
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT16 HcStatus;
+ //
+ // Detect whether the interrupt is caused by fatal error.
+ // see "UHCI Design Guid".
+ //
+ Status = ReadUHCStatusReg (PciIo, StatusRegAddr, &HcStatus);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ if (HcStatus & (USBSTS_HCPE | USBSTS_HSE | USBSTS_HCH)) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+
+}
+
+
+BOOLEAN
+IsHostSysOrProcessErr (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 StatusRegAddr
+ )
+/*++
+
+Routine Description:
+
+ Judge the status is HostSys,ProcessErr error or good
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ StatusRegAddr - Status register address
+
+Returns:
+
+ TRUE - Status is good
+ FALSE - Status is bad
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT16 HcStatus;
+ //
+ // Detect whether the interrupt is caused by serious error.
+ // see "UHCI Design Guid".
+ //
+ Status = ReadUHCStatusReg (PciIo, StatusRegAddr, &HcStatus);
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ if (HcStatus & (USBSTS_HSE | USBSTS_HCPE)) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+
+UINT16
+GetCurrentFrameNumber (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 FrameNumAddrOffset
+ )
+/*++
+
+Routine Description:
+
+ Get Current Frame Number
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ FrameNumAddrOffset - FrameNum register AddrOffset
+
+Returns:
+
+ Frame number
+
+--*/
+{
+ //
+ // Gets value in the USB frame number register.
+ //
+ UINT16 FrameNumber;
+
+ ReadUHCFrameNumberReg (PciIo, FrameNumAddrOffset, &FrameNumber);
+
+ return (UINT16) (FrameNumber & 0x03FF);
+}
+
+EFI_STATUS
+SetFrameListBaseAddress (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 FlBaseAddrReg,
+ IN UINT32 Addr
+ )
+/*++
+
+Routine Description:
+
+ Set FrameListBase Address
+
+Arguments:
+
+ PciIo - EFI_PCI_IO_PROTOCOL
+ FlBaseAddrReg - FrameListBase register
+ Addr - Address to set
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ //
+ // Sets value in the USB Frame List Base Address register.
+ //
+ return WriteUHCFrameListBaseReg (PciIo, FlBaseAddrReg, (UINT32) (Addr & 0xFFFFF000));
+}
+
+VOID
+EnableMaxPacketSize (
+ IN USB_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Enable Max Packet Size
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+
+Returns:
+
+ VOID
+
+--*/
+{
+ UINT16 CommandContent;
+ EFI_STATUS Status;
+
+ Status = ReadUHCCommandReg (
+ HcDev->PciIo,
+ (UINT32) (USBCMD),
+ &CommandContent
+ );
+
+ if ((CommandContent & USBCMD_MAXP) != USBCMD_MAXP) {
+ CommandContent |= USBCMD_MAXP;
+ WriteUHCCommandReg (
+ HcDev->PciIo,
+ (UINT32) (USBCMD),
+ CommandContent
+ );
+ }
+
+ return ;
+}
+
+EFI_STATUS
+CreateFrameList (
+ IN USB_HC_DEV *HcDev,
+ IN UINT32 FlBaseAddrReg
+ )
+/*++
+
+Routine Description:
+
+ CreateFrameList
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ FlBaseAddrReg - Frame List register
+
+Returns:
+
+ EFI_OUT_OF_RESOURCES - Can't allocate memory resources
+ EFI_UNSUPPORTED - Map memory fail
+ EFI_SUCCESS - Success
+
+--*/
+{
+ EFI_STATUS Status;
+ VOID *CommonBuffer;
+ EFI_PHYSICAL_ADDRESS MappedAddress;
+ VOID *Mapping;
+ UINTN BufferSizeInPages;
+ UINTN BufferSizeInBytes;
+
+ //
+ // The Frame List is a common buffer that will be
+ // accessed by both the cpu and the usb bus master
+ // at the same time.
+ // The Frame List ocupies 4K bytes,
+ // and must be aligned on 4-Kbyte boundaries.
+ //
+ BufferSizeInBytes = 4096;
+ BufferSizeInPages = EFI_SIZE_TO_PAGES (BufferSizeInBytes);
+ Status = HcDev->PciIo->AllocateBuffer (
+ HcDev->PciIo,
+ AllocateAnyPages,
+ EfiBootServicesData,
+ BufferSizeInPages,
+ &CommonBuffer,
+ 0
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = HcDev->PciIo->Map (
+ HcDev->PciIo,
+ EfiPciIoOperationBusMasterCommonBuffer,
+ CommonBuffer,
+ &BufferSizeInBytes,
+ &MappedAddress,
+ &Mapping
+ );
+ if (EFI_ERROR (Status) || (BufferSizeInBytes != 4096)) {
+ HcDev->PciIo->FreeBuffer (HcDev->PciIo, BufferSizeInPages, CommonBuffer);
+ return EFI_UNSUPPORTED;
+ }
+
+ HcDev->FrameListEntry = (FRAMELIST_ENTRY *) ((UINTN) MappedAddress);
+
+ HcDev->FrameListMapping = Mapping;
+
+ InitFrameList (HcDev);
+
+ //
+ // Tell the Host Controller where the Frame List lies,
+ // by set the Frame List Base Address Register.
+ //
+ SetFrameListBaseAddress (
+ HcDev->PciIo,
+ FlBaseAddrReg,
+ (UINT32) ((UINTN) HcDev->FrameListEntry)
+ );
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FreeFrameListEntry (
+ IN USB_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Free FrameList buffer
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS - success
+
+--*/
+{
+ //
+ // Unmap the common buffer for framelist entry,
+ // and free the common buffer.
+ // Uhci's frame list occupy 4k memory.
+ //
+ HcDev->PciIo->Unmap (HcDev->PciIo, HcDev->FrameListMapping);
+ HcDev->PciIo->FreeBuffer (
+ HcDev->PciIo,
+ EFI_SIZE_TO_PAGES (4096),
+ (VOID *) (HcDev->FrameListEntry)
+ );
+ return EFI_SUCCESS;
+}
+
+VOID
+InitFrameList (
+ IN USB_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Initialize FrameList
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+
+Returns:
+ VOID
+
+--*/
+{
+ FRAMELIST_ENTRY *FrameListPtr;
+ UINTN Index;
+
+ //
+ // Validate each Frame List Entry
+ //
+ FrameListPtr = HcDev->FrameListEntry;
+ for (Index = 0; Index < 1024; Index++) {
+ FrameListPtr->FrameListPtrTerminate = 1;
+ FrameListPtr->FrameListPtr = 0;
+ FrameListPtr->FrameListPtrQSelect = 0;
+ FrameListPtr->FrameListRsvd = 0;
+ FrameListPtr++;
+ }
+}
+//
+// //////////////////////////////////////////////////////////////
+//
+// QH TD related Helper Functions
+//
+////////////////////////////////////////////////////////////////
+//
+// functions for QH
+//
+EFI_STATUS
+AllocateQHStruct (
+ IN USB_HC_DEV *HcDev,
+ OUT QH_STRUCT **ppQHStruct
+ )
+/*++
+
+Routine Description:
+
+ Allocate QH Struct
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ ppQHStruct - QH_STRUCT content to return
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ *ppQHStruct = NULL;
+
+ //
+ // QH must align on 16 bytes alignment,
+ // since the memory allocated by UhciAllocatePool ()
+ // is aligned on 32 bytes, it is no need to adjust
+ // the allocated memory returned.
+ //
+ return UhciAllocatePool (HcDev, (UINT8 **) ppQHStruct, sizeof (QH_STRUCT));
+}
+
+
+EFI_STATUS
+CreateQH (
+ IN USB_HC_DEV *HcDev,
+ OUT QH_STRUCT **pptrQH
+ )
+/*++
+
+Routine Description:
+
+ CreateQH
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ ppQHStruct - QH_STRUCT content to return
+Returns:
+
+ EFI_SUCCESS - Success
+ EFI_OUT_OF_RESOURCES - Can't allocate memory
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // allocate align memory for QH_STRUCT
+ //
+ Status = AllocateQHStruct (HcDev, pptrQH);
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // init each field of the QH_STRUCT
+ //
+ //
+ // Make QH ready
+ //
+ SetQHHorizontalValidorInvalid (*pptrQH, FALSE);
+ SetQHVerticalValidorInvalid (*pptrQH, FALSE);
+
+ return EFI_SUCCESS;
+}
+
+VOID
+SetQHHorizontalLinkPtr (
+ IN QH_STRUCT *PtrQH,
+ IN VOID *ptrNext
+ )
+/*++
+
+Routine Description:
+
+ Set QH Horizontal Link Pointer
+
+Arguments:
+
+ PtrQH - QH_STRUCT
+ ptrNext - Data to write
+
+Returns:
+
+ VOID
+
+--*/
+{
+ //
+ // Since the QH_STRUCT is aligned on 16-byte boundaries,
+ // Only the highest 28bit of the address is valid
+ // (take 32bit address as an example).
+ //
+ PtrQH->QH.QHHorizontalPtr = (UINT32) ((UINTN) ptrNext >> 4);
+}
+
+VOID *
+GetQHHorizontalLinkPtr (
+ IN QH_STRUCT *PtrQH
+ )
+/*++
+
+Routine Description:
+
+ Get QH Horizontal Link Pointer
+
+Arguments:
+
+ PtrQH - QH_STRUCT
+
+
+Returns:
+
+ Data to return
+
+--*/
+{
+ //
+ // Restore the 28bit address to 32bit address
+ // (take 32bit address as an example)
+ //
+ return (VOID *) ((UINTN) (PtrQH->QH.QHHorizontalPtr << 4));
+}
+
+VOID
+SetQHHorizontalQHorTDSelect (
+ IN QH_STRUCT *PtrQH,
+ IN BOOLEAN bQH
+ )
+/*++
+
+Routine Description:
+
+ Set QH Horizontal QH or TD
+
+Arguments:
+
+ PtrQH - QH_STRUCT
+ bQH - TRUE is QH FALSE is TD
+
+Returns:
+ VOID
+
+--*/
+{
+ //
+ // if QH is connected, the specified bit is set,
+ // if TD is connected, the specified bit is cleared.
+ //
+ PtrQH->QH.QHHorizontalQSelect = bQH ? 1 : 0;
+}
+
+
+VOID
+SetQHHorizontalValidorInvalid (
+ IN QH_STRUCT *PtrQH,
+ IN BOOLEAN bValid
+ )
+/*++
+
+Routine Description:
+
+ Set QH Horizontal Valid or Invalid
+
+Arguments:
+
+ PtrQH - QH_STRUCT
+ bValid - TRUE is Valid FALSE is Invalid
+
+Returns:
+ VOID
+
+--*/
+{
+ //
+ // Valid means the horizontal link pointer is valid,
+ // else, it's invalid.
+ //
+ PtrQH->QH.QHHorizontalTerminate = bValid ? 0 : 1;
+}
+
+VOID
+SetQHVerticalLinkPtr (
+ IN QH_STRUCT *PtrQH,
+ IN VOID *ptrNext
+ )
+/*++
+
+Routine Description:
+
+ Set QH Vertical Link Pointer
+
+Arguments:
+
+ PtrQH - QH_STRUCT
+ ptrNext - Data to write
+Returns:
+
+ VOID
+
+--*/
+{
+ //
+ // Since the QH_STRUCT is aligned on 16-byte boundaries,
+ // Only the highest 28bit of the address is valid
+ // (take 32bit address as an example).
+ //
+ PtrQH->QH.QHVerticalPtr = (UINT32) ((UINTN) ptrNext >> 4);
+}
+
+VOID *
+GetQHVerticalLinkPtr (
+ IN QH_STRUCT *PtrQH
+ )
+/*++
+
+Routine Description:
+
+ Get QH Vertical Link Pointer
+
+Arguments:
+
+ PtrQH - QH_STRUCT
+
+Returns:
+
+ Data to return
+
+--*/
+{
+ //
+ // Restore the 28bit address to 32bit address
+ // (take 32bit address as an example)
+ //
+ return (VOID *) ((UINTN) (PtrQH->QH.QHVerticalPtr << 4));
+}
+
+VOID
+SetQHVerticalQHorTDSelect (
+ IN QH_STRUCT *PtrQH,
+ IN BOOLEAN bQH
+ )
+/*++
+
+Routine Description:
+
+ Set QH Vertical QH or TD
+
+Arguments:
+
+ PtrQH - QH_STRUCT
+ bQH - TRUE is QH FALSE is TD
+
+Returns:
+
+ VOID
+
+--*/
+{
+ //
+ // Set the specified bit if the Vertical Link Pointer pointing to a QH,
+ // Clear the specified bit if the Vertical Link Pointer pointing to a TD.
+ //
+ PtrQH->QH.QHVerticalQSelect = bQH ? 1 : 0;
+}
+
+BOOLEAN
+IsQHHorizontalQHSelect (
+ IN QH_STRUCT *PtrQH
+ )
+/*++
+
+Routine Description:
+
+ Is QH Horizontal QH Select
+
+Arguments:
+
+ PtrQH - QH_STRUCT
+
+Returns:
+
+ TRUE - QH
+ FALSE - TD
+
+--*/
+{
+ //
+ // Retrieve the information about whether the Horizontal Link Pointer
+ // pointing to a QH or TD.
+ //
+ return (BOOLEAN) (PtrQH->QH.QHHorizontalQSelect ? TRUE : FALSE);
+}
+
+VOID
+SetQHVerticalValidorInvalid (
+ IN QH_STRUCT *PtrQH,
+ IN BOOLEAN IsValid
+ )
+/*++
+
+Routine Description:
+
+ Set QH Vertical Valid or Invalid
+
+Arguments:
+
+ PtrQH - QH_STRUCT
+ IsValid - TRUE is valid FALSE is invalid
+
+Returns:
+
+ VOID
+
+--*/
+{
+ //
+ // If TRUE, indicates the Vertical Link Pointer field is valid,
+ // else, the field is invalid.
+ //
+ PtrQH->QH.QHVerticalTerminate = IsValid ? 0 : 1;
+}
+
+
+BOOLEAN
+GetQHVerticalValidorInvalid (
+ IN QH_STRUCT *PtrQH
+ )
+/*++
+
+Routine Description:
+
+ Get QH Vertical Valid or Invalid
+
+Arguments:
+
+ PtrQH - QH_STRUCT
+
+Returns:
+
+ TRUE - Valid
+ FALSE - Invalid
+
+--*/
+{
+ //
+ // If TRUE, indicates the Vertical Link Pointer field is valid,
+ // else, the field is invalid.
+ //
+ return (BOOLEAN) (!(PtrQH->QH.QHVerticalTerminate));
+}
+
+BOOLEAN
+GetQHHorizontalValidorInvalid (
+ IN QH_STRUCT *PtrQH
+ )
+/*++
+
+Routine Description:
+
+ Get QH Horizontal Valid or Invalid
+
+Arguments:
+
+ PtrQH - QH_STRUCT
+
+Returns:
+
+ TRUE - Valid
+ FALSE - Invalid
+
+--*/
+{
+ //
+ // If TRUE, meaning the Horizontal Link Pointer field is valid,
+ // else, the field is invalid.
+ //
+ return (BOOLEAN) (!(PtrQH->QH.QHHorizontalTerminate));
+}
+//
+// functions for TD
+//
+EFI_STATUS
+AllocateTDStruct (
+ IN USB_HC_DEV *HcDev,
+ OUT TD_STRUCT **ppTDStruct
+ )
+/*++
+
+Routine Description:
+
+ Allocate TD Struct
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ ppTDStruct - place to store TD_STRUCT pointer
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ *ppTDStruct = NULL;
+
+ //
+ // TD must align on 16 bytes alignment,
+ // since the memory allocated by UhciAllocatePool ()
+ // is aligned on 32 bytes, it is no need to adjust
+ // the allocated memory returned.
+ //
+ return UhciAllocatePool (
+ HcDev,
+ (UINT8 **) ppTDStruct,
+ sizeof (TD_STRUCT)
+ );
+}
+
+EFI_STATUS
+CreateTD (
+ IN USB_HC_DEV *HcDev,
+ OUT TD_STRUCT **pptrTD
+ )
+/*++
+
+Routine Description:
+
+ Create TD
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ pptrTD - TD_STRUCT pointer to store
+
+Returns:
+
+ EFI_OUT_OF_RESOURCES - Can't allocate resources
+ EFI_SUCCESS - Success
+
+--*/
+{
+ EFI_STATUS Status;
+ //
+ // create memory for TD_STRUCT, and align the memory.
+ //
+ Status = AllocateTDStruct (HcDev, pptrTD);
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Make TD ready.
+ //
+ SetTDLinkPtrValidorInvalid (*pptrTD, FALSE);
+
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GenSetupStageTD (
+ IN USB_HC_DEV *HcDev,
+ IN UINT8 DevAddr,
+ IN UINT8 Endpoint,
+ IN BOOLEAN bSlow,
+ IN UINT8 *pDevReq,
+ IN UINT8 RequestLen,
+ OUT TD_STRUCT **ppTD
+ )
+/*++
+
+Routine Description:
+
+ Generate Setup Stage TD
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ DevAddr - Device address
+ Endpoint - Endpoint number
+ bSlow - Full speed or low speed
+ pDevReq - Device request
+ RequestLen - Request length
+ ppTD - TD_STRUCT to return
+Returns:
+
+ EFI_OUT_OF_RESOURCES - Can't allocate memory
+ EFI_SUCCESS - Success
+
+--*/
+{
+ EFI_STATUS Status;
+ TD_STRUCT *pTDStruct;
+
+ Status = CreateTD (HcDev, &pTDStruct);
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SetTDLinkPtr (pTDStruct, NULL);
+
+ //
+ // Depth first fashion
+ //
+ SetTDLinkPtrDepthorBreadth (pTDStruct, TRUE);
+
+ //
+ // initialize as the last TD in the QH context,
+ // this field will be updated in the TD linkage process.
+ //
+ SetTDLinkPtrValidorInvalid (pTDStruct, FALSE);
+
+ //
+ // Disable Short Packet Detection by default
+ //
+ EnableorDisableTDShortPacket (pTDStruct, FALSE);
+
+ //
+ // Max error counter is 3, retry 3 times when error encountered.
+ //
+ SetTDControlErrorCounter (pTDStruct, 3);
+
+ //
+ // set device speed attribute
+ // (TRUE - Slow Device; FALSE - Full Speed Device)
+ //
+ SetTDLoworFullSpeedDevice (pTDStruct, bSlow);
+
+ //
+ // Non isochronous transfer TD
+ //
+ SetTDControlIsochronousorNot (pTDStruct, FALSE);
+
+ //
+ // Interrupt On Complete bit be set to zero,
+ // Disable IOC interrupt.
+ //
+ SetorClearTDControlIOC (pTDStruct, FALSE);
+
+ //
+ // Set TD Active bit
+ //
+ SetTDStatusActiveorInactive (pTDStruct, TRUE);
+
+ SetTDTokenMaxLength (pTDStruct, RequestLen);
+
+ SetTDTokenDataToggle0 (pTDStruct);
+
+ SetTDTokenEndPoint (pTDStruct, Endpoint);
+
+ SetTDTokenDeviceAddress (pTDStruct, DevAddr);
+
+ SetTDTokenPacketID (pTDStruct, SETUP_PACKET_ID);
+
+ pTDStruct->pTDBuffer = (UINT8 *) pDevReq;
+ pTDStruct->TDBufferLength = RequestLen;
+ SetTDDataBuffer (pTDStruct);
+
+ *ppTD = pTDStruct;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GenDataTD (
+ IN USB_HC_DEV *HcDev,
+ IN UINT8 DevAddr,
+ IN UINT8 Endpoint,
+ IN UINT8 *pData,
+ IN UINT8 Len,
+ IN UINT8 PktID,
+ IN UINT8 Toggle,
+ IN BOOLEAN bSlow,
+ OUT TD_STRUCT **ppTD
+ )
+/*++
+
+Routine Description:
+
+ Generate Data Stage TD
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ DevAddr - Device address
+ Endpoint - Endpoint number
+ pData - Data buffer
+ Len - Data length
+ PktID - Packet ID
+ Toggle - Data toggle value
+ bSlow - Full speed or low speed
+ ppTD - TD_STRUCT to return
+Returns:
+
+ EFI_OUT_OF_RESOURCES - Can't allocate memory
+ EFI_SUCCESS - Success
+
+--*/
+{
+ TD_STRUCT *pTDStruct;
+ EFI_STATUS Status;
+
+ Status = CreateTD (HcDev, &pTDStruct);
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SetTDLinkPtr (pTDStruct, NULL);
+
+ //
+ // Depth first fashion
+ //
+ SetTDLinkPtrDepthorBreadth (pTDStruct, TRUE);
+
+ //
+ // Link pointer pointing to TD struct
+ //
+ SetTDLinkPtrQHorTDSelect (pTDStruct, FALSE);
+
+ //
+ // initialize as the last TD in the QH context,
+ // this field will be updated in the TD linkage process.
+ //
+ SetTDLinkPtrValidorInvalid (pTDStruct, FALSE);
+
+ //
+ // Disable short packet detect
+ //
+ EnableorDisableTDShortPacket (pTDStruct, FALSE);
+ //
+ // Max error counter is 3
+ //
+ SetTDControlErrorCounter (pTDStruct, 3);
+
+ //
+ // set device speed attribute
+ // (TRUE - Slow Device; FALSE - Full Speed Device)
+ //
+ SetTDLoworFullSpeedDevice (pTDStruct, bSlow);
+
+ //
+ // Non isochronous transfer TD
+ //
+ SetTDControlIsochronousorNot (pTDStruct, FALSE);
+
+ //
+ // Disable Interrupt On Complete
+ // Disable IOC interrupt.
+ //
+ SetorClearTDControlIOC (pTDStruct, FALSE);
+
+ //
+ // Set Active bit
+ //
+ SetTDStatusActiveorInactive (pTDStruct, TRUE);
+
+ SetTDTokenMaxLength (pTDStruct, Len);
+
+ if (Toggle) {
+ SetTDTokenDataToggle1 (pTDStruct);
+ } else {
+ SetTDTokenDataToggle0 (pTDStruct);
+ }
+
+ SetTDTokenEndPoint (pTDStruct, Endpoint);
+
+ SetTDTokenDeviceAddress (pTDStruct, DevAddr);
+
+ SetTDTokenPacketID (pTDStruct, PktID);
+
+ pTDStruct->pTDBuffer = (UINT8 *) pData;
+ pTDStruct->TDBufferLength = Len;
+ SetTDDataBuffer (pTDStruct);
+ *ppTD = pTDStruct;
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+CreateStatusTD (
+ IN USB_HC_DEV *HcDev,
+ IN UINT8 DevAddr,
+ IN UINT8 Endpoint,
+ IN UINT8 PktID,
+ IN BOOLEAN bSlow,
+ OUT TD_STRUCT **ppTD
+ )
+/*++
+
+Routine Description:
+
+ Generate Status Stage TD
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ DevAddr - Device address
+ Endpoint - Endpoint number
+ PktID - Packet ID
+ bSlow - Full speed or low speed
+ ppTD - TD_STRUCT to return
+Returns:
+
+ EFI_OUT_OF_RESOURCES - Can't allocate memory
+ EFI_SUCCESS - Success
+
+--*/
+{
+ TD_STRUCT *ptrTDStruct;
+ EFI_STATUS Status;
+
+ Status = CreateTD (HcDev, &ptrTDStruct);
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SetTDLinkPtr (ptrTDStruct, NULL);
+
+ //
+ // Depth first fashion
+ //
+ SetTDLinkPtrDepthorBreadth (ptrTDStruct, TRUE);
+
+ //
+ // initialize as the last TD in the QH context,
+ // this field will be updated in the TD linkage process.
+ //
+ SetTDLinkPtrValidorInvalid (ptrTDStruct, FALSE);
+
+ //
+ // Disable short packet detect
+ //
+ EnableorDisableTDShortPacket (ptrTDStruct, FALSE);
+
+ //
+ // Max error counter is 3
+ //
+ SetTDControlErrorCounter (ptrTDStruct, 3);
+
+ //
+ // set device speed attribute
+ // (TRUE - Slow Device; FALSE - Full Speed Device)
+ //
+ SetTDLoworFullSpeedDevice (ptrTDStruct, bSlow);
+
+ //
+ // Non isochronous transfer TD
+ //
+ SetTDControlIsochronousorNot (ptrTDStruct, FALSE);
+
+ //
+ // Disable Interrupt On Complete
+ // Disable IOC interrupt.
+ //
+ SetorClearTDControlIOC (ptrTDStruct, FALSE);
+
+ //
+ // Set TD Active bit
+ //
+ SetTDStatusActiveorInactive (ptrTDStruct, TRUE);
+
+ SetTDTokenMaxLength (ptrTDStruct, 0);
+
+ SetTDTokenDataToggle1 (ptrTDStruct);
+
+ SetTDTokenEndPoint (ptrTDStruct, Endpoint);
+
+ SetTDTokenDeviceAddress (ptrTDStruct, DevAddr);
+
+ SetTDTokenPacketID (ptrTDStruct, PktID);
+
+ ptrTDStruct->pTDBuffer = NULL;
+ ptrTDStruct->TDBufferLength = 0;
+ SetTDDataBuffer (ptrTDStruct);
+
+ *ppTD = ptrTDStruct;
+
+ return EFI_SUCCESS;
+}
+
+
+VOID
+SetTDLinkPtrValidorInvalid (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN bValid
+ )
+/*++
+
+Routine Description:
+
+ Set TD Link Pointer Valid or Invalid
+
+Arguments:
+
+ ptrTDStruct - TD_STRUCT
+ bValid - TRUE is valid FALSE is invalid
+
+Returns:
+
+ VOID
+
+--*/
+{
+ //
+ // Valid means the link pointer is valid,
+ // else, it's invalid.
+ //
+ ptrTDStruct->TDData.TDLinkPtrTerminate = (bValid ? 0 : 1);
+}
+
+VOID
+SetTDLinkPtrQHorTDSelect (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN bQH
+ )
+/*++
+
+Routine Description:
+
+ Set TD Link Pointer QH or TD Select
+
+Arguments:
+
+ ptrTDStruct - TD_STRUCT
+ bQH - TRUE is QH FALSE is TD
+
+Returns:
+
+ VOID
+
+--*/
+{
+ //
+ // Indicate whether the Link Pointer pointing to a QH or TD
+ //
+ ptrTDStruct->TDData.TDLinkPtrQSelect = (bQH ? 1 : 0);
+}
+
+VOID
+SetTDLinkPtrDepthorBreadth (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN bDepth
+ )
+/*++
+
+Routine Description:
+
+ Set TD Link Pointer depth or bread priority
+
+Arguments:
+
+ ptrTDStruct - TD_STRUCT
+ bDepth - TRUE is Depth FALSE is Breadth
+
+Returns:
+
+ VOID
+
+--*/
+{
+ //
+ // If TRUE, indicating the host controller should process in depth first
+ // fashion,
+ // else, the host controller should process in breadth first fashion
+ //
+ ptrTDStruct->TDData.TDLinkPtrDepthSelect = (bDepth ? 1 : 0);
+}
+
+VOID
+SetTDLinkPtr (
+ IN TD_STRUCT *ptrTDStruct,
+ IN VOID *ptrNext
+ )
+/*++
+
+Routine Description:
+
+ Set TD Link Pointer
+
+Arguments:
+
+ ptrTDStruct - TD_STRUCT
+ ptrNext - Pointer to set
+
+Returns:
+
+ VOID
+
+--*/
+{
+ //
+ // Set TD Link Pointer. Since QH,TD align on 16-byte boundaries,
+ // only the highest 28 bits are valid. (if take 32bit address as an example)
+ //
+ ptrTDStruct->TDData.TDLinkPtr = (UINT32) ((UINTN) ptrNext >> 4);
+}
+
+VOID *
+GetTDLinkPtr (
+ IN TD_STRUCT *ptrTDStruct
+ )
+/*++
+
+Routine Description:
+
+ Get TD Link Pointer
+
+Arguments:
+
+ ptrTDStruct - TD_STRUCT
+
+Returns:
+
+ Pointer to get
+
+--*/
+{
+ //
+ // Get TD Link Pointer. Restore it back to 32bit
+ // (if take 32bit address as an example)
+ //
+ return (VOID *) ((UINTN) (ptrTDStruct->TDData.TDLinkPtr << 4));
+}
+
+BOOLEAN
+IsTDLinkPtrQHOrTD (
+ IN TD_STRUCT *ptrTDStruct
+ )
+/*++
+
+Routine Description:
+
+ Is TD Link Pointer is QH Or TD
+
+Arguments:
+
+ ptrTDStruct - TODO: add argument description
+
+Returns:
+
+ TRUE - QH
+ FALSE - TD
+
+--*/
+{
+ //
+ // Get the information about whether the Link Pointer field pointing to
+ // a QH or a TD.
+ //
+ return (BOOLEAN) (ptrTDStruct->TDData.TDLinkPtrQSelect);
+}
+
+VOID
+EnableorDisableTDShortPacket (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN bEnable
+ )
+/*++
+
+Routine Description:
+
+ Enable or Disable TD ShortPacket
+
+Arguments:
+
+ ptrTDStruct - TD_STRUCT
+ bEnable - TRUE is Enanble FALSE is Disable
+
+Returns:
+
+ VOID
+
+--*/
+{
+ //
+ // TRUE means enable short packet detection mechanism.
+ //
+ ptrTDStruct->TDData.TDStatusSPD = (bEnable ? 1 : 0);
+}
+
+VOID
+SetTDControlErrorCounter (
+ IN TD_STRUCT *ptrTDStruct,
+ IN UINT8 nMaxErrors
+ )
+/*++
+
+Routine Description:
+
+ Set TD Control ErrorCounter
+
+Arguments:
+
+ ptrTDStruct - TD_STRUCT
+ nMaxErrors - Error counter number
+
+Returns:
+
+ VOID
+
+--*/
+{
+ //
+ // valid value of nMaxErrors is 0,1,2,3
+ //
+ if (nMaxErrors > 3) {
+ nMaxErrors = 3;
+ }
+
+ ptrTDStruct->TDData.TDStatusErr = nMaxErrors;
+}
+
+
+VOID
+SetTDLoworFullSpeedDevice (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN bLowSpeedDevice
+ )
+{
+ //
+ // TRUE means the TD is targeting at a Low-speed device
+ //
+ ptrTDStruct->TDData.TDStatusLS = (bLowSpeedDevice ? 1 : 0);
+}
+
+VOID
+SetTDControlIsochronousorNot (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN IsIsochronous
+ )
+{
+ //
+ // TRUE means the TD belongs to Isochronous transfer type.
+ //
+ ptrTDStruct->TDData.TDStatusIOS = (IsIsochronous ? 1 : 0);
+}
+
+VOID
+SetorClearTDControlIOC (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN IsSet
+ )
+{
+ //
+ // If this bit is set, it indicates that the host controller should issue
+ // an interrupt on completion of the frame in which this TD is executed.
+ //
+ ptrTDStruct->TDData.TDStatusIOC = IsSet ? 1 : 0;
+}
+
+VOID
+SetTDStatusActiveorInactive (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN IsActive
+ )
+{
+ //
+ // If this bit is set, it indicates that the TD is active and can be
+ // executed.
+ //
+ if (IsActive) {
+ ptrTDStruct->TDData.TDStatus |= 0x80;
+ } else {
+ ptrTDStruct->TDData.TDStatus &= 0x7F;
+ }
+}
+
+UINT16
+SetTDTokenMaxLength (
+ IN TD_STRUCT *ptrTDStruct,
+ IN UINT16 MaximumLength
+ )
+{
+ //
+ // Specifies the maximum number of data bytes allowed for the transfer.
+ // the legal value extent is 0 ~ 0x500.
+ //
+ if (MaximumLength > 0x500) {
+ MaximumLength = 0x500;
+ }
+ ptrTDStruct->TDData.TDTokenMaxLen = MaximumLength - 1;
+
+ return MaximumLength;
+}
+
+VOID
+SetTDTokenDataToggle1 (
+ IN TD_STRUCT *ptrTDStruct
+ )
+{
+ //
+ // Set the data toggle bit to DATA1
+ //
+ ptrTDStruct->TDData.TDTokenDataToggle = 1;
+}
+
+VOID
+SetTDTokenDataToggle0 (
+ IN TD_STRUCT *ptrTDStruct
+ )
+{
+ //
+ // Set the data toggle bit to DATA0
+ //
+ ptrTDStruct->TDData.TDTokenDataToggle = 0;
+}
+
+UINT8
+GetTDTokenDataToggle (
+ IN TD_STRUCT *ptrTDStruct
+ )
+{
+ //
+ // Get the data toggle value.
+ //
+ return (UINT8) (ptrTDStruct->TDData.TDTokenDataToggle);
+}
+
+VOID
+SetTDTokenEndPoint (
+ IN TD_STRUCT *ptrTDStruct,
+ IN UINTN EndPoint
+ )
+{
+ //
+ // Set EndPoint Number the TD is targeting at.
+ //
+ ptrTDStruct->TDData.TDTokenEndPt = (UINT8) EndPoint;
+}
+
+VOID
+SetTDTokenDeviceAddress (
+ IN TD_STRUCT *ptrTDStruct,
+ IN UINTN DeviceAddress
+ )
+{
+ //
+ // Set Device Address the TD is targeting at.
+ //
+ ptrTDStruct->TDData.TDTokenDevAddr = (UINT8) DeviceAddress;
+}
+
+VOID
+SetTDTokenPacketID (
+ IN TD_STRUCT *ptrTDStruct,
+ IN UINT8 PID
+ )
+{
+ //
+ // Set the Packet Identification to be used for this transaction.
+ //
+ ptrTDStruct->TDData.TDTokenPID = PID;
+}
+
+VOID
+SetTDDataBuffer (
+ IN TD_STRUCT *ptrTDStruct
+ )
+{
+ //
+ // Set the beginning address of the data buffer that will be used
+ // during the transaction.
+ //
+ ptrTDStruct->TDData.TDBufferPtr = (UINT32) ((UINTN) (ptrTDStruct->pTDBuffer));
+}
+
+BOOLEAN
+IsTDStatusActive (
+ IN TD_STRUCT *ptrTDStruct
+ )
+{
+ UINT8 TDStatus;
+
+ //
+ // Detect whether the TD is active.
+ //
+ TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);
+ return (BOOLEAN) (TDStatus & 0x80);
+}
+
+BOOLEAN
+IsTDStatusStalled (
+ IN TD_STRUCT *ptrTDStruct
+ )
+{
+ UINT8 TDStatus;
+
+ //
+ // Detect whether the device/endpoint addressed by this TD is stalled.
+ //
+ TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);
+ return (BOOLEAN) (TDStatus & 0x40);
+}
+
+BOOLEAN
+IsTDStatusBufferError (
+ IN TD_STRUCT *ptrTDStruct
+ )
+{
+ UINT8 TDStatus;
+ //
+ // Detect whether Data Buffer Error is happened.
+ //
+ TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);
+ return (BOOLEAN) (TDStatus & 0x20);
+}
+
+BOOLEAN
+IsTDStatusBabbleError (
+ IN TD_STRUCT *ptrTDStruct
+ )
+{
+ UINT8 TDStatus;
+
+ //
+ // Detect whether Babble Error is happened.
+ //
+ TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);
+ return (BOOLEAN) (TDStatus & 0x10);
+}
+
+BOOLEAN
+IsTDStatusNAKReceived (
+ IN TD_STRUCT *ptrTDStruct
+ )
+{
+ UINT8 TDStatus;
+
+ //
+ // Detect whether NAK is received.
+ //
+ TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);
+ return (BOOLEAN) (TDStatus & 0x08);
+}
+
+BOOLEAN
+IsTDStatusCRCTimeOutError (
+ IN TD_STRUCT *ptrTDStruct
+ )
+{
+ UINT8 TDStatus;
+
+ //
+ // Detect whether CRC/Time Out Error is encountered.
+ //
+ TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);
+ return (BOOLEAN) (TDStatus & 0x04);
+}
+
+BOOLEAN
+IsTDStatusBitStuffError (
+ IN TD_STRUCT *ptrTDStruct
+ )
+{
+ UINT8 TDStatus;
+
+ //
+ // Detect whether Bitstuff Error is received.
+ //
+ TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus);
+ return (BOOLEAN) (TDStatus & 0x02);
+}
+
+UINT16
+GetTDStatusActualLength (
+ IN TD_STRUCT *ptrTDStruct
+ )
+{
+ //
+ // Retrieve the actual number of bytes that were tansferred.
+ // the value is encoded as n-1. so return the decoded value.
+ //
+ return (UINT16) ((ptrTDStruct->TDData.TDStatusActualLength) + 1);
+}
+
+UINT16
+GetTDTokenMaxLength (
+ IN TD_STRUCT *ptrTDStruct
+ )
+{
+ //
+ // Retrieve the maximum number of data bytes allowed for the trnasfer.
+ //
+ return (UINT16) ((ptrTDStruct->TDData.TDTokenMaxLen) + 1);
+}
+
+UINT8
+GetTDTokenEndPoint (
+ IN TD_STRUCT *ptrTDStruct
+ )
+{
+ //
+ // Retrieve the endpoint number the transaction is targeting at.
+ //
+ return (UINT8) (ptrTDStruct->TDData.TDTokenEndPt);
+}
+
+UINT8
+GetTDTokenDeviceAddress (
+ IN TD_STRUCT *ptrTDStruct
+ )
+{
+ //
+ // Retrieve the device address the transaction is targeting at.
+ //
+ return (UINT8) (ptrTDStruct->TDData.TDTokenDevAddr);
+}
+
+UINT8
+GetTDTokenPacketID (
+ IN TD_STRUCT *ptrTDStruct
+ )
+{
+ //
+ // Retrieve the Packet Identification information.
+ //
+ return (UINT8) (ptrTDStruct->TDData.TDTokenPID);
+}
+
+UINT8 *
+GetTDDataBuffer (
+ IN TD_STRUCT *ptrTDStruct
+ )
+{
+ //
+ // Retrieve the beginning address of the data buffer
+ // that involved in this transaction.
+ //
+ return ptrTDStruct->pTDBuffer;
+}
+
+BOOLEAN
+GetTDLinkPtrValidorInvalid (
+ IN TD_STRUCT *ptrTDStruct
+ )
+{
+ //
+ // Retrieve the information of whether the Link Pointer field
+ // is valid or not.
+ //
+ if (ptrTDStruct->TDData.TDLinkPtrTerminate) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+
+}
+
+UINTN
+CountTDsNumber (
+ IN TD_STRUCT *PtrFirstTD
+ )
+{
+ UINTN Number;
+ TD_STRUCT *ptr;
+ //
+ // Count the queued TDs number.
+ //
+ Number = 0;
+ ptr = PtrFirstTD;
+ while (ptr) {
+ ptr = (TD_STRUCT *) ptr->ptrNextTD;
+ Number++;
+ }
+
+ return Number;
+}
+
+
+
+VOID
+LinkTDToQH (
+ IN QH_STRUCT *PtrQH,
+ IN TD_STRUCT *PtrTD
+ )
+/*++
+
+Routine Description:
+
+ Link TD To QH
+
+Arguments:
+
+ PtrQH - QH_STRUCT
+ PtrTD - TD_STRUCT
+Returns:
+
+ VOID
+
+--*/
+{
+ if (PtrQH == NULL || PtrTD == NULL) {
+ return ;
+ }
+ //
+ // Validate QH Vertical Ptr field
+ //
+ SetQHVerticalValidorInvalid (PtrQH, TRUE);
+
+ //
+ // Vertical Ptr pointing to TD structure
+ //
+ SetQHVerticalQHorTDSelect (PtrQH, FALSE);
+
+ SetQHVerticalLinkPtr (PtrQH, (VOID *) PtrTD);
+
+ PtrQH->ptrDown = (VOID *) PtrTD;
+}
+
+VOID
+LinkTDToTD (
+ IN TD_STRUCT *ptrPreTD,
+ IN TD_STRUCT *PtrTD
+ )
+/*++
+
+Routine Description:
+
+ Link TD To TD
+
+Arguments:
+
+ ptrPreTD - Previous TD_STRUCT to be linked
+ PtrTD - TD_STRUCT to link
+Returns:
+
+ VOID
+
+--*/
+{
+ if (ptrPreTD == NULL || PtrTD == NULL) {
+ return ;
+ }
+ //
+ // Depth first fashion
+ //
+ SetTDLinkPtrDepthorBreadth (ptrPreTD, TRUE);
+
+ //
+ // Link pointer pointing to TD struct
+ //
+ SetTDLinkPtrQHorTDSelect (ptrPreTD, FALSE);
+
+ //
+ // Validate the link pointer valid bit
+ //
+ SetTDLinkPtrValidorInvalid (ptrPreTD, TRUE);
+
+ SetTDLinkPtr (ptrPreTD, PtrTD);
+
+ ptrPreTD->ptrNextTD = (VOID *) PtrTD;
+}
+//
+// Transfer Schedule related Helper Functions
+//
+VOID
+SetorClearCurFrameListTerminate (
+ IN FRAMELIST_ENTRY *pCurEntry,
+ IN BOOLEAN IsSet
+ )
+{
+ //
+ // If TRUE, empty the frame. If FALSE, indicate the Pointer field is valid.
+ //
+ pCurEntry->FrameListPtrTerminate = (IsSet ? 1 : 0);
+}
+
+VOID
+SetCurFrameListQHorTD (
+ IN FRAMELIST_ENTRY *pCurEntry,
+ IN BOOLEAN IsQH
+ )
+{
+ //
+ // This bit indicates to the hardware whether the item referenced by the
+ // link pointer is a TD or a QH.
+ //
+ pCurEntry->FrameListPtrQSelect = (IsQH ? 1 : 0);
+}
+
+BOOLEAN
+IsCurFrameListQHorTD (
+ IN FRAMELIST_ENTRY *pCurEntry
+ )
+{
+ //
+ // TRUE is QH
+ // FALSE is TD
+ //
+ return (BOOLEAN) (pCurEntry->FrameListPtrQSelect);
+}
+
+BOOLEAN
+GetCurFrameListTerminate (
+ IN FRAMELIST_ENTRY *pCurEntry
+ )
+{
+ //
+ // TRUE means the frame is empty,
+ // FALSE means the link pointer field is valid.
+ //
+ return (BOOLEAN) (pCurEntry->FrameListPtrTerminate);
+}
+
+VOID
+SetCurFrameListPointer (
+ IN FRAMELIST_ENTRY *pCurEntry,
+ IN UINT8 *ptr
+ )
+{
+ //
+ // Set the pointer field of the frame.
+ //
+ pCurEntry->FrameListPtr = (UINT32) ((UINTN) ptr >> 4);
+}
+
+VOID *
+GetCurFrameListPointer (
+ IN FRAMELIST_ENTRY *pCurEntry
+ )
+{
+ //
+ // Get the link pointer of the frame.
+ //
+ return (VOID *) ((UINTN) (pCurEntry->FrameListPtr << 4));
+
+}
+
+VOID
+LinkQHToFrameList (
+ IN FRAMELIST_ENTRY *pEntry,
+ IN UINT16 FrameListIndex,
+ IN QH_STRUCT *PtrQH
+ )
+/*++
+
+Routine Description:
+
+ Link QH To Frame List
+
+Arguments:
+
+ pEntry - FRAMELIST_ENTRY
+ FrameListIndex - Frame List Index
+ PtrQH - QH to link
+Returns:
+
+ VOID
+
+--*/
+{
+ FRAMELIST_ENTRY *pCurFrame;
+ QH_STRUCT *TempQH;
+ QH_STRUCT *NextTempQH;
+ TD_STRUCT *TempTD;
+ BOOLEAN LINK;
+
+ //
+ // Get frame list entry that the link process will begin from.
+ //
+ pCurFrame = pEntry + FrameListIndex;
+
+ //
+ // if current frame is empty
+ // then link the specified QH directly to the Frame List.
+ //
+ if (GetCurFrameListTerminate (pCurFrame)) {
+
+ //
+ // Link new QH to the frame list entry.
+ //
+ SetCurFrameListQHorTD (pCurFrame, TRUE);
+
+ SetCurFrameListPointer (pCurFrame, (UINT8 *) PtrQH);
+
+ //
+ // clear T bit in the Frame List, indicating that the frame list entry
+ // is no longer empty.
+ //
+ SetorClearCurFrameListTerminate (pCurFrame, FALSE);
+
+ return ;
+
+ } else {
+ //
+ // current frame list has link pointer
+ //
+ if (!IsCurFrameListQHorTD (pCurFrame)) {
+ //
+ // a TD is linked to the framelist entry
+ //
+ TempTD = (TD_STRUCT *) GetCurFrameListPointer (pCurFrame);
+
+ while (GetTDLinkPtrValidorInvalid (TempTD)) {
+
+ if (IsTDLinkPtrQHOrTD (TempTD)) {
+ //
+ // QH linked next to the TD
+ //
+ break;
+ }
+
+ TempTD = (TD_STRUCT *) GetTDLinkPtr (TempTD);
+ }
+
+ //
+ // either no ptr linked next to the TD or QH is linked next to the TD
+ //
+ if (!GetTDLinkPtrValidorInvalid (TempTD)) {
+
+ //
+ // no ptr linked next to the TD
+ //
+ TempTD->ptrNextQH = PtrQH;
+ SetTDLinkPtrQHorTDSelect (TempTD, TRUE);
+ SetTDLinkPtr (TempTD, PtrQH);
+ SetTDLinkPtrValidorInvalid (TempTD, TRUE);
+ return ;
+
+ } else {
+ //
+ // QH is linked next to the TD
+ //
+ TempQH = (QH_STRUCT *) GetTDLinkPtr (TempTD);
+ }
+ } else {
+ //
+ // a QH is linked to the framelist entry
+ //
+ TempQH = (QH_STRUCT *) GetCurFrameListPointer (pCurFrame);
+ }
+
+ //
+ // Set up Flag
+ //
+ LINK = TRUE;
+
+ //
+ // Avoid the same qh repeated linking in one frame entry
+ //
+ if (TempQH == PtrQH) {
+ LINK = FALSE;
+ return ;
+ }
+ //
+ // if current QH has next QH connected
+ //
+ while (GetQHHorizontalValidorInvalid (TempQH)) {
+ //
+ // Get next QH pointer
+ //
+ NextTempQH = (QH_STRUCT *) GetQHHorizontalLinkPtr (TempQH);
+
+ //
+ // Bulk transfer qh may be self-linked,
+ // so, the code below is to aVOID dead-loop when meeting self-linked qh
+ //
+ if (NextTempQH == TempQH) {
+ LINK = FALSE;
+ break;
+ }
+
+ TempQH = NextTempQH;
+
+ //
+ // Avoid the same qh repeated linking in one frame entry
+ //
+ if (TempQH == PtrQH) {
+ LINK = FALSE;
+ }
+ }
+
+ if (LINK) {
+ TempQH->ptrNext = PtrQH;
+ SetQHHorizontalQHorTDSelect (TempQH, TRUE);
+ SetQHHorizontalLinkPtr (TempQH, PtrQH);
+ SetQHHorizontalValidorInvalid (TempQH, TRUE);
+ }
+
+ return ;
+ }
+}
+
+EFI_STATUS
+ExecuteControlTransfer (
+ IN USB_HC_DEV *HcDev,
+ IN TD_STRUCT *PtrTD,
+ IN UINT32 wIndex,
+ OUT UINTN *ActualLen,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult
+ )
+/*++
+
+Routine Description:
+
+ Execute Control Transfer
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ PtrTD - TD_STRUCT
+ wIndex - No use
+ ActualLen - Actual transfered Len
+ TimeOut - TimeOut value in milliseconds
+ TransferResult - Transfer result
+Returns:
+
+ EFI_SUCCESS - Sucess
+ EFI_DEVICE_ERROR - Error
+
+
+--*/
+{
+ UINTN ErrTDPos;
+ UINTN Delay;
+ UINTN RequiredLen;
+ BOOLEAN TransferFinished;
+
+ ErrTDPos = 0;
+ *TransferResult = EFI_USB_NOERROR;
+ RequiredLen = *ActualLen;
+ *ActualLen = 0;
+
+ Delay = (TimeOut * STALL_1_MILLI_SECOND / 50) + 1;
+
+ do {
+ TransferFinished = CheckTDsResults (
+ PtrTD,
+ RequiredLen,
+ TransferResult,
+ &ErrTDPos,
+ ActualLen
+ );
+
+ if (TransferFinished) {
+ break;
+ }
+
+ //
+ // TD is inactive, which means the control transfer is end.
+ //
+ if ((*TransferResult & EFI_USB_ERR_NOTEXECUTE) != EFI_USB_ERR_NOTEXECUTE) {
+ break;
+ }
+
+ gBS->Stall (50);
+
+ } while (Delay--);
+
+ if (*TransferResult != EFI_USB_NOERROR) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ExecBulkorSyncInterruptTransfer (
+ IN USB_HC_DEV *HcDev,
+ IN TD_STRUCT *PtrTD,
+ IN UINT32 wIndex,
+ OUT UINTN *ActualLen,
+ OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult
+ )
+/*++
+
+Routine Description:
+
+ Execute Bulk or SyncInterrupt Transfer
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ PtrTD - TD_STRUCT
+ wIndex - No use
+ ActualLen - Actual transfered Len
+ DataToggle - Data Toggle
+ TimeOut - TimeOut value in milliseconds
+ TransferResult - Transfer result
+Returns:
+
+ EFI_SUCCESS - Sucess
+ EFI_DEVICE_ERROR - Error
+--*/
+{
+ UINTN ErrTDPos;
+ UINTN ScrollNum;
+ UINTN Delay;
+ UINTN RequiredLen;
+ BOOLEAN TransferFinished;
+
+ ErrTDPos = 0;
+ *TransferResult = EFI_USB_NOERROR;
+ RequiredLen = *ActualLen;
+ *ActualLen = 0;
+
+ Delay = (TimeOut * STALL_1_MILLI_SECOND / 50) + 1;
+
+ do {
+
+ TransferFinished = CheckTDsResults (
+ PtrTD,
+ RequiredLen,
+ TransferResult,
+ &ErrTDPos,
+ ActualLen
+ );
+
+ if (TransferFinished) {
+ break;
+ }
+
+ //
+ // TD is inactive, which means bulk or interrupt transfer's end.
+ //
+ if ((*TransferResult & EFI_USB_ERR_NOTEXECUTE) != EFI_USB_ERR_NOTEXECUTE) {
+ break;
+ }
+
+ gBS->Stall (50);
+
+ } while (Delay--);
+
+ //
+ // has error
+ //
+ if (*TransferResult != EFI_USB_NOERROR) {
+
+ //
+ // scroll the Data Toggle back to the last success TD
+ //
+ ScrollNum = CountTDsNumber (PtrTD) - ErrTDPos;
+ if (ScrollNum & 0x1) {
+ *DataToggle ^= 1;
+ }
+
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+VOID
+DelLinkSingleQH (
+ IN USB_HC_DEV *HcDev,
+ IN QH_STRUCT *PtrQH,
+ IN UINT16 FrameListIndex,
+ IN BOOLEAN SearchOther,
+ IN BOOLEAN Delete
+ )
+/*++
+
+Routine Description:
+
+ Unlink from frame list and delete single QH
+Arguments:
+
+ HcDev - USB_HC_DEV
+ PtrQH - QH_STRUCT
+ FrameListIndex - Frame List Index
+ SearchOther - Search Other QH
+ Delete - TRUE is to delete the QH
+Returns:
+ VOID
+--*/
+{
+ FRAMELIST_ENTRY *pCurFrame;
+ UINTN Index;
+ UINTN BeginFrame;
+ UINTN EndFrame;
+ QH_STRUCT *CurrentQH;
+ QH_STRUCT *NextQH;
+ TD_STRUCT *CurrentTD;
+ VOID *PtrPreQH;
+ BOOLEAN Found;
+
+ NextQH = NULL;
+ PtrPreQH = NULL;
+ Found = FALSE;
+
+ if (PtrQH == NULL) {
+ return ;
+ }
+
+ if (SearchOther) {
+ BeginFrame = 0;
+ EndFrame = 1024;
+ } else {
+ BeginFrame = FrameListIndex;
+ EndFrame = FrameListIndex + 1;
+ }
+
+ for (Index = BeginFrame; Index < EndFrame; Index++) {
+
+ pCurFrame = HcDev->FrameListEntry + (Index & 0x3FF);
+
+ if (GetCurFrameListTerminate (pCurFrame)) {
+ //
+ // current frame list is empty,search next frame list entry
+ //
+ continue;
+ }
+
+ if (!IsCurFrameListQHorTD (pCurFrame)) {
+ //
+ // TD linked to current framelist
+ //
+ CurrentTD = (TD_STRUCT *) GetCurFrameListPointer (pCurFrame);
+
+ while (GetTDLinkPtrValidorInvalid (CurrentTD)) {
+
+ if (IsTDLinkPtrQHOrTD (CurrentTD)) {
+ //
+ // QH linked next to the TD,break while ()
+ //
+ break;
+ }
+
+ CurrentTD = (TD_STRUCT *) GetTDLinkPtr (CurrentTD);
+ }
+
+ if (!GetTDLinkPtrValidorInvalid (CurrentTD)) {
+ //
+ // no QH linked next to the last TD,
+ // search next frame list
+ //
+ continue;
+ }
+
+ //
+ // a QH linked next to the last TD
+ //
+ CurrentQH = (QH_STRUCT *) GetTDLinkPtr (CurrentTD);
+
+ PtrPreQH = CurrentTD;
+
+ } else {
+ //
+ // a QH linked to current framelist
+ //
+ CurrentQH = (QH_STRUCT *) GetCurFrameListPointer (pCurFrame);
+
+ PtrPreQH = NULL;
+ }
+
+ if (CurrentQH == PtrQH) {
+
+ if (GetQHHorizontalValidorInvalid (PtrQH)) {
+ //
+ // there is QH connected after the QH found
+ //
+ //
+ // retrieve nex qh pointer of the qh found.
+ //
+ NextQH = GetQHHorizontalLinkPtr (PtrQH);
+ } else {
+ NextQH = NULL;
+ }
+
+ if (PtrPreQH) {
+ //
+ // QH linked to a TD struct
+ //
+ CurrentTD = (TD_STRUCT *) PtrPreQH;
+
+ SetTDLinkPtrValidorInvalid (CurrentTD, (BOOLEAN) ((NextQH == NULL) ? FALSE : TRUE));
+ SetTDLinkPtr (CurrentTD, NextQH);
+ CurrentTD->ptrNextQH = NextQH;
+
+ } else {
+ //
+ // QH linked directly to current framelist entry
+ //
+ SetorClearCurFrameListTerminate (pCurFrame, (BOOLEAN) ((NextQH == NULL) ? TRUE : FALSE));
+ SetCurFrameListPointer (pCurFrame, (UINT8 *) NextQH);
+ }
+
+ Found = TRUE;
+ //
+ // search next framelist entry
+ //
+ continue;
+ }
+
+ while (GetQHHorizontalValidorInvalid (CurrentQH)) {
+
+ PtrPreQH = CurrentQH;
+ //
+ // Get next horizontal linked QH
+ //
+ CurrentQH = (QH_STRUCT *) GetQHHorizontalLinkPtr (CurrentQH);
+ //
+ // the qh is found
+ //
+ if (CurrentQH == PtrQH) {
+ break;
+ }
+ }
+
+ //
+ // search next frame list entry
+ //
+ if (CurrentQH != PtrQH) {
+ //
+ // Not find the QH
+ //
+ continue;
+ }
+ //
+ // find the specified qh, then delink it from
+ // the horizontal QH list in the frame entry.
+ //
+
+ if (GetQHHorizontalValidorInvalid (PtrQH)) {
+ //
+ // there is QH connected after the QH found
+ //
+ //
+ // retrieve nex qh pointer of the qh found.
+ //
+ NextQH = GetQHHorizontalLinkPtr (PtrQH);
+
+ } else {
+ //
+ // NO QH connected after the QH found
+ //
+ NextQH = NULL;
+ //
+ // NULL the previous QH's link ptr and set Terminate field.
+ //
+ SetQHHorizontalValidorInvalid ((QH_STRUCT *) PtrPreQH, FALSE);
+ }
+
+ SetQHHorizontalLinkPtr ((QH_STRUCT *) PtrPreQH, NextQH);
+ ((QH_STRUCT *) PtrPreQH)->ptrNext = NextQH;
+
+ Found = TRUE;
+ }
+
+ if (Found && Delete) {
+ //
+ // free memory once used by the specific QH
+ //
+ UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));
+ }
+
+ return ;
+}
+
+
+VOID
+DeleteQueuedTDs (
+ IN USB_HC_DEV *HcDev,
+ IN TD_STRUCT *PtrFirstTD
+ )
+/*++
+Routine Description:
+
+ Delete Queued TDs
+Arguments:
+
+ HcDev - USB_HC_DEV
+ PtrFirstTD - TD link list head
+
+Returns:
+ VOID
+
+--*/
+{
+ TD_STRUCT *Tptr1;
+ TD_STRUCT *Tptr2;
+
+ Tptr1 = PtrFirstTD;
+ //
+ // Delete all the TDs in a queue.
+ //
+ while (Tptr1) {
+
+ Tptr2 = Tptr1;
+
+ if (!GetTDLinkPtrValidorInvalid (Tptr2)) {
+ Tptr1 = NULL;
+ } else {
+
+ Tptr1 = GetTDLinkPtr (Tptr2);
+
+ //
+ // TD link to itself
+ //
+ if (Tptr1 == Tptr2) {
+ Tptr1 = NULL;
+ }
+ }
+
+ UhciFreePool (HcDev, (UINT8 *) Tptr2, sizeof (TD_STRUCT));
+ }
+
+ return ;
+}
+
+VOID
+InsertQHTDToINTList (
+ IN USB_HC_DEV *HcDev,
+ IN QH_STRUCT *PtrQH,
+ IN TD_STRUCT *PtrFirstTD,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DataToggle,
+ IN UINTN DataLength,
+ IN UINTN PollingInterval,
+ IN VOID *Mapping,
+ IN UINT8 *DataBuffer,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,
+ IN VOID *Context
+ )
+/*++
+Routine Description:
+ Insert QH and TD To Interrupt List
+Arguments:
+
+ HcDev - USB_HC_DEV
+ PtrQH - QH_STRUCT
+ PtrFirstTD - First TD_STRUCT
+ DeviceAddress - Device Address
+ EndPointAddress - EndPoint Address
+ DataToggle - Data Toggle
+ DataLength - Data length
+ PollingInterval - Polling Interval when inserted to frame list
+ Mapping - Mapping alue
+ DataBuffer - Data buffer
+ CallBackFunction- CallBackFunction after interrupt transfeer
+ Context - CallBackFunction Context passed as function parameter
+Returns:
+ EFI_SUCCESS - Sucess
+ EFI_INVALID_PARAMETER - Paremeter is error
+
+--*/
+{
+ INTERRUPT_LIST *Node;
+
+ Node = AllocatePool (sizeof (INTERRUPT_LIST));
+ if (Node == NULL) {
+ return ;
+ }
+
+ //
+ // Fill Node field
+ //
+ Node->Signature = INTERRUPT_LIST_SIGNATURE;
+ Node->DevAddr = DeviceAddress;
+ Node->EndPoint = EndPointAddress;
+ Node->PtrQH = PtrQH;
+ Node->PtrFirstTD = PtrFirstTD;
+ Node->DataToggle = DataToggle;
+ Node->DataLen = DataLength;
+ Node->PollInterval = PollingInterval;
+ Node->Mapping = Mapping;
+ //
+ // DataBuffer is allocated host memory, not mapped memory
+ //
+ Node->DataBuffer = DataBuffer;
+ Node->InterruptCallBack = CallBackFunction;
+ Node->InterruptContext = Context;
+
+ //
+ // insert the new interrupt transfer to the head of the list.
+ // The interrupt transfer's monitor function scans the whole list from head
+ // to tail. The new interrupt transfer MUST be added to the head of the list
+ // for the sake of error recovery.
+ //
+ InsertHeadList (&(HcDev->InterruptListHead), &(Node->Link));
+
+ return ;
+}
+
+
+EFI_STATUS
+DeleteAsyncINTQHTDs (
+ IN USB_HC_DEV *HcDev,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ OUT UINT8 *DataToggle
+ )
+/*++
+Routine Description:
+
+ Delete Async INT QH and TDs
+Arguments:
+
+ HcDev - USB_HC_DEV
+ DeviceAddress - Device Address
+ EndPointAddress - EndPoint Address
+ DataToggle - Data Toggle
+
+Returns:
+ EFI_SUCCESS - Sucess
+ EFI_INVALID_PARAMETER - Paremeter is error
+
+--*/
+{
+ QH_STRUCT *MatchQH;
+ QH_STRUCT *ptrNextQH;
+ TD_STRUCT *MatchTD;
+ LIST_ENTRY *Link;
+ INTERRUPT_LIST *MatchList;
+ INTERRUPT_LIST *PtrList;
+ BOOLEAN Found;
+
+ UINT32 Result;
+ UINTN ErrTDPos;
+ UINTN ActualLen;
+
+ MatchQH = NULL;
+ MatchTD = NULL;
+ MatchList = NULL;
+
+ //
+ // no interrupt transaction exists
+ //
+ if (IsListEmpty (&(HcDev->InterruptListHead))) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // find the correct QH-TD that need to delete
+ // (by matching Device address and EndPoint number to match QH-TD )
+ //
+ Found = FALSE;
+ Link = &(HcDev->InterruptListHead);
+ do {
+
+ Link = Link->ForwardLink;
+ PtrList = INTERRUPT_LIST_FROM_LINK (Link);
+
+ if ((PtrList->DevAddr == DeviceAddress) && ((PtrList->EndPoint & 0x0f) == (EndPointAddress & 0x0f))) {
+ MatchList = PtrList;
+
+ Found = TRUE;
+ break;
+ }
+
+ } while (Link->ForwardLink != &(HcDev->InterruptListHead));
+
+ if (!Found) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // get current endpoint's data toggle bit and save.
+ //
+ ExecuteAsyncINTTDs (HcDev, MatchList, &Result, &ErrTDPos, &ActualLen);
+ UpdateAsyncINTQHTDs (MatchList, Result, (UINT32) ErrTDPos);
+ *DataToggle = MatchList->DataToggle;
+
+ MatchTD = MatchList->PtrFirstTD;
+ MatchQH = MatchList->PtrQH;
+ //
+ // find the first matching QH position in the FrameList
+ //
+ while (MatchQH) {
+
+ ptrNextQH = MatchQH->ptrNextIntQH;
+
+ //
+ // Search all the entries
+ //
+ DelLinkSingleQH (HcDev, MatchQH, 0, TRUE, TRUE);
+
+ MatchQH = ptrNextQH;
+ }
+
+ //
+ // Call PciIo->Unmap() to unmap the busmaster read/write
+ //
+ HcDev->PciIo->Unmap (HcDev->PciIo, MatchList->Mapping);
+
+ //
+ // free host data buffer allocated,
+ // mapped data buffer is freed by Unmap
+ //
+ if (MatchList->DataBuffer != NULL) {
+ gBS->FreePool (MatchList->DataBuffer);
+ }
+
+ //
+ // at last delete the TDs, to aVOID problems
+ //
+ DeleteQueuedTDs (HcDev, MatchTD);
+
+ //
+ // remove Match node from interrupt list
+ //
+ RemoveEntryList (&(MatchList->Link));
+ gBS->FreePool (MatchList);
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+CheckTDsResults (
+ IN TD_STRUCT *PtrTD,
+ IN UINTN RequiredLen,
+ OUT UINT32 *Result,
+ OUT UINTN *ErrTDPos,
+ OUT UINTN *ActualTransferSize
+ )
+/*++
+
+Routine Description:
+
+ Check TDs Results
+
+Arguments:
+
+ PtrTD - TD_STRUCT to check
+ RequiredLen - Required Len
+ Result - Transfer result
+ ErrTDPos - Error TD Position
+ ActualTransferSize - Actual Transfer Size
+
+Returns:
+
+ TRUE - Sucess
+ FALSE - Fail
+
+--*/
+{
+ UINTN Len;
+
+ *Result = EFI_USB_NOERROR;
+ *ErrTDPos = 0;
+
+ //
+ // Init to zero.
+ //
+ *ActualTransferSize = 0;
+
+ while (PtrTD) {
+
+ if (IsTDStatusActive (PtrTD)) {
+ *Result |= EFI_USB_ERR_NOTEXECUTE;
+ }
+
+ if (IsTDStatusStalled (PtrTD)) {
+ *Result |= EFI_USB_ERR_STALL;
+ }
+
+ if (IsTDStatusBufferError (PtrTD)) {
+ *Result |= EFI_USB_ERR_BUFFER;
+ }
+
+ if (IsTDStatusBabbleError (PtrTD)) {
+ *Result |= EFI_USB_ERR_BABBLE;
+ }
+
+ if (IsTDStatusNAKReceived (PtrTD)) {
+ *Result |= EFI_USB_ERR_NAK;
+ }
+
+ if (IsTDStatusCRCTimeOutError (PtrTD)) {
+ *Result |= EFI_USB_ERR_TIMEOUT;
+ }
+
+ if (IsTDStatusBitStuffError (PtrTD)) {
+ *Result |= EFI_USB_ERR_BITSTUFF;
+ }
+
+ //
+ // if any error encountered, stop processing the left TDs.
+ //
+ if (*Result) {
+ return FALSE;
+ }
+
+ Len = GetTDStatusActualLength (PtrTD) & 0x7FF;
+ *ActualTransferSize += Len;
+
+ if (*ActualTransferSize <= RequiredLen && Len < PtrTD->TDData.TDTokenMaxLen) {
+ //
+ // transter finished and actural length less than required length
+ //
+ goto Done;
+ }
+ //
+ // Accumulate actual transferred data length in each TD.
+ //
+ PtrTD = (TD_STRUCT *) (PtrTD->ptrNextTD);
+ //
+ // Record the first Error TD's position in the queue,
+ // this value is zero-based.
+ //
+ (*ErrTDPos)++;
+ }
+
+Done:
+ return TRUE;
+}
+
+
+VOID
+ExecuteAsyncINTTDs (
+ IN USB_HC_DEV *HcDev,
+ IN INTERRUPT_LIST *PtrList,
+ OUT UINT32 *Result,
+ OUT UINTN *ErrTDPos,
+ OUT UINTN *ActualLen
+ )
+/*++
+
+Routine Description:
+
+ Execute Async Interrupt TDs
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ PtrList - INTERRUPT_LIST
+ Result - Transfer result
+ ErrTDPos - Error TD Position
+ ActualTransferSize - Actual Transfer Size
+
+Returns:
+
+ VOID
+
+--*/
+{
+ //
+ // *ErrTDPos is zero-based value, indicating the first error TD's position
+ // in the TDs' sequence.
+ // *ErrTDPos value is only valid when *Result is not equal NOERROR.
+ //
+ UINTN RequiredLen;
+
+ RequiredLen = *ActualLen;
+ CheckTDsResults (PtrList->PtrFirstTD, RequiredLen, Result, ErrTDPos, ActualLen);
+
+ return ;
+}
+
+
+VOID
+UpdateAsyncINTQHTDs (
+ IN INTERRUPT_LIST *PtrList,
+ IN UINT32 Result,
+ IN UINT32 ErrTDPos
+ )
+/*++
+
+Routine Description:
+
+ Update Async Interrupt QH and TDs
+
+Arguments:
+
+ PtrList - INTERRUPT_LIST
+ Result - Transfer reslut
+ ErrTDPos - Error TD Position
+
+Returns:
+
+ VOID
+
+--*/
+{
+ QH_STRUCT *PtrFirstQH;
+ QH_STRUCT *PtrQH;
+ TD_STRUCT *PtrFirstTD;
+ TD_STRUCT *PtrTD;
+ UINT8 DataToggle;
+ UINT32 Index;
+
+ PtrFirstQH = PtrList->PtrQH;
+ PtrFirstTD = PtrList->PtrFirstTD;
+
+ DataToggle = 0;
+
+ if (Result == EFI_USB_NOERROR) {
+
+ PtrTD = PtrFirstTD;
+ while (PtrTD) {
+ DataToggle = GetTDTokenDataToggle (PtrTD);
+ PtrTD = PtrTD->ptrNextTD;
+ }
+
+ //
+ // save current DataToggle value to interrupt list.
+ // this value is used for tracing the interrupt endpoint DataToggle.
+ // when this interrupt transfer is deleted, the last DataToggle is saved
+ //
+ PtrList->DataToggle = DataToggle;
+
+ PtrTD = PtrFirstTD;
+
+ //
+ // Since DataToggle bit should toggle after each success transaction,
+ // the First TD's DataToggle bit will be updated to XOR of Last TD's
+ // DataToggle bit. If the First TD's DataToggle bit is not equal Last
+ // TD's DataToggle bit, that means it already be the XOR of Last TD's,
+ // so no update is needed.
+ //
+ if (DataToggle == GetTDTokenDataToggle (PtrFirstTD)) {
+ PtrTD = PtrFirstTD;
+ while (PtrTD) {
+
+ DataToggle ^= 1;
+ if (DataToggle) {
+ SetTDTokenDataToggle1 (PtrTD);
+ } else {
+ SetTDTokenDataToggle0 (PtrTD);
+ }
+
+ PtrTD = PtrTD->ptrNextTD;
+ }
+ }
+ //
+ // restore Link Pointer of QH to First TD
+ // (because QH's Link Pointer will change during TD execution)
+ //
+ PtrQH = PtrFirstQH;
+ while (PtrQH) {
+
+ LinkTDToQH (PtrQH, PtrFirstTD);
+ PtrQH = PtrQH->ptrNextIntQH;
+ }
+
+ //
+ // set all the TDs active
+ //
+ PtrTD = PtrFirstTD;
+ while (PtrTD) {
+ SetTDStatusActiveorInactive (PtrTD, TRUE);
+ PtrTD = PtrTD->ptrNextTD;
+ }
+
+ } else if (((Result & EFI_USB_ERR_NOTEXECUTE) == EFI_USB_ERR_NOTEXECUTE) ||
+ ((Result & EFI_USB_ERR_NAK) == EFI_USB_ERR_NAK)
+ ) {
+ //
+ // no update
+ //
+ } else {
+ //
+ // Have Errors
+ //
+ PtrTD = PtrFirstTD;
+ //
+ // not first TD error
+ //
+ if (ErrTDPos != 0) {
+ //
+ // get the last success TD
+ //
+ for (Index = 1; Index < ErrTDPos; Index++) {
+ PtrTD = PtrTD->ptrNextTD;
+ }
+ //
+ // update Data Toggle in the interrupt list node
+ //
+ PtrList->DataToggle = GetTDTokenDataToggle (PtrTD);
+
+ //
+ // get the error TD
+ //
+ PtrTD = PtrTD->ptrNextTD;
+
+ } else {
+ PtrList->DataToggle = GetTDTokenDataToggle (PtrTD);
+ }
+ //
+ // do not restore the QH's vertical link pointer,
+ // let the callback function do the rest of error handling.
+ //
+ }
+
+ return ;
+}
+
+VOID
+ReleaseInterruptList (
+ IN USB_HC_DEV *HcDev,
+ IN LIST_ENTRY *ListHead
+ )
+/*++
+
+Routine Description:
+
+ Release Interrupt List
+Arguments:
+
+ HcDev - USB_HC_DEV
+ ListHead - List head
+
+Returns:
+
+ VOID
+
+--*/
+{
+ LIST_ENTRY *Link;
+ LIST_ENTRY *SavedLink;
+ INTERRUPT_LIST *pNode;
+ TD_STRUCT *PtrTD;
+ TD_STRUCT *ptrNextTD;
+ QH_STRUCT *PtrQH;
+ QH_STRUCT *SavedQH;
+
+ if (ListHead == NULL) {
+ return ;
+ }
+
+ Link = ListHead;
+
+ //
+ // Free all the resources in the interrupt list
+ //
+ SavedLink = Link->ForwardLink;
+ while (!IsListEmpty (ListHead)) {
+
+ Link = SavedLink;
+
+ SavedLink = Link->ForwardLink;
+
+ pNode = INTERRUPT_LIST_FROM_LINK (Link);
+
+ RemoveEntryList (&pNode->Link);
+
+ SavedQH = pNode->PtrQH;
+ for (PtrQH = SavedQH; PtrQH != NULL; PtrQH = SavedQH) {
+ SavedQH = PtrQH->ptrNextIntQH;
+ UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));
+ }
+
+ PtrTD = pNode->PtrFirstTD;
+ while (PtrTD != NULL) {
+
+ ptrNextTD = PtrTD->ptrNextTD;
+ UhciFreePool (HcDev, (UINT8 *) PtrTD, sizeof (TD_STRUCT));
+ PtrTD = ptrNextTD;
+ }
+
+ gBS->FreePool (pNode);
+ }
+}
+
+
+EFI_STATUS
+InitializeMemoryManagement (
+ IN USB_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Initialize Memory Management
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS - Success
+--*/
+{
+ MEMORY_MANAGE_HEADER *MemoryHeader;
+ EFI_STATUS Status;
+ UINTN MemPages;
+
+ MemPages = NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES;
+ Status = CreateMemoryBlock (HcDev, &MemoryHeader, MemPages);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ HcDev->MemoryHeader = MemoryHeader;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CreateMemoryBlock (
+ IN USB_HC_DEV *HcDev,
+ OUT MEMORY_MANAGE_HEADER **MemoryHeader,
+ IN UINTN MemoryBlockSizeInPages
+ )
+/*++
+
+Routine Description:
+
+ Use PciIo->AllocateBuffer to allocate common buffer for the memory block,
+ and use PciIo->Map to map the common buffer for Bus Master Read/Write.
+
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ MemoryHeader - MEMORY_MANAGE_HEADER to output
+ MemoryBlockSizeInPages - MemoryBlockSizeInPages
+Returns:
+
+ EFI_SUCCESS - Success
+--*/
+{
+ EFI_STATUS Status;
+ VOID *CommonBuffer;
+ EFI_PHYSICAL_ADDRESS MappedAddress;
+ UINTN MemoryBlockSizeInBytes;
+ VOID *Mapping;
+
+ //
+ // Allocate memory for MemoryHeader
+ //
+ *MemoryHeader = AllocateZeroPool (sizeof (MEMORY_MANAGE_HEADER));
+ if (*MemoryHeader == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ (*MemoryHeader)->Next = NULL;
+
+ //
+ // set Memory block size
+ //
+ (*MemoryHeader)->MemoryBlockSizeInBytes = EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages);
+
+ //
+ // each bit in Bit Array will manage 32 bytes memory in memory block
+ //
+ (*MemoryHeader)->BitArraySizeInBytes = ((*MemoryHeader)->MemoryBlockSizeInBytes / 32) / 8;
+
+ //
+ // Allocate memory for BitArray
+ //
+ (*MemoryHeader)->BitArrayPtr = AllocateZeroPool ((*MemoryHeader)->BitArraySizeInBytes);
+ if ((*MemoryHeader)->BitArrayPtr == NULL) {
+ gBS->FreePool (*MemoryHeader);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Memory Block uses MemoryBlockSizeInPages pages,
+ // and it is allocated as common buffer use.
+ //
+ Status = HcDev->PciIo->AllocateBuffer (
+ HcDev->PciIo,
+ AllocateAnyPages,
+ EfiBootServicesData,
+ MemoryBlockSizeInPages,
+ &CommonBuffer,
+ 0
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool ((*MemoryHeader)->BitArrayPtr);
+ gBS->FreePool (*MemoryHeader);
+ return Status;
+ }
+
+ MemoryBlockSizeInBytes = EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages);
+ Status = HcDev->PciIo->Map (
+ HcDev->PciIo,
+ EfiPciIoOperationBusMasterCommonBuffer,
+ CommonBuffer,
+ &MemoryBlockSizeInBytes,
+ &MappedAddress,
+ &Mapping
+ );
+ //
+ // if returned Mapped size is less than the size we request,do not support.
+ //
+ if (EFI_ERROR (Status) || (MemoryBlockSizeInBytes != EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages))) {
+ HcDev->PciIo->FreeBuffer (HcDev->PciIo, MemoryBlockSizeInPages, CommonBuffer);
+ gBS->FreePool ((*MemoryHeader)->BitArrayPtr);
+ gBS->FreePool (*MemoryHeader);
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Set Memory block initial address
+ //
+ (*MemoryHeader)->MemoryBlockPtr = (UINT8 *) ((UINTN) MappedAddress);
+ (*MemoryHeader)->Mapping = Mapping;
+
+ ZeroMem (
+ (*MemoryHeader)->MemoryBlockPtr,
+ EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages)
+ );
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FreeMemoryHeader (
+ IN USB_HC_DEV *HcDev,
+ IN MEMORY_MANAGE_HEADER *MemoryHeader
+ )
+/*++
+
+Routine Description:
+
+ Free Memory Header
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ MemoryHeader - MemoryHeader to be freed
+
+Returns:
+
+ EFI_INVALID_PARAMETER - Parameter is error
+ EFI_SUCCESS - Success
+
+--*/
+{
+ if ((MemoryHeader == NULL) || (HcDev == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // unmap the common buffer used by the memory block
+ //
+ HcDev->PciIo->Unmap (HcDev->PciIo, MemoryHeader->Mapping);
+
+ //
+ // free common buffer
+ //
+ HcDev->PciIo->FreeBuffer (
+ HcDev->PciIo,
+ EFI_SIZE_TO_PAGES (MemoryHeader->MemoryBlockSizeInBytes),
+ MemoryHeader->MemoryBlockPtr
+ );
+ //
+ // free bit array
+ //
+ gBS->FreePool (MemoryHeader->BitArrayPtr);
+ //
+ // free memory header
+ //
+ gBS->FreePool (MemoryHeader);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+UhciAllocatePool (
+ IN USB_HC_DEV *HcDev,
+ OUT UINT8 **Pool,
+ IN UINTN AllocSize
+ )
+/*++
+
+Routine Description:
+
+ Uhci Allocate Pool
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ Pool - Place to store pointer to the memory buffer
+ AllocSize - Alloc Size
+
+Returns:
+
+ EFI_SUCCESS - Success
+
+--*/
+{
+ MEMORY_MANAGE_HEADER *MemoryHeader;
+ MEMORY_MANAGE_HEADER *TempHeaderPtr;
+ MEMORY_MANAGE_HEADER *NewMemoryHeader;
+ UINTN RealAllocSize;
+ UINTN MemoryBlockSizeInPages;
+ EFI_STATUS Status;
+
+ *Pool = NULL;
+
+ MemoryHeader = HcDev->MemoryHeader;
+ ASSERT (MemoryHeader != NULL);
+
+ //
+ // allocate unit is 32 bytes (align on 32 byte)
+ //
+ if (AllocSize & 0x1F) {
+ RealAllocSize = (AllocSize / 32 + 1) * 32;
+ } else {
+ RealAllocSize = AllocSize;
+ }
+
+ //
+ // There may be linked MemoryHeaders.
+ // To allocate a free pool in Memory blocks,
+ // must search in the MemoryHeader link list
+ // until enough free pool is found.
+ //
+ Status = EFI_NOT_FOUND;
+ for (TempHeaderPtr = MemoryHeader; TempHeaderPtr != NULL;
+ TempHeaderPtr = TempHeaderPtr->Next) {
+
+ Status = AllocMemInMemoryBlock (
+ TempHeaderPtr,
+ (VOID **) Pool,
+ RealAllocSize / 32
+ );
+ if (!EFI_ERROR (Status)) {
+ ZeroMem (*Pool, AllocSize);
+ return EFI_SUCCESS;
+ }
+ }
+
+ //
+ // There is no enough memory,
+ // Create a new Memory Block
+ //
+
+ //
+ // if pool size is larger than NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES,
+ // just allocate a large enough memory block.
+ //
+ if (RealAllocSize > EFI_PAGES_TO_SIZE (NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES)) {
+ MemoryBlockSizeInPages = EFI_SIZE_TO_PAGES (RealAllocSize) + 1;
+ } else {
+ MemoryBlockSizeInPages = NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES;
+ }
+
+ Status = CreateMemoryBlock (HcDev, &NewMemoryHeader, MemoryBlockSizeInPages);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Link the new Memory Block to the Memory Header list
+ //
+ InsertMemoryHeaderToList (MemoryHeader, NewMemoryHeader);
+
+ Status = AllocMemInMemoryBlock (
+ NewMemoryHeader,
+ (VOID **) Pool,
+ RealAllocSize / 32
+ );
+
+ if (!EFI_ERROR (Status)) {
+ ZeroMem (*Pool, AllocSize);
+ }
+
+ return Status;
+}
+
+VOID
+UhciFreePool (
+ IN USB_HC_DEV *HcDev,
+ IN UINT8 *Pool,
+ IN UINTN AllocSize
+ )
+/*++
+
+Routine Description:
+
+ Uhci Free Pool
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ Pool - Pool to free
+ AllocSize - Pool size
+
+Returns:
+
+ VOID
+
+--*/
+{
+ MEMORY_MANAGE_HEADER *MemoryHeader;
+ MEMORY_MANAGE_HEADER *TempHeaderPtr;
+ UINTN StartBytePos;
+ UINTN Index;
+ UINT8 StartBitPos;
+ UINT8 Index2;
+ UINTN Count;
+ UINTN RealAllocSize;
+
+ MemoryHeader = HcDev->MemoryHeader;
+
+ //
+ // allocate unit is 32 byte (align on 32 byte)
+ //
+ if (AllocSize & 0x1F) {
+ RealAllocSize = (AllocSize / 32 + 1) * 32;
+ } else {
+ RealAllocSize = AllocSize;
+ }
+ //
+ // scan the memory header linked list for
+ // the asigned memory to free.
+ //
+ for (TempHeaderPtr = MemoryHeader;TempHeaderPtr != NULL;
+ TempHeaderPtr = TempHeaderPtr->Next) {
+
+ if ((Pool >= TempHeaderPtr->MemoryBlockPtr) &&
+ ((Pool + RealAllocSize) <= (TempHeaderPtr->MemoryBlockPtr + TempHeaderPtr->MemoryBlockSizeInBytes))
+ ) {
+ //
+ // Pool is in the Memory Block area,
+ // find the start byte and bit in the bit array
+ //
+ StartBytePos = ((Pool - TempHeaderPtr->MemoryBlockPtr) / 32) / 8;
+ StartBitPos = (UINT8) (((Pool - TempHeaderPtr->MemoryBlockPtr) / 32) & 0x7);
+
+ //
+ // reset associated bits in bit arry
+ //
+ for (Index = StartBytePos, Index2 = StartBitPos, Count = 0; Count < (RealAllocSize / 32); Count++) {
+
+ TempHeaderPtr->BitArrayPtr[Index] ^= (UINT8) (bit (Index2));
+ Index2++;
+ if (Index2 == 8) {
+ Index += 1;
+ Index2 = 0;
+ }
+ }
+ //
+ // break the loop
+ //
+ break;
+ }
+ }
+
+ //
+ // Release emptied memory blocks (only if the memory block is not
+ // the first one in the memory header list
+ //
+ for (TempHeaderPtr = MemoryHeader->Next; TempHeaderPtr != NULL;) {
+ //
+ // Debug
+ //
+ ASSERT (MemoryHeader->Next != NULL);
+
+ if (IsMemoryBlockEmptied (TempHeaderPtr)) {
+
+ DelinkMemoryBlock (MemoryHeader, TempHeaderPtr);
+ //
+ // when the TempHeaderPtr is freed in FreeMemoryHeader(),
+ // the TempHeaderPtr is pointing to nonsense content.
+ //
+ FreeMemoryHeader (HcDev, TempHeaderPtr);
+ //
+ // reset the TempHeaderPtr, continue search for
+ // another empty memory block.
+ //
+ TempHeaderPtr = MemoryHeader->Next;
+ continue;
+ }
+
+ TempHeaderPtr = TempHeaderPtr->Next;
+ }
+}
+
+VOID
+InsertMemoryHeaderToList (
+ IN MEMORY_MANAGE_HEADER *MemoryHeader,
+ IN MEMORY_MANAGE_HEADER *NewMemoryHeader
+ )
+/*++
+
+Routine Description:
+
+ Insert Memory Header To List
+
+Arguments:
+
+ MemoryHeader - MEMORY_MANAGE_HEADER
+ NewMemoryHeader - MEMORY_MANAGE_HEADER
+
+Returns:
+
+ VOID
+
+--*/
+{
+ MEMORY_MANAGE_HEADER *TempHeaderPtr;
+
+ for (TempHeaderPtr = MemoryHeader; TempHeaderPtr != NULL;
+ TempHeaderPtr = TempHeaderPtr->Next) {
+ if (TempHeaderPtr->Next == NULL) {
+ TempHeaderPtr->Next = NewMemoryHeader;
+ break;
+ }
+ }
+}
+
+EFI_STATUS
+AllocMemInMemoryBlock (
+ IN MEMORY_MANAGE_HEADER *MemoryHeader,
+ OUT VOID **Pool,
+ IN UINTN NumberOfMemoryUnit
+ )
+/*++
+
+Routine Description:
+
+ Alloc Memory In MemoryBlock
+
+Arguments:
+
+ MemoryHeader - MEMORY_MANAGE_HEADER
+ Pool - Place to store pointer to memory
+ NumberOfMemoryUnit - Number Of Memory Unit
+
+Returns:
+
+ EFI_NOT_FOUND - Can't find the free memory
+ EFI_SUCCESS - Success
+
+--*/
+{
+ UINTN TempBytePos;
+ UINTN FoundBytePos;
+ UINT8 Index;
+ UINT8 FoundBitPos;
+ UINT8 ByteValue;
+ UINT8 BitValue;
+ UINTN NumberOfZeros;
+ UINTN Count;
+
+ FoundBytePos = 0;
+ FoundBitPos = 0;
+ ByteValue = MemoryHeader->BitArrayPtr[0];
+ NumberOfZeros = 0;
+ Index = 0;
+
+ for (TempBytePos = 0; TempBytePos < MemoryHeader->BitArraySizeInBytes;) {
+
+ //
+ // Pop out BitValue from a byte in TempBytePos.
+ //
+ BitValue = (UINT8) (ByteValue & 0x1);
+ //
+ // right shift the byte
+ //
+ ByteValue /= 2;
+
+ if (BitValue == 0) {
+ //
+ // Found a free bit, the NumberOfZeros only record the number
+ // of those consecutive zeros
+ //
+ NumberOfZeros++;
+ //
+ // Found enough consecutive free space, break the loop
+ //
+ if (NumberOfZeros >= NumberOfMemoryUnit) {
+ break;
+ }
+ } else {
+ //
+ // Encountering a '1', meant the bit is ocupied.
+ //
+ if (NumberOfZeros >= NumberOfMemoryUnit) {
+ //
+ // Found enough consecutive free space,break the loop
+ //
+ break;
+ } else {
+ //
+ // the NumberOfZeros only record the number of those consecutive zeros,
+ // so reset the NumberOfZeros to 0 when encountering '1' before finding
+ // enough consecutive '0's
+ //
+ NumberOfZeros = 0;
+ //
+ // reset the (FoundBytePos,FoundBitPos) to the position of '1'
+ //
+ FoundBytePos = TempBytePos;
+ FoundBitPos = Index;
+ }
+ }
+ //
+ // step forward a bit
+ //
+ Index++;
+ if (Index == 8) {
+ //
+ // step forward a byte, getting the byte value,
+ // and reset the bit pos.
+ //
+ TempBytePos += 1;
+ ByteValue = MemoryHeader->BitArrayPtr[TempBytePos];
+ Index = 0;
+ }
+ }
+
+ if (NumberOfZeros < NumberOfMemoryUnit) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Found enough free space.
+ //
+
+ //
+ // The values recorded in (FoundBytePos,FoundBitPos) have two conditions:
+ // 1)(FoundBytePos,FoundBitPos) record the position
+ // of the last '1' before the consecutive '0's, it must
+ // be adjusted to the start position of the consecutive '0's.
+ // 2)the start address of the consecutive '0's is just the start of
+ // the bitarray. so no need to adjust the values of
+ // (FoundBytePos,FoundBitPos).
+ //
+ if ((MemoryHeader->BitArrayPtr[0] & bit (0)) != 0) {
+ FoundBitPos += 1;
+ }
+
+ //
+ // Have the (FoundBytePos,FoundBitPos) make sense.
+ //
+ if (FoundBitPos > 7) {
+ FoundBytePos += 1;
+ FoundBitPos -= 8;
+ }
+
+ //
+ // Set the memory as allocated
+ //
+ for (TempBytePos = FoundBytePos, Index = FoundBitPos,Count = 0;
+ Count < NumberOfMemoryUnit; Count ++) {
+
+ MemoryHeader->BitArrayPtr[TempBytePos] |= bit (Index);
+ Index++;
+ if (Index == 8) {
+ TempBytePos += 1;
+ Index = 0;
+ }
+ }
+
+ *Pool = MemoryHeader->MemoryBlockPtr + (FoundBytePos * 8 + FoundBitPos) * 32;
+
+ return EFI_SUCCESS;
+}
+
+BOOLEAN
+IsMemoryBlockEmptied (
+ IN MEMORY_MANAGE_HEADER *MemoryHeaderPtr
+ )
+/*++
+
+Routine Description:
+
+ Is Memory Block Emptied
+
+Arguments:
+
+ MemoryHeaderPtr - MEMORY_MANAGE_HEADER
+
+Returns:
+
+ TRUE - Empty
+ FALSE - Not Empty
+
+--*/
+{
+ UINTN Index;
+
+ for (Index = 0; Index < MemoryHeaderPtr->BitArraySizeInBytes; Index++) {
+ if (MemoryHeaderPtr->BitArrayPtr[Index] != 0) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+VOID
+DelinkMemoryBlock (
+ IN MEMORY_MANAGE_HEADER *FirstMemoryHeader,
+ IN MEMORY_MANAGE_HEADER *NeedFreeMemoryHeader
+ )
+/*++
+
+Routine Description:
+
+ Delink Memory Block
+
+Arguments:
+
+ FirstMemoryHeader - MEMORY_MANAGE_HEADER
+ NeedFreeMemoryHeader - MEMORY_MANAGE_HEADER
+
+Returns:
+
+ VOID
+
+--*/
+{
+ MEMORY_MANAGE_HEADER *TempHeaderPtr;
+
+ if ((FirstMemoryHeader == NULL) || (NeedFreeMemoryHeader == NULL)) {
+ return ;
+ }
+ for (TempHeaderPtr = FirstMemoryHeader; TempHeaderPtr != NULL;
+ TempHeaderPtr = TempHeaderPtr->Next) {
+
+ if (TempHeaderPtr->Next == NeedFreeMemoryHeader) {
+ //
+ // Link the before and after
+ //
+ TempHeaderPtr->Next = NeedFreeMemoryHeader->Next;
+ break;
+ }
+ }
+}
+
+EFI_STATUS
+DelMemoryManagement (
+ IN USB_HC_DEV *HcDev
+ )
+/*++
+
+Routine Description:
+
+ Delete Memory Management
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+
+Returns:
+
+ EFI_SUCCESS - Success
+
+--*/
+{
+ MEMORY_MANAGE_HEADER *TempHeaderPtr;
+
+ for (TempHeaderPtr = HcDev->MemoryHeader->Next; TempHeaderPtr != NULL;) {
+
+ DelinkMemoryBlock (HcDev->MemoryHeader, TempHeaderPtr);
+ //
+ // when the TempHeaderPtr is freed in FreeMemoryHeader(),
+ // the TempHeaderPtr is pointing to nonsense content.
+ //
+ FreeMemoryHeader (HcDev, TempHeaderPtr);
+ //
+ // reset the TempHeaderPtr,continue free another memory block.
+ //
+ TempHeaderPtr = HcDev->MemoryHeader->Next;
+ }
+
+ FreeMemoryHeader (HcDev, HcDev->MemoryHeader);
+
+ return EFI_SUCCESS;
+}
+
+
+VOID
+CleanUsbTransactions (
+ IN USB_HC_DEV *HcDev
+ )
+{
+ //
+ // only asynchronous interrupt transfers are always alive on the bus
+ //
+ ReleaseInterruptList (HcDev, &(HcDev->InterruptListHead));
+}
+
+VOID
+TurnOffUSBEmulation (
+ IN EFI_PCI_IO_PROTOCOL *PciIo
+ )
+/*++
+
+ Routine Description:
+ Disable USB Emulation
+ Arguments:
+ PciIo - EFI_PCI_IO_PROTOCOL
+ Returns:
+ VOID
+--*/
+{
+ UINT16 Command;
+
+ //
+ // Disable USB Emulation
+ //
+ Command = 0;
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ USB_EMULATION,
+ 1,
+ &Command
+ );
+
+ return ;
+}
diff --git a/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.c b/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.c
new file mode 100644
index 0000000..1eba8be
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.c
@@ -0,0 +1,3498 @@
+/*++
+
+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:
+
+ Uhci.c
+
+Abstract:
+
+
+Revision History
+--*/
+
+#include "uhci.h"
+
+//
+// Prototypes
+// Driver model protocol interface
+//
+
+EFI_STATUS
+EFIAPI
+UHCIDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+EFI_STATUS
+EFIAPI
+UHCIDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+EFIAPI
+UHCIDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+EFIAPI
+UHCIDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+//
+// UHCI interface functions
+//
+
+EFI_STATUS
+EFIAPI
+UHCIReset (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT16 Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+UHCIGetState (
+ IN EFI_USB_HC_PROTOCOL *This,
+ OUT EFI_USB_HC_STATE *State
+ );
+
+EFI_STATUS
+EFIAPI
+UHCISetState (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN EFI_USB_HC_STATE State
+ );
+
+EFI_STATUS
+EFIAPI
+UHCIControlTransfer (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN BOOLEAN IsSlowDevice,
+ IN UINT8 MaximumPacketLength,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION TransferDirection,
+ IN OUT VOID *Data, OPTIONAL
+ IN OUT UINTN *DataLength, OPTIONAL
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult
+ );
+
+EFI_STATUS
+EFIAPI
+UHCIBulkTransfer (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 MaximumPacketLength,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult
+ );
+
+EFI_STATUS
+EFIAPI
+UHCIAsyncInterruptTransfer (
+ IN EFI_USB_HC_PROTOCOL * This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN BOOLEAN IsSlowDevice,
+ IN UINT8 MaxiumPacketLength,
+ IN BOOLEAN IsNewTransfer,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN PollingInterval, OPTIONAL
+ IN UINTN DataLength, OPTIONAL
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction, OPTIONAL
+ IN VOID *Context OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+UHCISyncInterruptTransfer (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN BOOLEAN IsSlowDevice,
+ IN UINT8 MaximumPacketLength,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult
+ );
+
+EFI_STATUS
+EFIAPI
+UHCIIsochronousTransfer (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 MaximumPacketLength,
+ IN OUT VOID *Data,
+ IN UINTN DataLength,
+ OUT UINT32 *TransferResult
+ );
+
+EFI_STATUS
+EFIAPI
+UHCIAsyncIsochronousTransfer (
+ IN EFI_USB_HC_PROTOCOL * This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 MaximumPacketLength,
+ IN OUT VOID *Data,
+ IN UINTN DataLength,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
+ IN VOID *Context OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+UHCIGetRootHubPortNumber (
+ IN EFI_USB_HC_PROTOCOL *This,
+ OUT UINT8 *PortNumber
+ );
+
+EFI_STATUS
+EFIAPI
+UHCIGetRootHubPortStatus (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 PortNumber,
+ OUT EFI_USB_PORT_STATUS *PortStatus
+ );
+
+EFI_STATUS
+EFIAPI
+UHCISetRootHubPortFeature (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+ );
+
+EFI_STATUS
+EFIAPI
+UHCIClearRootHubPortFeature (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+ );
+
+//
+// Asynchronous interrupt transfer monitor function
+//
+VOID
+EFIAPI
+MonitorInterruptTrans (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+//
+// UHCI Driver Global Variables
+//
+EFI_DRIVER_BINDING_PROTOCOL gUhciDriverBinding = {
+ UHCIDriverBindingSupported,
+ UHCIDriverBindingStart,
+ UHCIDriverBindingStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+EFI_STATUS
+EFIAPI
+UHCIDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+ Routine Description:
+ Test to see if this driver supports ControllerHandle. Any ControllerHandle
+ that has UsbHcProtocol installed will be supported.
+
+ Arguments:
+ This - Protocol instance pointer.
+ Controller, - Handle of device to test
+ RemainingDevicePath - Not used
+
+ Returns:
+ EFI_SUCCESS - This driver supports this device.
+ EFI_UNSUPPORTED - This driver does not support this device.
+
+--*/
+{
+ EFI_STATUS OpenStatus;
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ USB_CLASSC UsbClassCReg;
+
+ //
+ // Test whether there is PCI IO Protocol attached on the controller handle.
+ //
+ OpenStatus = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (OpenStatus)) {
+ return OpenStatus;
+ }
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ CLASSC,
+ sizeof (USB_CLASSC) / sizeof (UINT8),
+ &UsbClassCReg
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Test whether the controller belongs to UHCI type
+ //
+ if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) ||
+ (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) ||
+ (UsbClassCReg.PI != PCI_CLASSC_PI_UHCI)) {
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return EFI_UNSUPPORTED;
+ }
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return EFI_SUCCESS;
+
+}
+
+EFI_STATUS
+EFIAPI
+UHCIDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+ Routine Description:
+ Starting the Usb UHCI Driver
+
+ Arguments:
+ This - Protocol instance pointer.
+ Controller - Handle of device to test
+ RemainingDevicePath - Not used
+
+ Returns:
+ EFI_SUCCESS - This driver supports this device.
+ EFI_UNSUPPORTED - This driver does not support this device.
+ EFI_DEVICE_ERROR - This driver cannot be started due to device
+ Error
+ EFI_OUT_OF_RESOURCES
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN FlBaseAddrReg;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ USB_HC_DEV *HcDev;
+
+ HcDev = NULL;
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Turn off USB emulation
+ //
+ TurnOffUSBEmulation (PciIo);
+
+ //
+ // Enable the USB Host Controller
+ //
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationEnable,
+ EFI_PCI_DEVICE_ENABLE,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // allocate memory for UHC private data structure
+ //
+ HcDev = AllocateZeroPool (sizeof (USB_HC_DEV));
+ if (HcDev == NULL) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // init EFI_USB_HC_PROTOCOL protocol interface and install the protocol
+ //
+ HcDev->UsbHc.Reset = UHCIReset;
+ HcDev->UsbHc.GetState = UHCIGetState;
+ HcDev->UsbHc.SetState = UHCISetState;
+ HcDev->UsbHc.ControlTransfer = UHCIControlTransfer;
+ HcDev->UsbHc.BulkTransfer = UHCIBulkTransfer;
+ HcDev->UsbHc.AsyncInterruptTransfer = UHCIAsyncInterruptTransfer;
+ HcDev->UsbHc.SyncInterruptTransfer = UHCISyncInterruptTransfer;
+ HcDev->UsbHc.IsochronousTransfer = UHCIIsochronousTransfer;
+ HcDev->UsbHc.AsyncIsochronousTransfer = UHCIAsyncIsochronousTransfer;
+ HcDev->UsbHc.GetRootHubPortNumber = UHCIGetRootHubPortNumber;
+ HcDev->UsbHc.GetRootHubPortStatus = UHCIGetRootHubPortStatus;
+ HcDev->UsbHc.SetRootHubPortFeature = UHCISetRootHubPortFeature;
+ HcDev->UsbHc.ClearRootHubPortFeature = UHCIClearRootHubPortFeature;
+
+ HcDev->UsbHc.MajorRevision = 0x1;
+ HcDev->UsbHc.MinorRevision = 0x1;
+
+ //
+ // Init UHCI private data structures
+ //
+ HcDev->Signature = USB_HC_DEV_SIGNATURE;
+ HcDev->PciIo = PciIo;
+
+ FlBaseAddrReg = USBFLBASEADD;
+
+ //
+ // Allocate and Init Host Controller's Frame List Entry
+ //
+ Status = CreateFrameList (HcDev, (UINT32) FlBaseAddrReg);
+ if (EFI_ERROR (Status)) {
+
+ if (HcDev != NULL) {
+ gBS->FreePool (HcDev);
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Init interrupt list head in the HcDev structure.
+ //
+ InitializeListHead (&(HcDev->InterruptListHead));
+
+ //
+ // Create timer for interrupt transfer result polling
+ //
+ Status = gBS->CreateEvent (
+ EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,
+ EFI_TPL_NOTIFY,
+ MonitorInterruptTrans,
+ HcDev,
+ &HcDev->InterruptTransTimer
+ );
+ if (EFI_ERROR (Status)) {
+
+ FreeFrameListEntry (HcDev);
+
+ if (HcDev != NULL) {
+ gBS->FreePool (HcDev);
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Here set interrupt transfer polling timer in 50ms unit.
+ //
+ Status = gBS->SetTimer (
+ HcDev->InterruptTransTimer,
+ TimerPeriodic,
+ INTERRUPT_POLLING_TIME
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->CloseEvent (HcDev->InterruptTransTimer);
+
+ FreeFrameListEntry (HcDev);
+
+ if (HcDev != NULL) {
+ gBS->FreePool (HcDev);
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // QH,TD structures must in common buffer that will be
+ // accessed by both cpu and usb bus master at the same time.
+ // so, there must has memory management for QH,TD structures.
+ //
+ Status = InitializeMemoryManagement (HcDev);
+ if (EFI_ERROR (Status)) {
+
+ gBS->CloseEvent (HcDev->InterruptTransTimer);
+
+ FreeFrameListEntry (HcDev);
+
+ if (HcDev != NULL) {
+ gBS->FreePool (HcDev);
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return Status;
+ }
+
+ //
+ // Install Host Controller Protocol
+ //
+ Status = gBS->InstallProtocolInterface (
+ &Controller,
+ &gEfiUsbHcProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &HcDev->UsbHc
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->CloseEvent (HcDev->InterruptTransTimer);
+ FreeFrameListEntry (HcDev);
+ DelMemoryManagement (HcDev);
+
+ if (HcDev != NULL) {
+ gBS->FreePool (HcDev);
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return Status;
+ }
+
+ //
+ // component name protocol.
+ //
+ HcDev->ControllerNameTable = NULL;
+ AddUnicodeString (
+ "eng",
+ gUhciComponentName.SupportedLanguages,
+ &HcDev->ControllerNameTable,
+ (CHAR16 *) L"Usb Universal Host Controller"
+ );
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+UnInstallUHCInterface (
+ IN EFI_HANDLE Controller,
+ IN EFI_USB_HC_PROTOCOL *This
+ )
+/*++
+ Routine Description:
+ UnInstall UHCInterface
+ Arguments:
+ Controller - Controller handle
+ This - Protocol instance pointer.
+ Returns:
+ EFI_SUCCESS
+ others
+--*/
+{
+ USB_HC_DEV *HcDev;
+
+ HcDev = USB_HC_DEV_FROM_THIS (This);
+
+ gBS->UninstallProtocolInterface (
+ Controller,
+ &gEfiUsbHcProtocolGuid,
+ &HcDev->UsbHc
+ );
+
+ //
+ // first stop USB Host Controller
+ //
+ This->SetState (This, EfiUsbHcStateHalt);
+
+ //
+ // Delete interrupt transfer polling timer
+ //
+ gBS->CloseEvent (HcDev->InterruptTransTimer);
+
+ //
+ // Delete all the asynchronous interrupt transfers in the interrupt list
+ // and free associated memory
+ //
+ ReleaseInterruptList (HcDev, &(HcDev->InterruptListHead));
+
+ //
+ // free Frame List Entry.
+ //
+ FreeFrameListEntry (HcDev);
+
+ //
+ // Free common buffer allocated for QH,TD structures
+ //
+ DelMemoryManagement (HcDev);
+
+ if (HcDev->ControllerNameTable) {
+ FreeUnicodeStringTable (HcDev->ControllerNameTable);
+ }
+ //
+ // Disable the USB Host Controller
+ //
+ HcDev->PciIo->Attributes (
+ HcDev->PciIo,
+ EfiPciIoAttributeOperationDisable,
+ EFI_PCI_DEVICE_ENABLE,
+ NULL
+ );
+
+ gBS->FreePool (HcDev);
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+UHCIDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+/*++
+
+ Routine Description:
+ Stop this driver on ControllerHandle. Support stoping any child handles
+ created by this driver.
+
+ Arguments:
+ This - Protocol instance pointer.
+ Controller - Handle of device to stop driver on
+ NumberOfChildren - Number of Children in the ChildHandleBuffer
+ ChildHandleBuffer - List of handles for the children we need to stop.
+
+ Returns:
+ EFI_SUCCESS
+ others
+
+--*/
+{
+ EFI_USB_HC_PROTOCOL *UsbHc;
+ EFI_STATUS OpenStatus;
+
+ OpenStatus = gBS->OpenProtocol (
+ Controller,
+ &gEfiUsbHcProtocolGuid,
+ (VOID **) &UsbHc,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ //
+ // Test whether the Controller handler passed in is a valid
+ // Usb controller handle that should be supported, if not,
+ // return the error status directly
+ //
+ if (EFI_ERROR (OpenStatus)) {
+ return OpenStatus;
+ }
+ //
+ // free all the controller related memory and uninstall UHCI Protocol.
+ //
+ UnInstallUHCInterface (Controller, UsbHc);
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return EFI_SUCCESS;
+
+}
+
+
+EFI_STATUS
+EFIAPI
+UHCIReset (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT16 Attributes
+ )
+/*++
+
+ Routine Description:
+ Provides software reset for the USB host controller.
+
+ Arguments:
+
+ This A pointer to the EFI_USB_HC_PROTOCOL instance.
+
+ Attributes A bit mask of the reset operation to perform.
+ See below for a list of the supported bit mask values.
+
+ #define EFI_USB_HC_RESET_GLOBAL 0x0001
+ #define EFI_USB_HC_RESET_HOST_CONTROLLER 0x0002
+
+ EFI_USB_HC_RESET_GLOBAL
+ If this bit is set, a global reset signal will be sent to the USB bus.
+ This resets all of the USB bus logic, including the USB host
+ controller hardware and all the devices attached on the USB bus.
+ EFI_USB_HC_RESET_HOST_CONTROLLER
+ If this bit is set, the USB host controller hardware will be reset.
+ No reset signal will be sent to the USB bus.
+
+ Returns:
+ EFI_SUCCESS
+ The reset operation succeeded.
+ EFI_INVALID_PARAMETER
+ Attributes is not valid.
+ EFI_DEVICE_ERROR
+ An error was encountered while attempting to perform
+ the reset operation.
+--*/
+{
+ BOOLEAN Match;
+ USB_HC_DEV *HcDev;
+ UINT32 CommandRegAddr;
+ UINT32 FlBaseAddrReg;
+ UINT16 Command;
+ EFI_STATUS Status;
+
+ Match = FALSE;
+ HcDev = USB_HC_DEV_FROM_THIS (This);
+
+ CommandRegAddr = (UINT32) (USBCMD);
+ FlBaseAddrReg = (UINT32) (USBFLBASEADD);
+
+ if ((Attributes & EFI_USB_HC_RESET_GLOBAL) != 0) {
+ Match = TRUE;
+ //
+ // set the Global Reset bit in the command register
+ //
+ Status = ReadUHCCommandReg (
+ HcDev->PciIo,
+ CommandRegAddr,
+ &Command
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Command |= USBCMD_GRESET;
+ Status = WriteUHCCommandReg (
+ HcDev->PciIo,
+ CommandRegAddr,
+ Command
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Wait 50ms for root port to let reset complete
+ // See UHCI spec page122 Reset signaling
+ //
+ gBS->Stall (ROOT_PORT_REST_TIME);
+
+ //
+ // Clear the Global Reset bit to zero.
+ //
+ Command &= ~USBCMD_GRESET;
+ Status = WriteUHCCommandReg (
+ HcDev->PciIo,
+ CommandRegAddr,
+ Command
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // UHCI spec page120 reset recovery time
+ //
+ gBS->Stall (PORT_RESET_RECOVERY_TIME);
+ }
+
+ if ((Attributes & EFI_USB_HC_RESET_HOST_CONTROLLER) != 0) {
+ Match = TRUE;
+ //
+ // set Host Controller Reset bit to 1
+ //
+ Status = ReadUHCCommandReg (
+ HcDev->PciIo,
+ CommandRegAddr,
+ &Command
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Command |= USBCMD_HCRESET;
+ Status = WriteUHCCommandReg (
+ HcDev->PciIo,
+ CommandRegAddr,
+ Command
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // this bit will be reset by Host Controller when reset is completed.
+ // wait 10ms to let reset complete
+ //
+ gBS->Stall (PORT_RESET_RECOVERY_TIME);
+ }
+
+ if (!Match) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Delete all old transactions on the USB bus
+ //
+ CleanUsbTransactions (HcDev);
+
+ //
+ // Initialize Universal Host Controller's Frame List Data Structure
+ //
+ InitFrameList (HcDev);
+
+ //
+ // Reset may cause Frame List Base Address Register reset to zero,
+ // so set the original value back again.
+ //
+ SetFrameListBaseAddress (
+ HcDev->PciIo,
+ FlBaseAddrReg,
+ (UINT32) ((UINTN) HcDev->FrameListEntry)
+ );
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+UHCIGetState (
+ IN EFI_USB_HC_PROTOCOL *This,
+ OUT EFI_USB_HC_STATE *State
+ )
+/*++
+
+ Routine Description:
+ Retrieves current state of the USB host controller.
+
+ Arguments:
+
+ This A pointer to the EFI_USB_HC_PROTOCOL instance.
+
+ State A pointer to the EFI_USB_HC_STATE data structure that
+ indicates current state of the USB host controller.
+ Type EFI_USB_HC_STATE is defined below.
+
+ typedef enum {
+ EfiUsbHcStateHalt,
+ EfiUsbHcStateOperational,
+ EfiUsbHcStateSuspend,
+ EfiUsbHcStateMaximum
+ } EFI_USB_HC_STATE;
+
+ Returns:
+ EFI_SUCCESS
+ The state information of the host controller was returned in State.
+ EFI_INVALID_PARAMETER
+ State is NULL.
+ EFI_DEVICE_ERROR
+ An error was encountered while attempting to retrieve the
+ host controller's current state.
+--*/
+{
+ USB_HC_DEV *HcDev;
+ UINT32 CommandRegAddr;
+ UINT32 StatusRegAddr;
+ UINT16 UhcCommand;
+ UINT16 UhcStatus;
+ EFI_STATUS Status;
+
+ if (State == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HcDev = USB_HC_DEV_FROM_THIS (This);
+
+ CommandRegAddr = (UINT32) (USBCMD);
+ StatusRegAddr = (UINT32) (USBSTS);
+
+ Status = ReadUHCCommandReg (
+ HcDev->PciIo,
+ CommandRegAddr,
+ &UhcCommand
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = ReadUHCCommandReg (
+ HcDev->PciIo,
+ StatusRegAddr,
+ &UhcStatus
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (UhcCommand & USBCMD_EGSM) {
+ *State = EfiUsbHcStateSuspend;
+ return EFI_SUCCESS;
+ }
+
+ if ((UhcStatus & USBSTS_HCH) == 0) {
+ *State = EfiUsbHcStateOperational;
+ } else {
+ *State = EfiUsbHcStateHalt;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+UHCISetState (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN EFI_USB_HC_STATE State
+ )
+/*++
+
+ Routine Description:
+ Sets the USB host controller to a specific state.
+
+ Arguments:
+
+ This A pointer to the EFI_USB_HC_PROTOCOL instance.
+
+ State Indicates the state of the host controller that will be set.
+
+ Returns:
+ EFI_SUCCESS
+ The USB host controller was successfully placed in the state
+ specified by State.
+ EFI_INVALID_PARAMETER
+ State is invalid.
+ EFI_DEVICE_ERROR
+ Failed to set the state specified by State due to device error.
+--*/
+{
+ USB_HC_DEV *HcDev;
+ UINT32 CommandRegAddr;
+ UINT32 StatusRegAddr;
+ UINT16 Command;
+ EFI_USB_HC_STATE CurrentState;
+ EFI_STATUS Status;
+
+ HcDev = USB_HC_DEV_FROM_THIS (This);
+
+ CommandRegAddr = (UINT32) (USBCMD);
+ StatusRegAddr = (UINT32) (USBSTS);
+
+ Status = UHCIGetState (This, &CurrentState);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ switch (State) {
+
+ case EfiUsbHcStateHalt:
+ if (CurrentState == EfiUsbHcStateHalt) {
+ return EFI_SUCCESS;
+ }
+
+ Status = ReadUHCCommandReg (
+ HcDev->PciIo,
+ CommandRegAddr,
+ &Command
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Command &= ~USBCMD_RS;
+
+ Status = WriteUHCCommandReg (
+ HcDev->PciIo,
+ CommandRegAddr,
+ Command
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ StatusRegAddr = (UINT32) (USBSTS);
+ //
+ // ensure the HC is in halt status after send the stop command
+ //
+ if (WaitForUHCHalt (HcDev->PciIo, StatusRegAddr, STALL_1_SECOND) == EFI_TIMEOUT) {
+ return EFI_DEVICE_ERROR;
+ }
+ break;
+
+ case EfiUsbHcStateOperational:
+ if (IsHostSysOrProcessErr (HcDev->PciIo, StatusRegAddr)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ switch (CurrentState) {
+
+ case EfiUsbHcStateOperational:
+ return EFI_SUCCESS;
+
+ case EfiUsbHcStateHalt:
+ //
+ // Set Run/Stop bit to 1.
+ //
+ Status = ReadUHCCommandReg (
+ HcDev->PciIo,
+ CommandRegAddr,
+ &Command
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Command |= USBCMD_RS | USBCMD_MAXP;
+ Status = WriteUHCCommandReg (
+ HcDev->PciIo,
+ CommandRegAddr,
+ Command
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ break;
+
+ case EfiUsbHcStateSuspend:
+ Status = ReadUHCCommandReg (
+ HcDev->PciIo,
+ CommandRegAddr,
+ &Command
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // FGR(Force Global Resume) bit is 0
+ //
+ if ((Command | (~USBCMD_FGR)) != 0xFF) {
+ //
+ // Write FGR bit to 1
+ //
+ Command |= USBCMD_FGR;
+ WriteUHCCommandReg (
+ HcDev->PciIo,
+ CommandRegAddr,
+ Command
+ );
+ }
+
+ //
+ // wait 20ms to let resume complete
+ // (20ms is specified by UHCI spec)
+ //
+ gBS->Stall (FORCE_GLOBAL_RESUME_TIME);
+
+ //
+ // Write FGR bit to 0 and EGSM(Enter Global Suspend Mode) bit to 0
+ //
+ Command &= ~USBCMD_FGR;
+ Command &= ~USBCMD_EGSM;
+ Command |= USBCMD_RS;
+ WriteUHCCommandReg (
+ HcDev->PciIo,
+ CommandRegAddr,
+ Command
+ );
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case EfiUsbHcStateSuspend:
+ if (CurrentState == EfiUsbHcStateSuspend) {
+ return EFI_SUCCESS;
+ }
+
+ Status = UHCISetState (This, EfiUsbHcStateHalt);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Set Enter Global Suspend Mode bit to 1.
+ //
+ Status = ReadUHCCommandReg (
+ HcDev->PciIo,
+ CommandRegAddr,
+ &Command
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Command |= USBCMD_EGSM;
+ Status = WriteUHCCommandReg (
+ HcDev->PciIo,
+ CommandRegAddr,
+ Command
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+UHCIGetRootHubPortNumber (
+ IN EFI_USB_HC_PROTOCOL *This,
+ OUT UINT8 *PortNumber
+ )
+/*++
+
+ Routine Description:
+ Retrieves the number of root hub ports.
+
+ Arguments:
+
+ This A pointer to the EFI_USB_HC_PROTOCOL instance.
+
+ PortNumber A pointer to the number of the root hub ports.
+
+ Returns:
+ EFI_SUCCESS
+ The port number was retrieved successfully.
+ EFI_INVALID_PARAMETER
+ PortNumber is NULL.
+ EFI_DEVICE_ERROR
+ An error was encountered while attempting to
+ retrieve the port number.
+--*/
+{
+ USB_HC_DEV *HcDev;
+ UINT32 PSAddr;
+ UINT16 RHPortControl;
+ UINT32 Index;
+ EFI_STATUS Status;
+
+ HcDev = USB_HC_DEV_FROM_THIS (This);
+
+ if (PortNumber == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *PortNumber = 0;
+
+ for (Index = 0; Index < 2; Index++) {
+ PSAddr = (UINT32) (USBPORTSC1 + Index * 2);
+ Status = ReadRootPortReg (
+ HcDev->PciIo,
+ PSAddr,
+ &RHPortControl
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Port Register content is valid
+ //
+ if (RHPortControl != 0xff) {
+ (*PortNumber)++;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+UHCIGetRootHubPortStatus (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 PortNumber,
+ OUT EFI_USB_PORT_STATUS *PortStatus
+ )
+/*++
+
+ Routine Description:
+ Retrieves the current status of a USB root hub port.
+
+ Arguments:
+
+ This A pointer to the EFI_USB_HC_PROTOCOL.
+
+ PortNumber Specifies the root hub port from which the status
+ is to be retrieved. This value is zero-based. For example,
+ if a root hub has two ports, then the first port is numbered 0,
+ and the second port is numbered 1.
+
+ PortStatus A pointer to the current port status bits and
+ port status change bits.
+
+ Returns:
+ EFI_SUCCESS
+ The status of the USB root hub port specified by PortNumber
+ was returned in PortStatus.
+ EFI_INVALID_PARAMETER
+ PortNumber is invalid.
+ EFI_DEVICE_ERROR - Can't read register
+--*/
+{
+ USB_HC_DEV *HcDev;
+ UINT32 PSAddr;
+ UINT16 RHPortStatus;
+ UINT8 TotalPortNumber;
+ EFI_STATUS Status;
+
+ if (PortStatus == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ UHCIGetRootHubPortNumber (This, &TotalPortNumber);
+ if (PortNumber >= TotalPortNumber) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HcDev = USB_HC_DEV_FROM_THIS (This);
+ PSAddr = (UINT32) (USBPORTSC1 + PortNumber * 2);
+
+ //
+ // Clear port status
+ //
+ PortStatus->PortStatus = 0;
+ PortStatus->PortChangeStatus = 0;
+
+ Status = ReadRootPortReg (
+ HcDev->PciIo,
+ PSAddr,
+ &RHPortStatus
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Fill Port Status bits
+ //
+
+ //
+ // Current Connect Status
+ //
+ if (RHPortStatus & USBPORTSC_CCS) {
+ PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION;
+ }
+ //
+ // Port Enabled/Disabled
+ //
+ if (RHPortStatus & USBPORTSC_PED) {
+ PortStatus->PortStatus |= USB_PORT_STAT_ENABLE;
+ }
+
+ //
+ // Port Suspend
+ //
+ if (RHPortStatus & USBPORTSC_SUSP) {
+ PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND;
+ }
+
+ //
+ // Port Reset
+ //
+ if (RHPortStatus & USBPORTSC_PR) {
+ PortStatus->PortStatus |= USB_PORT_STAT_RESET;
+ }
+
+ //
+ // Low Speed Device Attached
+ //
+ if (RHPortStatus & USBPORTSC_LSDA) {
+ PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED;
+ }
+ //
+ // Fill Port Status Change bits
+ //
+
+ //
+ // Connect Status Change
+ //
+ if (RHPortStatus & USBPORTSC_CSC) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION;
+ }
+
+ //
+ // Port Enabled/Disabled Change
+ //
+ if (RHPortStatus & USBPORTSC_PEDC) {
+ PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+UHCISetRootHubPortFeature (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+ )
+/*++
+
+ Routine Description:
+ Sets a feature for the specified root hub port.
+
+ Arguments:
+
+ This A pointer to the EFI_USB_HC_PROTOCOL.
+
+ PortNumber Specifies the root hub port whose feature
+ is requested to be set.
+
+ PortFeature Indicates the feature selector associated
+ with the feature set request.
+
+ Returns:
+ EFI_SUCCESS
+ The feature specified by PortFeature was set for the
+ USB root hub port specified by PortNumber.
+ EFI_INVALID_PARAMETER
+ PortNumber is invalid or PortFeature is invalid.
+ EFI_DEVICE_ERROR
+ Can't read register
+--*/
+{
+ USB_HC_DEV *HcDev;
+ UINT32 PSAddr;
+ UINT32 CommandRegAddr;
+ //
+ // root hub port status
+ //
+ UINT16 RHPortControl;
+ UINT16 Command;
+ UINT8 TotalPortNumber;
+ EFI_STATUS Status;
+
+ UHCIGetRootHubPortNumber (This, &TotalPortNumber);
+ if (PortNumber >= TotalPortNumber) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HcDev = USB_HC_DEV_FROM_THIS (This);
+
+ PSAddr = (UINT32) (USBPORTSC1 + PortNumber * 2);
+ CommandRegAddr = (UINT32) (USBCMD);
+
+ Status = ReadRootPortReg (
+ HcDev->PciIo,
+ PSAddr,
+ &RHPortControl
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ switch (PortFeature) {
+
+ case EfiUsbPortSuspend:
+ Status = ReadUHCCommandReg (
+ HcDev->PciIo,
+ CommandRegAddr,
+ &Command
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (!(Command & USBCMD_EGSM)) {
+ //
+ // if global suspend is not active, can set port suspend
+ //
+ RHPortControl &= 0xfff5;
+ RHPortControl |= USBPORTSC_SUSP;
+ }
+ break;
+
+ case EfiUsbPortReset:
+ RHPortControl &= 0xfff5;
+ //
+ // Set the reset bit
+ //
+ RHPortControl |= USBPORTSC_PR;
+ break;
+
+ case EfiUsbPortPower:
+ break;
+
+ case EfiUsbPortEnable:
+ RHPortControl &= 0xfff5;
+ RHPortControl |= USBPORTSC_PED;
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ WriteRootPortReg (
+ HcDev->PciIo,
+ PSAddr,
+ RHPortControl
+ );
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+UHCIClearRootHubPortFeature (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 PortNumber,
+ IN EFI_USB_PORT_FEATURE PortFeature
+ )
+/*++
+
+ Routine Description:
+ Clears a feature for the specified root hub port.
+
+ Arguments:
+
+ This A pointer to the EFI_USB_HC_PROTOCOL instance.
+
+ PortNumber Specifies the root hub port whose feature
+ is requested to be cleared.
+
+ PortFeature Indicates the feature selector associated with the
+ feature clear request.
+
+ Returns:
+ EFI_SUCCESS
+ The feature specified by PortFeature was cleared for the
+ USB root hub port specified by PortNumber.
+ EFI_INVALID_PARAMETER
+ PortNumber is invalid or PortFeature is invalid.
+ EFI_DEVICE_ERROR
+ Can't read register
+--*/
+{
+ USB_HC_DEV *HcDev;
+ UINT32 PSAddr;
+ UINT16 RHPortControl;
+ UINT8 TotalPortNumber;
+ EFI_STATUS Status;
+
+ UHCIGetRootHubPortNumber (This, &TotalPortNumber);
+
+ if (PortNumber >= TotalPortNumber) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HcDev = USB_HC_DEV_FROM_THIS (This);
+ PSAddr = (UINT32) (USBPORTSC1 + PortNumber * 2);
+
+ Status = ReadRootPortReg (
+ HcDev->PciIo,
+ PSAddr,
+ &RHPortControl
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ switch (PortFeature) {
+ //
+ // clear PORT_ENABLE feature means disable port.
+ //
+ case EfiUsbPortEnable:
+ RHPortControl &= 0xfff5;
+ RHPortControl &= ~USBPORTSC_PED;
+ break;
+
+ //
+ // clear PORT_SUSPEND feature means resume the port.
+ // (cause a resume on the specified port if in suspend mode)
+ //
+ case EfiUsbPortSuspend:
+ RHPortControl &= 0xfff5;
+ RHPortControl &= ~USBPORTSC_SUSP;
+ break;
+
+ //
+ // no operation
+ //
+ case EfiUsbPortPower:
+ break;
+
+ //
+ // clear PORT_RESET means clear the reset signal.
+ //
+ case EfiUsbPortReset:
+ RHPortControl &= 0xfff5;
+ RHPortControl &= ~USBPORTSC_PR;
+ break;
+
+ //
+ // clear connect status change
+ //
+ case EfiUsbPortConnectChange:
+ RHPortControl &= 0xfff5;
+ RHPortControl |= USBPORTSC_CSC;
+ break;
+
+ //
+ // clear enable/disable status change
+ //
+ case EfiUsbPortEnableChange:
+ RHPortControl &= 0xfff5;
+ RHPortControl |= USBPORTSC_PEDC;
+ break;
+
+ //
+ // root hub does not support this request
+ //
+ case EfiUsbPortSuspendChange:
+ break;
+
+ //
+ // root hub does not support this request
+ //
+ case EfiUsbPortOverCurrentChange:
+ break;
+
+ //
+ // root hub does not support this request
+ //
+ case EfiUsbPortResetChange:
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ WriteRootPortReg (
+ HcDev->PciIo,
+ PSAddr,
+ RHPortControl
+ );
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+UHCIControlTransfer (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN BOOLEAN IsSlowDevice,
+ IN UINT8 MaximumPacketLength,
+ IN EFI_USB_DEVICE_REQUEST *Request,
+ IN EFI_USB_DATA_DIRECTION TransferDirection,
+ IN OUT VOID *Data, OPTIONAL
+ IN OUT UINTN *DataLength, OPTIONAL
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult
+ )
+/*++
+
+ Routine Description:
+ Submits control transfer to a target USB device.
+
+ Arguments:
+
+ This A pointer to the EFI_USB_HC_PROTOCOL instance.
+
+ DeviceAddress Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+
+ IsSlowDevice Indicates whether the target device is slow device
+ or full-speed device.
+
+ MaximumPacketLength Indicates the maximum packet size that the
+ default control transfer endpoint is capable of
+ sending or receiving.
+
+ Request A pointer to the USB device request that will be sent
+ to the USB device.
+
+ TransferDirection Specifies the data direction for the transfer.
+ There are three values available, DataIn, DataOut
+ and NoData.
+
+ Data A pointer to the buffer of data that will be transmitted
+ to USB device or received from USB device.
+
+ DataLength Indicates the size, in bytes, of the data buffer
+ specified by Data.
+
+ TimeOut Indicates the maximum time, in microseconds,
+ which the transfer is allowed to complete.
+
+ TransferResult A pointer to the detailed result information generated
+ by this control transfer.
+
+ Returns:
+ EFI_SUCCESS
+ The control transfer was completed successfully.
+ EFI_OUT_OF_RESOURCES
+ The control transfer could not be completed due to a lack of resources.
+ EFI_INVALID_PARAMETER
+ Some parameters are invalid.
+ EFI_TIMEOUT
+ The control transfer failed due to timeout.
+ EFI_DEVICE_ERROR
+ The control transfer failed due to host controller or device error.
+ Caller should check TranferResult for detailed error information.
+
+--*/
+{
+ USB_HC_DEV *HcDev;
+ UINT32 StatusReg;
+ UINT32 FrameNumReg;
+ UINT8 PktID;
+ QH_STRUCT *PtrQH;
+ TD_STRUCT *PtrTD;
+ TD_STRUCT *PtrPreTD;
+ TD_STRUCT *PtrSetupTD;
+ TD_STRUCT *PtrStatusTD;
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN DataLen;
+ UINT8 *PtrDataSource;
+ UINT8 *Ptr;
+ UINT8 DataToggle;
+ UINT16 LoadFrameListIndex;
+ UINT8 PktSize;
+
+ UINT8 *RequestMappedAddress;
+ VOID *RequestMapping;
+ UINTN RequestLen;
+
+ EFI_PHYSICAL_ADDRESS TempPtr;
+ VOID *Mapping;
+
+ TD_STRUCT *PtrFirstDataTD;
+ TD_STRUCT *ptrLastDataTD;
+ BOOLEAN FirstTD;
+
+ FirstTD = FALSE;
+ RequestMappedAddress = NULL;
+ RequestMapping = NULL;
+ Mapping = NULL;
+ PtrFirstDataTD = NULL;
+ ptrLastDataTD = NULL;
+ PktID = INPUT_PACKET_ID;
+ Mapping = NULL;
+ HcDev = USB_HC_DEV_FROM_THIS (This);
+ StatusReg = (UINT32) (USBSTS);
+ FrameNumReg = (UINT32) (USBFRNUM);
+ PtrPreTD = NULL;
+ PtrTD = NULL;
+
+ //
+ // Parameters Checking
+ //
+ if (Request == NULL || TransferResult == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // if errors exist that cause host controller halt,
+ // then return EFI_DEVICE_ERROR.
+ //
+ if (!IsStatusOK (HcDev->PciIo, StatusReg)) {
+
+ ClearStatusReg (HcDev->PciIo, StatusReg);
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // low speed usb devices are limited to only an eight-byte
+ // maximum data payload size
+ //
+ if (IsSlowDevice && (MaximumPacketLength != 8)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (MaximumPacketLength != 8 &&
+ MaximumPacketLength != 16 &&
+ MaximumPacketLength != 32 &&
+ MaximumPacketLength != 64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((TransferDirection != EfiUsbNoData) && (DataLength == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (TransferDirection) {
+
+ case EfiUsbDataIn:
+ PktID = INPUT_PACKET_ID;
+ PtrDataSource = Data;
+ DataLen = *DataLength;
+
+ //
+ // map the source data buffer for bus master access.
+ // BusMasterWrite means cpu read
+ //
+ Status = HcDev->PciIo->Map (
+ HcDev->PciIo,
+ EfiPciIoOperationBusMasterWrite,
+ PtrDataSource,
+ &DataLen,
+ &TempPtr,
+ &Mapping
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Ptr = (UINT8 *) ((UINTN) TempPtr);
+ break;
+
+ case EfiUsbDataOut:
+ PktID = OUTPUT_PACKET_ID;
+ PtrDataSource = Data;
+ DataLen = *DataLength;
+
+ //
+ // map the source data buffer for bus master access.
+ // BusMasterRead means cpu write
+ //
+ Status = HcDev->PciIo->Map (
+ HcDev->PciIo,
+ EfiPciIoOperationBusMasterRead,
+ PtrDataSource,
+ &DataLen,
+ &TempPtr,
+ &Mapping
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Ptr = (UINT8 *) ((UINTN) TempPtr);
+ break;
+
+ //
+ // no data stage
+ //
+ case EfiUsbNoData:
+ if ((DataLength != NULL) && (*DataLength != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PktID = OUTPUT_PACKET_ID;
+ PtrDataSource = NULL;
+ DataLen = 0;
+ Ptr = NULL;
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = ClearStatusReg (HcDev->PciIo, StatusReg);
+ if (EFI_ERROR (Status)) {
+ HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // create QH structure and init
+ //
+ Status = CreateQH (HcDev, &PtrQH);
+ if (EFI_ERROR (Status)) {
+ HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
+ return Status;
+ }
+
+ //
+ // map the Request for bus master access.
+ // BusMasterRead means cpu write
+ //
+ RequestLen = sizeof (EFI_USB_DEVICE_REQUEST);
+ Status = HcDev->PciIo->Map (
+ HcDev->PciIo,
+ EfiPciIoOperationBusMasterRead,
+ (UINT8 *) Request,
+ &RequestLen,
+ &TempPtr,
+ &RequestMapping
+ );
+
+ if (EFI_ERROR (Status)) {
+ HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
+ UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));
+ return Status;
+ }
+
+ RequestMappedAddress = (UINT8 *) ((UINTN) TempPtr);
+
+ //
+ // generate Setup Stage TD
+ //
+ Status = GenSetupStageTD (
+ HcDev,
+ DeviceAddress,
+ 0,
+ IsSlowDevice,
+ (UINT8 *) RequestMappedAddress,
+ sizeof (EFI_USB_DEVICE_REQUEST),
+ &PtrSetupTD
+ );
+
+ if (EFI_ERROR (Status)) {
+ HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
+ UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));
+ HcDev->PciIo->Unmap (HcDev->PciIo, RequestMapping);
+ return Status;
+ }
+
+ //
+ // Data Stage of Control Transfer
+ //
+ DataToggle = 1;
+ FirstTD = TRUE;
+ while (DataLen > 0) {
+ //
+ // create TD structures and link together
+ //
+
+ //
+ // PktSize is the data load size that each TD carries.
+ //
+ PktSize = (UINT8) DataLen;
+ if (DataLen > MaximumPacketLength) {
+ PktSize = MaximumPacketLength;
+ }
+
+ Status = GenDataTD (
+ HcDev,
+ DeviceAddress,
+ 0,
+ Ptr,
+ PktSize,
+ PktID,
+ DataToggle,
+ IsSlowDevice,
+ &PtrTD
+ );
+
+ if (EFI_ERROR (Status)) {
+ //
+ // free all resources occupied
+ //
+ HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
+ UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));
+ HcDev->PciIo->Unmap (HcDev->PciIo, RequestMapping);
+ DeleteQueuedTDs (HcDev, PtrSetupTD);
+ DeleteQueuedTDs (HcDev, PtrFirstDataTD);
+ return Status;
+ }
+
+ //
+ // Link two TDs in vertical depth
+ //
+ if (FirstTD) {
+ PtrFirstDataTD = PtrTD;
+ PtrFirstDataTD->ptrNextTD = NULL;
+ FirstTD = FALSE;
+ } else {
+ LinkTDToTD (PtrPreTD, PtrTD);
+ }
+
+ PtrPreTD = PtrTD;
+
+ DataToggle ^= 1;
+ Ptr += PktSize;
+ DataLen -= PktSize;
+ }
+
+ ptrLastDataTD = PtrTD;
+
+ //
+ // Status Stage of Control Transfer
+ //
+ if (PktID == OUTPUT_PACKET_ID) {
+ PktID = INPUT_PACKET_ID;
+ } else {
+ PktID = OUTPUT_PACKET_ID;
+ }
+
+ //
+ // create Status Stage TD structure
+ //
+ Status = CreateStatusTD (
+ HcDev,
+ DeviceAddress,
+ 0,
+ PktID,
+ IsSlowDevice,
+ &PtrStatusTD
+ );
+
+ if (EFI_ERROR (Status)) {
+ HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
+ UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));
+ HcDev->PciIo->Unmap (HcDev->PciIo, RequestMapping);
+ DeleteQueuedTDs (HcDev, PtrSetupTD);
+ DeleteQueuedTDs (HcDev, PtrFirstDataTD);
+ return Status;
+ }
+
+ if (IsSlowDevice) {
+ //
+ // link setup TD structures to QH structure
+ //
+ LinkTDToQH (PtrQH, PtrSetupTD);
+
+ LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);
+
+ //
+ // link QH-TDs to total 100 frame list entry to speed up the execution.
+ //
+ for (Index = 0; Index < 100; Index++) {
+ LinkQHToFrameList (
+ HcDev->FrameListEntry,
+ (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),
+ PtrQH
+ );
+ }
+ //
+ // Poll QH-TDs execution and get result.
+ // detail status is returned
+ //
+ Status = ExecuteControlTransfer (
+ HcDev,
+ PtrSetupTD,
+ LoadFrameListIndex,
+ DataLength,
+ TimeOut,
+ TransferResult
+ );
+ //
+ // Remove Control Transfer QH-TDs structure from the frame list
+ // and update the pointers in the Frame List
+ // and other pointers in other related QH structures.
+ //
+ for (Index = 0; Index < 100; Index++) {
+ DelLinkSingleQH (
+ HcDev,
+ PtrQH,
+ (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),
+ FALSE,
+ FALSE
+ );
+ }
+ //
+ // delete setup stage TD; the QH is reserved for the next stages.
+ //
+ DeleteQueuedTDs (HcDev, PtrSetupTD);
+
+ //
+ // if setup stage error, return error
+ //
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+ //
+ // some control transfers do not have Data Stage
+ //
+ if (PtrFirstDataTD != NULL) {
+
+ LinkTDToQH (PtrQH, PtrFirstDataTD);
+ LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);
+
+ for (Index = 0; Index < 500; Index++) {
+ LinkQHToFrameList (
+ HcDev->FrameListEntry,
+ (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),
+ PtrQH
+ );
+ }
+
+ Status = ExecuteControlTransfer (
+ HcDev,
+ PtrFirstDataTD,
+ LoadFrameListIndex,
+ DataLength,
+ TimeOut,
+ TransferResult
+ );
+
+ for (Index = 0; Index < 500; Index++) {
+ DelLinkSingleQH (
+ HcDev,
+ PtrQH,
+ (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),
+ FALSE,
+ FALSE
+ );
+ }
+ //
+ // delete data stage TD; the QH is reserved for the next stage.
+ //
+ DeleteQueuedTDs (HcDev, PtrFirstDataTD);
+ }
+ //
+ // if data stage error, goto done and return error
+ //
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ LinkTDToQH (PtrQH, PtrStatusTD);
+ //
+ // get the frame list index that the QH-TDs will be linked to.
+ //
+ LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);
+
+ for (Index = 0; Index < 100; Index++) {
+ //
+ // put the QH-TDs directly or indirectly into the proper place
+ // in the Frame List
+ //
+ LinkQHToFrameList (
+ HcDev->FrameListEntry,
+ (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),
+ PtrQH
+ );
+ }
+ //
+ // Poll QH-TDs execution and get result.
+ // detail status is returned
+ //
+ Status = ExecuteControlTransfer (
+ HcDev,
+ PtrStatusTD,
+ LoadFrameListIndex,
+ DataLength,
+ TimeOut,
+ TransferResult
+ );
+
+ //
+ // Delete Control Transfer QH-TDs structure
+ // and update the pointers in the Frame List
+ // and other pointers in other related QH structures.
+ //
+ // TRUE means must search other framelistindex
+ //
+ for (Index = 0; Index < 100; Index++) {
+ DelLinkSingleQH (
+ HcDev,
+ PtrQH,
+ (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),
+ FALSE,
+ FALSE
+ );
+ }
+
+ DeleteQueuedTDs (HcDev, PtrStatusTD);
+
+ } else {
+ //
+ // link setup stage TD with data stage TD
+ //
+ PtrPreTD = PtrSetupTD;
+ if (PtrFirstDataTD != NULL) {
+ LinkTDToTD (PtrSetupTD, PtrFirstDataTD);
+ PtrPreTD = ptrLastDataTD;
+ }
+ //
+ // link status TD with previous TD
+ //
+ LinkTDToTD (PtrPreTD, PtrStatusTD);
+
+ //
+ // link QH with TD
+ //
+ LinkTDToQH (PtrQH, PtrSetupTD);
+
+ LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);
+ for (Index = 0; Index < 500; Index++) {
+ //
+ // put the QH-TDs directly or indirectly into the proper place
+ // in the Frame List
+ //
+ LinkQHToFrameList (
+ HcDev->FrameListEntry,
+ (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),
+ PtrQH
+ );
+ }
+ //
+ // Poll QH-TDs execution and get result.
+ // detail status is returned
+ //
+ Status = ExecuteControlTransfer (
+ HcDev,
+ PtrSetupTD,
+ LoadFrameListIndex,
+ DataLength,
+ TimeOut,
+ TransferResult
+ );
+ //
+ // Remove Control Transfer QH-TDs structure from the frame list
+ // and update the pointers in the Frame List
+ // and other pointers in other related QH structures.
+ //
+ for (Index = 0; Index < 500; Index++) {
+ DelLinkSingleQH (
+ HcDev,
+ PtrQH,
+ (UINT16) ((LoadFrameListIndex + Index) & 0x3FF),
+ FALSE,
+ FALSE
+ );
+ }
+
+ DeleteQueuedTDs (HcDev, PtrSetupTD);
+ }
+
+Done:
+
+ UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));
+
+ if (Mapping != NULL) {
+ HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
+ }
+
+ if (RequestMapping != NULL) {
+ HcDev->PciIo->Unmap (HcDev->PciIo, RequestMapping);
+ }
+ //
+ // if has errors that cause host controller halt,
+ // then return EFI_DEVICE_ERROR directly.
+ //
+ if (!IsStatusOK (HcDev->PciIo, StatusReg)) {
+
+ ClearStatusReg (HcDev->PciIo, StatusReg);
+ *TransferResult |= EFI_USB_ERR_SYSTEM;
+ return EFI_DEVICE_ERROR;
+ }
+
+ ClearStatusReg (HcDev->PciIo, StatusReg);
+ HcDev->PciIo->Flush (HcDev->PciIo);
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+UHCIBulkTransfer (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 MaximumPacketLength,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult
+ )
+/*++
+
+ Routine Description:
+ Submits bulk transfer to a bulk endpoint of a USB device.
+
+ Arguments:
+
+ This A pointer to the EFI_USB_HC_PROTOCOL instance.
+
+ DeviceAddress Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ EndPointAddress The combination of an endpoint number and an
+ endpoint direction of the target USB device.
+ Each endpoint address supports data transfer in
+ one direction except the control endpoint
+ (whose default endpoint address is 0).
+ It is the caller's responsibility to make sure that
+ the EndPointAddress represents a bulk endpoint.
+
+ MaximumPacketLength Indicates the maximum packet size the target endpoint
+ is capable of sending or receiving.
+
+ Data A pointer to the buffer of data that will be transmitted
+ to USB device or received from USB device.
+ DataLength When input, indicates the size, in bytes, of the data buffer
+ specified by Data. When output, indicates the actually
+ transferred data size.
+
+ DataToggle A pointer to the data toggle value. On input, it indicates
+ the initial data toggle value the bulk transfer should adopt;
+ on output, it is updated to indicate the data toggle value
+ of the subsequent bulk transfer.
+
+ TimeOut Indicates the maximum time, in microseconds, which the
+ transfer is allowed to complete.
+
+ TransferResult A pointer to the detailed result information of the
+ bulk transfer.
+
+ Returns:
+ EFI_SUCCESS
+ The bulk transfer was completed successfully.
+ EFI_OUT_OF_RESOURCES
+ The bulk transfer could not be submitted due to lack of resource.
+ EFI_INVALID_PARAMETER
+ Some parameters are invalid.
+ EFI_TIMEOUT
+ The bulk transfer failed due to timeout.
+ EFI_DEVICE_ERROR
+ The bulk transfer failed due to host controller or device error.
+ Caller should check TranferResult for detailed error information.
+
+--*/
+{
+ USB_HC_DEV *HcDev;
+ UINT32 StatusReg;
+ UINT32 FrameNumReg;
+ UINTN DataLen;
+ QH_STRUCT *PtrQH;
+ TD_STRUCT *PtrFirstTD;
+ TD_STRUCT *PtrTD;
+ TD_STRUCT *PtrPreTD;
+ UINT16 LoadFrameListIndex;
+ UINT16 SavedFrameListIndex;
+ UINT8 PktID;
+ UINT8 *PtrDataSource;
+ UINT8 *Ptr;
+ BOOLEAN IsFirstTD;
+ EFI_STATUS Status;
+ UINT32 Index;
+ UINT8 PktSize;
+
+ EFI_USB_DATA_DIRECTION TransferDirection;
+ //
+ // Used to calculate how many entries are linked to the
+ // specified bulk transfer QH-TDs
+ //
+ UINT32 LinkTimes;
+
+ BOOLEAN ShortPacketEnable;
+ EFI_PHYSICAL_ADDRESS TempPtr;
+ VOID *Mapping;
+
+ HcDev = USB_HC_DEV_FROM_THIS (This);
+ StatusReg = (UINT32) (USBSTS);
+ FrameNumReg = (UINT32) (USBFRNUM);
+ PktID = INPUT_PACKET_ID;
+ PtrTD = NULL;
+ PtrFirstTD = NULL;
+ PtrPreTD = NULL;
+ LinkTimes = 1;
+ DataLen = 0;
+ Ptr = NULL;
+ ShortPacketEnable = FALSE;
+ Mapping = NULL;
+
+ //
+ // Parameters Checking
+ //
+
+ if ((DataLength == NULL) ||
+ (Data == NULL) ||
+ (TransferResult == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // if has errors that cause host controller halt,
+ // then return EFI_DEVICE_ERROR directly.
+ //
+ if (!IsStatusOK (HcDev->PciIo, StatusReg)) {
+
+ ClearStatusReg (HcDev->PciIo, StatusReg);
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (*DataLength == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((*DataToggle != 1) && (*DataToggle != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (MaximumPacketLength != 8 &&
+ MaximumPacketLength != 16 &&
+ MaximumPacketLength != 32 &&
+ MaximumPacketLength != 64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Enable the maximum packet size (64bytes)
+ // that can be used for full speed bandwidth reclamation
+ // at the end of a frame.
+ //
+ EnableMaxPacketSize (HcDev);
+
+ Status = ClearStatusReg (HcDev->PciIo, StatusReg);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // construct QH and TD data structures,
+ // and link them together
+ //
+ if (EndPointAddress & 0x80) {
+ TransferDirection = EfiUsbDataIn;
+ } else {
+ TransferDirection = EfiUsbDataOut;
+ }
+
+ switch (TransferDirection) {
+
+ case EfiUsbDataIn:
+ ShortPacketEnable = TRUE;
+ PktID = INPUT_PACKET_ID;
+ PtrDataSource = Data;
+ DataLen = *DataLength;
+
+ //
+ // BusMasterWrite means cpu read
+ //
+ Status = HcDev->PciIo->Map (
+ HcDev->PciIo,
+ EfiPciIoOperationBusMasterWrite,
+ PtrDataSource,
+ &DataLen,
+ &TempPtr,
+ &Mapping
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Ptr = (UINT8 *) ((UINTN) TempPtr);
+ break;
+
+ case EfiUsbDataOut:
+ PktID = OUTPUT_PACKET_ID;
+ PtrDataSource = Data;
+ DataLen = *DataLength;
+
+ //
+ // BusMasterRead means cpu write
+ //
+ Status = HcDev->PciIo->Map (
+ HcDev->PciIo,
+ EfiPciIoOperationBusMasterRead,
+ PtrDataSource,
+ &DataLen,
+ &TempPtr,
+ &Mapping
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Ptr = (UINT8 *) ((UINTN) TempPtr);
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // create QH structure and init
+ //
+ Status = CreateQH (HcDev, &PtrQH);
+ if (EFI_ERROR (Status)) {
+ HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
+ return Status;
+ }
+
+ //
+ // i is used to calculate the total number of TDs.
+ //
+ Index = 0;
+
+ IsFirstTD = TRUE;
+ while (DataLen > 0) {
+
+ //
+ // create TD structures and link together
+ //
+
+ PktSize = (UINT8) DataLen;
+ if (DataLen > MaximumPacketLength) {
+ PktSize = MaximumPacketLength;
+ }
+
+ Status = GenDataTD (
+ HcDev,
+ DeviceAddress,
+ EndPointAddress,
+ Ptr,
+ PktSize,
+ PktID,
+ *DataToggle,
+ FALSE,
+ &PtrTD
+ );
+
+ if (EFI_ERROR (Status)) {
+ HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
+ UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));
+ DeleteQueuedTDs (HcDev, PtrFirstTD);
+ return Status;
+ }
+
+ //
+ // Enable short packet detection.
+ // (default action is disabling short packet detection)
+ //
+ if (ShortPacketEnable) {
+ EnableorDisableTDShortPacket (PtrTD, TRUE);
+ }
+
+ if (IsFirstTD) {
+ PtrFirstTD = PtrTD;
+ PtrFirstTD->ptrNextTD = NULL;
+ IsFirstTD = FALSE;
+ } else {
+ //
+ // Link two TDs in vertical depth
+ //
+ LinkTDToTD (PtrPreTD, PtrTD);
+ }
+
+ Index++;
+
+ PtrPreTD = PtrTD;
+
+ *DataToggle ^= 1;
+ Ptr += PktSize;
+ DataLen -= PktSize;
+ }
+
+ //
+ // link TD structures to QH structure
+ //
+ LinkTDToQH (PtrQH, PtrFirstTD);
+
+ //
+ // calculate how many entries are linked to the specified bulk transfer QH-TDs
+ // the below values are referred to the USB spec revision1.1.
+ //
+ switch (MaximumPacketLength) {
+ case 8:
+ LinkTimes = Index / 71 + 1;
+ break;
+
+ case 16:
+ LinkTimes = Index / 51 + 1;
+ break;
+
+ case 32:
+ LinkTimes = Index / 33 + 1;
+ break;
+
+ case 64:
+ LinkTimes = Index / 19 + 1;
+ break;
+ }
+
+ LinkTimes += 500;
+
+ //
+ // put QH-TDs into Frame list
+ //
+ LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);
+ SavedFrameListIndex = LoadFrameListIndex;
+
+ for (Index = 0; Index <= LinkTimes; Index++) {
+
+ //
+ // put the QH-TD directly or indirectly into the proper place
+ // in the Frame List
+ //
+ LinkQHToFrameList (HcDev->FrameListEntry, LoadFrameListIndex, PtrQH);
+
+ LoadFrameListIndex += 1;
+ LoadFrameListIndex &= 0x3FF;
+ }
+
+ LoadFrameListIndex = SavedFrameListIndex;
+
+ //
+ // Execute QH-TD and get result
+ //
+ //
+ // detail status is put into the Result field in the pIRP
+ // the Data Toggle value is also re-updated to the value
+ // of the last successful TD
+ //
+ Status = ExecBulkorSyncInterruptTransfer (
+ HcDev,
+ PtrFirstTD,
+ LoadFrameListIndex,
+ DataLength,
+ DataToggle,
+ TimeOut,
+ TransferResult
+ );
+
+ //
+ // Delete Bulk transfer QH-TD structure
+ // and maitain the pointers in the Frame List
+ // and other pointers in related QH structure
+ //
+ // TRUE means must search other framelistindex
+ //
+ for (Index = 0; Index <= LinkTimes; Index++) {
+ DelLinkSingleQH (
+ HcDev,
+ PtrQH,
+ LoadFrameListIndex,
+ FALSE,
+ FALSE
+ );
+ LoadFrameListIndex += 1;
+ LoadFrameListIndex &= 0x3FF;
+ }
+
+ UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));
+
+ DeleteQueuedTDs (HcDev, PtrFirstTD);
+
+ if (Mapping != NULL) {
+ HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
+ }
+
+ //
+ // if has errors that cause host controller halt,
+ // then return EFI_DEVICE_ERROR directly.
+ //
+ if (!IsStatusOK (HcDev->PciIo, StatusReg)) {
+
+ ClearStatusReg (HcDev->PciIo, StatusReg);
+ *TransferResult |= EFI_USB_ERR_SYSTEM;
+ return EFI_DEVICE_ERROR;
+ }
+
+ ClearStatusReg (HcDev->PciIo, StatusReg);
+
+ HcDev->PciIo->Flush (HcDev->PciIo);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+UHCIAsyncInterruptTransfer (
+ IN EFI_USB_HC_PROTOCOL * This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN BOOLEAN IsSlowDevice,
+ IN UINT8 MaxiumPacketLength,
+ IN BOOLEAN IsNewTransfer,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN PollingInterval, OPTIONAL
+ IN UINTN DataLength, OPTIONAL
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction, OPTIONAL
+ IN VOID *Context OPTIONAL
+ )
+/*++
+
+ Routine Description:
+ Submits an asynchronous interrupt transfer to an
+ interrupt endpoint of a USB device.
+
+ Arguments:
+
+ This A pointer to the EFI_USB_HC_PROTOCOL instance.
+
+ DeviceAddress Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+
+ EndPointAddress The combination of an endpoint number and an endpoint
+ direction of the target USB device. Each endpoint address
+ supports data transfer in one direction except the
+ control endpoint (whose default endpoint address is 0).
+ It is the caller's responsibility to make sure that
+ the EndPointAddress represents an interrupt endpoint.
+
+ IsSlowDevice Indicates whether the target device is slow device
+ or full-speed device.
+
+ MaxiumPacketLength Indicates the maximum packet size the target endpoint
+ is capable of sending or receiving.
+
+ IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between
+ the host and the target interrupt endpoint.
+ If FALSE, the specified asynchronous interrupt pipe
+ is canceled.
+
+ DataToggle A pointer to the data toggle value. On input, it is valid
+ when IsNewTransfer is TRUE, and it indicates the initial
+ data toggle value the asynchronous interrupt transfer
+ should adopt.
+ On output, it is valid when IsNewTransfer is FALSE,
+ and it is updated to indicate the data toggle value of
+ the subsequent asynchronous interrupt transfer.
+
+ PollingInterval Indicates the interval, in milliseconds, that the
+ asynchronous interrupt transfer is polled.
+ This parameter is required when IsNewTransfer is TRUE.
+
+ DataLength Indicates the length of data to be received at the
+ rate specified by PollingInterval from the target
+ asynchronous interrupt endpoint. This parameter
+ is only required when IsNewTransfer is TRUE.
+
+ CallBackFunction The Callback function.This function is called at the
+ rate specified by PollingInterval.This parameter is
+ only required when IsNewTransfer is TRUE.
+
+ Context The context that is passed to the CallBackFunction.
+ This is an optional parameter and may be NULL.
+
+ Returns:
+ EFI_SUCCESS
+ The asynchronous interrupt transfer request has been successfully
+ submitted or canceled.
+ EFI_INVALID_PARAMETER
+ Some parameters are invalid.
+ EFI_OUT_OF_RESOURCES
+ The request could not be completed due to a lack of resources.
+ EFI_DEVICE_ERROR
+ Can't read register
+--*/
+{
+ USB_HC_DEV *HcDev;
+ UINT32 StatusReg;
+ UINT32 FrameNumReg;
+ UINTN DataLen;
+ QH_STRUCT *ptrFirstQH;
+ QH_STRUCT *PtrQH;
+ QH_STRUCT *ptrPreQH;
+ TD_STRUCT *PtrFirstTD;
+ TD_STRUCT *PtrTD;
+ TD_STRUCT *PtrPreTD;
+ UINT16 LoadFrameListIndex;
+ UINT16 Index;
+ UINT8 PktID;
+ UINT8 *Ptr;
+ UINT8 *MappedPtr;
+ BOOLEAN IsFirstTD;
+ BOOLEAN IsFirstQH;
+ EFI_STATUS Status;
+ BOOLEAN ShortPacketEnable;
+ UINT8 CurrentDataToggle;
+ EFI_PHYSICAL_ADDRESS TempPtr;
+ VOID *Mapping;
+ UINT8 PktSize;
+ QH_STRUCT *TempQH;
+ EFI_TPL OldTpl;
+
+ HcDev = USB_HC_DEV_FROM_THIS (This);
+ StatusReg = (UINT32) (USBSTS);
+ FrameNumReg = (UINT32) (USBFRNUM);
+ Mapping = NULL;
+ ShortPacketEnable = FALSE;
+
+ PktID = INPUT_PACKET_ID;
+ PtrTD = NULL;
+ PtrFirstTD = NULL;
+ PtrPreTD = NULL;
+ Ptr = NULL;
+ PtrQH = NULL;
+ ptrPreQH = NULL;
+ ptrFirstQH = NULL;
+
+ if ((EndPointAddress & 0x80) == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // delete Async interrupt transfer request
+ //
+ if (!IsNewTransfer) {
+
+ OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY);
+
+ Status = DeleteAsyncINTQHTDs (
+ HcDev,
+ DeviceAddress,
+ EndPointAddress,
+ DataToggle
+ );
+
+ gBS->RestoreTPL (OldTpl);
+
+ return Status;
+ }
+ //
+ // if has errors that cause host controller halt,
+ // then return EFI_DEVICE_ERROR directly.
+ //
+ if (!IsStatusOK (HcDev->PciIo, StatusReg)) {
+
+ ClearStatusReg (HcDev->PciIo, StatusReg);
+ return EFI_DEVICE_ERROR;
+ }
+
+ ClearStatusReg (HcDev->PciIo, StatusReg);
+
+ //
+ // submit Async interrupt transfer request
+ //
+ if (PollingInterval < 1 || PollingInterval > 255) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (DataLength == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((*DataToggle != 1) && (*DataToggle != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ShortPacketEnable = TRUE;
+ PktID = INPUT_PACKET_ID;
+ DataLen = DataLength;
+ Ptr = AllocatePool (DataLen);
+ if (Ptr == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // BusMasterWrite means cpu read
+ //
+ Status = HcDev->PciIo->Map (
+ HcDev->PciIo,
+ EfiPciIoOperationBusMasterWrite,
+ Ptr,
+ &DataLen,
+ &TempPtr,
+ &Mapping
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (Ptr);
+ return Status;
+ }
+
+ MappedPtr = (UINT8 *) ((UINTN) TempPtr);
+
+ CurrentDataToggle = *DataToggle;
+
+ IsFirstTD = TRUE;
+
+ while (DataLen > 0) {
+ //
+ // create TD structures and link together
+ //
+
+ PktSize = (UINT8) DataLen;
+ if (DataLen > MaxiumPacketLength) {
+ PktSize = MaxiumPacketLength;
+ }
+
+ Status = GenDataTD (
+ HcDev,
+ DeviceAddress,
+ EndPointAddress,
+ MappedPtr,
+ PktSize,
+ PktID,
+ CurrentDataToggle,
+ IsSlowDevice,
+ &PtrTD
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (Ptr);
+ HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
+ DeleteQueuedTDs (HcDev, PtrFirstTD);
+ return Status;
+ }
+ //
+ // Enable short packet detection.
+ //
+ if (ShortPacketEnable) {
+ EnableorDisableTDShortPacket (PtrTD, TRUE);
+ }
+
+ if (IsFirstTD) {
+ PtrFirstTD = PtrTD;
+ PtrFirstTD->ptrNextTD = NULL;
+ IsFirstTD = FALSE;
+ } else {
+ //
+ // Link two TDs in vertical depth
+ //
+ LinkTDToTD (PtrPreTD, PtrTD);
+ }
+
+ PtrPreTD = PtrTD;
+
+ CurrentDataToggle ^= 1;
+ MappedPtr += PktSize;
+ DataLen -= PktSize;
+ }
+
+ //
+ // roll one value back
+ //
+ CurrentDataToggle ^= 1;
+
+ //
+ // create a list of QH structures and init,
+ // link TDs to all the QHs, and link all the QHs together using internal
+ // defined pointer of the QH_STRUCT.
+ //
+ IsFirstQH = TRUE;
+ ptrPreQH = NULL;
+ for (Index = 0; Index < 1024;) {
+
+ Status = CreateQH (HcDev, &PtrQH);
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (Ptr);
+ HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
+ DeleteQueuedTDs (HcDev, PtrFirstTD);
+ PtrQH = ptrFirstQH;
+ while (PtrQH) {
+ TempQH = PtrQH;
+ PtrQH = TempQH->ptrNextIntQH;
+ UhciFreePool (HcDev, (UINT8 *) TempQH, sizeof (QH_STRUCT));
+ }
+
+ return Status;
+ }
+
+ //
+ // link TD structures to QH structure
+ //
+ LinkTDToQH (PtrQH, PtrFirstTD);
+
+ if (IsFirstQH) {
+ ptrFirstQH = PtrQH;
+ ptrFirstQH->ptrNextIntQH = NULL;
+ IsFirstQH = FALSE;
+ } else {
+ //
+ // link neighbor QH structures together
+ //
+ ptrPreQH->ptrNextIntQH = PtrQH;
+ }
+
+ ptrPreQH = PtrQH;
+
+ Index = (UINT16) (PollingInterval + Index);
+ }
+ //
+ // last QH in QH list should set its next QH pointer to NULL.
+ //
+ PtrQH->ptrNextIntQH = NULL;
+
+ //
+ // Save QH-TD structures in Interrupt transfer list,
+ // for monitor interrupt transfer execution routine use.
+ //
+ InsertQHTDToINTList (
+ HcDev,
+ ptrFirstQH,
+ PtrFirstTD,
+ DeviceAddress,
+ EndPointAddress,
+ CurrentDataToggle,
+ DataLength,
+ PollingInterval,
+ Mapping,
+ Ptr,
+ CallBackFunction,
+ Context
+ );
+
+ //
+ // put QHs-TDs into Frame list
+ //
+ LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);
+
+ PtrQH = ptrFirstQH;
+
+ for (Index = LoadFrameListIndex; Index < (1024 + LoadFrameListIndex);) {
+
+ //
+ // put the QH-TD directly or indirectly into the proper place
+ // in the Frame List
+ //
+ LinkQHToFrameList (HcDev->FrameListEntry, (UINT16) (Index & 0x3FF), PtrQH);
+
+ Index = (UINT16) (PollingInterval + Index);
+
+ PtrQH = PtrQH->ptrNextIntQH;
+ }
+
+ HcDev->PciIo->Flush (HcDev->PciIo);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+UHCISyncInterruptTransfer (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN BOOLEAN IsSlowDevice,
+ IN UINT8 MaximumPacketLength,
+ IN OUT VOID *Data,
+ IN OUT UINTN *DataLength,
+ IN OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult
+ )
+/*++
+
+ Routine Description:
+ Submits synchronous interrupt transfer to an interrupt endpoint
+ of a USB device.
+
+ Arguments:
+
+ This A pointer to the EFI_USB_HC_PROTOCOL instance.
+
+ DeviceAddress Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+
+ EndPointAddress The combination of an endpoint number and an endpoint
+ direction of the target USB device. Each endpoint
+ address supports data transfer in one direction
+ except the control endpoint (whose default
+ endpoint address is 0). It is the caller's responsibility
+ to make sure that the EndPointAddress represents
+ an interrupt endpoint.
+
+ IsSlowDevice Indicates whether the target device is slow device
+ or full-speed device.
+
+ MaximumPacketLength Indicates the maximum packet size the target endpoint
+ is capable of sending or receiving.
+
+ Data A pointer to the buffer of data that will be transmitted
+ to USB device or received from USB device.
+
+ DataLength On input, the size, in bytes, of the data buffer specified
+ by Data. On output, the number of bytes transferred.
+
+ DataToggle A pointer to the data toggle value. On input, it indicates
+ the initial data toggle value the synchronous interrupt
+ transfer should adopt;
+ on output, it is updated to indicate the data toggle value
+ of the subsequent synchronous interrupt transfer.
+
+ TimeOut Indicates the maximum time, in microseconds, which the
+ transfer is allowed to complete.
+
+ TransferResult A pointer to the detailed result information from
+ the synchronous interrupt transfer.
+
+ Returns:
+ EFI_SUCCESS
+ The synchronous interrupt transfer was completed successfully.
+ EFI_OUT_OF_RESOURCES
+ The synchronous interrupt transfer could not be submitted due
+ to lack of resource.
+ EFI_INVALID_PARAMETER
+ Some parameters are invalid.
+ EFI_TIMEOUT
+ The synchronous interrupt transfer failed due to timeout.
+ EFI_DEVICE_ERROR
+ The synchronous interrupt transfer failed due to host controller
+ or device error. Caller should check TranferResult for detailed
+ error information.
+--*/
+{
+ USB_HC_DEV *HcDev;
+ UINT32 StatusReg;
+ UINT32 FrameNumReg;
+ UINTN DataLen;
+ QH_STRUCT *PtrQH;
+ TD_STRUCT *PtrFirstTD;
+ TD_STRUCT *PtrTD;
+ TD_STRUCT *PtrPreTD;
+ UINT16 LoadFrameListIndex;
+ UINT16 SavedFrameListIndex;
+ UINT32 Index;
+ UINT32 LinkTimes;
+ UINT8 PktID;
+ UINT8 *PtrDataSource;
+ UINT8 *Ptr;
+ BOOLEAN IsFirstTD;
+ EFI_STATUS Status;
+ BOOLEAN ShortPacketEnable;
+ EFI_PHYSICAL_ADDRESS TempPtr;
+ VOID *Mapping;
+ UINT8 PktSize;
+
+ HcDev = USB_HC_DEV_FROM_THIS (This);
+ StatusReg = (UINT32) (USBSTS);
+ FrameNumReg = (UINT32) (USBFRNUM);
+ ShortPacketEnable = FALSE;
+ Mapping = NULL;
+ PktID = INPUT_PACKET_ID;
+ PtrTD = NULL;
+ PtrFirstTD = NULL;
+ PtrPreTD = NULL;
+ DataLen = 0;
+ Ptr = NULL;
+ Index = 0;
+ LinkTimes = 0;
+
+ //
+ // Parameters Checking
+ //
+
+ if ((DataLength == NULL) ||
+ (Data == NULL) ||
+ (TransferResult == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // if has errors that cause host controller halt,
+ // then return EFI_DEVICE_ERROR directly.
+ //
+ if (!IsStatusOK (HcDev->PciIo, StatusReg)) {
+
+ ClearStatusReg (HcDev->PciIo, StatusReg);
+ *TransferResult = EFI_USB_ERR_SYSTEM;
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ((EndPointAddress & 0x80) == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*DataLength == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((*DataToggle != 1) && (*DataToggle != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (MaximumPacketLength > 64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (IsSlowDevice && (MaximumPacketLength > 8)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ClearStatusReg (HcDev->PciIo, StatusReg);
+
+ //
+ // submit Sync interrupt transfer request
+ //
+ ShortPacketEnable = TRUE;
+ PktID = INPUT_PACKET_ID;
+ DataLen = *DataLength;
+ PtrDataSource = Data;
+
+ //
+ // create QH structure and init
+ //
+ Status = CreateQH (HcDev, &PtrQH);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // BusMasterWrite means cpu read
+ //
+ Status = HcDev->PciIo->Map (
+ HcDev->PciIo,
+ EfiPciIoOperationBusMasterWrite,
+ PtrDataSource,
+ &DataLen,
+ &TempPtr,
+ &Mapping
+ );
+ if (EFI_ERROR (Status)) {
+ UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));
+ return Status;
+ }
+
+ Ptr = (UINT8 *) ((UINTN) TempPtr);
+
+ IsFirstTD = TRUE;
+ while (DataLen > 0) {
+ //
+ // create TD structures and link together
+ //
+ PktSize = (UINT8) DataLen;
+ if (DataLen > MaximumPacketLength) {
+ PktSize = MaximumPacketLength;
+ }
+
+ Status = GenDataTD (
+ HcDev,
+ DeviceAddress,
+ EndPointAddress,
+ Ptr,
+ PktSize,
+ PktID,
+ *DataToggle,
+ IsSlowDevice,
+ &PtrTD
+ );
+ if (EFI_ERROR (Status)) {
+ UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));
+ HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
+ DeleteQueuedTDs (HcDev, PtrFirstTD);
+ return Status;
+ }
+ //
+ // Enable short packet detection.
+ //
+ if (ShortPacketEnable) {
+ EnableorDisableTDShortPacket (PtrTD, TRUE);
+ }
+
+ if (IsFirstTD) {
+ PtrFirstTD = PtrTD;
+ PtrFirstTD->ptrNextTD = NULL;
+ IsFirstTD = FALSE;
+ } else {
+ //
+ // Link two TDs in vertical depth
+ //
+ LinkTDToTD (PtrPreTD, PtrTD);
+ }
+
+ Index++;
+
+ PtrPreTD = PtrTD;
+
+ *DataToggle ^= 1;
+ Ptr += PktSize;
+ DataLen -= PktSize;
+ }
+
+ //
+ // link TD structures to QH structure
+ //
+ LinkTDToQH (PtrQH, PtrFirstTD);
+
+ switch (MaximumPacketLength) {
+ case 8:
+ LinkTimes = Index / 71 + 1;
+ break;
+
+ case 16:
+ LinkTimes = Index / 51 + 1;
+ break;
+
+ case 32:
+ LinkTimes = Index / 33 + 1;
+ break;
+
+ case 64:
+ LinkTimes = Index / 19 + 1;
+ break;
+ }
+
+ LinkTimes += 100;
+
+ LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF);
+ SavedFrameListIndex = LoadFrameListIndex;
+
+ for (Index = 0; Index < LinkTimes; Index++) {
+
+ //
+ // put the QH-TD directly or indirectly into the proper place
+ // in the Frame List
+ //
+ LinkQHToFrameList (HcDev->FrameListEntry, LoadFrameListIndex, PtrQH);
+
+ LoadFrameListIndex += 1;
+ LoadFrameListIndex &= 0x3FF;
+ }
+
+ LoadFrameListIndex = SavedFrameListIndex;
+ //
+ // detail status is put into the Result field in the pIRP
+ // the Data Toggle value is also re-updated to the value
+ // of the last successful TD
+ //
+ Status = ExecBulkorSyncInterruptTransfer (
+ HcDev,
+ PtrFirstTD,
+ LoadFrameListIndex,
+ DataLength,
+ DataToggle,
+ TimeOut,
+ TransferResult
+ );
+ //
+ // Delete Sync Interrupt transfer QH-TD structure
+ // and maintain the pointers in the Frame List
+ // and other pointers in related QH structure
+ //
+ // TRUE means must search other framelistindex
+ //
+ for (Index = 0; Index <= LinkTimes; Index++) {
+ DelLinkSingleQH (
+ HcDev,
+ PtrQH,
+ LoadFrameListIndex,
+ FALSE,
+ FALSE
+ );
+ LoadFrameListIndex += 1;
+ LoadFrameListIndex &= 0x3FF;
+ }
+
+ UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT));
+
+ DeleteQueuedTDs (HcDev, PtrFirstTD);
+
+ HcDev->PciIo->Unmap (HcDev->PciIo, Mapping);
+
+ //
+ // if has errors that cause host controller halt,
+ // then return EFI_DEVICE_ERROR directly.
+ //
+ if (!IsStatusOK (HcDev->PciIo, StatusReg)) {
+
+ ClearStatusReg (HcDev->PciIo, StatusReg);
+ *TransferResult |= EFI_USB_ERR_SYSTEM;
+ return EFI_DEVICE_ERROR;
+ }
+
+ ClearStatusReg (HcDev->PciIo, StatusReg);
+
+ HcDev->PciIo->Flush (HcDev->PciIo);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+UHCIIsochronousTransfer (
+ IN EFI_USB_HC_PROTOCOL *This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 MaximumPacketLength,
+ IN OUT VOID *Data,
+ IN UINTN DataLength,
+ OUT UINT32 *TransferResult
+ )
+/*++
+
+ Routine Description:
+ Submits isochronous transfer to a target USB device.
+
+ Arguments:
+
+ This - A pointer to the EFI_USB_HC_PROTOCOL instance.
+ DeviceAddress - Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+ EndPointAddress - End point address
+ MaximumPacketLength - Indicates the maximum packet size that the
+ default control transfer endpoint is capable of
+ sending or receiving.
+ Data - A pointer to the buffer of data that will be transmitted
+ to USB device or received from USB device.
+ DataLength - Indicates the size, in bytes, of the data buffer
+ specified by Data.
+ TransferResult - A pointer to the detailed result information generated
+ by this control transfer.
+ Returns:
+ EFI_UNSUPPORTED
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
+
+
+EFI_STATUS
+EFIAPI
+UHCIAsyncIsochronousTransfer (
+ IN EFI_USB_HC_PROTOCOL * This,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 MaximumPacketLength,
+ IN OUT VOID *Data,
+ IN UINTN DataLength,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack,
+ IN VOID *Context OPTIONAL
+ )
+/*++
+
+ Routine Description:
+ Submits Async isochronous transfer to a target USB device.
+
+ Arguments:
+
+ This - A pointer to the EFI_USB_HC_PROTOCOL instance.
+
+ DeviceAddress - Represents the address of the target device on the USB,
+ which is assigned during USB enumeration.
+
+ EndPointAddress - End point address
+
+ MaximumPacketLength - Indicates the maximum packet size that the
+ default control transfer endpoint is capable of
+ sending or receiving.
+
+ Data - A pointer to the buffer of data that will be transmitted
+ to USB device or received from USB device.
+
+ IsochronousCallBack - When the transfer complete, the call back function will be called
+
+ Context - Pass to the call back function as parameter
+
+ Returns:
+ EFI_UNSUPPORTED
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
+
+VOID
+EFIAPI
+MonitorInterruptTrans (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+ Routine Description:
+ Interrupt transfer periodic check handler
+ Arguments:
+ Event - Interrupt event
+ Contex - Pointer to USB_HC_DEV
+ Returns:
+ None
+--*/
+{
+
+ USB_HC_DEV *HcDev;
+ INTERRUPT_LIST *PtrList;
+ LIST_ENTRY *Link;
+ UINT32 Result;
+ VOID *DataBuffer;
+ UINTN DataLen;
+ UINTN ActualLen;
+ UINTN ErrTDPos;
+ UINT32 StatusAddr;
+ LIST_ENTRY *NextLink;
+
+ HcDev = (USB_HC_DEV *) Context;
+ StatusAddr = (UINT32) (USBSTS);
+
+ //
+ // interrupt transfer list is empty, means that no interrupt transfer
+ // is submitted by far.
+ //
+ if (IsListEmpty (&(HcDev->InterruptListHead))) {
+ return ;
+ }
+
+ NextLink = HcDev->InterruptListHead.ForwardLink;
+ do {
+
+ Link = NextLink;
+ NextLink = Link->ForwardLink;
+
+ PtrList = INTERRUPT_LIST_FROM_LINK (Link);
+
+ //
+ // get TD execution results.
+ // ErrTDPos is zero-based value indicating the first error TD's position
+ // in the TDs' list.
+ // This value is only valid when Result not equal NOERROR.
+ //
+ ExecuteAsyncINTTDs (
+ HcDev,
+ PtrList,
+ &Result,
+ &ErrTDPos,
+ &ActualLen
+ );
+
+ //
+ // interrupt transfer has not been executed yet.
+ //
+ if (((Result & EFI_USB_ERR_NAK) == EFI_USB_ERR_NAK) ||
+ ((Result & EFI_USB_ERR_NOTEXECUTE) == EFI_USB_ERR_NOTEXECUTE)) {
+ continue;
+ }
+ //
+ // get actual data length transferred data and its data length.
+ //
+ DataLen = ActualLen;
+ DataBuffer = AllocatePool (DataLen);
+ if (DataBuffer == NULL) {
+ return ;
+ }
+
+ CopyMem (
+ DataBuffer,
+ PtrList->PtrFirstTD->pTDBuffer,
+ DataLen
+ );
+
+ //
+ // only if interrupt endpoint responds
+ // and the interrupt transfer stops because of completion
+ // or error, then we will call callback function.
+ //
+ if (Result == EFI_USB_NOERROR) {
+ //
+ // add for real platform debug
+ //
+ if (PtrList->InterruptCallBack != NULL) {
+ (PtrList->InterruptCallBack) (
+ DataBuffer,
+ DataLen,
+ PtrList->InterruptContext,
+ Result
+ );
+ }
+
+ if (DataBuffer) {
+ gBS->FreePool (DataBuffer);
+ }
+
+ //
+ // update should done after data buffer got.
+ //
+ UpdateAsyncINTQHTDs (PtrList, Result, (UINT32) ErrTDPos);
+
+ } else {
+
+ DEBUG ((EFI_D_ERROR, "interrupt transfer error code is %x\n", Result));
+
+ if (DataBuffer) {
+ gBS->FreePool (DataBuffer);
+ }
+ //
+ // leave error recovery to its related device driver.
+ // A common case of the error recovery is to re-submit the interrupt
+ // transfer.
+ // When an interrupt transfer is re-submitted, its position in the linked
+ // list is changed. It is inserted to the head of the linked list, while
+ // this function scans the whole list from head to tail. Thus, the
+ // re-submitted interrupt transfer's callback function will not be called
+ // again in this round.
+ //
+ if (PtrList->InterruptCallBack != NULL) {
+ (PtrList->InterruptCallBack) (
+ NULL,
+ 0,
+ PtrList->InterruptContext,
+ Result
+ );
+ }
+ }
+ } while (NextLink != &(HcDev->InterruptListHead));
+
+}
diff --git a/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.h b/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.h
new file mode 100644
index 0000000..93da46c
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.h
@@ -0,0 +1,1187 @@
+/*++
+
+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:
+
+ Uhci.h
+
+Abstract:
+
+
+Revision History
+--*/
+
+#ifndef _UHCI_H
+#define _UHCI_H
+
+/*
+ * Universal Host Controller Interface data structures and defines
+ */
+
+#include <IndustryStandard/Pci22.h>
+
+#define EFI_D_UHCI EFI_D_INFO
+
+//
+// stall time
+//
+#define STALL_1_MILLI_SECOND 1000
+#define STALL_1_SECOND 1000 * STALL_1_MILLI_SECOND
+
+#define FORCE_GLOBAL_RESUME_TIME 20 * STALL_1_MILLI_SECOND
+
+#define ROOT_PORT_REST_TIME 50 * STALL_1_MILLI_SECOND
+
+#define PORT_RESET_RECOVERY_TIME 10 * STALL_1_MILLI_SECOND
+
+//
+// 50 ms
+//
+#define INTERRUPT_POLLING_TIME 50 * 1000 * 10
+
+//
+// UHCI IO Space Address Register Register locates at
+// offset 20 ~ 23h of PCI Configuration Space (UHCI spec, Revision 1.1),
+// so, its BAR Index is 4.
+//
+#define USB_BAR_INDEX 4
+
+//
+// One memory block uses 1 page (common buffer for QH,TD use.)
+//
+#define NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES 1
+
+
+#define bit(a) 1 << (a)
+
+//
+// ////////////////////////////////////////////////////////////////////////
+//
+// Universal Host Controller Registers Definitions
+//
+//////////////////////////////////////////////////////////////////////////
+extern UINT16 USBBaseAddr;
+
+/* Command register */
+#define USBCMD 0 /* Command Register Offset 00-01h */
+#define USBCMD_RS bit (0) /* Run/Stop */
+#define USBCMD_HCRESET bit (1) /* Host reset */
+#define USBCMD_GRESET bit (2) /* Global reset */
+#define USBCMD_EGSM bit (3) /* Global Suspend Mode */
+#define USBCMD_FGR bit (4) /* Force Global Resume */
+#define USBCMD_SWDBG bit (5) /* SW Debug mode */
+#define USBCMD_CF bit (6) /* Config Flag (sw only) */
+#define USBCMD_MAXP bit (7) /* Max Packet (0 = 32, 1 = 64) */
+
+/* Status register */
+#define USBSTS 2 /* Status Register Offset 02-03h */
+#define USBSTS_USBINT bit (0) /* Interrupt due to IOC */
+#define USBSTS_ERROR bit (1) /* Interrupt due to error */
+#define USBSTS_RD bit (2) /* Resume Detect */
+#define USBSTS_HSE bit (3) /* Host System Error*/
+#define USBSTS_HCPE bit (4) /* Host Controller Process Error*/
+#define USBSTS_HCH bit (5) /* HC Halted */
+
+/* Interrupt enable register */
+#define USBINTR 4 /* Interrupt Enable Register 04-05h */
+#define USBINTR_TIMEOUT bit (0) /* Timeout/CRC error enable */
+#define USBINTR_RESUME bit (1) /* Resume interrupt enable */
+#define USBINTR_IOC bit (2) /* Interrupt On Complete enable */
+#define USBINTR_SP bit (3) /* Short packet interrupt enable */
+
+/* Frame Number Register Offset 06-08h */
+#define USBFRNUM 6
+
+/* Frame List Base Address Register Offset 08-0Bh */
+#define USBFLBASEADD 8
+
+/* Start of Frame Modify Register Offset 0Ch */
+#define USBSOF 0x0c
+
+/* USB port status and control registers */
+#define USBPORTSC1 0x10 /*Port 1 offset 10-11h */
+#define USBPORTSC2 0x12 /*Port 2 offset 12-13h */
+
+#define USBPORTSC_CCS bit (0) /* Current Connect Status*/
+#define USBPORTSC_CSC bit (1) /* Connect Status Change */
+#define USBPORTSC_PED bit (2) /* Port Enable / Disable */
+#define USBPORTSC_PEDC bit (3) /* Port Enable / Disable Change */
+#define USBPORTSC_LSL bit (4) /* Line Status Low bit*/
+#define USBPORTSC_LSH bit (5) /* Line Status High bit*/
+#define USBPORTSC_RD bit (6) /* Resume Detect */
+#define USBPORTSC_LSDA bit (8) /* Low Speed Device Attached */
+#define USBPORTSC_PR bit (9) /* Port Reset */
+#define USBPORTSC_SUSP bit (12) /* Suspend */
+
+/* PCI Configuration Registers for USB */
+
+//
+// Class Code Register offset
+//
+#define CLASSC 0x09
+//
+// USB IO Space Base Address Register offset
+//
+#define USBBASE 0x20
+
+//
+// USB legacy Support
+//
+#define USB_EMULATION 0xc0
+
+//
+// USB Base Class Code,Sub-Class Code and Programming Interface.
+//
+#define PCI_CLASSC_PI_UHCI 0x00
+
+#define SETUP_PACKET_ID 0x2D
+#define INPUT_PACKET_ID 0x69
+#define OUTPUT_PACKET_ID 0xE1
+#define ERROR_PACKET_ID 0x55
+
+//
+// ////////////////////////////////////////////////////////////////////////
+//
+// USB Transfer Mechanism Data Structures
+//
+//////////////////////////////////////////////////////////////////////////
+#pragma pack(1)
+//
+// USB Class Code structure
+//
+typedef struct {
+ UINT8 PI;
+ UINT8 SubClassCode;
+ UINT8 BaseCode;
+} USB_CLASSC;
+
+typedef struct {
+ UINT32 QHHorizontalTerminate : 1;
+ UINT32 QHHorizontalQSelect : 1;
+ UINT32 QHHorizontalRsvd : 2;
+ UINT32 QHHorizontalPtr : 28;
+ UINT32 QHVerticalTerminate : 1;
+ UINT32 QHVerticalQSelect : 1;
+ UINT32 QHVerticalRsvd : 2;
+ UINT32 QHVerticalPtr : 28;
+} QUEUE_HEAD;
+
+typedef struct {
+ UINT32 TDLinkPtrTerminate : 1;
+ UINT32 TDLinkPtrQSelect : 1;
+ UINT32 TDLinkPtrDepthSelect : 1;
+ UINT32 TDLinkPtrRsvd : 1;
+ UINT32 TDLinkPtr : 28;
+ UINT32 TDStatusActualLength : 11;
+ UINT32 TDStatusRsvd : 5;
+ UINT32 TDStatus : 8;
+ UINT32 TDStatusIOC : 1;
+ UINT32 TDStatusIOS : 1;
+ UINT32 TDStatusLS : 1;
+ UINT32 TDStatusErr : 2;
+ UINT32 TDStatusSPD : 1;
+ UINT32 TDStatusRsvd2 : 2;
+ UINT32 TDTokenPID : 8;
+ UINT32 TDTokenDevAddr : 7;
+ UINT32 TDTokenEndPt : 4;
+ UINT32 TDTokenDataToggle : 1;
+ UINT32 TDTokenRsvd : 1;
+ UINT32 TDTokenMaxLen : 11;
+ UINT32 TDBufferPtr;
+} TD;
+
+#pragma pack()
+
+typedef struct {
+ QUEUE_HEAD QH;
+ VOID *ptrNext;
+ VOID *ptrDown;
+ VOID *ptrNextIntQH; // for interrupt transfer's special use
+ VOID *LoopPtr;
+} QH_STRUCT;
+
+typedef struct {
+ TD TDData;
+ UINT8 *pTDBuffer;
+ VOID *ptrNextTD;
+ VOID *ptrNextQH;
+ UINT16 TDBufferLength;
+ UINT16 reserved;
+} TD_STRUCT;
+
+//
+// ////////////////////////////////////////////////////////////////////////
+//
+// Universal Host Controller Device Data Structure
+//
+//////////////////////////////////////////////////////////////////////////
+#define USB_HC_DEV_FROM_THIS(a) CR (a, USB_HC_DEV, UsbHc, USB_HC_DEV_SIGNATURE)
+
+#define USB_HC_DEV_SIGNATURE EFI_SIGNATURE_32 ('u', 'h', 'c', 'i')
+#define INTERRUPT_LIST_SIGNATURE EFI_SIGNATURE_32 ('i', 'n', 't', 's')
+typedef struct {
+ UINTN Signature;
+
+ LIST_ENTRY Link;
+ UINT8 DevAddr;
+ UINT8 EndPoint;
+ UINT8 DataToggle;
+ UINT8 Reserved[5];
+ TD_STRUCT *PtrFirstTD;
+ QH_STRUCT *PtrQH;
+ UINTN DataLen;
+ UINTN PollInterval;
+ VOID *Mapping;
+ UINT8 *DataBuffer; // allocated host memory, not mapped memory
+ EFI_ASYNC_USB_TRANSFER_CALLBACK InterruptCallBack;
+ VOID *InterruptContext;
+} INTERRUPT_LIST;
+
+#define INTERRUPT_LIST_FROM_LINK(a) CR (a, INTERRUPT_LIST, Link, INTERRUPT_LIST_SIGNATURE)
+
+typedef struct {
+ UINT32 FrameListPtrTerminate : 1;
+ UINT32 FrameListPtrQSelect : 1;
+ UINT32 FrameListRsvd : 2;
+ UINT32 FrameListPtr : 28;
+
+} FRAMELIST_ENTRY;
+
+typedef struct _MEMORY_MANAGE_HEADER {
+ UINT8 *BitArrayPtr;
+ UINTN BitArraySizeInBytes;
+ UINT8 *MemoryBlockPtr;
+ UINTN MemoryBlockSizeInBytes;
+ VOID *Mapping;
+ struct _MEMORY_MANAGE_HEADER *Next;
+} MEMORY_MANAGE_HEADER;
+
+typedef struct {
+ UINTN Signature;
+ EFI_USB_HC_PROTOCOL UsbHc;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ //
+ // local data
+ //
+ LIST_ENTRY InterruptListHead;
+ FRAMELIST_ENTRY *FrameListEntry;
+ VOID *FrameListMapping;
+ MEMORY_MANAGE_HEADER *MemoryHeader;
+ EFI_EVENT InterruptTransTimer;
+ EFI_UNICODE_STRING_TABLE *ControllerNameTable;
+
+} USB_HC_DEV;
+
+extern EFI_DRIVER_BINDING_PROTOCOL gUhciDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gUhciComponentName;
+
+EFI_STATUS
+WriteUHCCommandReg (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 CmdAddrOffset,
+ IN UINT16 UsbCmd
+ );
+
+EFI_STATUS
+ReadUHCCommandReg (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 CmdAddrOffset,
+ IN OUT UINT16 *Data
+ );
+
+EFI_STATUS
+WriteUHCStatusReg (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 StatusAddrOffset,
+ IN UINT16 UsbSts
+ );
+
+EFI_STATUS
+ReadUHCStatusReg (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 StatusAddrOffset,
+ IN OUT UINT16 *Data
+ );
+
+EFI_STATUS
+ClearStatusReg (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 StatusAddrOffset
+ );
+
+EFI_STATUS
+ReadUHCFrameNumberReg (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 FrameNumAddrOffset,
+ IN OUT UINT16 *Data
+ );
+
+EFI_STATUS
+WriteUHCFrameListBaseReg (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 FlBaseAddrOffset,
+ IN UINT32 UsbFrameListBaseAddr
+ );
+
+EFI_STATUS
+ReadRootPortReg (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 PortAddrOffset,
+ IN OUT UINT16 *Data
+ );
+
+EFI_STATUS
+WriteRootPortReg (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 PortAddrOffset,
+ IN UINT16 ControlBits
+ );
+
+EFI_STATUS
+WaitForUHCHalt (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 StatusRegAddr,
+ IN UINTN Timeout
+ );
+
+BOOLEAN
+IsStatusOK (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 StatusRegAddr
+ );
+
+BOOLEAN
+IsHostSysOrProcessErr (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 StatusRegAddr
+ );
+
+//
+// This routine programs the USB frame number register. We assume that the
+// HC schedule execution is stopped.
+//
+EFI_STATUS
+SetFrameNumberReg (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 FRNUMAddr,
+ IN UINT16 Index
+ );
+
+UINT16
+GetCurrentFrameNumber (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 FRNUMAddr
+ );
+
+EFI_STATUS
+SetFrameListBaseAddress (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 FLBASEADDRReg,
+ IN UINT32 Addr
+ );
+
+UINT32
+GetFrameListBaseAddress (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT32 FLBAddr
+ );
+
+EFI_STATUS
+CreateFrameList (
+ IN USB_HC_DEV *HcDev,
+ IN UINT32 FLBASEADDRReg
+ );
+
+EFI_STATUS
+FreeFrameListEntry (
+ IN USB_HC_DEV *UhcDev
+ );
+
+VOID
+InitFrameList (
+ IN USB_HC_DEV *HcDev
+ );
+
+
+EFI_STATUS
+CreateQH (
+ IN USB_HC_DEV *HcDev,
+ OUT QH_STRUCT **pptrQH
+ );
+
+VOID
+SetQHHorizontalLinkPtr (
+ IN QH_STRUCT *ptrQH,
+ IN VOID *ptrNext
+ );
+
+VOID *
+GetQHHorizontalLinkPtr (
+ IN QH_STRUCT *ptrQH
+ );
+
+VOID
+SetQHHorizontalQHorTDSelect (
+ IN QH_STRUCT *ptrQH,
+ IN BOOLEAN bQH
+ );
+
+VOID
+SetQHHorizontalValidorInvalid (
+ IN QH_STRUCT *ptrQH,
+ IN BOOLEAN bValid
+ );
+
+VOID
+SetQHVerticalLinkPtr (
+ IN QH_STRUCT *ptrQH,
+ IN VOID *ptrNext
+ );
+
+VOID *
+GetQHVerticalLinkPtr (
+ IN QH_STRUCT *ptrQH
+ );
+
+VOID
+SetQHVerticalQHorTDSelect (
+ IN QH_STRUCT *ptrQH,
+ IN BOOLEAN bQH
+ );
+
+BOOLEAN
+IsQHHorizontalQHSelect (
+ IN QH_STRUCT *ptrQH
+ );
+
+VOID
+SetQHVerticalValidorInvalid (
+ IN QH_STRUCT *ptrQH,
+ IN BOOLEAN bValid
+ );
+
+BOOLEAN
+GetQHVerticalValidorInvalid (
+ IN QH_STRUCT *ptrQH
+ );
+
+EFI_STATUS
+AllocateTDStruct (
+ IN USB_HC_DEV *HcDev,
+ OUT TD_STRUCT **ppTDStruct
+ );
+/*++
+
+Routine Description:
+
+ Allocate TD Struct
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ ppTDStruct - place to store TD_STRUCT pointer
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+
+EFI_STATUS
+CreateTD (
+ IN USB_HC_DEV *HcDev,
+ OUT TD_STRUCT **pptrTD
+ );
+/*++
+
+Routine Description:
+
+ Create TD
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ pptrTD - TD_STRUCT pointer to store
+
+Returns:
+
+ EFI_OUT_OF_RESOURCES - Can't allocate resources
+ EFI_SUCCESS - Success
+
+--*/
+
+
+EFI_STATUS
+GenSetupStageTD (
+ IN USB_HC_DEV *HcDev,
+ IN UINT8 DevAddr,
+ IN UINT8 Endpoint,
+ IN BOOLEAN bSlow,
+ IN UINT8 *pDevReq,
+ IN UINT8 RequestLen,
+ OUT TD_STRUCT **ppTD
+ );
+/*++
+
+Routine Description:
+
+ Generate Setup Stage TD
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ DevAddr - Device address
+ Endpoint - Endpoint number
+ bSlow - Full speed or low speed
+ pDevReq - Device request
+ RequestLen - Request length
+ ppTD - TD_STRUCT to return
+Returns:
+
+ EFI_OUT_OF_RESOURCES - Can't allocate memory
+ EFI_SUCCESS - Success
+
+--*/
+
+EFI_STATUS
+GenDataTD (
+ IN USB_HC_DEV *HcDev,
+ IN UINT8 DevAddr,
+ IN UINT8 Endpoint,
+ IN UINT8 *pData,
+ IN UINT8 Len,
+ IN UINT8 PktID,
+ IN UINT8 Toggle,
+ IN BOOLEAN bSlow,
+ OUT TD_STRUCT **ppTD
+ );
+/*++
+
+Routine Description:
+
+ Generate Data Stage TD
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ DevAddr - Device address
+ Endpoint - Endpoint number
+ pData - Data buffer
+ Len - Data length
+ PktID - Packet ID
+ Toggle - Data toggle value
+ bSlow - Full speed or low speed
+ ppTD - TD_STRUCT to return
+Returns:
+
+ EFI_OUT_OF_RESOURCES - Can't allocate memory
+ EFI_SUCCESS - Success
+
+--*/
+
+EFI_STATUS
+CreateStatusTD (
+ IN USB_HC_DEV *HcDev,
+ IN UINT8 DevAddr,
+ IN UINT8 Endpoint,
+ IN UINT8 PktID,
+ IN BOOLEAN bSlow,
+ OUT TD_STRUCT **ppTD
+ );
+/*++
+
+Routine Description:
+
+ Generate Setup Stage TD
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ DevAddr - Device address
+ Endpoint - Endpoint number
+ bSlow - Full speed or low speed
+ pDevReq - Device request
+ RequestLen - Request length
+ ppTD - TD_STRUCT to return
+Returns:
+
+ EFI_OUT_OF_RESOURCES - Can't allocate memory
+ EFI_SUCCESS - Success
+
+--*/
+
+VOID
+SetTDLinkPtrValidorInvalid (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN bValid
+ );
+
+VOID
+SetTDLinkPtrQHorTDSelect (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN bQH
+ );
+
+VOID
+SetTDLinkPtrDepthorBreadth (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN bDepth
+ );
+
+VOID
+SetTDLinkPtr (
+ IN TD_STRUCT *ptrTDStruct,
+ IN VOID *ptrNext
+ );
+
+VOID *
+GetTDLinkPtr (
+ IN TD_STRUCT *ptrTDStruct
+ );
+
+VOID
+EnableorDisableTDShortPacket (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN bEnable
+ );
+
+VOID
+SetTDControlErrorCounter (
+ IN TD_STRUCT *ptrTDStruct,
+ IN UINT8 nMaxErrors
+ );
+
+VOID
+SetTDLoworFullSpeedDevice (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN bLowSpeedDevice
+ );
+
+VOID
+SetTDControlIsochronousorNot (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN bIsochronous
+ );
+
+VOID
+SetorClearTDControlIOC (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN bSet
+ );
+
+VOID
+SetTDStatusActiveorInactive (
+ IN TD_STRUCT *ptrTDStruct,
+ IN BOOLEAN bActive
+ );
+
+UINT16
+SetTDTokenMaxLength (
+ IN TD_STRUCT *ptrTDStruct,
+ IN UINT16 nMaxLen
+ );
+
+VOID
+SetTDTokenDataToggle1 (
+ IN TD_STRUCT *ptrTDStruct
+ );
+
+VOID
+SetTDTokenDataToggle0 (
+ IN TD_STRUCT *ptrTDStruct
+ );
+
+UINT8
+GetTDTokenDataToggle (
+ IN TD_STRUCT *ptrTDStruct
+ );
+
+VOID
+SetTDTokenEndPoint (
+ IN TD_STRUCT *ptrTDStruct,
+ IN UINTN nEndPoint
+ );
+
+VOID
+SetTDTokenDeviceAddress (
+ IN TD_STRUCT *ptrTDStruct,
+ IN UINTN nDevAddr
+ );
+
+VOID
+SetTDTokenPacketID (
+ IN TD_STRUCT *ptrTDStruct,
+ IN UINT8 nPID
+ );
+
+VOID
+SetTDDataBuffer (
+ IN TD_STRUCT *ptrTDStruct
+ );
+
+BOOLEAN
+IsTDStatusActive (
+ IN TD_STRUCT *ptrTDStruct
+ );
+
+BOOLEAN
+IsTDStatusStalled (
+ IN TD_STRUCT *ptrTDStruct
+ );
+
+BOOLEAN
+IsTDStatusBufferError (
+ IN TD_STRUCT *ptrTDStruct
+ );
+
+BOOLEAN
+IsTDStatusBabbleError (
+ IN TD_STRUCT *ptrTDStruct
+ );
+
+BOOLEAN
+IsTDStatusNAKReceived (
+ IN TD_STRUCT *ptrTDStruct
+ );
+
+BOOLEAN
+IsTDStatusCRCTimeOutError (
+ IN TD_STRUCT *ptrTDStruct
+ );
+
+BOOLEAN
+IsTDStatusBitStuffError (
+ IN TD_STRUCT *ptrTDStruct
+ );
+
+UINT16
+GetTDStatusActualLength (
+ IN TD_STRUCT *ptrTDStruct
+ );
+
+UINT16
+GetTDTokenMaxLength (
+ IN TD_STRUCT *ptrTDStruct
+ );
+
+UINT8
+GetTDTokenEndPoint (
+ IN TD_STRUCT *ptrTDStruct
+ );
+
+UINT8
+GetTDTokenDeviceAddress (
+ IN TD_STRUCT *ptrTDStruct
+ );
+
+UINT8
+GetTDTokenPacketID (
+ IN TD_STRUCT *ptrTDStruct
+ );
+
+UINT8 *
+GetTDDataBuffer (
+ IN TD_STRUCT *ptrTDStruct
+ );
+
+BOOLEAN
+GetTDLinkPtrValidorInvalid (
+ IN TD_STRUCT *ptrTDStruct
+ );
+
+UINTN
+CountTDsNumber (
+ IN TD_STRUCT *ptrFirstTD
+ );
+
+VOID
+LinkTDToQH (
+ IN QH_STRUCT *ptrQH,
+ IN TD_STRUCT *ptrTD
+ );
+
+VOID
+LinkTDToTD (
+ IN TD_STRUCT *ptrPreTD,
+ IN TD_STRUCT *ptrTD
+ );
+
+VOID
+SetorClearCurFrameListTerminate (
+ IN FRAMELIST_ENTRY *pCurEntry,
+ IN BOOLEAN bSet
+ );
+
+VOID
+SetCurFrameListQHorTD (
+ IN FRAMELIST_ENTRY *pCurEntry,
+ IN BOOLEAN bQH
+ );
+
+BOOLEAN
+GetCurFrameListTerminate (
+ IN FRAMELIST_ENTRY *pCurEntry
+ );
+
+VOID
+SetCurFrameListPointer (
+ IN FRAMELIST_ENTRY *pCurEntry,
+ IN UINT8 *ptr
+ );
+
+VOID *
+GetCurFrameListPointer (
+ IN FRAMELIST_ENTRY *pCurEntry
+ );
+
+VOID
+LinkQHToFrameList (
+ IN FRAMELIST_ENTRY *pEntry,
+ IN UINT16 FrameListIndex,
+ IN QH_STRUCT *ptrQH
+ );
+/*++
+
+Routine Description:
+
+ Link QH To Frame List
+
+Arguments:
+
+ pEntry - FRAMELIST_ENTRY
+ FrameListIndex - Frame List Index
+ PtrQH - QH to link
+Returns:
+
+ VOID
+
+--*/
+VOID
+DeleteQHTDs (
+ IN FRAMELIST_ENTRY *pEntry,
+ IN QH_STRUCT *ptrQH,
+ IN TD_STRUCT *ptrFirstTD,
+ IN UINT16 FrameListIndex,
+ IN BOOLEAN SearchOther
+ );
+
+VOID
+DelLinkSingleQH (
+ IN USB_HC_DEV *HcDev,
+ IN QH_STRUCT *ptrQH,
+ IN UINT16 FrameListIndex,
+ IN BOOLEAN SearchOther,
+ IN BOOLEAN Delete
+ );
+
+VOID
+DeleteQueuedTDs (
+ IN USB_HC_DEV *HcDev,
+ IN TD_STRUCT *ptrFirstTD
+ );
+
+VOID
+InsertQHTDToINTList (
+ IN USB_HC_DEV *HcDev,
+ IN QH_STRUCT *ptrQH,
+ IN TD_STRUCT *ptrFirstTD,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ IN UINT8 DataToggle,
+ IN UINTN DataLength,
+ IN UINTN PollingInterval,
+ IN VOID *Mapping,
+ IN UINT8 *DataBuffer,
+ IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction,
+ IN VOID *Context
+ );
+/*++
+Routine Description:
+ Insert QH and TD To Interrupt List
+Arguments:
+
+ HcDev - USB_HC_DEV
+ PtrQH - QH_STRUCT
+ PtrFirstTD - First TD_STRUCT
+ DeviceAddress - Device Address
+ EndPointAddress - EndPoint Address
+ DataToggle - Data Toggle
+ DataLength - Data length
+ PollingInterval - Polling Interval when inserted to frame list
+ Mapping - Mapping alue
+ DataBuffer - Data buffer
+ CallBackFunction- CallBackFunction after interrupt transfeer
+ Context - CallBackFunction Context passed as function parameter
+Returns:
+ EFI_SUCCESS - Sucess
+ EFI_INVALID_PARAMETER - Paremeter is error
+
+--*/
+
+EFI_STATUS
+DeleteAsyncINTQHTDs (
+ IN USB_HC_DEV *HcDev,
+ IN UINT8 DeviceAddress,
+ IN UINT8 EndPointAddress,
+ OUT UINT8 *DataToggle
+ );
+/*++
+Routine Description:
+
+ Delete Async INT QH and TDs
+Arguments:
+
+ HcDev - USB_HC_DEV
+ DeviceAddress - Device Address
+ EndPointAddress - EndPoint Address
+ DataToggle - Data Toggle
+
+Returns:
+ EFI_SUCCESS - Sucess
+ EFI_INVALID_PARAMETER - Paremeter is error
+
+--*/
+BOOLEAN
+CheckTDsResults (
+ IN TD_STRUCT *ptrTD,
+ IN UINTN RequiredLen,
+ OUT UINT32 *Result,
+ OUT UINTN *ErrTDPos,
+ OUT UINTN *ActualTransferSize
+ );
+/*++
+
+Routine Description:
+
+ Check TDs Results
+
+Arguments:
+
+ PtrTD - TD_STRUCT to check
+ RequiredLen - Required Len
+ Result - Transfer result
+ ErrTDPos - Error TD Position
+ ActualTransferSize - Actual Transfer Size
+
+Returns:
+
+ TRUE - Sucess
+ FALSE - Fail
+
+--*/
+VOID
+ExecuteAsyncINTTDs (
+ IN USB_HC_DEV *HcDev,
+ IN INTERRUPT_LIST *ptrList,
+ OUT UINT32 *Result,
+ OUT UINTN *ErrTDPos,
+ OUT UINTN *ActualLen
+ ) ;
+/*++
+
+Routine Description:
+
+ Execute Async Interrupt TDs
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ PtrList - INTERRUPT_LIST
+ Result - Transfer result
+ ErrTDPos - Error TD Position
+ ActualTransferSize - Actual Transfer Size
+
+Returns:
+
+ VOID
+
+--*/
+VOID
+UpdateAsyncINTQHTDs (
+ IN INTERRUPT_LIST *ptrList,
+ IN UINT32 Result,
+ IN UINT32 ErrTDPos
+ );
+/*++
+
+Routine Description:
+
+ Update Async Interrupt QH and TDs
+
+Arguments:
+
+ PtrList - INTERRUPT_LIST
+ Result - Transfer reslut
+ ErrTDPos - Error TD Position
+
+Returns:
+
+ VOID
+
+--*/
+VOID
+ReleaseInterruptList (
+ IN USB_HC_DEV *HcDev,
+ IN LIST_ENTRY *ListHead
+ );
+/*++
+
+Routine Description:
+
+ Release Interrupt List
+Arguments:
+
+ HcDev - USB_HC_DEV
+ ListHead - List head
+
+Returns:
+
+ VOID
+
+--*/
+EFI_STATUS
+ExecuteControlTransfer (
+ IN USB_HC_DEV *HcDev,
+ IN TD_STRUCT *ptrTD,
+ IN UINT32 wIndex,
+ OUT UINTN *ActualLen,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult
+ );
+/*++
+
+Routine Description:
+
+ Execute Control Transfer
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ PtrTD - TD_STRUCT
+ wIndex - No use
+ ActualLen - Actual transfered Len
+ TimeOut - TimeOut value in milliseconds
+ TransferResult - Transfer result
+Returns:
+
+ EFI_SUCCESS - Sucess
+ EFI_DEVICE_ERROR - Error
+
+
+--*/
+EFI_STATUS
+ExecBulkorSyncInterruptTransfer (
+ IN USB_HC_DEV *HcDev,
+ IN TD_STRUCT *ptrTD,
+ IN UINT32 wIndex,
+ OUT UINTN *ActualLen,
+ OUT UINT8 *DataToggle,
+ IN UINTN TimeOut,
+ OUT UINT32 *TransferResult
+ );
+/*++
+
+Routine Description:
+
+ Execute Bulk or SyncInterrupt Transfer
+
+Arguments:
+
+ HcDev - USB_HC_DEV
+ PtrTD - TD_STRUCT
+ wIndex - No use
+ ActualLen - Actual transfered Len
+ DataToggle - Data Toggle
+ TimeOut - TimeOut value in milliseconds
+ TransferResult - Transfer result
+Returns:
+
+ EFI_SUCCESS - Sucess
+ EFI_DEVICE_ERROR - Error
+--*/
+
+EFI_STATUS
+InitializeMemoryManagement (
+ IN USB_HC_DEV *HcDev
+ );
+
+EFI_STATUS
+CreateMemoryBlock (
+ IN USB_HC_DEV *HcDev,
+ IN MEMORY_MANAGE_HEADER **MemoryHeader,
+ IN UINTN MemoryBlockSizeInPages
+ );
+
+EFI_STATUS
+FreeMemoryHeader (
+ IN USB_HC_DEV *HcDev,
+ IN MEMORY_MANAGE_HEADER *MemoryHeader
+ );
+
+EFI_STATUS
+UhciAllocatePool (
+ IN USB_HC_DEV *UhcDev,
+ IN UINT8 **Pool,
+ IN UINTN AllocSize
+ );
+
+VOID
+UhciFreePool (
+ IN USB_HC_DEV *HcDev,
+ IN UINT8 *Pool,
+ IN UINTN AllocSize
+ );
+
+VOID
+InsertMemoryHeaderToList (
+ IN MEMORY_MANAGE_HEADER *MemoryHeader,
+ IN MEMORY_MANAGE_HEADER *NewMemoryHeader
+ );
+
+EFI_STATUS
+AllocMemInMemoryBlock (
+ IN MEMORY_MANAGE_HEADER *MemoryHeader,
+ IN VOID **Pool,
+ IN UINTN NumberOfMemoryUnit
+ );
+
+BOOLEAN
+IsMemoryBlockEmptied (
+ IN MEMORY_MANAGE_HEADER *MemoryHeaderPtr
+ );
+
+VOID
+DelinkMemoryBlock (
+ IN MEMORY_MANAGE_HEADER *FirstMemoryHeader,
+ IN MEMORY_MANAGE_HEADER *FreeMemoryHeader
+ );
+
+EFI_STATUS
+DelMemoryManagement (
+ IN USB_HC_DEV *HcDev
+ );
+
+VOID
+EnableMaxPacketSize (
+ IN USB_HC_DEV *HcDev
+ );
+
+VOID
+CleanUsbTransactions (
+ IN USB_HC_DEV *HcDev
+ );
+
+VOID
+TurnOffUSBEmulation (
+ IN EFI_PCI_IO_PROTOCOL *PciIo
+ );
+
+#endif
diff --git a/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Decode.c b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Decode.c
new file mode 100644
index 0000000..f851b9b
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Decode.c
@@ -0,0 +1,1661 @@
+/*++
+
+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:
+ decode.c
+
+Abstract:
+
+Revision history:
+
+--*/
+
+// TODO: fix comment to add: Module Name: DECODE.C
+#include "undi32.h"
+
+
+#pragma data_seg("rtdata")
+
+//
+// Global variables defined outside this file
+//
+extern PXE_SW_UNDI *pxe; // !pxe structure
+extern PXE_SW_UNDI *pxe_31; // !pxe structure for 3.1 drivers
+extern UNDI32_DEV *UNDI32DeviceList[MAX_NIC_INTERFACES];
+
+//
+// Global variables defined in this file
+//
+UNDI_CALL_TABLE api_table[PXE_OPCODE_LAST_VALID+1] = { \
+ {PXE_CPBSIZE_NOT_USED,PXE_DBSIZE_NOT_USED,0, (UINT16)(ANY_STATE),UNDI_GetState },\
+ {(UINT16)(DONT_CHECK),PXE_DBSIZE_NOT_USED,0,(UINT16)(ANY_STATE),UNDI_Start },\
+ {PXE_CPBSIZE_NOT_USED,PXE_DBSIZE_NOT_USED,0,MUST_BE_STARTED,UNDI_Stop },\
+ {PXE_CPBSIZE_NOT_USED,sizeof(PXE_DB_GET_INIT_INFO),0,MUST_BE_STARTED, UNDI_GetInitInfo },\
+ {PXE_CPBSIZE_NOT_USED,sizeof(PXE_DB_GET_CONFIG_INFO),0,MUST_BE_STARTED, UNDI_GetConfigInfo },\
+ {sizeof(PXE_CPB_INITIALIZE),(UINT16)(DONT_CHECK),(UINT16)(DONT_CHECK),MUST_BE_STARTED,UNDI_Initialize },\
+ {PXE_CPBSIZE_NOT_USED,PXE_DBSIZE_NOT_USED,(UINT16)(DONT_CHECK), MUST_BE_INITIALIZED,UNDI_Reset },\
+ {PXE_CPBSIZE_NOT_USED,PXE_DBSIZE_NOT_USED,0, MUST_BE_INITIALIZED,UNDI_Shutdown },\
+ {PXE_CPBSIZE_NOT_USED,PXE_DBSIZE_NOT_USED,(UINT16)(DONT_CHECK), MUST_BE_INITIALIZED,UNDI_Interrupt },\
+ {(UINT16)(DONT_CHECK),(UINT16)(DONT_CHECK),(UINT16)(DONT_CHECK), MUST_BE_INITIALIZED, UNDI_RecFilter },\
+ {(UINT16)(DONT_CHECK),(UINT16)(DONT_CHECK),(UINT16)(DONT_CHECK), MUST_BE_INITIALIZED, UNDI_StnAddr },\
+ {PXE_CPBSIZE_NOT_USED, (UINT16)(DONT_CHECK), (UINT16)(DONT_CHECK), MUST_BE_INITIALIZED, UNDI_Statistics },\
+ {sizeof(PXE_CPB_MCAST_IP_TO_MAC),sizeof(PXE_DB_MCAST_IP_TO_MAC), (UINT16)(DONT_CHECK),MUST_BE_INITIALIZED, UNDI_ip2mac },\
+ {(UINT16)(DONT_CHECK),(UINT16)(DONT_CHECK),(UINT16)(DONT_CHECK), MUST_BE_INITIALIZED, UNDI_NVData },\
+ {PXE_CPBSIZE_NOT_USED,(UINT16)(DONT_CHECK),(UINT16)(DONT_CHECK), MUST_BE_INITIALIZED, UNDI_Status },\
+ {(UINT16)(DONT_CHECK),PXE_DBSIZE_NOT_USED,(UINT16)(DONT_CHECK), MUST_BE_INITIALIZED, UNDI_FillHeader },\
+ {(UINT16)(DONT_CHECK),PXE_DBSIZE_NOT_USED,(UINT16)(DONT_CHECK), MUST_BE_INITIALIZED, UNDI_Transmit },\
+ {sizeof(PXE_CPB_RECEIVE),sizeof(PXE_DB_RECEIVE),0,MUST_BE_INITIALIZED, UNDI_Receive } \
+};
+
+//
+// end of global variables
+//
+
+VOID
+UNDI_GetState (
+ IN PXE_CDB *CdbPtr,
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+ This routine determines the operational state of the UNDI. It updates the state flags in the
+ Command Descriptor Block based on information derived from the AdapterInfo instance data.
+
+ To ensure the command has completed successfully, CdbPtr->StatCode will contain the result of
+ the command execution.
+
+ The CdbPtr->StatFlags will contain a STOPPED, STARTED, or INITIALIZED state once the command
+ has successfully completed.
+
+ Keep in mind the AdapterInfo->State is the active state of the adapter (based on software
+ interrogation), and the CdbPtr->StateFlags is the passed back information that is reflected
+ to the caller of the UNDI API.
+
+Arguments:
+ CdbPtr - Pointer to the command descriptor block.
+ AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
+
+Returns:
+ None
+
+--*/
+{
+ CdbPtr->StatFlags |= AdapterInfo->State;
+ return ;
+}
+
+VOID
+UNDI_Start (
+ IN PXE_CDB *CdbPtr,
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+ This routine is used to change the operational state of the UNDI from stopped to started.
+ It will do this as long as the adapter's state is PXE_STATFLAGS_GET_STATE_STOPPED, otherwise
+ the CdbPtr->StatFlags will reflect a command failure, and the CdbPtr->StatCode will reflect the
+ UNDI as having already been started.
+
+ This routine is modified to reflect the undi 1.1 specification changes. The
+ changes in the spec are mainly in the callback routines, the new spec adds
+ 3 more callbacks and a unique id.
+ Since this UNDI supports both old and new undi specifications,
+ The NIC's data structure is filled in with the callback routines (depending
+ on the version) pointed to in the caller's CpbPtr. This seeds the Delay,
+ Virt2Phys, Block, and Mem_IO for old and new versions and Map_Mem, UnMap_Mem
+ and Sync_Mem routines and a unique id variable for the new version.
+ This is the function which an external entity (SNP, O/S, etc) would call
+ to provide it's I/O abstraction to the UNDI.
+
+ It's final action is to change the AdapterInfo->State to PXE_STATFLAGS_GET_STATE_STARTED.
+
+Arguments:
+ CdbPtr - Pointer to the command descriptor block.
+ AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
+
+Returns:
+ None
+
+--*/
+{
+ PXE_CPB_START_30 *CpbPtr;
+ PXE_CPB_START_31 *CpbPtr_31;
+
+ //
+ // check if it is already started.
+ //
+ if (AdapterInfo->State != PXE_STATFLAGS_GET_STATE_STOPPED) {
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ CdbPtr->StatCode = PXE_STATCODE_ALREADY_STARTED;
+ return ;
+ }
+
+ if (CdbPtr->CPBsize != sizeof(PXE_CPB_START_30) &&
+ CdbPtr->CPBsize != sizeof(PXE_CPB_START_31)) {
+
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;
+ return ;
+ }
+
+ CpbPtr = (PXE_CPB_START_30 *) (UINTN) (CdbPtr->CPBaddr);
+ CpbPtr_31 = (PXE_CPB_START_31 *) (UINTN) (CdbPtr->CPBaddr);
+
+ if (AdapterInfo->VersionFlag == 0x30) {
+ AdapterInfo->Delay_30 = (bsptr_30) (UINTN) CpbPtr->Delay;
+ AdapterInfo->Virt2Phys_30 = (virtphys_30) (UINTN) CpbPtr->Virt2Phys;
+ AdapterInfo->Block_30 = (block_30) (UINTN) CpbPtr->Block;
+ //
+ // patch for old buggy 3.0 code:
+ // In EFI1.0 undi used to provide the full (absolute) I/O address to the
+ // i/o calls and SNP used to provide a callback that used GlobalIoFncs and
+ // everything worked fine! In EFI 1.1, UNDI is not using the full
+ // i/o or memory address to access the device, The base values for the i/o
+ // and memory address is abstracted by the device specific PciIoFncs and
+ // UNDI only uses the offset values. Since UNDI3.0 cannot provide any
+ // identification to SNP, SNP cannot use nic specific PciIoFncs callback!
+ //
+ // To fix this and make undi3.0 work with SNP in EFI1.1 we
+ // use a TmpMemIo function that is defined in init.c
+ // This breaks the runtime driver feature of undi, but what to do
+ // if we have to provide the 3.0 compatibility (including the 3.0 bugs)
+ //
+ // This TmpMemIo function also takes a UniqueId parameter
+ // (as in undi3.1 design) and so initialize the UniqueId as well here
+ // Note: AdapterInfo->Mem_Io_30 is just filled for consistency with other
+ // parameters but never used, we only use Mem_Io field in the In/Out routines
+ // inside e100b.c.
+ //
+ AdapterInfo->Mem_Io_30 = (mem_io_30) (UINTN) CpbPtr->Mem_IO;
+ AdapterInfo->Mem_Io = (mem_io) (UINTN) TmpMemIo;
+ AdapterInfo->Unique_ID = (UINT64) (UINTN) AdapterInfo;
+
+ } else {
+ AdapterInfo->Delay = (bsptr) (UINTN) CpbPtr_31->Delay;
+ AdapterInfo->Virt2Phys = (virtphys) (UINTN) CpbPtr_31->Virt2Phys;
+ AdapterInfo->Block = (block) (UINTN) CpbPtr_31->Block;
+ AdapterInfo->Mem_Io = (mem_io) (UINTN) CpbPtr_31->Mem_IO;
+
+ AdapterInfo->Map_Mem = (map_mem) (UINTN) CpbPtr_31->Map_Mem;
+ AdapterInfo->UnMap_Mem = (unmap_mem) (UINTN) CpbPtr_31->UnMap_Mem;
+ AdapterInfo->Sync_Mem = (sync_mem) (UINTN) CpbPtr_31->Sync_Mem;
+ AdapterInfo->Unique_ID = CpbPtr_31->Unique_ID;
+ }
+
+ AdapterInfo->State = PXE_STATFLAGS_GET_STATE_STARTED;
+
+ return ;
+}
+
+VOID
+UNDI_Stop (
+ IN PXE_CDB *CdbPtr,
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+ This routine is used to change the operational state of the UNDI from started to stopped.
+ It will not do this if the adapter's state is PXE_STATFLAGS_GET_STATE_INITIALIZED, otherwise
+ the CdbPtr->StatFlags will reflect a command failure, and the CdbPtr->StatCode will reflect the
+ UNDI as having already not been shut down.
+
+ The NIC's data structure will have the Delay, Virt2Phys, and Block, pointers zero'd out..
+
+ It's final action is to change the AdapterInfo->State to PXE_STATFLAGS_GET_STATE_STOPPED.
+
+Arguments:
+ CdbPtr - Pointer to the command descriptor block.
+ AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
+
+Returns:
+ None
+
+--*/
+{
+ if (AdapterInfo->State == PXE_STATFLAGS_GET_STATE_INITIALIZED) {
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ CdbPtr->StatCode = PXE_STATCODE_NOT_SHUTDOWN;
+ return ;
+ }
+
+ AdapterInfo->Delay_30 = 0;
+ AdapterInfo->Virt2Phys_30 = 0;
+ AdapterInfo->Block_30 = 0;
+
+ AdapterInfo->Delay = 0;
+ AdapterInfo->Virt2Phys = 0;
+ AdapterInfo->Block = 0;
+
+ AdapterInfo->Map_Mem = 0;
+ AdapterInfo->UnMap_Mem = 0;
+ AdapterInfo->Sync_Mem = 0;
+
+ AdapterInfo->State = PXE_STATFLAGS_GET_STATE_STOPPED;
+
+ return ;
+}
+
+VOID
+UNDI_GetInitInfo (
+ IN PXE_CDB *CdbPtr,
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+ This routine is used to retrieve the initialization information that is needed by drivers and
+ applications to initialize the UNDI. This will fill in data in the Data Block structure that is
+ pointed to by the caller's CdbPtr->DBaddr. The fields filled in are as follows:
+
+ MemoryRequired, FrameDataLen, LinkSpeeds[0-3], NvCount, NvWidth, MediaHeaderLen, HWaddrLen,
+ MCastFilterCnt, TxBufCnt, TxBufSize, RxBufCnt, RxBufSize, IFtype, Duplex, and LoopBack.
+
+ In addition, the CdbPtr->StatFlags ORs in that this NIC supports cable detection. (APRIORI knowledge)
+
+Arguments:
+ CdbPtr - Pointer to the command descriptor block.
+ AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
+
+Returns:
+ None
+
+--*/
+{
+ PXE_DB_GET_INIT_INFO *DbPtr;
+
+ DbPtr = (PXE_DB_GET_INIT_INFO *) (UINTN) (CdbPtr->DBaddr);
+
+ DbPtr->MemoryRequired = MEMORY_NEEDED;
+ DbPtr->FrameDataLen = PXE_MAX_TXRX_UNIT_ETHER;
+ DbPtr->LinkSpeeds[0] = 10;
+ DbPtr->LinkSpeeds[1] = 100;
+ DbPtr->LinkSpeeds[2] = DbPtr->LinkSpeeds[3] = 0;
+ DbPtr->NvCount = MAX_EEPROM_LEN;
+ DbPtr->NvWidth = 4;
+ DbPtr->MediaHeaderLen = PXE_MAC_HEADER_LEN_ETHER;
+ DbPtr->HWaddrLen = PXE_HWADDR_LEN_ETHER;
+ DbPtr->MCastFilterCnt = MAX_MCAST_ADDRESS_CNT;
+
+ DbPtr->TxBufCnt = TX_BUFFER_COUNT;
+ DbPtr->TxBufSize = sizeof (TxCB);
+ DbPtr->RxBufCnt = RX_BUFFER_COUNT;
+ DbPtr->RxBufSize = sizeof (RxFD);
+
+ DbPtr->IFtype = PXE_IFTYPE_ETHERNET;
+ DbPtr->SupportedDuplexModes = PXE_DUPLEX_ENABLE_FULL_SUPPORTED |
+ PXE_DUPLEX_FORCE_FULL_SUPPORTED;
+ DbPtr->SupportedLoopBackModes = PXE_LOOPBACK_INTERNAL_SUPPORTED |
+ PXE_LOOPBACK_EXTERNAL_SUPPORTED;
+
+ CdbPtr->StatFlags |= PXE_STATFLAGS_CABLE_DETECT_SUPPORTED;
+ return ;
+}
+
+VOID
+UNDI_GetConfigInfo (
+ IN PXE_CDB *CdbPtr,
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+ This routine is used to retrieve the configuration information about the NIC being controlled by
+ this driver. This will fill in data in the Data Block structure that is pointed to by the caller's CdbPtr->DBaddr.
+ The fields filled in are as follows:
+
+ DbPtr->pci.BusType, DbPtr->pci.Bus, DbPtr->pci.Device, and DbPtr->pci.
+
+ In addition, the DbPtr->pci.Config.Dword[0-63] grabs a copy of this NIC's PCI configuration space.
+
+Arguments:
+ CdbPtr - Pointer to the command descriptor block.
+ AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
+
+Returns:
+ None
+
+--*/
+{
+ UINT16 Index;
+ PXE_DB_GET_CONFIG_INFO *DbPtr;
+
+ DbPtr = (PXE_DB_GET_CONFIG_INFO *) (UINTN) (CdbPtr->DBaddr);
+
+ DbPtr->pci.BusType = PXE_BUSTYPE_PCI;
+ DbPtr->pci.Bus = AdapterInfo->Bus;
+ DbPtr->pci.Device = AdapterInfo->Device;
+ DbPtr->pci.Function = AdapterInfo->Function;
+
+ for (Index = 0; Index < MAX_PCI_CONFIG_LEN; Index++) {
+ DbPtr->pci.Config.Dword[Index] = AdapterInfo->Config[Index];
+ }
+
+ return ;
+}
+
+VOID
+UNDI_Initialize (
+ IN PXE_CDB *CdbPtr,
+ NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+ This routine resets the network adapter and initializes the UNDI using the parameters supplied in
+ the CPB. This command must be issued before the network adapter can be setup to transmit and
+ receive packets.
+
+ Once the memory requirements of the UNDI are obtained by using the GetInitInfo command, a block
+ of non-swappable memory may need to be allocated. The address of this memory must be passed to
+ UNDI during the Initialize in the CPB. This memory is used primarily for transmit and receive buffers.
+
+ The fields CableDetect, LinkSpeed, Duplex, LoopBack, MemoryPtr, and MemoryLength are set with information
+ that was passed in the CPB and the NIC is initialized.
+
+ If the NIC initialization fails, the CdbPtr->StatFlags are updated with PXE_STATFLAGS_COMMAND_FAILED
+ Otherwise, AdapterInfo->State is updated with PXE_STATFLAGS_GET_STATE_INITIALIZED showing the state of
+ the UNDI is now initialized.
+
+Arguments:
+ CdbPtr - Pointer to the command descriptor block.
+ AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
+
+Returns:
+ None
+
+--*/
+{
+ PXE_CPB_INITIALIZE *CpbPtr;
+ PXE_DB_INITIALIZE *DbPtr;
+
+ if ((CdbPtr->OpFlags != PXE_OPFLAGS_INITIALIZE_DETECT_CABLE) &&
+ (CdbPtr->OpFlags != PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE)) {
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;
+ return ;
+ }
+
+ //
+ // check if it is already initialized
+ //
+ if (AdapterInfo->State == PXE_STATFLAGS_GET_STATE_INITIALIZED) {
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ CdbPtr->StatCode = PXE_STATCODE_ALREADY_INITIALIZED;
+ return ;
+ }
+
+ CpbPtr = (PXE_CPB_INITIALIZE *) (UINTN) CdbPtr->CPBaddr;
+ DbPtr = (PXE_DB_INITIALIZE *) (UINTN) CdbPtr->DBaddr;
+
+ if (CpbPtr->MemoryLength < (UINT32) MEMORY_NEEDED) {
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ CdbPtr->StatCode = PXE_STATCODE_INVALID_CPB;
+ return ;
+ }
+
+ //
+ // default behaviour is to detect the cable, if the 3rd param is 1,
+ // do not do that
+ //
+ AdapterInfo->CableDetect = (UINT8) ((CdbPtr->OpFlags == (UINT16) PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE) ? (UINT8) 0 : (UINT8) 1);
+ AdapterInfo->LinkSpeedReq = (UINT16) CpbPtr->LinkSpeed;
+ AdapterInfo->DuplexReq = CpbPtr->DuplexMode;
+ AdapterInfo->LoopBack = CpbPtr->LoopBackMode;
+ AdapterInfo->MemoryPtr = CpbPtr->MemoryAddr;
+ AdapterInfo->MemoryLength = CpbPtr->MemoryLength;
+
+ CdbPtr->StatCode = (PXE_STATCODE) E100bInit (AdapterInfo);
+
+ if (CdbPtr->StatCode != PXE_STATCODE_SUCCESS) {
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ } else {
+ AdapterInfo->State = PXE_STATFLAGS_GET_STATE_INITIALIZED;
+ }
+
+ return ;
+}
+
+VOID
+UNDI_Reset (
+ IN PXE_CDB *CdbPtr,
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+ This routine resets the network adapter and initializes the UNDI using the parameters supplied in
+ the CPB. The transmit and receive queues are emptied and any pending interrupts are cleared.
+
+ If the NIC reset fails, the CdbPtr->StatFlags are updated with PXE_STATFLAGS_COMMAND_FAILED
+
+Arguments:
+ CdbPtr - Pointer to the command descriptor block.
+ AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
+
+Returns:
+ None
+
+--*/
+{
+ if (CdbPtr->OpFlags != PXE_OPFLAGS_NOT_USED &&
+ CdbPtr->OpFlags != PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS &&
+ CdbPtr->OpFlags != PXE_OPFLAGS_RESET_DISABLE_FILTERS ) {
+
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;
+ return ;
+ }
+
+ CdbPtr->StatCode = (UINT16) E100bReset (AdapterInfo, CdbPtr->OpFlags);
+
+ if (CdbPtr->StatCode != PXE_STATCODE_SUCCESS) {
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ }
+}
+
+VOID
+UNDI_Shutdown (
+ IN PXE_CDB *CdbPtr,
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+ This routine resets the network adapter and leaves it in a safe state for another driver to
+ initialize. Any pending transmits or receives are lost. Receive filters and external
+ interrupt enables are disabled. Once the UNDI has been shutdown, it can then be stopped
+ or initialized again.
+
+ If the NIC reset fails, the CdbPtr->StatFlags are updated with PXE_STATFLAGS_COMMAND_FAILED
+
+ Otherwise, AdapterInfo->State is updated with PXE_STATFLAGS_GET_STATE_STARTED showing the state of
+ the NIC as being started.
+
+Arguments:
+ CdbPtr - Pointer to the command descriptor block.
+ AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
+
+Returns:
+ None
+
+--*/
+{
+ //
+ // do the shutdown stuff here
+ //
+ CdbPtr->StatCode = (UINT16) E100bShutdown (AdapterInfo);
+
+ if (CdbPtr->StatCode != PXE_STATCODE_SUCCESS) {
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ } else {
+ AdapterInfo->State = PXE_STATFLAGS_GET_STATE_STARTED;
+ }
+
+ return ;
+}
+
+VOID
+UNDI_Interrupt (
+ IN PXE_CDB *CdbPtr,
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+ This routine can be used to read and/or change the current external interrupt enable
+ settings. Disabling an external interrupt enable prevents and external (hardware)
+ interrupt from being signaled by the network device. Internally the interrupt events
+ can still be polled by using the UNDI_GetState command.
+
+ The resulting information on the interrupt state will be passed back in the CdbPtr->StatFlags.
+
+Arguments:
+ CdbPtr - Pointer to the command descriptor block.
+ AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
+
+Returns:
+ None
+
+--*/
+{
+ UINT8 IntMask;
+
+ IntMask = (UINT8)(UINTN)(CdbPtr->OpFlags & (PXE_OPFLAGS_INTERRUPT_RECEIVE |
+ PXE_OPFLAGS_INTERRUPT_TRANSMIT |
+ PXE_OPFLAGS_INTERRUPT_COMMAND |
+ PXE_OPFLAGS_INTERRUPT_SOFTWARE));
+
+ switch (CdbPtr->OpFlags & PXE_OPFLAGS_INTERRUPT_OPMASK) {
+ case PXE_OPFLAGS_INTERRUPT_READ:
+ break;
+
+ case PXE_OPFLAGS_INTERRUPT_ENABLE:
+ if (IntMask == 0) {
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;
+ return ;
+ }
+
+ AdapterInfo->int_mask = IntMask;
+ E100bSetInterruptState (AdapterInfo);
+ break;
+
+ case PXE_OPFLAGS_INTERRUPT_DISABLE:
+ if (IntMask != 0) {
+ AdapterInfo->int_mask &= ~(IntMask);
+ E100bSetInterruptState (AdapterInfo);
+ break;
+ }
+
+ //
+ // else fall thru.
+ //
+ default:
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;
+ return ;
+ }
+
+ if ((AdapterInfo->int_mask & PXE_OPFLAGS_INTERRUPT_RECEIVE) != 0) {
+ CdbPtr->StatFlags |= PXE_STATFLAGS_INTERRUPT_RECEIVE;
+
+ }
+
+ if ((AdapterInfo->int_mask & PXE_OPFLAGS_INTERRUPT_TRANSMIT) != 0) {
+ CdbPtr->StatFlags |= PXE_STATFLAGS_INTERRUPT_TRANSMIT;
+
+ }
+
+ if ((AdapterInfo->int_mask & PXE_OPFLAGS_INTERRUPT_COMMAND) != 0) {
+ CdbPtr->StatFlags |= PXE_STATFLAGS_INTERRUPT_COMMAND;
+
+ }
+
+ return ;
+}
+
+VOID
+UNDI_RecFilter (
+ IN PXE_CDB *CdbPtr,
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+ This routine is used to read and change receive filters and, if supported, read
+ and change multicast MAC address filter list.
+
+Arguments:
+ CdbPtr - Pointer to the command descriptor block.
+ AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
+
+Returns:
+ None
+
+--*/
+{
+ UINT16 NewFilter;
+ UINT16 OpFlags;
+ PXE_DB_RECEIVE_FILTERS *DbPtr;
+ UINT8 *MacAddr;
+ UINTN MacCount;
+ UINT16 Index;
+ UINT16 copy_len;
+ UINT8 *ptr1;
+ UINT8 *ptr2;
+ OpFlags = CdbPtr->OpFlags;
+ NewFilter = (UINT16) (OpFlags & 0x1F);
+
+ switch (OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_OPMASK) {
+ case PXE_OPFLAGS_RECEIVE_FILTER_READ:
+
+ //
+ // not expecting a cpb, not expecting any filter bits
+ //
+ if ((NewFilter != 0) || (CdbPtr->CPBsize != 0)) {
+ goto BadCdb;
+
+ }
+
+ if ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) == 0) {
+ goto JustRead;
+
+ }
+
+ NewFilter |= AdapterInfo->Rx_Filter;
+ //
+ // all other flags are ignored except mcast_reset
+ //
+ break;
+
+ case PXE_OPFLAGS_RECEIVE_FILTER_ENABLE:
+ //
+ // there should be atleast one other filter bit set.
+ //
+ if (NewFilter == 0) {
+ //
+ // nothing to enable
+ //
+ goto BadCdb;
+ }
+
+ if (CdbPtr->CPBsize != 0) {
+ //
+ // this must be a multicast address list!
+ // don't accept the list unless selective_mcast is set
+ // don't accept confusing mcast settings with this
+ //
+ if (((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) == 0) ||
+ ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) != 0) ||
+ ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST) != 0) ||
+ ((CdbPtr->CPBsize % sizeof (PXE_MAC_ADDR)) != 0) ) {
+ goto BadCdb;
+ }
+
+ MacAddr = (UINT8 *) ((UINTN) (CdbPtr->CPBaddr));
+ MacCount = CdbPtr->CPBsize / sizeof (PXE_MAC_ADDR);
+
+ for (; MacCount-- != 0; MacAddr += sizeof (PXE_MAC_ADDR)) {
+ if (MacAddr[0] != 0x01 || MacAddr[1] != 0x00 || MacAddr[2] != 0x5E || (MacAddr[3] & 0x80) != 0) {
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ CdbPtr->StatCode = PXE_STATCODE_INVALID_CPB;
+ return ;
+ }
+ }
+ }
+
+ //
+ // check selective mcast case enable case
+ //
+ if ((OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) != 0) {
+ if (((OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) != 0) ||
+ ((OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST) != 0) ) {
+ goto BadCdb;
+
+ }
+ //
+ // if no cpb, make sure we have an old list
+ //
+ if ((CdbPtr->CPBsize == 0) && (AdapterInfo->mcast_list.list_len == 0)) {
+ goto BadCdb;
+ }
+ }
+ //
+ // if you want to enable anything, you got to have unicast
+ // and you have what you already enabled!
+ //
+ NewFilter |= (PXE_OPFLAGS_RECEIVE_FILTER_UNICAST | AdapterInfo->Rx_Filter);
+
+ break;
+
+ case PXE_OPFLAGS_RECEIVE_FILTER_DISABLE:
+
+ //
+ // mcast list not expected, i.e. no cpb here!
+ //
+ if (CdbPtr->CPBsize != PXE_CPBSIZE_NOT_USED) {
+ goto BadCdb;
+ }
+
+ NewFilter = (UINT16) ((~(CdbPtr->OpFlags & 0x1F)) & AdapterInfo->Rx_Filter);
+
+ break;
+
+ default:
+ goto BadCdb;
+ }
+
+ if ((OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) != 0) {
+ AdapterInfo->mcast_list.list_len = 0;
+ NewFilter &= (~PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST);
+ }
+
+ E100bSetfilter (AdapterInfo, NewFilter, CdbPtr->CPBaddr, CdbPtr->CPBsize);
+
+JustRead:
+ //
+ // give the current mcast list
+ //
+ if ((CdbPtr->DBsize != 0) && (AdapterInfo->mcast_list.list_len != 0)) {
+ //
+ // copy the mc list to db
+ //
+
+ DbPtr = (PXE_DB_RECEIVE_FILTERS *) (UINTN) CdbPtr->DBaddr;
+ ptr1 = (UINT8 *) (&DbPtr->MCastList[0]);
+
+ //
+ // DbPtr->mc_count = AdapterInfo->mcast_list.list_len;
+ //
+ copy_len = (UINT16) (AdapterInfo->mcast_list.list_len * PXE_MAC_LENGTH);
+
+ if (copy_len > CdbPtr->DBsize) {
+ copy_len = CdbPtr->DBsize;
+
+ }
+
+ ptr2 = (UINT8 *) (&AdapterInfo->mcast_list.mc_list[0]);
+ for (Index = 0; Index < copy_len; Index++) {
+ ptr1[Index] = ptr2[Index];
+ }
+ }
+ //
+ // give the stat flags here
+ //
+ if (AdapterInfo->Receive_Started) {
+ CdbPtr->StatFlags |= AdapterInfo->Rx_Filter;
+
+ }
+
+ return ;
+
+BadCdb:
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;
+}
+
+VOID
+UNDI_StnAddr (
+ IN PXE_CDB *CdbPtr,
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+ This routine is used to get the current station and broadcast MAC addresses, and to change the
+ current station MAC address.
+
+Arguments:
+ CdbPtr - Pointer to the command descriptor block.
+ AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
+
+Returns:
+ None
+
+--*/
+{
+ PXE_CPB_STATION_ADDRESS *CpbPtr;
+ PXE_DB_STATION_ADDRESS *DbPtr;
+ UINT16 Index;
+
+ if (CdbPtr->OpFlags == PXE_OPFLAGS_STATION_ADDRESS_RESET) {
+ //
+ // configure the permanent address.
+ // change the AdapterInfo->CurrentNodeAddress field.
+ //
+ if (CompareMem (
+ &AdapterInfo->CurrentNodeAddress[0],
+ &AdapterInfo->PermNodeAddress[0],
+ PXE_MAC_LENGTH
+ ) != 0) {
+ for (Index = 0; Index < PXE_MAC_LENGTH; Index++) {
+ AdapterInfo->CurrentNodeAddress[Index] = AdapterInfo->PermNodeAddress[Index];
+ }
+
+ E100bSetupIAAddr (AdapterInfo);
+ }
+ }
+
+ if (CdbPtr->CPBaddr != (UINT64) 0) {
+ CpbPtr = (PXE_CPB_STATION_ADDRESS *) (UINTN) (CdbPtr->CPBaddr);
+ //
+ // configure the new address
+ //
+ for (Index = 0; Index < PXE_MAC_LENGTH; Index++) {
+ AdapterInfo->CurrentNodeAddress[Index] = CpbPtr->StationAddr[Index];
+ }
+
+ E100bSetupIAAddr (AdapterInfo);
+ }
+
+ if (CdbPtr->DBaddr != (UINT64) 0) {
+ DbPtr = (PXE_DB_STATION_ADDRESS *) (UINTN) (CdbPtr->DBaddr);
+ //
+ // fill it with the new values
+ //
+ for (Index = 0; Index < PXE_MAC_LENGTH; Index++) {
+ DbPtr->StationAddr[Index] = AdapterInfo->CurrentNodeAddress[Index];
+ DbPtr->BroadcastAddr[Index] = AdapterInfo->BroadcastNodeAddress[Index];
+ DbPtr->PermanentAddr[Index] = AdapterInfo->PermNodeAddress[Index];
+ }
+ }
+
+ return ;
+}
+
+VOID
+UNDI_Statistics (
+ IN PXE_CDB *CdbPtr,
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+ This routine is used to read and clear the NIC traffic statistics. This command is supported only
+ if the !PXE structure's Implementation flags say so.
+
+ Results will be parsed out in the following manner:
+ CdbPtr->DBaddr.Data[0] R Total Frames (Including frames with errors and dropped frames)
+ CdbPtr->DBaddr.Data[1] R Good Frames (All frames copied into receive buffer)
+ CdbPtr->DBaddr.Data[2] R Undersize Frames (Frames below minimum length for media <64 for ethernet)
+ CdbPtr->DBaddr.Data[4] R Dropped Frames (Frames that were dropped because receive buffers were full)
+ CdbPtr->DBaddr.Data[8] R CRC Error Frames (Frames with alignment or CRC errors)
+ CdbPtr->DBaddr.Data[A] T Total Frames (Including frames with errors and dropped frames)
+ CdbPtr->DBaddr.Data[B] T Good Frames (All frames copied into transmit buffer)
+ CdbPtr->DBaddr.Data[C] T Undersize Frames (Frames below minimum length for media <64 for ethernet)
+ CdbPtr->DBaddr.Data[E] T Dropped Frames (Frames that were dropped because of collisions)
+ CdbPtr->DBaddr.Data[14] T Total Collision Frames (Total collisions on this subnet)
+
+Arguments:
+ CdbPtr - Pointer to the command descriptor block.
+ AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
+
+Returns:
+ None
+
+--*/
+{
+ if ((CdbPtr->OpFlags &~(PXE_OPFLAGS_STATISTICS_RESET)) != 0) {
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;
+ return ;
+ }
+
+ if ((CdbPtr->OpFlags & PXE_OPFLAGS_STATISTICS_RESET) != 0) {
+ //
+ // Reset the statistics
+ //
+ CdbPtr->StatCode = (UINT16) E100bStatistics (AdapterInfo, 0, 0);
+ } else {
+ CdbPtr->StatCode = (UINT16) E100bStatistics (AdapterInfo, CdbPtr->DBaddr, CdbPtr->DBsize);
+ }
+
+ return ;
+}
+
+VOID
+UNDI_ip2mac (
+ IN PXE_CDB *CdbPtr,
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+ This routine is used to translate a multicast IP address to a multicast MAC address.
+
+ This results in a MAC address composed of 25 bits of fixed data with the upper 23 bits of the IP
+ address being appended to it. Results passed back in the equivalent of CdbPtr->DBaddr->MAC[0-5].
+
+Arguments:
+ CdbPtr - Pointer to the command descriptor block.
+ AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
+
+Returns:
+ None
+
+--*/
+{
+ PXE_CPB_MCAST_IP_TO_MAC *CpbPtr;
+ PXE_DB_MCAST_IP_TO_MAC *DbPtr;
+ UINT8 *TmpPtr;
+
+ CpbPtr = (PXE_CPB_MCAST_IP_TO_MAC *) (UINTN) CdbPtr->CPBaddr;
+ DbPtr = (PXE_DB_MCAST_IP_TO_MAC *) (UINTN) CdbPtr->DBaddr;
+
+ if ((CdbPtr->OpFlags & PXE_OPFLAGS_MCAST_IPV6_TO_MAC) != 0) {
+ //
+ // for now this is not supported
+ //
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ CdbPtr->StatCode = PXE_STATCODE_UNSUPPORTED;
+ return ;
+ }
+
+ TmpPtr = (UINT8 *) (&CpbPtr->IP.IPv4);
+ //
+ // check if the ip given is a mcast IP
+ //
+ if ((TmpPtr[0] & 0xF0) != 0xE0) {
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ CdbPtr->StatCode = PXE_STATCODE_INVALID_CPB;
+ }
+ //
+ // take the last 23 bits in IP.
+ // be very careful. accessing word on a non-word boundary will hang motherboard codenamed Big Sur
+ // casting the mac array (in the middle) to a UINT32 pointer and accessing
+ // the UINT32 content hung the system...
+ //
+ DbPtr->MAC[0] = 0x01;
+ DbPtr->MAC[1] = 0x00;
+ DbPtr->MAC[2] = 0x5e;
+ DbPtr->MAC[3] = (UINT8) (TmpPtr[1] & 0x7f);
+ DbPtr->MAC[4] = (UINT8) TmpPtr[2];
+ DbPtr->MAC[5] = (UINT8) TmpPtr[3];
+
+ return ;
+}
+
+VOID
+UNDI_NVData (
+ IN PXE_CDB *CdbPtr,
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+ This routine is used to read and write non-volatile storage on the NIC (if supported). The NVRAM
+ could be EEPROM, FLASH, or battery backed RAM.
+
+ This is an optional function according to the UNDI specification (or will be......)
+
+Arguments:
+ CdbPtr - Pointer to the command descriptor block.
+ AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
+
+Returns:
+ None
+
+--*/
+{
+ PXE_DB_NVDATA *DbPtr;
+ UINT16 Index;
+
+ if ((CdbPtr->OpFlags == PXE_OPFLAGS_NVDATA_READ) != 0) {
+
+ if ((CdbPtr->DBsize == PXE_DBSIZE_NOT_USED) != 0) {
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;
+ return ;
+ }
+
+ DbPtr = (PXE_DB_NVDATA *) (UINTN) CdbPtr->DBaddr;
+
+ for (Index = 0; Index < MAX_PCI_CONFIG_LEN; Index++) {
+ DbPtr->Data.Dword[Index] = AdapterInfo->NVData[Index];
+
+ }
+
+ } else {
+ //
+ // no write for now
+ //
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ CdbPtr->StatCode = PXE_STATCODE_UNSUPPORTED;
+ }
+
+ return ;
+}
+
+VOID
+UNDI_Status (
+ IN PXE_CDB *CdbPtr,
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+ This routine returns the current interrupt status and/or the transmitted buffer addresses.
+ If the current interrupt status is returned, pending interrupts will be acknowledged by this
+ command. Transmitted buffer addresses that are written to the DB are removed from the transmit
+ buffer queue.
+
+ Normally, this command would be polled with interrupts disabled.
+
+ The transmit buffers are returned in CdbPtr->DBaddr->TxBufer[0 - NumEntries].
+ The interrupt status is returned in CdbPtr->StatFlags.
+
+Arguments:
+ CdbPtr - Pointer to the command descriptor block.
+ AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
+
+Returns:
+ None
+
+--*/
+{
+ PXE_DB_GET_STATUS *DbPtr;
+ PXE_DB_GET_STATUS TmpGetStatus;
+ UINT16 Index;
+ UINT16 Status;
+ UINT16 NumEntries;
+ RxFD *RxPtr;
+
+ //
+ // Fill in temporary GetStatus storage.
+ //
+ RxPtr = &AdapterInfo->rx_ring[AdapterInfo->cur_rx_ind];
+
+ if ((RxPtr->cb_header.status & RX_COMPLETE) != 0) {
+ TmpGetStatus.RxFrameLen = RxPtr->ActualCount & 0x3fff;
+ } else {
+ TmpGetStatus.RxFrameLen = 0;
+ }
+
+ TmpGetStatus.reserved = 0;
+
+ //
+ // Fill in size of next available receive packet and
+ // reserved field in caller's DB storage.
+ //
+ DbPtr = (PXE_DB_GET_STATUS *) (UINTN) CdbPtr->DBaddr;
+
+ if (CdbPtr->DBsize > 0 && CdbPtr->DBsize < sizeof (UINT32) * 2) {
+ CopyMem (DbPtr, &TmpGetStatus, CdbPtr->DBsize);
+ } else {
+ CopyMem (DbPtr, &TmpGetStatus, sizeof (UINT32) * 2);
+ }
+
+ //
+ //
+ //
+ if ((CdbPtr->OpFlags & PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS) != 0) {
+ //
+ // DBsize of zero is invalid if Tx buffers are requested.
+ //
+ if (CdbPtr->DBsize == 0) {
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;
+ return ;
+ }
+
+ //
+ // remember this b4 we overwrite
+ //
+ NumEntries = (UINT16) (CdbPtr->DBsize - sizeof (UINT64));
+
+ //
+ // We already filled in 2 UINT32s.
+ //
+ CdbPtr->DBsize = sizeof (UINT32) * 2;
+
+ //
+ // will claim any hanging free CBs
+ //
+ CheckCBList (AdapterInfo);
+
+ if (AdapterInfo->xmit_done_head == AdapterInfo->xmit_done_tail) {
+ CdbPtr->StatFlags |= PXE_STATFLAGS_GET_STATUS_TXBUF_QUEUE_EMPTY;
+ } else {
+ for (Index = 0; NumEntries >= sizeof (UINT64); Index++, NumEntries -= sizeof (UINT64)) {
+ if (AdapterInfo->xmit_done_head != AdapterInfo->xmit_done_tail) {
+ DbPtr->TxBuffer[Index] = AdapterInfo->xmit_done[AdapterInfo->xmit_done_head];
+ AdapterInfo->xmit_done_head = next (AdapterInfo->xmit_done_head);
+ CdbPtr->DBsize += sizeof (UINT64);
+ } else {
+ break;
+ }
+ }
+ }
+
+ if (AdapterInfo->xmit_done_head != AdapterInfo->xmit_done_tail) {
+ CdbPtr->StatFlags |= PXE_STATFLAGS_DB_WRITE_TRUNCATED;
+
+ }
+ //
+ // check for a receive buffer and give it's size in db
+ //
+ }
+ //
+ //
+ //
+ if ((CdbPtr->OpFlags & PXE_OPFLAGS_GET_INTERRUPT_STATUS) != 0) {
+
+ Status = InWord (AdapterInfo, AdapterInfo->ioaddr + SCBStatus);
+ AdapterInfo->Int_Status |= Status;
+
+ //
+ // acknoledge the interrupts
+ //
+ OutWord (AdapterInfo, (UINT16) (Status & 0xfc00), (UINT32) (AdapterInfo->ioaddr + SCBStatus));
+
+ //
+ // report all the outstanding interrupts
+ //
+ Status = AdapterInfo->Int_Status;
+ if ((Status & SCB_STATUS_FR) != 0) {
+ CdbPtr->StatFlags |= PXE_STATFLAGS_GET_STATUS_RECEIVE;
+ }
+
+ if ((Status & SCB_STATUS_SWI) != 0) {
+ CdbPtr->StatFlags |= PXE_STATFLAGS_GET_STATUS_SOFTWARE;
+ }
+ }
+
+ return ;
+}
+
+VOID
+UNDI_FillHeader (
+ IN PXE_CDB *CdbPtr,
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+ This routine is used to fill media header(s) in transmit packet(s).
+ Copies the MAC address into the media header whether it is dealing
+ with fragmented or non-fragmented packets.
+
+Arguments:
+ CdbPtr - Pointer to the command descriptor block.
+ AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
+
+Returns:
+ None
+
+--*/
+{
+ PXE_CPB_FILL_HEADER *Cpb;
+ PXE_CPB_FILL_HEADER_FRAGMENTED *Cpbf;
+ EtherHeader *MacHeader;
+ UINTN Index;
+
+ if (CdbPtr->CPBsize == PXE_CPBSIZE_NOT_USED) {
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;
+ return ;
+ }
+
+ if ((CdbPtr->OpFlags & PXE_OPFLAGS_FILL_HEADER_FRAGMENTED) != 0) {
+ Cpbf = (PXE_CPB_FILL_HEADER_FRAGMENTED *) (UINTN) CdbPtr->CPBaddr;
+
+ //
+ // assume 1st fragment is big enough for the mac header
+ //
+ if ((Cpbf->FragCnt == 0) || (Cpbf->FragDesc[0].FragLen < PXE_MAC_HEADER_LEN_ETHER)) {
+ //
+ // no buffers given
+ //
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;
+ return ;
+ }
+
+ MacHeader = (EtherHeader *) (UINTN) Cpbf->FragDesc[0].FragAddr;
+ //
+ // we don't swap the protocol bytes
+ //
+ MacHeader->type = Cpbf->Protocol;
+
+ for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {
+ MacHeader->dest_addr[Index] = Cpbf->DestAddr[Index];
+ MacHeader->src_addr[Index] = Cpbf->SrcAddr[Index];
+ }
+ } else {
+ Cpb = (PXE_CPB_FILL_HEADER *) (UINTN) CdbPtr->CPBaddr;
+
+ MacHeader = (EtherHeader *) (UINTN) Cpb->MediaHeader;
+ //
+ // we don't swap the protocol bytes
+ //
+ MacHeader->type = Cpb->Protocol;
+
+ for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {
+ MacHeader->dest_addr[Index] = Cpb->DestAddr[Index];
+ MacHeader->src_addr[Index] = Cpb->SrcAddr[Index];
+ }
+ }
+
+ return ;
+}
+
+VOID
+UNDI_Transmit (
+ IN PXE_CDB *CdbPtr,
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+ This routine is used to place a packet into the transmit queue. The data buffers given to
+ this command are to be considered locked and the application or network driver loses
+ ownership of these buffers and must not free or relocate them until the ownership returns.
+
+ When the packets are transmitted, a transmit complete interrupt is generated (if interrupts
+ are disabled, the transmit interrupt status is still set and can be checked using the UNDI_Status
+ command.
+
+ Some implementations and adapters support transmitting multiple packets with one transmit
+ command. If this feature is supported, the transmit CPBs can be linked in one transmit
+ command.
+
+ All UNDIs support fragmented frames, now all network devices or protocols do. If a fragmented
+ frame CPB is given to UNDI and the network device does not support fragmented frames
+ (see !PXE.Implementation flag), the UNDI will have to copy the fragments into a local buffer
+ before transmitting.
+
+
+Arguments:
+ CdbPtr - Pointer to the command descriptor block.
+ AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
+
+Returns:
+ None
+
+--*/
+{
+
+ if (CdbPtr->CPBsize == PXE_CPBSIZE_NOT_USED) {
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;
+ return ;
+ }
+
+ CdbPtr->StatCode = (PXE_STATCODE) E100bTransmit (AdapterInfo, CdbPtr->CPBaddr, CdbPtr->OpFlags);
+
+ if (CdbPtr->StatCode != PXE_STATCODE_SUCCESS) {
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ }
+
+ return ;
+}
+
+VOID
+UNDI_Receive (
+ IN PXE_CDB *CdbPtr,
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+ When the network adapter has received a frame, this command is used to copy the frame
+ into the driver/application storage location. Once a frame has been copied, it is
+ removed from the receive queue.
+
+Arguments:
+ CdbPtr - Pointer to the command descriptor block.
+ AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
+
+Returns:
+ None
+
+--*/
+{
+ PXE_CPB_RECEIVE *cpbptr;
+
+ //
+ // check if RU has started...
+ //
+ if (!AdapterInfo->Receive_Started) {
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ CdbPtr->StatCode = PXE_STATCODE_NOT_INITIALIZED;
+ return ;
+ }
+
+ cpbptr = (PXE_CPB_RECEIVE *) (UINTN) CdbPtr->CPBaddr;
+
+ CdbPtr->StatCode = (UINT16) E100bReceive (AdapterInfo, CdbPtr->CPBaddr, CdbPtr->DBaddr);
+ if (CdbPtr->StatCode != PXE_STATCODE_SUCCESS) {
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+
+ }
+
+ return ;
+}
+
+VOID
+UNDI_APIEntry_old (
+ IN UINT64 cdb
+ )
+/*++
+
+Routine Description:
+ This is the main SW UNDI API entry using the older nii protocol.
+ The parameter passed in is a 64 bit flat model virtual
+ address of the cdb. We then jump into the common routine for both old and
+ new nii protocol entries.
+
+Arguments:
+ CdbPtr - Pointer to the command descriptor block.
+ AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
+
+Returns:
+ None
+
+--*/
+// TODO: cdb - add argument and description to function comment
+{
+ PXE_CDB *CdbPtr;
+ NIC_DATA_INSTANCE *AdapterInfo;
+
+ if (cdb == (UINT64) 0) {
+ return ;
+
+ }
+
+ CdbPtr = (PXE_CDB *) (UINTN) cdb;
+
+ if (CdbPtr->IFnum >= pxe->IFcnt) {
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;
+ return ;
+ }
+
+ AdapterInfo = &(UNDI32DeviceList[CdbPtr->IFnum]->NicInfo);
+
+ //
+ // entering from older entry point
+ //
+ AdapterInfo->VersionFlag = 0x30;
+ UNDI_APIEntry_Common (cdb);
+}
+
+VOID
+UNDI_APIEntry_new (
+ IN UINT64 cdb
+ )
+/*++
+
+Routine Description:
+ This is the main SW UNDI API entry using the newer nii protocol.
+ The parameter passed in is a 64 bit flat model virtual
+ address of the cdb. We then jump into the common routine for both old and
+ new nii protocol entries.
+
+Arguments:
+ CdbPtr - Pointer to the command descriptor block.
+ AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
+
+Returns:
+ None
+
+--*/
+// TODO: cdb - add argument and description to function comment
+{
+ PXE_CDB *CdbPtr;
+ NIC_DATA_INSTANCE *AdapterInfo;
+
+ if (cdb == (UINT64) 0) {
+ return ;
+
+ }
+
+ CdbPtr = (PXE_CDB *) (UINTN) cdb;
+
+ if (CdbPtr->IFnum >= pxe_31->IFcnt) {
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;
+ return ;
+ }
+
+ AdapterInfo = &(UNDI32DeviceList[CdbPtr->IFnum]->NicInfo);
+ //
+ // entering from older entry point
+ //
+ AdapterInfo->VersionFlag = 0x31;
+ UNDI_APIEntry_Common (cdb);
+}
+
+VOID
+UNDI_APIEntry_Common (
+ IN UINT64 cdb
+ )
+/*++
+
+Routine Description:
+ This is the common routine for both old and new entry point procedures.
+ The parameter passed in is a 64 bit flat model virtual
+ address of the cdb. We then jump into the service routine pointed to by the
+ Api_Table[OpCode].
+
+Arguments:
+ CdbPtr - Pointer to the command descriptor block.
+ AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
+
+Returns:
+ None
+
+--*/
+// TODO: cdb - add argument and description to function comment
+{
+ PXE_CDB *CdbPtr;
+ NIC_DATA_INSTANCE *AdapterInfo;
+ UNDI_CALL_TABLE *tab_ptr;
+
+ CdbPtr = (PXE_CDB *) (UINTN) cdb;
+
+ //
+ // check the OPCODE range
+ //
+ if ((CdbPtr->OpCode > PXE_OPCODE_LAST_VALID) ||
+ (CdbPtr->StatCode != PXE_STATCODE_INITIALIZE) ||
+ (CdbPtr->StatFlags != PXE_STATFLAGS_INITIALIZE) ||
+ (CdbPtr->IFnum >= pxe_31->IFcnt) ) {
+ goto badcdb;
+
+ }
+
+ if (CdbPtr->CPBsize == PXE_CPBSIZE_NOT_USED) {
+ if (CdbPtr->CPBaddr != PXE_CPBADDR_NOT_USED) {
+ goto badcdb;
+ }
+ } else if (CdbPtr->CPBaddr == PXE_CPBADDR_NOT_USED) {
+ goto badcdb;
+ }
+
+ if (CdbPtr->DBsize == PXE_DBSIZE_NOT_USED) {
+ if (CdbPtr->DBaddr != PXE_DBADDR_NOT_USED) {
+ goto badcdb;
+ }
+ } else if (CdbPtr->DBaddr == PXE_DBADDR_NOT_USED) {
+ goto badcdb;
+ }
+
+ //
+ // check if cpbsize and dbsize are as needed
+ // check if opflags are as expected
+ //
+ tab_ptr = &api_table[CdbPtr->OpCode];
+
+ if (tab_ptr->cpbsize != (UINT16) (DONT_CHECK) && tab_ptr->cpbsize != CdbPtr->CPBsize) {
+ goto badcdb;
+ }
+
+ if (tab_ptr->dbsize != (UINT16) (DONT_CHECK) && tab_ptr->dbsize != CdbPtr->DBsize) {
+ goto badcdb;
+ }
+
+ if (tab_ptr->opflags != (UINT16) (DONT_CHECK) && tab_ptr->opflags != CdbPtr->OpFlags) {
+ goto badcdb;
+
+ }
+
+ AdapterInfo = &(UNDI32DeviceList[CdbPtr->IFnum]->NicInfo);
+
+ //
+ // check if UNDI_State is valid for this call
+ //
+ if (tab_ptr->state != (UINT16) (-1)) {
+ //
+ // should atleast be started
+ //
+ if (AdapterInfo->State == PXE_STATFLAGS_GET_STATE_STOPPED) {
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ CdbPtr->StatCode = PXE_STATCODE_NOT_STARTED;
+ return ;
+ }
+ //
+ // check if it should be initialized
+ //
+ if (tab_ptr->state == 2) {
+ if (AdapterInfo->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) {
+ CdbPtr->StatCode = PXE_STATCODE_NOT_INITIALIZED;
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ return ;
+ }
+ }
+ }
+ //
+ // set the return variable for success case here
+ //
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE;
+ CdbPtr->StatCode = PXE_STATCODE_SUCCESS;
+
+ tab_ptr->api_ptr (CdbPtr, AdapterInfo);
+ return ;
+ //
+ // %% AVL - check for command linking
+ //
+badcdb:
+ CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB;
+ return ;
+}
+
+UINT8
+ChkSum (
+ IN VOID *Buffer,
+ IN UINT16 Len
+ )
+/*++
+
+Routine Description:
+ This does an 8 bit check sum of the passed in buffer for Len bytes.
+ This is primarily used to update the check sum in the SW UNDI header.
+
+Arguments:
+ Buffer - Pointer to the passed in buffer to check sum
+ Len - Length of buffer to be check summed in bytes.
+
+Returns:
+ None
+
+--*/
+{
+ UINT8 Chksum;
+ INT8 *Bp;
+
+ Chksum = 0;
+ if ((Bp = Buffer) != NULL) {
+ while (Len--) {
+ Chksum = (UINT8) (Chksum +*Bp++);
+
+ }
+
+ }
+
+ return Chksum;
+}
+
+VOID
+PxeUpdate (
+ IN NIC_DATA_INSTANCE *NicPtr,
+ IN PXE_SW_UNDI *PxePtr
+ )
+/*++
+
+Routine Description:
+ When called with a null NicPtr, this routine decrements the number of NICs
+ this UNDI is supporting and removes the NIC_DATA_POINTER from the array.
+ Otherwise, it increments the number of NICs this UNDI is supported and
+ updates the pxe.Fudge to ensure a proper check sum results.
+
+Arguments:
+ NicPtr - Pointer to the NIC data structure.
+
+Returns:
+ None
+
+--*/
+// TODO: PxePtr - add argument and description to function comment
+{
+ if (NicPtr == NULL) {
+ if (PxePtr->IFcnt > 0) {
+ //
+ // number of NICs this undi supports
+ //
+ PxePtr->IFcnt--;
+ }
+
+ PxePtr->Fudge = (UINT8) (PxePtr->Fudge - ChkSum ((VOID *) PxePtr, PxePtr->Len));
+ return ;
+ }
+
+ //
+ // number of NICs this undi supports
+ //
+ PxePtr->IFcnt++;
+ PxePtr->Fudge = (UINT8) (PxePtr->Fudge - ChkSum ((VOID *) PxePtr, PxePtr->Len));
+
+ return ;
+}
+
+VOID
+PxeStructInit (
+ IN PXE_SW_UNDI *PxePtr,
+ IN UINTN VersionFlag
+ )
+/*++
+
+Routine Description:
+ Initialize the !PXE structure
+
+Arguments:
+ RemainingDevicePath - Not used, always produce all possible children.
+
+Returns:
+ EFI_SUCCESS - This driver is added to Controller.
+ other - This driver does not support this device.
+
+--*/
+// TODO: PxePtr - add argument and description to function comment
+// TODO: VersionFlag - add argument and description to function comment
+{
+ //
+ // Initialize the !PXE structure
+ //
+ PxePtr->Signature = PXE_ROMID_SIGNATURE;
+ PxePtr->Len = sizeof (PXE_SW_UNDI);
+ //
+ // cksum
+ //
+ PxePtr->Fudge = 0;
+ //
+ // number of NICs this undi supports
+ //
+ PxePtr->IFcnt = 0;
+ PxePtr->Rev = PXE_ROMID_REV;
+ PxePtr->MajorVer = PXE_ROMID_MAJORVER;
+ PxePtr->MinorVer = PXE_ROMID_MINORVER;
+ PxePtr->reserved1 = 0;
+
+ PxePtr->Implementation = PXE_ROMID_IMP_SW_VIRT_ADDR |
+ PXE_ROMID_IMP_FRAG_SUPPORTED |
+ PXE_ROMID_IMP_CMD_LINK_SUPPORTED |
+ PXE_ROMID_IMP_NVDATA_READ_ONLY |
+ PXE_ROMID_IMP_STATION_ADDR_SETTABLE |
+ PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED |
+ PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED |
+ PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED |
+ PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED |
+ PXE_ROMID_IMP_SOFTWARE_INT_SUPPORTED |
+ PXE_ROMID_IMP_PACKET_RX_INT_SUPPORTED;
+
+ if (VersionFlag == 0x30) {
+ PxePtr->EntryPoint = (UINT64) UNDI_APIEntry_old;
+ } else {
+ PxePtr->EntryPoint = (UINT64) UNDI_APIEntry_new;
+ PxePtr->MinorVer = PXE_ROMID_MINORVER_31;
+ }
+
+ PxePtr->reserved2[0] = 0;
+ PxePtr->reserved2[1] = 0;
+ PxePtr->reserved2[2] = 0;
+ PxePtr->BusCnt = 1;
+ PxePtr->BusType[0] = PXE_BUSTYPE_PCI;
+
+ PxePtr->Fudge = (UINT8) (PxePtr->Fudge - ChkSum ((VOID *) PxePtr, PxePtr->Len));
+}
+
+#pragma data_seg()
diff --git a/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/E100b.c b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/E100b.c
new file mode 100644
index 0000000..5b69a46
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/E100b.c
@@ -0,0 +1,3772 @@
+/*++
+
+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:
+
+
+ E100B.C
+
+Abstract:
+
+
+Revision History
+
+--*/
+
+#include "undi32.h"
+
+static UINT8 basic_config_cmd[22] = {
+ 22, 0x08,
+ 0, 0,
+ 0, (UINT8)0x80,
+ 0x32, 0x03,
+ 1, 0,
+ 0x2E, 0,
+ 0x60, 0,
+ (UINT8)0xf2, 0x48,
+ 0, 0x40,
+ (UINT8)0xf2, (UINT8)0x80, // 0x40=Force full-duplex
+ 0x3f, 0x05,
+};
+
+//
+// How to wait for the command unit to accept a command.
+// Typically this takes 0 ticks.
+//
+#define wait_for_cmd_done(cmd_ioaddr) \
+{ \
+ INT16 wait = 2000; \
+ while ((InByte (AdapterInfo, cmd_ioaddr) != 0) && --wait >= 0) \
+ DelayIt (AdapterInfo, 10); \
+ if (wait == 0) \
+ DelayIt (AdapterInfo, 50); \
+}
+
+UINT8
+InByte (
+ IN NIC_DATA_INSTANCE *AdapterInfo,
+ IN UINT32 Port
+ )
+/*++
+
+Routine Description:
+ This function calls the MemIo callback to read a byte from the device's
+ address space
+ Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine)
+ which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have
+ to make undi3.0 a special case
+
+Arguments:
+ Port - Which port to read from.
+
+Returns:
+ Results - The data read from the port.
+
+--*/
+// TODO: AdapterInfo - add argument and description to function comment
+{
+ UINT8 Results;
+
+ (*AdapterInfo->Mem_Io) (
+ AdapterInfo->Unique_ID,
+ PXE_MEM_READ,
+ 1,
+ (UINT64)Port,
+ (UINT64) (UINTN) &Results
+ );
+ return Results;
+}
+
+UINT16
+InWord (
+ IN NIC_DATA_INSTANCE *AdapterInfo,
+ IN UINT32 Port
+ )
+/*++
+
+Routine Description:
+ This function calls the MemIo callback to read a word from the device's
+ address space
+ Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine)
+ which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have
+ to make undi3.0 a special case
+
+Arguments:
+ Port - Which port to read from.
+
+Returns:
+ Results - The data read from the port.
+
+--*/
+// TODO: AdapterInfo - add argument and description to function comment
+{
+ UINT16 Results;
+
+ (*AdapterInfo->Mem_Io) (
+ AdapterInfo->Unique_ID,
+ PXE_MEM_READ,
+ 2,
+ (UINT64)Port,
+ (UINT64)(UINTN)&Results
+ );
+ return Results;
+}
+
+UINT32
+InLong (
+ IN NIC_DATA_INSTANCE *AdapterInfo,
+ IN UINT32 Port
+ )
+/*++
+
+Routine Description:
+ This function calls the MemIo callback to read a dword from the device's
+ address space
+ Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine)
+ which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have
+ to make undi3.0 a special case
+
+Arguments:
+ Port - Which port to read from.
+
+Returns:
+ Results - The data read from the port.
+
+--*/
+// TODO: AdapterInfo - add argument and description to function comment
+{
+ UINT32 Results;
+
+ (*AdapterInfo->Mem_Io) (
+ AdapterInfo->Unique_ID,
+ PXE_MEM_READ,
+ 4,
+ (UINT64)Port,
+ (UINT64)(UINTN)&Results
+ );
+ return Results;
+}
+
+VOID
+OutByte (
+ IN NIC_DATA_INSTANCE *AdapterInfo,
+ IN UINT8 Data,
+ IN UINT32 Port
+ )
+/*++
+
+Routine Description:
+ This function calls the MemIo callback to write a byte from the device's
+ address space
+ Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine)
+ which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have
+ to make undi3.0 a special case
+
+Arguments:
+ Data - Data to write to Port.
+ Port - Which port to write to.
+
+Returns:
+ none
+
+--*/
+// TODO: AdapterInfo - add argument and description to function comment
+{
+ UINT8 Val;
+
+ Val = Data;
+ (*AdapterInfo->Mem_Io) (
+ AdapterInfo->Unique_ID,
+ PXE_MEM_WRITE,
+ 1,
+ (UINT64)Port,
+ (UINT64)(UINTN)(UINTN)&Val
+ );
+ return ;
+}
+
+VOID
+OutWord (
+ IN NIC_DATA_INSTANCE *AdapterInfo,
+ IN UINT16 Data,
+ IN UINT32 Port
+ )
+/*++
+
+Routine Description:
+ This function calls the MemIo callback to write a word from the device's
+ address space
+ Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine)
+ which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have
+ to make undi3.0 a special case
+
+Arguments:
+ Data - Data to write to Port.
+ Port - Which port to write to.
+
+Returns:
+ none
+
+--*/
+// TODO: AdapterInfo - add argument and description to function comment
+{
+ UINT16 Val;
+
+ Val = Data;
+ (*AdapterInfo->Mem_Io) (
+ AdapterInfo->Unique_ID,
+ PXE_MEM_WRITE,
+ 2,
+ (UINT64)Port,
+ (UINT64)(UINTN)&Val
+ );
+ return ;
+}
+
+VOID
+OutLong (
+ IN NIC_DATA_INSTANCE *AdapterInfo,
+ IN UINT32 Data,
+ IN UINT32 Port
+ )
+/*++
+
+Routine Description:
+ This function calls the MemIo callback to write a dword from the device's
+ address space
+ Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine)
+ which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have
+ to make undi3.0 a special case
+
+Arguments:
+ Data - Data to write to Port.
+ Port - Which port to write to.
+
+Returns:
+ none
+
+--*/
+// TODO: AdapterInfo - add argument and description to function comment
+{
+ UINT32 Val;
+
+ Val = Data;
+ (*AdapterInfo->Mem_Io) (
+ AdapterInfo->Unique_ID,
+ PXE_MEM_WRITE,
+ 4,
+ (UINT64)Port,
+ (UINT64)(UINTN)&Val
+ );
+ return ;
+}
+
+UINTN
+MapIt (
+ IN NIC_DATA_INSTANCE *AdapterInfo,
+ IN UINT64 MemAddr,
+ IN UINT32 Size,
+ IN UINT32 Direction,
+ OUT UINT64 MappedAddr
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AdapterInfo - TODO: add argument description
+ MemAddr - TODO: add argument description
+ Size - TODO: add argument description
+ Direction - TODO: add argument description
+ MappedAddr - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ UINT64 *PhyAddr;
+
+ PhyAddr = (UINT64 *) (UINTN) MappedAddr;
+ //
+ // mapping is different for theold and new NII protocols
+ //
+ if (AdapterInfo->VersionFlag == 0x30) {
+ if (AdapterInfo->Virt2Phys_30 == (VOID *) NULL) {
+ *PhyAddr = (UINT64) AdapterInfo->MemoryPtr;
+ } else {
+ (*AdapterInfo->Virt2Phys_30) (MemAddr, (UINT64) (UINTN) PhyAddr);
+ }
+
+ if (*PhyAddr > FOUR_GIGABYTE) {
+ return PXE_STATCODE_INVALID_PARAMETER;
+ }
+ } else {
+ if (AdapterInfo->Map_Mem == (VOID *) NULL) {
+ //
+ // this UNDI cannot handle addresses beyond 4 GB without a map routine
+ //
+ if (MemAddr > FOUR_GIGABYTE) {
+ return PXE_STATCODE_INVALID_PARAMETER;
+ } else {
+ *PhyAddr = MemAddr;
+ }
+ } else {
+ (*AdapterInfo->Map_Mem) (
+ AdapterInfo->Unique_ID,
+ MemAddr,
+ Size,
+ Direction,
+ MappedAddr
+ );
+ }
+ }
+
+ return PXE_STATCODE_SUCCESS;
+}
+
+VOID
+UnMapIt (
+ IN NIC_DATA_INSTANCE *AdapterInfo,
+ IN UINT64 MemAddr,
+ IN UINT32 Size,
+ IN UINT32 Direction,
+ IN UINT64 MappedAddr
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AdapterInfo - TODO: add argument description
+ MemAddr - TODO: add argument description
+ Size - TODO: add argument description
+ Direction - TODO: add argument description
+ MappedAddr - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ if (AdapterInfo->VersionFlag > 0x30) {
+ //
+ // no mapping service
+ //
+ if (AdapterInfo->UnMap_Mem != (VOID *) NULL) {
+ (*AdapterInfo->UnMap_Mem) (
+ AdapterInfo->Unique_ID,
+ MemAddr,
+ Size,
+ Direction,
+ MappedAddr
+ );
+
+ }
+ }
+
+ return ;
+}
+
+VOID
+DelayIt (
+ IN NIC_DATA_INSTANCE *AdapterInfo,
+ UINT16 MicroSeconds
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+ AdapterInfo - Pointer to the NIC data structure information
+ which the UNDI driver is layering on..
+
+Returns:
+
+--*/
+// TODO: MicroSeconds - add argument and description to function comment
+{
+ if (AdapterInfo->VersionFlag == 0x30) {
+ (*AdapterInfo->Delay_30) (MicroSeconds);
+ } else {
+ (*AdapterInfo->Delay) (AdapterInfo->Unique_ID, MicroSeconds);
+ }
+}
+
+VOID
+BlockIt (
+ IN NIC_DATA_INSTANCE *AdapterInfo,
+ UINT32 flag
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+ AdapterInfo - Pointer to the NIC data structure information
+ which the UNDI driver is layering on..
+
+Returns:
+
+--*/
+// TODO: flag - add argument and description to function comment
+{
+ if (AdapterInfo->VersionFlag == 0x30) {
+ (*AdapterInfo->Block_30) (flag);
+ } else {
+ (*AdapterInfo->Block) (AdapterInfo->Unique_ID, flag);
+ }
+}
+
+UINT8
+Load_Base_Regs (
+ NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AdapterInfo - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ //
+ // we will use the linear (flat) memory model and fill our base registers
+ // with 0's so that the entire physical address is our offset
+ //
+ //
+ // we reset the statistics totals here because this is where we are loading stats addr
+ //
+ AdapterInfo->RxTotals = 0;
+ AdapterInfo->TxTotals = 0;
+
+ //
+ // Load the statistics block address.
+ //
+ wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd);
+ OutLong (AdapterInfo, (UINT32) AdapterInfo->stat_phy_addr, AdapterInfo->ioaddr + SCBPointer);
+ OutByte (AdapterInfo, CU_STATSADDR, AdapterInfo->ioaddr + SCBCmd);
+ AdapterInfo->statistics->done_marker = 0;
+
+ wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd);
+ OutLong (AdapterInfo, 0, AdapterInfo->ioaddr + SCBPointer);
+ OutByte (AdapterInfo, RX_ADDR_LOAD, AdapterInfo->ioaddr + SCBCmd);
+
+ wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd);
+ OutLong (AdapterInfo, 0, AdapterInfo->ioaddr + SCBPointer);
+ OutByte (AdapterInfo, CU_CMD_BASE, AdapterInfo->ioaddr + SCBCmd);
+
+ return 0;
+}
+
+UINT8
+IssueCB (
+ NIC_DATA_INSTANCE *AdapterInfo,
+ TxCB *cmd_ptr
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AdapterInfo - TODO: add argument description
+ cmd_ptr - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ UINT16 status;
+
+ wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd);
+
+ //
+ // read the CU status, if it is idle, write the address of cb_ptr
+ // in the scbpointer and issue a cu_start,
+ // if it is suspended, remove the suspend bit in the previous command
+ // block and issue a resume
+ //
+ // Ensure that the CU Active Status bit is not on from previous CBs.
+ //
+ status = InWord (AdapterInfo, AdapterInfo->ioaddr + SCBStatus);
+
+ //
+ // Skip acknowledging the interrupt if it is not already set
+ //
+
+ //
+ // ack only the cna the integer
+ //
+ if ((status & SCB_STATUS_CNA) != 0) {
+ OutWord (AdapterInfo, SCB_STATUS_CNA, AdapterInfo->ioaddr + SCBStatus);
+
+ }
+
+ if ((status & SCB_STATUS_CU_MASK) == SCB_STATUS_CU_IDLE) {
+ //
+ // give a cu_start
+ //
+ OutLong (AdapterInfo, cmd_ptr->PhysTCBAddress, AdapterInfo->ioaddr + SCBPointer);
+ OutByte (AdapterInfo, CU_START, AdapterInfo->ioaddr + SCBCmd);
+ } else {
+ //
+ // either active or suspended, give a resume
+ //
+
+ cmd_ptr->PrevTCBVirtualLinkPtr->cb_header.command &= ~(CmdSuspend | CmdIntr);
+ OutByte (AdapterInfo, CU_RESUME, AdapterInfo->ioaddr + SCBCmd);
+ }
+
+ return 0;
+}
+
+UINT8
+Configure (
+ NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AdapterInfo - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ //
+ // all command blocks are of TxCB format
+ //
+ TxCB *cmd_ptr;
+ UINT8 *data_ptr;
+ INT16 Index;
+ UINT8 my_filter;
+
+ cmd_ptr = GetFreeCB (AdapterInfo);
+ data_ptr = (UINT8 *) (&cmd_ptr->PhysTBDArrayAddres);
+
+ //
+ // start the config data right after the command header
+ //
+ for (Index = 0; Index < sizeof (basic_config_cmd); Index++) {
+ data_ptr[Index] = basic_config_cmd[Index];
+ }
+
+ my_filter = (UINT8) ((AdapterInfo->Rx_Filter & PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS) ? 1 : 0);
+ my_filter |= (AdapterInfo->Rx_Filter & PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST) ? 0 : 2;
+
+ data_ptr[15] |= my_filter;
+ data_ptr[19] = (UINT8) (AdapterInfo->Duplex ? 0xC0 : 0x80);
+ data_ptr[21] = (UINT8) ((AdapterInfo->Rx_Filter & PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST) ? 0x0D : 0x05);
+
+ //
+ // check if we have to use the AUI port instead
+ //
+ if ((AdapterInfo->PhyRecord[0] & 0x8000) != 0) {
+ data_ptr[15] |= 0x80;
+ data_ptr[8] = 0;
+ }
+
+ BlockIt (AdapterInfo, TRUE);
+ cmd_ptr->cb_header.command = CmdSuspend | CmdConfigure;
+
+ IssueCB (AdapterInfo, cmd_ptr);
+ wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd);
+
+ BlockIt (AdapterInfo, FALSE);
+
+ CommandWaitForCompletion (cmd_ptr, AdapterInfo);
+
+ //
+ // restore the cb values for tx
+ //
+ cmd_ptr->PhysTBDArrayAddres = cmd_ptr->PhysArrayAddr;
+ cmd_ptr->ByteCount = cmd_ptr->Threshold = cmd_ptr->TBDCount = 0;
+ //
+ // fields beyond the immediatedata are assumed to be safe
+ // add the CB to the free list again
+ //
+ SetFreeCB (AdapterInfo, cmd_ptr);
+ return 0;
+}
+
+UINT8
+E100bSetupIAAddr (
+ NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AdapterInfo - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ //
+ // all command blocks are of TxCB format
+ //
+ TxCB *cmd_ptr;
+ UINT16 *data_ptr;
+ UINT16 *eaddrs;
+
+ eaddrs = (UINT16 *) AdapterInfo->CurrentNodeAddress;
+
+ cmd_ptr = GetFreeCB (AdapterInfo);
+ data_ptr = (UINT16 *) (&cmd_ptr->PhysTBDArrayAddres);
+
+ //
+ // AVOID a bug (?!) here by marking the command already completed.
+ //
+ cmd_ptr->cb_header.command = (CmdSuspend | CmdIASetup);
+ cmd_ptr->cb_header.status = 0;
+ data_ptr[0] = eaddrs[0];
+ data_ptr[1] = eaddrs[1];
+ data_ptr[2] = eaddrs[2];
+
+ BlockIt (AdapterInfo, TRUE);
+ IssueCB (AdapterInfo, cmd_ptr);
+ wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd);
+ BlockIt (AdapterInfo, FALSE);
+
+ CommandWaitForCompletion (cmd_ptr, AdapterInfo);
+
+ //
+ // restore the cb values for tx
+ //
+ cmd_ptr->PhysTBDArrayAddres = cmd_ptr->PhysArrayAddr;
+ cmd_ptr->ByteCount = cmd_ptr->Threshold = cmd_ptr->TBDCount = 0;
+ //
+ // fields beyond the immediatedata are assumed to be safe
+ // add the CB to the free list again
+ //
+ SetFreeCB (AdapterInfo, cmd_ptr);
+ return 0;
+}
+
+VOID
+StopRU (
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+ Instructs the NIC to stop receiving packets.
+
+Arguments:
+ AdapterInfo - Pointer to the NIC data structure information
+ which the UNDI driver is layering on..
+Returns:
+
+--*/
+{
+ if (AdapterInfo->Receive_Started) {
+
+ //
+ // Todo: verify that we must wait for previous command completion.
+ //
+ wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd);
+
+ //
+ // Disable interrupts, and stop the chip's Rx process.
+ //
+ OutWord (AdapterInfo, INT_MASK, AdapterInfo->ioaddr + SCBCmd);
+ OutWord (AdapterInfo, INT_MASK | RX_ABORT, AdapterInfo->ioaddr + SCBCmd);
+
+ AdapterInfo->Receive_Started = FALSE;
+ }
+
+ return ;
+}
+
+INT8
+StartRU (
+ NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+ Instructs the NIC to start receiving packets.
+
+Arguments:
+ AdapterInfo - Pointer to the NIC data structure information
+ which the UNDI driver is layering on..
+Returns:
+ 0 - Successful
+ -1 - Already Started
+--*/
+{
+
+ if (AdapterInfo->Receive_Started) {
+ //
+ // already started
+ //
+ return -1;
+ }
+
+ AdapterInfo->cur_rx_ind = 0;
+ AdapterInfo->Int_Status = 0;
+
+ wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd);
+
+ OutLong (AdapterInfo, (UINT32) AdapterInfo->rx_phy_addr, AdapterInfo->ioaddr + SCBPointer);
+ OutByte (AdapterInfo, RX_START, AdapterInfo->ioaddr + SCBCmd);
+
+ wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd);
+
+ AdapterInfo->Receive_Started = TRUE;
+ return 0;
+}
+
+UINTN
+E100bInit (
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+ Configures the chip. This routine expects the NIC_DATA_INSTANCE structure to be filled in.
+
+Arguments:
+ AdapterInfo - Pointer to the NIC data structure information
+ which the UNDI driver is layering on..
+
+Returns:
+ 0 - Successful
+ PXE_STATCODE_NOT_ENOUGH_MEMORY - Insufficient length of locked memory
+ other - Failure initializing chip
+--*/
+{
+ PCI_CONFIG_HEADER *CfgHdr;
+ UINTN stat;
+ UINTN rx_size;
+ UINTN tx_size;
+
+ if (AdapterInfo->MemoryLength < MEMORY_NEEDED) {
+ return PXE_STATCODE_NOT_ENOUGH_MEMORY;
+ }
+
+ stat = MapIt (
+ AdapterInfo,
+ AdapterInfo->MemoryPtr,
+ AdapterInfo->MemoryLength,
+ TO_AND_FROM_DEVICE,
+ (UINT64)(UINTN) &AdapterInfo->Mapped_MemoryPtr
+ );
+
+ if (stat != 0) {
+ return stat;
+ }
+
+ CfgHdr = (PCI_CONFIG_HEADER *) &(AdapterInfo->Config[0]);
+
+ //
+ // fill in the ioaddr, int... from the config space
+ //
+ AdapterInfo->int_num = CfgHdr->int_line;
+
+ //
+ // we don't need to validate integer number, what if they don't want to assign one?
+ // if (AdapterInfo->int_num == 0 || AdapterInfo->int_num == 0xff)
+ // return PXE_STATCODE_DEVICE_FAILURE;
+ //
+ AdapterInfo->ioaddr = 0;
+ AdapterInfo->VendorID = CfgHdr->VendorID;
+ AdapterInfo->DeviceID = CfgHdr->DeviceID;
+ AdapterInfo->RevID = CfgHdr->RevID;
+ AdapterInfo->SubVendorID = CfgHdr->SubVendorID;
+ AdapterInfo->SubSystemID = CfgHdr->SubSystemID;
+ AdapterInfo->flash_addr = 0;
+
+ //
+ // Read the station address EEPROM before doing the reset.
+ // Perhaps this should even be done before accepting the device,
+ // then we wouldn't have a device name with which to report the error.
+ //
+ if (E100bReadEepromAndStationAddress (AdapterInfo) != 0) {
+ return PXE_STATCODE_DEVICE_FAILURE;
+
+ }
+ //
+ // ## calculate the buffer #s depending on memory given
+ // ## calculate the rx and tx ring pointers
+ //
+
+ AdapterInfo->TxBufCnt = TX_BUFFER_COUNT;
+ AdapterInfo->RxBufCnt = RX_BUFFER_COUNT;
+ rx_size = (AdapterInfo->RxBufCnt * sizeof (RxFD));
+ tx_size = (AdapterInfo->TxBufCnt * sizeof (TxCB));
+ AdapterInfo->rx_ring = (RxFD *) (UINTN) (AdapterInfo->MemoryPtr);
+ AdapterInfo->tx_ring = (TxCB *) (UINTN) (AdapterInfo->MemoryPtr + rx_size);
+ AdapterInfo->statistics = (struct speedo_stats *) (UINTN) (AdapterInfo->MemoryPtr + rx_size + tx_size);
+
+ AdapterInfo->rx_phy_addr = AdapterInfo->Mapped_MemoryPtr;
+ AdapterInfo->tx_phy_addr = AdapterInfo->Mapped_MemoryPtr + rx_size;
+ AdapterInfo->stat_phy_addr = AdapterInfo->tx_phy_addr + tx_size;
+
+ //
+ // auto detect.
+ //
+ AdapterInfo->PhyAddress = 0xFF;
+ AdapterInfo->Rx_Filter = PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST;
+ AdapterInfo->Receive_Started = FALSE;
+ AdapterInfo->mcast_list.list_len = 0;
+ return InitializeChip (AdapterInfo);
+}
+
+UINT8
+E100bSetInterruptState (
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+ Sets the interrupt state for the NIC.
+
+Arguments:
+ AdapterInfo - Pointer to the NIC data structure information
+ which the UNDI driver is layering on..
+Returns:
+ 0 - Successful
+--*/
+{
+ //
+ // don't set receive interrupt if receiver is disabled...
+ //
+ UINT16 cmd_word;
+
+ if ((AdapterInfo->int_mask & PXE_OPFLAGS_INTERRUPT_RECEIVE) != 0) {
+ cmd_word = InWord (AdapterInfo, AdapterInfo->ioaddr + SCBCmd);
+ cmd_word &= ~INT_MASK;
+ OutWord (AdapterInfo, cmd_word, AdapterInfo->ioaddr + SCBCmd);
+ } else {
+ //
+ // disable ints, should not be given for SW Int.
+ //
+ OutWord (AdapterInfo, INT_MASK, AdapterInfo->ioaddr + SCBCmd);
+ }
+
+ if ((AdapterInfo->int_mask & PXE_OPFLAGS_INTERRUPT_SOFTWARE) != 0) {
+ //
+ // reset the bit in our mask, it is only one time!!
+ //
+ AdapterInfo->int_mask &= ~(PXE_OPFLAGS_INTERRUPT_SOFTWARE);
+ cmd_word = InWord (AdapterInfo, AdapterInfo->ioaddr + SCBCmd);
+ cmd_word |= DRVR_INT;
+ OutWord (AdapterInfo, cmd_word, AdapterInfo->ioaddr + SCBCmd);
+ }
+
+ return 0;
+}
+//
+// we are not going to disable broadcast for the WOL's sake!
+//
+UINTN
+E100bSetfilter (
+ NIC_DATA_INSTANCE *AdapterInfo,
+ UINT16 new_filter,
+ UINT64 cpb,
+ UINT32 cpbsize
+ )
+/*++
+
+Routine Description:
+ Instructs the NIC to start receiving packets.
+
+Arguments:
+ AdapterInfo - Pointer to the NIC data structure information
+ which the UNDI driver is layering on..
+ new_filter -
+ cpb -
+ cpbsize -
+
+Returns:
+ 0 - Successful
+ -1 - Already Started
+--*/
+{
+ PXE_CPB_RECEIVE_FILTERS *mc_list = (PXE_CPB_RECEIVE_FILTERS *) (UINTN)cpb;
+ UINT16 cfg_flt;
+ UINT16 old_filter;
+ UINT16 Index;
+ UINT16 Index2;
+ UINT16 mc_count;
+ TxCB *cmd_ptr;
+ struct MC_CB_STRUCT *data_ptr;
+ UINT16 mc_byte_cnt;
+
+ old_filter = AdapterInfo->Rx_Filter;
+
+ //
+ // only these bits need a change in the configuration
+ // actually change in bcast requires configure but we ignore that change
+ //
+ cfg_flt = PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS |
+ PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST;
+
+ if ((old_filter & cfg_flt) != (new_filter & cfg_flt)) {
+ XmitWaitForCompletion (AdapterInfo);
+
+ if (AdapterInfo->Receive_Started) {
+ StopRU (AdapterInfo);
+ }
+
+ AdapterInfo->Rx_Filter = (UINT8) (new_filter | PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST);
+ Configure (AdapterInfo);
+ }
+
+ //
+ // check if mcast setting changed
+ //
+ if ( ((new_filter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) !=
+ (old_filter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) ) ||
+ (mc_list != NULL) ) {
+
+
+ if (mc_list != NULL) {
+ mc_count = AdapterInfo->mcast_list.list_len = (UINT16) (cpbsize / PXE_MAC_LENGTH);
+
+ for (Index = 0; (Index < mc_count && Index < MAX_MCAST_ADDRESS_CNT); Index++) {
+ for (Index2 = 0; Index2 < PXE_MAC_LENGTH; Index2++) {
+ AdapterInfo->mcast_list.mc_list[Index][Index2] = mc_list->MCastList[Index][Index2];
+ }
+ }
+ }
+
+ //
+ // are we setting the list or resetting??
+ //
+ if ((new_filter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) != 0) {
+ //
+ // we are setting a new list!
+ //
+ mc_count = AdapterInfo->mcast_list.list_len;
+ //
+ // count should be the actual # of bytes in the list
+ // so multiply this with 6
+ //
+ mc_byte_cnt = (UINT16) ((mc_count << 2) + (mc_count << 1));
+ AdapterInfo->Rx_Filter |= PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST;
+ } else {
+ //
+ // disabling the list in the NIC.
+ //
+ mc_byte_cnt = mc_count = 0;
+ AdapterInfo->Rx_Filter &= (~PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST);
+ }
+
+ //
+ // before issuing any new command!
+ //
+ XmitWaitForCompletion (AdapterInfo);
+
+ if (AdapterInfo->Receive_Started) {
+ StopRU (AdapterInfo);
+
+ }
+
+ cmd_ptr = GetFreeCB (AdapterInfo);
+ if (cmd_ptr == NULL) {
+ return PXE_STATCODE_QUEUE_FULL;
+ }
+ //
+ // fill the command structure and issue
+ //
+ data_ptr = (struct MC_CB_STRUCT *) (&cmd_ptr->PhysTBDArrayAddres);
+ //
+ // first 2 bytes are the count;
+ //
+ data_ptr->count = mc_byte_cnt;
+ for (Index = 0; Index < mc_count; Index++) {
+ for (Index2 = 0; Index2 < PXE_HWADDR_LEN_ETHER; Index2++) {
+ data_ptr->m_list[Index][Index2] = AdapterInfo->mcast_list.mc_list[Index][Index2];
+ }
+ }
+
+ cmd_ptr->cb_header.command = CmdSuspend | CmdMulticastList;
+ cmd_ptr->cb_header.status = 0;
+
+ BlockIt (AdapterInfo, TRUE);
+ IssueCB (AdapterInfo, cmd_ptr);
+ wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd);
+
+ BlockIt (AdapterInfo, FALSE);
+
+ CommandWaitForCompletion (cmd_ptr, AdapterInfo);
+
+ cmd_ptr->PhysTBDArrayAddres = cmd_ptr->PhysArrayAddr;
+ cmd_ptr->ByteCount = cmd_ptr->Threshold = cmd_ptr->TBDCount = 0;
+ //
+ // fields beyond the immediatedata are assumed to be safe
+ // add the CB to the free list again
+ //
+ SetFreeCB (AdapterInfo, cmd_ptr);
+ }
+
+ if (new_filter != 0) {
+ //
+ // enable unicast and start the RU
+ //
+ AdapterInfo->Rx_Filter |= (new_filter | PXE_OPFLAGS_RECEIVE_FILTER_UNICAST);
+ StartRU (AdapterInfo);
+ } else {
+ //
+ // may be disabling everything!
+ //
+ if (AdapterInfo->Receive_Started) {
+ StopRU (AdapterInfo);
+ }
+
+ AdapterInfo->Rx_Filter |= (~PXE_OPFLAGS_RECEIVE_FILTER_UNICAST);
+ }
+
+ return 0;
+}
+
+UINTN
+E100bTransmit (
+ NIC_DATA_INSTANCE *AdapterInfo,
+ UINT64 cpb,
+ UINT16 opflags
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AdapterInfo - TODO: add argument description
+ cpb - TODO: add argument description
+ opflags - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ PXE_CPB_TRANSMIT_FRAGMENTS *tx_ptr_f;
+ PXE_CPB_TRANSMIT *tx_ptr_1;
+ TxCB *tcb_ptr;
+ UINT64 Tmp_ptr;
+ UINTN stat;
+ INT32 Index;
+ UINT16 wait_sec;
+
+ tx_ptr_1 = (PXE_CPB_TRANSMIT *) (UINTN) cpb;
+ tx_ptr_f = (PXE_CPB_TRANSMIT_FRAGMENTS *) (UINTN) cpb;
+
+ //
+ // stop reentrancy here
+ //
+ if (AdapterInfo->in_transmit) {
+ return PXE_STATCODE_BUSY;
+
+ }
+
+ AdapterInfo->in_transmit = TRUE;
+
+ //
+ // Prevent interrupts from changing the Tx ring from underneath us.
+ //
+ // Calculate the Tx descriptor entry.
+ //
+ if ((tcb_ptr = GetFreeCB (AdapterInfo)) == NULL) {
+ AdapterInfo->in_transmit = FALSE;
+ return PXE_STATCODE_QUEUE_FULL;
+ }
+
+ AdapterInfo->TxTotals++;
+
+ tcb_ptr->cb_header.command = (CmdSuspend | CmdTx | CmdTxFlex);
+ tcb_ptr->cb_header.status = 0;
+
+ //
+ // no immediate data, set EOF in the ByteCount
+ //
+ tcb_ptr->ByteCount = 0x8000;
+
+ //
+ // The data region is always in one buffer descriptor, Tx FIFO
+ // threshold of 256.
+ // 82557 multiplies the threashold value by 8, so give 256/8
+ //
+ tcb_ptr->Threshold = 32;
+ if ((opflags & PXE_OPFLAGS_TRANSMIT_FRAGMENTED) != 0) {
+
+ if (tx_ptr_f->FragCnt > MAX_XMIT_FRAGMENTS) {
+ SetFreeCB (AdapterInfo, tcb_ptr);
+ AdapterInfo->in_transmit = FALSE;
+ return PXE_STATCODE_INVALID_PARAMETER;
+ }
+
+ tcb_ptr->TBDCount = (UINT8) tx_ptr_f->FragCnt;
+
+ for (Index = 0; Index < tx_ptr_f->FragCnt; Index++) {
+ stat = MapIt (
+ AdapterInfo,
+ tx_ptr_f->FragDesc[Index].FragAddr,
+ tx_ptr_f->FragDesc[Index].FragLen,
+ TO_DEVICE,
+ (UINT64)(UINTN) &Tmp_ptr
+ );
+ if (stat != 0) {
+ SetFreeCB (AdapterInfo, tcb_ptr);
+ AdapterInfo->in_transmit = FALSE;
+ return PXE_STATCODE_INVALID_PARAMETER;
+ }
+
+ tcb_ptr->TBDArray[Index].phys_buf_addr = (UINT32) Tmp_ptr;
+ tcb_ptr->TBDArray[Index].buf_len = tx_ptr_f->FragDesc[Index].FragLen;
+ }
+
+ tcb_ptr->free_data_ptr = tx_ptr_f->FragDesc[0].FragAddr;
+
+ } else {
+ //
+ // non fragmented case
+ //
+ tcb_ptr->TBDCount = 1;
+ stat = MapIt (
+ AdapterInfo,
+ tx_ptr_1->FrameAddr,
+ tx_ptr_1->DataLen + tx_ptr_1->MediaheaderLen,
+ TO_DEVICE,
+ (UINT64)(UINTN) &Tmp_ptr
+ );
+ if (stat != 0) {
+ SetFreeCB (AdapterInfo, tcb_ptr);
+ AdapterInfo->in_transmit = FALSE;
+ return PXE_STATCODE_INVALID_PARAMETER;
+ }
+
+ tcb_ptr->TBDArray[0].phys_buf_addr = (UINT32) (Tmp_ptr);
+ tcb_ptr->TBDArray[0].buf_len = tx_ptr_1->DataLen + tx_ptr_1->MediaheaderLen;
+ tcb_ptr->free_data_ptr = tx_ptr_1->FrameAddr;
+ }
+
+ //
+ // must wait for previous command completion only if it was a non-transmit
+ //
+ BlockIt (AdapterInfo, TRUE);
+ IssueCB (AdapterInfo, tcb_ptr);
+ BlockIt (AdapterInfo, FALSE);
+
+ //
+ // see if we need to wait for completion here
+ //
+ if ((opflags & PXE_OPFLAGS_TRANSMIT_BLOCK) != 0) {
+ //
+ // don't wait for more than 1 second!!!
+ //
+ wait_sec = 1000;
+ while (tcb_ptr->cb_header.status == 0) {
+ DelayIt (AdapterInfo, 10);
+ wait_sec--;
+ if (wait_sec == 0) {
+ break;
+ }
+ }
+ //
+ // we need to un-map any mapped buffers here
+ //
+ if ((opflags & PXE_OPFLAGS_TRANSMIT_FRAGMENTED) != 0) {
+
+ for (Index = 0; Index < tx_ptr_f->FragCnt; Index++) {
+ Tmp_ptr = tcb_ptr->TBDArray[Index].phys_buf_addr;
+ UnMapIt (
+ AdapterInfo,
+ tx_ptr_f->FragDesc[Index].FragAddr,
+ tx_ptr_f->FragDesc[Index].FragLen,
+ TO_DEVICE,
+ (UINT64) Tmp_ptr
+ );
+ }
+ } else {
+ Tmp_ptr = tcb_ptr->TBDArray[0].phys_buf_addr;
+ UnMapIt (
+ AdapterInfo,
+ tx_ptr_1->FrameAddr,
+ tx_ptr_1->DataLen + tx_ptr_1->MediaheaderLen,
+ TO_DEVICE,
+ (UINT64) Tmp_ptr
+ );
+ }
+
+ if (tcb_ptr->cb_header.status == 0) {
+ SetFreeCB (AdapterInfo, tcb_ptr);
+ AdapterInfo->in_transmit = FALSE;
+ return PXE_STATCODE_DEVICE_FAILURE;
+ }
+
+ SetFreeCB (AdapterInfo, tcb_ptr);
+ }
+ //
+ // CB will be set free later in get_status (or when we run out of xmit buffers
+ //
+ AdapterInfo->in_transmit = FALSE;
+
+ return 0;
+}
+
+UINTN
+E100bReceive (
+ NIC_DATA_INSTANCE *AdapterInfo,
+ UINT64 cpb,
+ UINT64 db
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AdapterInfo - TODO: add argument description
+ cpb - TODO: add argument description
+ db - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ PXE_CPB_RECEIVE *rx_cpbptr;
+ PXE_DB_RECEIVE *rx_dbptr;
+ RxFD *rx_ptr;
+ INT32 status;
+ INT32 Index;
+ UINT16 pkt_len;
+ UINT16 ret_code;
+ PXE_FRAME_TYPE pkt_type;
+ UINT16 Tmp_len;
+ EtherHeader *hdr_ptr;
+ ret_code = PXE_STATCODE_NO_DATA;
+ pkt_type = PXE_FRAME_TYPE_NONE;
+ status = InWord (AdapterInfo, AdapterInfo->ioaddr + SCBStatus);
+ AdapterInfo->Int_Status |= status;
+ //
+ // acknoledge the interrupts
+ //
+ OutWord (AdapterInfo, (UINT16) (status & 0xfc00), (UINT32) (AdapterInfo->ioaddr + SCBStatus));
+
+ //
+ // include the prev ints as well
+ //
+ status = AdapterInfo->Int_Status;
+ rx_cpbptr = (PXE_CPB_RECEIVE *) (UINTN) cpb;
+ rx_dbptr = (PXE_DB_RECEIVE *) (UINTN) db;
+
+ rx_ptr = &AdapterInfo->rx_ring[AdapterInfo->cur_rx_ind];
+
+ //
+ // be in a loop just in case (we may drop a pkt)
+ //
+ while ((status = rx_ptr->cb_header.status) & RX_COMPLETE) {
+
+ AdapterInfo->RxTotals++;
+ //
+ // If we own the next entry, it's a new packet. Send it up.
+ //
+ if (rx_ptr->forwarded) {
+ goto FreeRFD;
+
+ }
+
+ //
+ // discard bad frames
+ //
+
+ //
+ // crc, align, dma overrun, too short, receive error (v22 no coll)
+ //
+ if ((status & 0x0D90) != 0) {
+ goto FreeRFD;
+
+ }
+
+ //
+ // make sure the status is OK
+ //
+ if ((status & 0x02000) == 0) {
+ goto FreeRFD;
+ }
+
+ pkt_len = (UINT16) (rx_ptr->ActualCount & 0x3fff);
+
+ if (pkt_len != 0) {
+
+ Tmp_len = pkt_len;
+ if (pkt_len > rx_cpbptr->BufferLen) {
+ Tmp_len = (UINT16) rx_cpbptr->BufferLen;
+ }
+
+ CopyMem ((INT8 *) (UINTN) rx_cpbptr->BufferAddr, (INT8 *) &rx_ptr->RFDBuffer, Tmp_len);
+
+ hdr_ptr = (EtherHeader *) &rx_ptr->RFDBuffer;
+ //
+ // fill the CDB and break the loop
+ //
+
+ //
+ // includes header
+ //
+ rx_dbptr->FrameLen = pkt_len;
+ rx_dbptr->MediaHeaderLen = PXE_MAC_HEADER_LEN_ETHER;
+
+ for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {
+ if (hdr_ptr->dest_addr[Index] != AdapterInfo->CurrentNodeAddress[Index]) {
+ break;
+ }
+ }
+
+ if (Index >= PXE_HWADDR_LEN_ETHER) {
+ pkt_type = PXE_FRAME_TYPE_UNICAST;
+ } else {
+ for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {
+ if (hdr_ptr->dest_addr[Index] != AdapterInfo->BroadcastNodeAddress[Index]) {
+ break;
+ }
+ }
+
+ if (Index >= PXE_HWADDR_LEN_ETHER) {
+ pkt_type = PXE_FRAME_TYPE_BROADCAST;
+ } else {
+ if ((hdr_ptr->dest_addr[0] & 1) == 1) {
+ //
+ // mcast
+ //
+
+ pkt_type = PXE_FRAME_TYPE_MULTICAST;
+ } else {
+ pkt_type = PXE_FRAME_TYPE_PROMISCUOUS;
+ }
+ }
+ }
+
+ rx_dbptr->Type = pkt_type;
+ rx_dbptr->Protocol = hdr_ptr->type;
+
+ for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {
+ rx_dbptr->SrcAddr[Index] = hdr_ptr->src_addr[Index];
+ rx_dbptr->DestAddr[Index] = hdr_ptr->dest_addr[Index];
+ }
+
+ rx_ptr->forwarded = TRUE;
+ //
+ // success
+ //
+ ret_code = 0;
+ Recycle_RFD (AdapterInfo, AdapterInfo->cur_rx_ind);
+ AdapterInfo->cur_rx_ind++;
+ if (AdapterInfo->cur_rx_ind == AdapterInfo->RxBufCnt) {
+ AdapterInfo->cur_rx_ind = 0;
+ }
+ break;
+ }
+
+FreeRFD:
+ Recycle_RFD (AdapterInfo, AdapterInfo->cur_rx_ind);
+ AdapterInfo->cur_rx_ind++;
+ if (AdapterInfo->cur_rx_ind == AdapterInfo->RxBufCnt) {
+ AdapterInfo->cur_rx_ind = 0;
+ }
+
+ rx_ptr = &AdapterInfo->rx_ring[AdapterInfo->cur_rx_ind];
+ }
+
+ if (pkt_type == PXE_FRAME_TYPE_NONE) {
+ AdapterInfo->Int_Status &= (~SCB_STATUS_FR);
+ }
+
+ status = InWord (AdapterInfo, AdapterInfo->ioaddr + SCBStatus);
+ if ((status & SCB_RUS_NO_RESOURCES) != 0) {
+ //
+ // start the receive unit here!
+ // leave all the filled frames,
+ //
+ SetupReceiveQueues (AdapterInfo);
+ OutLong (AdapterInfo, (UINT32) AdapterInfo->rx_phy_addr, AdapterInfo->ioaddr + SCBPointer);
+ OutWord (AdapterInfo, RX_START, AdapterInfo->ioaddr + SCBCmd);
+ AdapterInfo->cur_rx_ind = 0;
+ }
+
+ return ret_code;
+}
+
+INT16
+E100bReadEepromAndStationAddress (
+ NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AdapterInfo - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ INT32 Index;
+ INT32 Index2;
+ UINT16 sum;
+ UINT16 eeprom_len;
+ UINT8 addr_len;
+ UINT16 *eedata;
+
+ eedata = (UINT16 *) (&AdapterInfo->NVData[0]);
+
+ sum = 0;
+ addr_len = E100bGetEepromAddrLen (AdapterInfo);
+
+ //
+ // in words
+ //
+ AdapterInfo->NVData_Len = eeprom_len = (UINT16) (1 << addr_len);
+ for (Index2 = 0, Index = 0; Index < eeprom_len; Index++) {
+ UINT16 value;
+ value = E100bReadEeprom (AdapterInfo, Index, addr_len);
+ eedata[Index] = value;
+ sum = (UINT16) (sum + value);
+ if (Index < 3) {
+ AdapterInfo->PermNodeAddress[Index2++] = (UINT8) value;
+ AdapterInfo->PermNodeAddress[Index2++] = (UINT8) (value >> 8);
+ }
+ }
+
+ if (sum != 0xBABA) {
+ return -1;
+ }
+
+ for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {
+ AdapterInfo->CurrentNodeAddress[Index] = AdapterInfo->PermNodeAddress[Index];
+ }
+
+ for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {
+ AdapterInfo->BroadcastNodeAddress[Index] = 0xff;
+ }
+
+ for (Index = PXE_HWADDR_LEN_ETHER; Index < PXE_MAC_LENGTH; Index++) {
+ AdapterInfo->CurrentNodeAddress[Index] = 0;
+ AdapterInfo->PermNodeAddress[Index] = 0;
+ AdapterInfo->BroadcastNodeAddress[Index] = 0;
+ }
+
+ return 0;
+}
+
+//
+// CBList is a circular linked list
+// 1) When all are free, Tail->next == Head and FreeCount == # allocated
+// 2) When none are free, Tail == Head and FreeCount == 0
+// 3) when one is free, Tail == Head and Freecount == 1
+// 4) First non-Free frame is always at Tail->next
+//
+UINT8
+SetupCBlink (
+ NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AdapterInfo - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ TxCB *head_ptr;
+ TxCB *tail_ptr;
+ TxCB *cur_ptr;
+ INT32 Index;
+ UINTN array_off;
+
+ cur_ptr = &(AdapterInfo->tx_ring[0]);
+ array_off = (UINTN) (&cur_ptr->TBDArray) - (UINTN) cur_ptr;
+ for (Index = 0; Index < AdapterInfo->TxBufCnt; Index++) {
+ cur_ptr[Index].cb_header.status = 0;
+ cur_ptr[Index].cb_header.command = 0;
+
+ cur_ptr[Index].PhysTCBAddress =
+ (UINT32) AdapterInfo->tx_phy_addr + (Index * sizeof (TxCB));
+
+ cur_ptr[Index].PhysArrayAddr = (UINT32)(cur_ptr[Index].PhysTCBAddress + array_off);
+ cur_ptr[Index].PhysTBDArrayAddres = (UINT32)(cur_ptr[Index].PhysTCBAddress + array_off);
+
+ cur_ptr->free_data_ptr = (UINT64) 0;
+
+ if (Index < AdapterInfo->TxBufCnt - 1) {
+ cur_ptr[Index].cb_header.link = cur_ptr[Index].PhysTCBAddress + sizeof (TxCB);
+ cur_ptr[Index].NextTCBVirtualLinkPtr = &cur_ptr[Index + 1];
+ cur_ptr[Index + 1].PrevTCBVirtualLinkPtr = &cur_ptr[Index];
+ }
+ }
+
+ head_ptr = &cur_ptr[0];
+ tail_ptr = &cur_ptr[AdapterInfo->TxBufCnt - 1];
+ tail_ptr->cb_header.link = head_ptr->PhysTCBAddress;
+ tail_ptr->NextTCBVirtualLinkPtr = head_ptr;
+ head_ptr->PrevTCBVirtualLinkPtr = tail_ptr;
+
+ AdapterInfo->FreeCBCount = AdapterInfo->TxBufCnt;
+ AdapterInfo->FreeTxHeadPtr = head_ptr;
+ //
+ // set tail of the free list, next to this would be either in use
+ // or the head itself
+ //
+ AdapterInfo->FreeTxTailPtr = tail_ptr;
+
+ AdapterInfo->xmit_done_head = AdapterInfo->xmit_done_tail = 0;
+
+ return 0;
+}
+
+TxCB *
+GetFreeCB (
+ NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AdapterInfo - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ TxCB *free_cb_ptr;
+
+ //
+ // claim any hanging free CBs
+ //
+ if (AdapterInfo->FreeCBCount <= 1) {
+ CheckCBList (AdapterInfo);
+ }
+
+ //
+ // don't use up the last CB problem if the previous CB that the CU used
+ // becomes the last CB we submit because of the SUSPEND bit we set.
+ // the CU thinks it was never cleared.
+ //
+
+ if (AdapterInfo->FreeCBCount <= 1) {
+ return NULL;
+ }
+
+ BlockIt (AdapterInfo, TRUE);
+ free_cb_ptr = AdapterInfo->FreeTxHeadPtr;
+ AdapterInfo->FreeTxHeadPtr = free_cb_ptr->NextTCBVirtualLinkPtr;
+ --AdapterInfo->FreeCBCount;
+ BlockIt (AdapterInfo, FALSE);
+ return free_cb_ptr;
+}
+
+VOID
+SetFreeCB (
+ IN NIC_DATA_INSTANCE *AdapterInfo,
+ IN TxCB *cb_ptr
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AdapterInfo - TODO: add argument description
+ cb_ptr - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ //
+ // here we assume cb are returned in the order they are taken out
+ // and we link the newly freed cb at the tail of free cb list
+ //
+ cb_ptr->cb_header.status = 0;
+ cb_ptr->free_data_ptr = (UINT64) 0;
+
+ AdapterInfo->FreeTxTailPtr = cb_ptr;
+ ++AdapterInfo->FreeCBCount;
+ return ;
+}
+
+UINT16
+next (
+ IN UINT16 ind
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ ind - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ UINT16 Tmp;
+
+ Tmp = (UINT16) (ind + 1);
+ if (Tmp >= (TX_BUFFER_COUNT << 1)) {
+ Tmp = 0;
+ }
+
+ return Tmp;
+}
+
+UINT16
+CheckCBList (
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AdapterInfo - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ TxCB *Tmp_ptr;
+ UINT16 cnt;
+
+ cnt = 0;
+ while (1) {
+ Tmp_ptr = AdapterInfo->FreeTxTailPtr->NextTCBVirtualLinkPtr;
+ if ((Tmp_ptr->cb_header.status & CMD_STATUS_MASK) != 0) {
+ //
+ // check if Q is full
+ //
+ if (next (AdapterInfo->xmit_done_tail) != AdapterInfo->xmit_done_head) {
+ AdapterInfo->xmit_done[AdapterInfo->xmit_done_tail] = Tmp_ptr->free_data_ptr;
+
+ UnMapIt (
+ AdapterInfo,
+ Tmp_ptr->free_data_ptr,
+ Tmp_ptr->TBDArray[0].buf_len,
+ TO_DEVICE,
+ (UINT64) Tmp_ptr->TBDArray[0].phys_buf_addr
+ );
+
+ AdapterInfo->xmit_done_tail = next (AdapterInfo->xmit_done_tail);
+ }
+
+ SetFreeCB (AdapterInfo, Tmp_ptr);
+ } else {
+ break;
+ }
+ }
+
+ return cnt;
+}
+//
+// Description : Initialize the RFD list list by linking each element together
+// in a circular list. The simplified memory model is used.
+// All data is in the RFD. The RFDs are linked together and the
+// last one points back to the first one. When the current RFD
+// is processed (frame received), its EL bit is set and the EL
+// bit in the previous RXFD is cleared.
+// Allocation done during INIT, this is making linked list.
+//
+UINT8
+SetupReceiveQueues (
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AdapterInfo - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ RxFD *rx_ptr;
+ RxFD *head_ptr;
+ RxFD *tail_ptr;
+ UINT16 Index;
+
+ AdapterInfo->cur_rx_ind = 0;
+ rx_ptr = (&AdapterInfo->rx_ring[0]);
+
+ for (Index = 0; Index < AdapterInfo->RxBufCnt; Index++) {
+ rx_ptr[Index].cb_header.status = 0;
+ rx_ptr[Index].cb_header.command = 0;
+ rx_ptr[Index].RFDSize = RX_BUFFER_SIZE;
+ rx_ptr[Index].ActualCount = 0;
+ //
+ // RBDs not used, simple memory model
+ //
+ rx_ptr[Index].rx_buf_addr = (UINT32) (-1);
+
+ //
+ // RBDs not used, simple memory model
+ //
+ rx_ptr[Index].forwarded = FALSE;
+
+ //
+ // don't use Tmp_ptr if it is beyond the last one
+ //
+ if (Index < AdapterInfo->RxBufCnt - 1) {
+ rx_ptr[Index].cb_header.link = (UINT32) AdapterInfo->rx_phy_addr + ((Index + 1) * sizeof (RxFD));
+ }
+ }
+
+ head_ptr = (&AdapterInfo->rx_ring[0]);
+ tail_ptr = (&AdapterInfo->rx_ring[AdapterInfo->RxBufCnt - 1]);
+ tail_ptr->cb_header.link = (UINT32) AdapterInfo->rx_phy_addr;
+
+ //
+ // set the EL bit
+ //
+ tail_ptr->cb_header.command = 0xC000;
+ AdapterInfo->RFDTailPtr = tail_ptr;
+ return 0;
+}
+
+VOID
+Recycle_RFD (
+ IN NIC_DATA_INSTANCE *AdapterInfo,
+ IN UINT16 rx_index
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AdapterInfo - TODO: add argument description
+ rx_index - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ RxFD *rx_ptr;
+ RxFD *tail_ptr;
+ //
+ // change the EL bit and change the AdapterInfo->RxTailPtr
+ // rx_ptr is assumed to be the head of the Q
+ // AdapterInfo->rx_forwarded[rx_index] = FALSE;
+ //
+ rx_ptr = &AdapterInfo->rx_ring[rx_index];
+ tail_ptr = AdapterInfo->RFDTailPtr;
+ //
+ // set el_bit and suspend bit
+ //
+ rx_ptr->cb_header.command = 0xc000;
+ rx_ptr->cb_header.status = 0;
+ rx_ptr->ActualCount = 0;
+ rx_ptr->forwarded = FALSE;
+ AdapterInfo->RFDTailPtr = rx_ptr;
+ //
+ // resetting the el_bit.
+ //
+ tail_ptr->cb_header.command = 0;
+ //
+ // check the receive unit, fix if there is any problem
+ //
+ return ;
+}
+//
+// Serial EEPROM section.
+//
+// EEPROM_Ctrl bits.
+//
+#define EE_SHIFT_CLK 0x01 /* EEPROM shift clock. */
+#define EE_CS 0x02 /* EEPROM chip select. */
+#define EE_DI 0x04 /* EEPROM chip data in. */
+#define EE_WRITE_0 0x01
+#define EE_WRITE_1 0x05
+#define EE_DO 0x08 /* EEPROM chip data out. */
+#define EE_ENB (0x4800 | EE_CS)
+
+//
+// Delay between EEPROM clock transitions.
+// This will actually work with no delay on 33Mhz PCI.
+//
+#define eeprom_delay(nanosec) DelayIt (AdapterInfo, nanosec);
+
+//
+// The EEPROM commands include the alway-set leading bit.
+//
+#define EE_WRITE_CMD 5 // 101b
+#define EE_READ_CMD 6 // 110b
+#define EE_ERASE_CMD (7 << 6)
+
+VOID
+shift_bits_out (
+ IN NIC_DATA_INSTANCE *AdapterInfo,
+ IN UINT16 val,
+ IN UINT8 num_bits
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AdapterInfo - TODO: add argument description
+ val - TODO: add argument description
+ num_bits - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ INT32 Index;
+ UINT8 Tmp;
+ UINT32 EEAddr;
+
+ EEAddr = AdapterInfo->ioaddr + SCBeeprom;
+
+ for (Index = num_bits; Index >= 0; Index--) {
+ INT16 dataval;
+
+ //
+ // will be 0 or 4
+ //
+ dataval = (INT16) ((val & (1 << Index)) ? EE_DI : 0);
+
+ //
+ // mask off the data_in bit
+ //
+ Tmp = (UINT8) (InByte (AdapterInfo, EEAddr) &~EE_DI);
+ Tmp |= dataval;
+ OutByte (AdapterInfo, Tmp, EEAddr);
+ eeprom_delay (100);
+ //
+ // raise the eeprom clock
+ //
+ OutByte (AdapterInfo, (UINT8) (Tmp | EE_SHIFT_CLK), EEAddr);
+ eeprom_delay (150);
+ //
+ // lower the eeprom clock
+ //
+ OutByte (AdapterInfo, (UINT8) (Tmp &~EE_SHIFT_CLK), EEAddr);
+ eeprom_delay (150);
+ }
+}
+
+UINT16
+shift_bits_in (
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AdapterInfo - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ UINT8 Tmp;
+ INT32 Index;
+ UINT16 retval;
+ UINT32 EEAddr;
+
+ EEAddr = AdapterInfo->ioaddr + SCBeeprom;
+
+ retval = 0;
+ for (Index = 15; Index >= 0; Index--) {
+ //
+ // raise the clock
+ //
+
+ //
+ // mask off the data_in bit
+ //
+ Tmp = InByte (AdapterInfo, EEAddr);
+ OutByte (AdapterInfo, (UINT8) (Tmp | EE_SHIFT_CLK), EEAddr);
+ eeprom_delay (100);
+ Tmp = InByte (AdapterInfo, EEAddr);
+ retval = (UINT16) ((retval << 1) | ((Tmp & EE_DO) ? 1 : 0));
+ //
+ // lower the clock
+ //
+ OutByte (AdapterInfo, (UINT8) (Tmp &~EE_SHIFT_CLK), EEAddr);
+ eeprom_delay (100);
+ }
+
+ return retval;
+}
+
+BOOLEAN
+E100bSetEepromLockOut (
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+ This routine sets the EEPROM lockout bit to gain exclusive access to the
+ eeprom. the access bit is the most significant bit in the General Control
+ Register 2 in the SCB space.
+
+Arguments:
+ AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
+
+Returns:
+ TRUE - if it got the access
+ FALSE - if it fails to get the exclusive access
+
+--*/
+{
+ UINTN wait;
+ UINT8 tmp;
+
+ if ((AdapterInfo->DeviceID == D102_DEVICE_ID) ||
+ (AdapterInfo->RevID >= D102_REVID)) {
+
+ wait = 500;
+
+ while (wait--) {
+
+ tmp = InByte (AdapterInfo, AdapterInfo->ioaddr + SCBGenCtrl2);
+ tmp |= GCR2_EEPROM_ACCESS_SEMAPHORE;
+ OutByte (AdapterInfo, tmp, AdapterInfo->ioaddr + SCBGenCtrl2);
+
+ DelayIt (AdapterInfo, 50);
+ tmp = InByte (AdapterInfo, AdapterInfo->ioaddr + SCBGenCtrl2);
+
+ if (tmp & GCR2_EEPROM_ACCESS_SEMAPHORE) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+VOID
+E100bReSetEepromLockOut (
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+ This routine Resets the EEPROM lockout bit to giveup access to the
+ eeprom. the access bit is the most significant bit in the General Control
+ Register 2 in the SCB space.
+
+Arguments:
+ AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
+
+Returns:
+ None
+
+--*/
+{
+ UINT8 tmp;
+
+ if ((AdapterInfo->DeviceID == D102_DEVICE_ID) ||
+ (AdapterInfo->RevID >= D102_REVID)) {
+
+ tmp = InByte (AdapterInfo, AdapterInfo->ioaddr + SCBGenCtrl2);
+ tmp &= ~(GCR2_EEPROM_ACCESS_SEMAPHORE);
+ OutByte (AdapterInfo, tmp, AdapterInfo->ioaddr + SCBGenCtrl2);
+
+ DelayIt (AdapterInfo, 50);
+ }
+}
+
+UINT16
+E100bReadEeprom (
+ IN NIC_DATA_INSTANCE *AdapterInfo,
+ IN INT32 Location,
+ IN UINT8 AddrLen
+ )
+/*++
+
+Routine Description:
+ Using the NIC data structure information, read the EEPROM to get a Word of data for the MAC address.
+
+Arguments:
+ AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
+ Location - Word offset into the MAC address to read.
+ AddrLen - Number of bits of address length.
+
+Returns:
+ RetVal - The word read from the EEPROM.
+
+--*/
+{
+ UINT16 RetVal;
+ UINT8 Tmp;
+
+ UINT32 EEAddr;
+ UINT16 ReadCmd;
+
+ EEAddr = AdapterInfo->ioaddr + SCBeeprom;
+ ReadCmd = (UINT16) (Location | (EE_READ_CMD << AddrLen));
+
+ RetVal = 0;
+
+ //
+ // get exclusive access to the eeprom first!
+ //
+ E100bSetEepromLockOut (AdapterInfo);
+
+ //
+ // eeprom control reg bits: x,x,x,x,DO,DI,CS,SK
+ // to write the opcode+data value out one bit at a time in DI starting at msb
+ // and then out a 1 to sk, wait, out 0 to SK and wait
+ // repeat this for all the bits to be written
+ //
+
+ //
+ // 11110010b
+ //
+ Tmp = (UINT8) (InByte (AdapterInfo, EEAddr) & 0xF2);
+ OutByte (AdapterInfo, (UINT8) (Tmp | EE_CS), EEAddr);
+
+ //
+ // 3 for the read opcode 110b
+ //
+ shift_bits_out (AdapterInfo, ReadCmd, (UINT8) (3 + AddrLen));
+
+ //
+ // read the eeprom word one bit at a time
+ //
+ RetVal = shift_bits_in (AdapterInfo);
+
+ //
+ // Terminate the EEPROM access and leave eeprom in a clean state.
+ //
+ Tmp = InByte (AdapterInfo, EEAddr);
+ Tmp &= ~(EE_CS | EE_DI);
+ OutByte (AdapterInfo, Tmp, EEAddr);
+
+ //
+ // raise the clock and lower the eeprom shift clock
+ //
+ OutByte (AdapterInfo, (UINT8) (Tmp | EE_SHIFT_CLK), EEAddr);
+ eeprom_delay (100);
+
+ OutByte (AdapterInfo, (UINT8) (Tmp &~EE_SHIFT_CLK), EEAddr);
+ eeprom_delay (100);
+
+ //
+ // giveup access to the eeprom
+ //
+ E100bReSetEepromLockOut (AdapterInfo);
+
+ return RetVal;
+}
+
+UINT8
+E100bGetEepromAddrLen (
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+ Using the NIC data structure information, read the EEPROM to determine how many bits of address length
+ this EEPROM is in Words.
+
+Arguments:
+ AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
+
+Returns:
+ RetVal - The word read from the EEPROM.
+
+--*/
+{
+ UINT8 Tmp;
+ UINT8 AddrLen;
+ UINT32 EEAddr;
+ //
+ // assume 64word eeprom (so,6 bits of address_length)
+ //
+ UINT16 ReadCmd;
+
+ EEAddr = AdapterInfo->ioaddr + SCBeeprom;
+ ReadCmd = (EE_READ_CMD << 6);
+
+ //
+ // get exclusive access to the eeprom first!
+ //
+ E100bSetEepromLockOut (AdapterInfo);
+
+ //
+ // address we are trying to read is 0
+ // eeprom control reg bits: x,x,x,x,DO,,DI,,CS,SK
+ // to write the opcode+data value out one bit at a time in DI starting at msb
+ // and then out a 1 to sk, wait, out 0 to SK and wait
+ // repeat this for all the bits to be written
+ //
+ Tmp = (UINT8) (InByte (AdapterInfo, EEAddr) & 0xF2);
+
+ //
+ // enable eeprom access
+ //
+ OutByte (AdapterInfo, (UINT8) (Tmp | EE_CS), EEAddr);
+
+ //
+ // 3 for opcode, 6 for the default address len
+ //
+ shift_bits_out (AdapterInfo, ReadCmd, (UINT8) (3 + 6));
+
+ //
+ // (in case of a 64 word eeprom).
+ // read the "dummy zero" from EE_DO to say that the address we wrote
+ // (six 0s) is accepted, write more zeros (until 8) to get a "dummy zero"
+ //
+
+ //
+ // assume the smallest
+ //
+ AddrLen = 6;
+ Tmp = InByte (AdapterInfo, EEAddr);
+ while ((AddrLen < 8) && ((Tmp & EE_DO) != 0)) {
+ OutByte (AdapterInfo, (UINT8) (Tmp &~EE_DI), EEAddr);
+ eeprom_delay (100);
+
+ //
+ // raise the eeprom clock
+ //
+ OutByte (AdapterInfo, (UINT8) (Tmp | EE_SHIFT_CLK), EEAddr);
+ eeprom_delay (150);
+
+ //
+ // lower the eeprom clock
+ //
+ OutByte (AdapterInfo, (UINT8) (Tmp &~EE_SHIFT_CLK), EEAddr);
+ eeprom_delay (150);
+ Tmp = InByte (AdapterInfo, EEAddr);
+ AddrLen++;
+ }
+
+ //
+ // read the eeprom word, even though we don't need this
+ //
+ shift_bits_in (AdapterInfo);
+
+ //
+ // Terminate the EEPROM access.
+ //
+ Tmp = InByte (AdapterInfo, EEAddr);
+ Tmp &= ~(EE_CS | EE_DI);
+ OutByte (AdapterInfo, Tmp, EEAddr);
+
+ //
+ // raise the clock and lower the eeprom shift clock
+ //
+ OutByte (AdapterInfo, (UINT8) (Tmp | EE_SHIFT_CLK), EEAddr);
+ eeprom_delay (100);
+
+ OutByte (AdapterInfo, (UINT8) (Tmp &~EE_SHIFT_CLK), EEAddr);
+ eeprom_delay (100);
+
+ //
+ // giveup access to the eeprom!
+ //
+ E100bReSetEepromLockOut (AdapterInfo);
+
+ return AddrLen;
+}
+
+UINTN
+E100bStatistics (
+ NIC_DATA_INSTANCE *AdapterInfo,
+ UINT64 DBaddr,
+ UINT16 DBsize
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AdapterInfo - TODO: add argument description
+ DBaddr - TODO: add argument description
+ DBsize - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ PXE_DB_STATISTICS db;
+ //
+ // wait upto one second (each wait is 100 micro s)
+ //
+ UINT32 Wait;
+ Wait = 10000;
+ wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd);
+
+ //
+ // Clear statistics done marker.
+ //
+ AdapterInfo->statistics->done_marker = 0;
+
+ //
+ // Issue statistics dump (or dump w/ reset) command.
+ //
+ OutByte (
+ AdapterInfo,
+ (UINT8) (DBsize ? CU_SHOWSTATS : CU_DUMPSTATS),
+ (UINT32) (AdapterInfo->ioaddr + SCBCmd)
+ );
+
+ //
+ // Wait for command to complete.
+ //
+ // zero the db here just to chew up a little more time.
+ //
+
+ ZeroMem ((VOID *) &db, sizeof db);
+
+ while (Wait != 0) {
+ //
+ // Wait a bit before checking.
+ //
+
+ DelayIt (AdapterInfo, 100);
+
+ //
+ // Look for done marker at end of statistics.
+ //
+
+ switch (AdapterInfo->statistics->done_marker) {
+ case 0xA005:
+ case 0xA007:
+ break;
+
+ default:
+ Wait--;
+ continue;
+ }
+
+ //
+ // if we did not "continue" from the above switch, we are done,
+ //
+ break;
+ }
+
+ //
+ // If this is a reset, we are out of here!
+ //
+ if (DBsize == 0) {
+ return PXE_STATCODE_SUCCESS;
+ }
+
+ //
+ // Convert NIC statistics counter format to EFI/UNDI
+ // specification statistics counter format.
+ //
+
+ //
+ // 54 3210 fedc ba98 7654 3210
+ // db.Supported = 01 0000 0100 1101 0001 0111;
+ //
+ db.Supported = 0x104D17;
+
+ //
+ // Statistics from the NIC
+ //
+
+ db.Data[0x01] = AdapterInfo->statistics->rx_good_frames;
+
+ db.Data[0x02] = AdapterInfo->statistics->rx_runt_errs;
+
+ db.Data[0x08] = AdapterInfo->statistics->rx_crc_errs +
+ AdapterInfo->statistics->rx_align_errs;
+
+ db.Data[0x04] = db.Data[0x02] +
+ db.Data[0x08] +
+ AdapterInfo->statistics->rx_resource_errs +
+ AdapterInfo->statistics->rx_overrun_errs;
+
+ db.Data[0x00] = db.Data[0x01] + db.Data[0x04];
+
+ db.Data[0x0B] = AdapterInfo->statistics->tx_good_frames;
+
+ db.Data[0x0E] = AdapterInfo->statistics->tx_coll16_errs +
+ AdapterInfo->statistics->tx_late_colls +
+ AdapterInfo->statistics->tx_underruns +
+ AdapterInfo->statistics->tx_one_colls +
+ AdapterInfo->statistics->tx_multi_colls;
+
+ db.Data[0x14] = AdapterInfo->statistics->tx_total_colls;
+
+ db.Data[0x0A] = db.Data[0x0B] +
+ db.Data[0x0E] +
+ AdapterInfo->statistics->tx_lost_carrier;
+
+ if (DBsize > sizeof db) {
+ DBsize = sizeof db;
+ }
+
+ CopyMem ((VOID *) (UINTN) DBaddr, (VOID *) &db, (UINTN) DBsize);
+
+ return PXE_STATCODE_SUCCESS;
+}
+
+UINTN
+E100bReset (
+ IN NIC_DATA_INSTANCE *AdapterInfo,
+ IN INT32 OpFlags
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AdapterInfo - TODO: add argument description
+ OpFlags - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+
+ UINT16 save_filter;
+ //
+ // disable the interrupts
+ //
+ OutWord (AdapterInfo, INT_MASK, AdapterInfo->ioaddr + SCBCmd);
+
+ //
+ // wait for the tx queue to complete
+ //
+ CheckCBList (AdapterInfo);
+
+ XmitWaitForCompletion (AdapterInfo);
+
+ if (AdapterInfo->Receive_Started) {
+ StopRU (AdapterInfo);
+ }
+
+ InitializeChip (AdapterInfo);
+
+ //
+ // check the opflags and restart receive filters
+ //
+ if ((OpFlags & PXE_OPFLAGS_RESET_DISABLE_FILTERS) == 0) {
+
+ save_filter = AdapterInfo->Rx_Filter;
+ //
+ // if we give the filter same as Rx_Filter,
+ // this routine will not set mcast list (it thinks there is no change)
+ // to force it, we will reset that flag in the Rx_Filter
+ //
+ AdapterInfo->Rx_Filter &= (~PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST);
+ E100bSetfilter (AdapterInfo, save_filter, (UINT64) 0, (UINT32) 0);
+ }
+
+ if ((OpFlags & PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS) != 0) {
+ //
+ // disable the interrupts
+ //
+ AdapterInfo->int_mask = 0;
+ }
+ //
+ // else leave the interrupt in the pre-set state!!!
+ //
+ E100bSetInterruptState (AdapterInfo);
+
+ return 0;
+}
+
+UINTN
+E100bShutdown (
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AdapterInfo - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ //
+ // disable the interrupts
+ //
+ OutWord (AdapterInfo, INT_MASK, AdapterInfo->ioaddr + SCBCmd);
+
+ //
+ // stop the receive unit
+ //
+ if (AdapterInfo->Receive_Started) {
+ StopRU (AdapterInfo);
+ }
+
+ //
+ // wait for the tx queue to complete
+ //
+ CheckCBList (AdapterInfo);
+ if (AdapterInfo->FreeCBCount != AdapterInfo->TxBufCnt) {
+ wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd);
+ }
+
+ //
+ // we do not want to reset the phy, it takes a long time to renegotiate the
+ // link after that (3-4 seconds)
+ //
+ InitializeChip (AdapterInfo);
+ SelectiveReset (AdapterInfo);
+ return 0;
+}
+
+VOID
+MdiWrite (
+ IN NIC_DATA_INSTANCE *AdapterInfo,
+ IN UINT8 RegAddress,
+ IN UINT8 PhyAddress,
+ IN UINT16 DataValue
+ )
+/*++
+
+Routine Description:
+ This routine will write a value to the specified MII register
+ of an external MDI compliant device (e.g. PHY 100). The command will
+ execute in polled mode.
+
+Arguments:
+ AdapterInfo - pointer to the structure that contains the NIC's context.
+ RegAddress - The MII register that we are writing to
+ PhyAddress - The MDI address of the Phy component.
+ DataValue - The value that we are writing to the MII register.
+
+Returns:
+ nothing
+--*/
+{
+ UINT32 WriteCommand;
+
+ WriteCommand = ((UINT32) DataValue) |
+ ((UINT32)(RegAddress << 16)) |
+ ((UINT32)(PhyAddress << 21)) |
+ ((UINT32)(MDI_WRITE << 26));
+
+ //
+ // Issue the write command to the MDI control register.
+ //
+ OutLong (AdapterInfo, WriteCommand, AdapterInfo->ioaddr + SCBCtrlMDI);
+
+ //
+ // wait 20usec before checking status
+ //
+ DelayIt (AdapterInfo, 20);
+
+ //
+ // poll for the mdi write to complete
+ while ((InLong (AdapterInfo, AdapterInfo->ioaddr + SCBCtrlMDI) &
+ MDI_PHY_READY) == 0){
+ DelayIt (AdapterInfo, 20);
+ }
+}
+
+VOID
+MdiRead (
+ IN NIC_DATA_INSTANCE *AdapterInfo,
+ IN UINT8 RegAddress,
+ IN UINT8 PhyAddress,
+ IN OUT UINT16 *DataValue
+ )
+/*++
+
+Routine Description:
+ This routine will read a value from the specified MII register
+ of an external MDI compliant device (e.g. PHY 100), and return
+ it to the calling routine. The command will execute in polled mode.
+
+Arguments:
+ AdapterInfo - pointer to the structure that contains the NIC's context.
+ RegAddress - The MII register that we are reading from
+ PhyAddress - The MDI address of the Phy component.
+ DataValue - pointer to the value that we read from the MII register.
+
+Returns:
+
+--*/
+{
+ UINT32 ReadCommand;
+
+ ReadCommand = ((UINT32) (RegAddress << 16)) |
+ ((UINT32) (PhyAddress << 21)) |
+ ((UINT32) (MDI_READ << 26));
+
+ //
+ // Issue the read command to the MDI control register.
+ //
+ OutLong (AdapterInfo, ReadCommand, AdapterInfo->ioaddr + SCBCtrlMDI);
+
+ //
+ // wait 20usec before checking status
+ //
+ DelayIt (AdapterInfo, 20);
+
+ //
+ // poll for the mdi read to complete
+ //
+ while ((InLong (AdapterInfo, AdapterInfo->ioaddr + SCBCtrlMDI) &
+ MDI_PHY_READY) == 0) {
+ DelayIt (AdapterInfo, 20);
+
+ }
+
+ *DataValue = InWord (AdapterInfo, AdapterInfo->ioaddr + SCBCtrlMDI);
+}
+
+VOID
+PhyReset (
+ NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+ This routine will reset the PHY that the adapter is currently
+ configured to use.
+
+Arguments:
+ AdapterInfo - pointer to the structure that contains the NIC's context.
+
+Returns:
+
+--*/
+{
+ UINT16 MdiControlReg;
+
+ MdiControlReg = (MDI_CR_AUTO_SELECT |
+ MDI_CR_RESTART_AUTO_NEG |
+ MDI_CR_RESET);
+
+ //
+ // Write the MDI control register with our new Phy configuration
+ //
+ MdiWrite (
+ AdapterInfo,
+ MDI_CONTROL_REG,
+ AdapterInfo->PhyAddress,
+ MdiControlReg
+ );
+
+ return ;
+}
+
+BOOLEAN
+PhyDetect (
+ NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+ This routine will detect what phy we are using, set the line
+ speed, FDX or HDX, and configure the phy if necessary.
+
+ The following combinations are supported:
+ - TX or T4 PHY alone at PHY address 1
+ - T4 or TX PHY at address 1 and MII PHY at address 0
+ - 82503 alone (10Base-T mode, no full duplex support)
+ - 82503 and MII PHY (TX or T4) at address 0
+
+ The sequence / priority of detection is as follows:
+ - PHY 1 with cable termination
+ - PHY 0 with cable termination
+ - PHY 1 (if found) without cable termination
+ - 503 interface
+
+ Additionally auto-negotiation capable (NWAY) and parallel
+ detection PHYs are supported. The flow-chart is described in
+ the 82557 software writer's manual.
+
+ NOTE: 1. All PHY MDI registers are read in polled mode.
+ 2. The routines assume that the 82557 has been RESET and we have
+ obtained the virtual memory address of the CSR.
+ 3. PhyDetect will not RESET the PHY.
+ 4. If FORCEFDX is set, SPEED should also be set. The driver will
+ check the values for inconsistency with the detected PHY
+ technology.
+ 5. PHY 1 (the PHY on the adapter) may have an address in the range
+ 1 through 31 inclusive. The driver will accept addresses in
+ this range.
+ 6. Driver ignores FORCEFDX and SPEED overrides if a 503 interface
+ is detected.
+
+Arguments:
+ AdapterInfo - pointer to the structure that contains the NIC's context.
+
+Returns:
+ TRUE - If a Phy was detected, and configured correctly.
+ FALSE - If a valid phy could not be detected and configured.
+
+--*/
+{
+ UINT16 *eedata;
+ UINT16 MdiControlReg;
+ UINT16 MdiStatusReg;
+ BOOLEAN FoundPhy1;
+ UINT8 ReNegotiateTime;
+
+ eedata = (UINT16 *) (&AdapterInfo->NVData[0]);
+
+ FoundPhy1 = FALSE;
+ ReNegotiateTime = 35;
+ //
+ // EEPROM word [6] contains the Primary PHY record in which the least 3 bits
+ // indicate the PHY address
+ // and word [7] contains the secondary PHY record
+ //
+ AdapterInfo->PhyRecord[0] = eedata[6];
+ AdapterInfo->PhyRecord[1] = eedata[7];
+ AdapterInfo->PhyAddress = (UINT8) (AdapterInfo->PhyRecord[0] & 7);
+
+ //
+ // Check for a phy address over-ride of 32 which indicates force use of 82503
+ // not detecting the link in this case
+ //
+ if (AdapterInfo->PhyAddress == 32) {
+ //
+ // 503 interface over-ride
+ // Record the current speed and duplex. We will be in half duplex
+ // mode unless the user used the force full duplex over-ride.
+ //
+ AdapterInfo->LinkSpeed = 10;
+ return (TRUE);
+ }
+
+ //
+ // If the Phy Address is between 1-31 then we must first look for phy 1,
+ // at that address.
+ //
+ if ((AdapterInfo->PhyAddress > 0) && (AdapterInfo->PhyAddress < 32)) {
+
+ //
+ // Read the MDI control and status registers at phy 1
+ // and check if we found a valid phy
+ //
+ MdiRead (
+ AdapterInfo,
+ MDI_CONTROL_REG,
+ AdapterInfo->PhyAddress,
+ &MdiControlReg
+ );
+
+ MdiRead (
+ AdapterInfo,
+ MDI_STATUS_REG,
+ AdapterInfo->PhyAddress,
+ &MdiStatusReg
+ );
+
+ if (!((MdiControlReg == 0xffff) ||
+ ((MdiStatusReg == 0) && (MdiControlReg == 0)))) {
+
+ //
+ // we have a valid phy1
+ // Read the status register again because of sticky bits
+ //
+ FoundPhy1 = TRUE;
+ MdiRead (
+ AdapterInfo,
+ MDI_STATUS_REG,
+ AdapterInfo->PhyAddress,
+ &MdiStatusReg
+ );
+
+ //
+ // If there is a valid link then use this Phy.
+ //
+ if (MdiStatusReg & MDI_SR_LINK_STATUS) {
+ return (SetupPhy(AdapterInfo));
+ }
+ }
+ }
+
+ //
+ // Next try to detect a PHY at address 0x00 because there was no Phy 1,
+ // or Phy 1 didn't have link, or we had a phy 0 over-ride
+ //
+
+ //
+ // Read the MDI control and status registers at phy 0
+ //
+ MdiRead (AdapterInfo, MDI_CONTROL_REG, 0, &MdiControlReg);
+ MdiRead (AdapterInfo, MDI_STATUS_REG, 0, &MdiStatusReg);
+
+ //
+ // check if we found a valid phy 0
+ //
+ if (((MdiControlReg == 0xffff) ||
+ ((MdiStatusReg == 0) && (MdiControlReg == 0)))) {
+
+ //
+ // we don't have a valid phy at address 0
+ // if phy address was forced to 0, then error out because we
+ // didn't find a phy at that address
+ //
+ if (AdapterInfo->PhyAddress == 0x0000) {
+ return (FALSE);
+ } else {
+ //
+ // at this point phy1 does not have link and there is no phy 0 at all
+ // if we are forced to detect the cable, error out here!
+ //
+ if (AdapterInfo->CableDetect != 0) {
+ return FALSE;
+
+ }
+
+ if (FoundPhy1) {
+ //
+ // no phy 0, but there is a phy 1 (no link I guess), so use phy 1
+ //
+ return SetupPhy (AdapterInfo);
+ } else {
+ //
+ // didn't find phy 0 or phy 1, so assume a 503 interface
+ //
+ AdapterInfo->PhyAddress = 32;
+
+ //
+ // Record the current speed and duplex. We'll be in half duplex
+ // mode unless the user used the force full duplex over-ride.
+ //
+ AdapterInfo->LinkSpeed = 10;
+ return (TRUE);
+ }
+ }
+ } else {
+ //
+ // We have a valid phy at address 0. If phy 0 has a link then we use
+ // phy 0. If Phy 0 doesn't have a link then we use Phy 1 (no link)
+ // if phy 1 is present, or phy 0 if phy 1 is not present
+ // If phy 1 was present, then we must isolate phy 1 before we enable
+ // phy 0 to see if Phy 0 has a link.
+ //
+ if (FoundPhy1) {
+ //
+ // isolate phy 1
+ //
+ MdiWrite (
+ AdapterInfo,
+ MDI_CONTROL_REG,
+ AdapterInfo->PhyAddress,
+ MDI_CR_ISOLATE
+ );
+
+ //
+ // wait 100 microseconds for the phy to isolate.
+ //
+ DelayIt (AdapterInfo, 100);
+ }
+
+ //
+ // Since this Phy is at address 0, we must enable it. So clear
+ // the isolate bit, and set the auto-speed select bit
+ //
+ MdiWrite (
+ AdapterInfo,
+ MDI_CONTROL_REG,
+ 0,
+ MDI_CR_AUTO_SELECT
+ );
+
+ //
+ // wait 100 microseconds for the phy to be enabled.
+ //
+ DelayIt (AdapterInfo, 100);
+
+ //
+ // restart the auto-negotion process
+ //
+ MdiWrite (
+ AdapterInfo,
+ MDI_CONTROL_REG,
+ 0,
+ MDI_CR_RESTART_AUTO_NEG | MDI_CR_AUTO_SELECT
+ );
+
+ //
+ // wait no more than 3.5 seconds for auto-negotiation to complete
+ //
+ while (ReNegotiateTime) {
+ //
+ // Read the status register twice because of sticky bits
+ //
+ MdiRead (AdapterInfo, MDI_STATUS_REG, 0, &MdiStatusReg);
+ MdiRead (AdapterInfo, MDI_STATUS_REG, 0, &MdiStatusReg);
+
+ if (MdiStatusReg & MDI_SR_AUTO_NEG_COMPLETE) {
+ break;
+ }
+
+ DelayIt (AdapterInfo, 100);
+ ReNegotiateTime--;
+ }
+
+ //
+ // Read the status register again because of sticky bits
+ //
+ MdiRead (AdapterInfo, MDI_STATUS_REG, 0, &MdiStatusReg);
+
+ //
+ // If the link was not set
+ //
+ if ((MdiStatusReg & MDI_SR_LINK_STATUS) == 0) {
+ //
+ // PHY1 does not have a link and phy 0 does not have a link
+ // do not proceed if we need to detect the link!
+ //
+ if (AdapterInfo->CableDetect != 0) {
+ return FALSE;
+ }
+
+ //
+ // the link wasn't set, so use phy 1 if phy 1 was present
+ //
+ if (FoundPhy1) {
+ //
+ // isolate phy 0
+ //
+ MdiWrite (AdapterInfo, MDI_CONTROL_REG, 0, MDI_CR_ISOLATE);
+
+ //
+ // wait 100 microseconds for the phy to isolate.
+ //
+ DelayIt (AdapterInfo, 100);
+
+ //
+ // Now re-enable PHY 1
+ //
+ MdiWrite (
+ AdapterInfo,
+ MDI_CONTROL_REG,
+ AdapterInfo->PhyAddress,
+ MDI_CR_AUTO_SELECT
+ );
+
+ //
+ // wait 100 microseconds for the phy to be enabled
+ //
+ DelayIt (AdapterInfo, 100);
+
+ //
+ // restart the auto-negotion process
+ //
+ MdiWrite (
+ AdapterInfo,
+ MDI_CONTROL_REG,
+ AdapterInfo->PhyAddress,
+ MDI_CR_RESTART_AUTO_NEG | MDI_CR_AUTO_SELECT
+ );
+
+ //
+ // Don't wait for it to complete (we didn't have link earlier)
+ //
+ return (SetupPhy (AdapterInfo));
+ }
+ }
+
+ //
+ // Definitely using Phy 0
+ //
+ AdapterInfo->PhyAddress = 0;
+ return (SetupPhy(AdapterInfo));
+ }
+}
+
+BOOLEAN
+SetupPhy (
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+ This routine will setup phy 1 or phy 0 so that it is configured
+ to match a speed and duplex over-ride option. If speed or
+ duplex mode is not explicitly specified in the registry, the
+ driver will skip the speed and duplex over-ride code, and
+ assume the adapter is automatically setting the line speed, and
+ the duplex mode. At the end of this routine, any truly Phy
+ specific code will be executed (each Phy has its own quirks,
+ and some require that certain special bits are set).
+
+ NOTE: The driver assumes that SPEED and FORCEFDX are specified at the
+ same time. If FORCEDPX is set without speed being set, the driver
+ will encouter a fatal error and log a message into the event viewer.
+
+Arguments:
+ AdapterInfo - pointer to the structure that contains the NIC's context.
+
+Returns:
+ TRUE - If the phy could be configured correctly
+ FALSE - If the phy couldn't be configured correctly, because an
+ unsupported over-ride option was used
+
+--*/
+{
+ UINT16 MdiControlReg;
+ UINT16 MdiStatusReg;
+ UINT16 MdiIdLowReg;
+ UINT16 MdiIdHighReg;
+ UINT16 MdiMiscReg;
+ UINT32 PhyId;
+ BOOLEAN ForcePhySetting;
+
+ ForcePhySetting = FALSE;
+
+ //
+ // If we are NOT forcing a setting for line speed or full duplex, then
+ // we won't force a link setting, and we'll jump down to the phy
+ // specific code.
+ //
+ if (((AdapterInfo->LinkSpeedReq) || (AdapterInfo->DuplexReq))) {
+ //
+ // Find out what kind of technology this Phy is capable of.
+ //
+ MdiRead (
+ AdapterInfo,
+ MDI_STATUS_REG,
+ AdapterInfo->PhyAddress,
+ &MdiStatusReg
+ );
+
+ //
+ // Read the MDI control register at our phy
+ //
+ MdiRead (
+ AdapterInfo,
+ MDI_CONTROL_REG,
+ AdapterInfo->PhyAddress,
+ &MdiControlReg
+ );
+
+ //
+ // Now check the validity of our forced option. If the force option is
+ // valid, then force the setting. If the force option is not valid,
+ // we'll set a flag indicating that we should error out.
+ //
+
+ //
+ // If speed is forced to 10mb
+ //
+ if (AdapterInfo->LinkSpeedReq == 10) {
+ //
+ // If half duplex is forced
+ //
+ if ((AdapterInfo->DuplexReq & PXE_FORCE_HALF_DUPLEX) != 0) {
+ if (MdiStatusReg & MDI_SR_10T_HALF_DPX) {
+
+ MdiControlReg &= ~(MDI_CR_10_100 | MDI_CR_AUTO_SELECT | MDI_CR_FULL_HALF);
+ ForcePhySetting = TRUE;
+ }
+ } else if ((AdapterInfo->DuplexReq & PXE_FORCE_FULL_DUPLEX) != 0) {
+
+ //
+ // If full duplex is forced
+ //
+ if (MdiStatusReg & MDI_SR_10T_FULL_DPX) {
+
+ MdiControlReg &= ~(MDI_CR_10_100 | MDI_CR_AUTO_SELECT);
+ MdiControlReg |= MDI_CR_FULL_HALF;
+ ForcePhySetting = TRUE;
+ }
+ } else {
+ //
+ // If auto duplex (we actually set phy to 1/2)
+ //
+ if (MdiStatusReg & (MDI_SR_10T_FULL_DPX | MDI_SR_10T_HALF_DPX)) {
+
+ MdiControlReg &= ~(MDI_CR_10_100 | MDI_CR_AUTO_SELECT | MDI_CR_FULL_HALF);
+ ForcePhySetting = TRUE;
+ }
+ }
+ }
+
+ //
+ // If speed is forced to 100mb
+ //
+ else if (AdapterInfo->LinkSpeedReq == 100) {
+ //
+ // If half duplex is forced
+ //
+ if ((AdapterInfo->DuplexReq & PXE_FORCE_HALF_DUPLEX) != 0) {
+ if (MdiStatusReg & (MDI_SR_TX_HALF_DPX | MDI_SR_T4_CAPABLE)) {
+
+ MdiControlReg &= ~(MDI_CR_AUTO_SELECT | MDI_CR_FULL_HALF);
+ MdiControlReg |= MDI_CR_10_100;
+ ForcePhySetting = TRUE;
+ }
+ } else if ((AdapterInfo->DuplexReq & PXE_FORCE_FULL_DUPLEX) != 0) {
+ //
+ // If full duplex is forced
+ //
+ if (MdiStatusReg & MDI_SR_TX_FULL_DPX) {
+ MdiControlReg &= ~MDI_CR_AUTO_SELECT;
+ MdiControlReg |= (MDI_CR_10_100 | MDI_CR_FULL_HALF);
+ ForcePhySetting = TRUE;
+ }
+ } else {
+ //
+ // If auto duplex (we set phy to 1/2)
+ //
+ if (MdiStatusReg & (MDI_SR_TX_HALF_DPX | MDI_SR_T4_CAPABLE)) {
+
+ MdiControlReg &= ~(MDI_CR_AUTO_SELECT | MDI_CR_FULL_HALF);
+ MdiControlReg |= MDI_CR_10_100;
+ ForcePhySetting = TRUE;
+ }
+ }
+ }
+
+ if (!ForcePhySetting) {
+ return (FALSE);
+ }
+
+ //
+ // Write the MDI control register with our new Phy configuration
+ //
+ MdiWrite (
+ AdapterInfo,
+ MDI_CONTROL_REG,
+ AdapterInfo->PhyAddress,
+ MdiControlReg
+ );
+
+ //
+ // wait 100 milliseconds for auto-negotiation to complete
+ //
+ DelayIt (AdapterInfo, 100);
+ }
+
+ //
+ // Find out specifically what Phy this is. We do this because for certain
+ // phys there are specific bits that must be set so that the phy and the
+ // 82557 work together properly.
+ //
+
+ MdiRead (
+ AdapterInfo,
+ PHY_ID_REG_1,
+ AdapterInfo->PhyAddress,
+ &MdiIdLowReg
+ );
+ MdiRead (
+ AdapterInfo,
+ PHY_ID_REG_2,
+ AdapterInfo->PhyAddress,
+ &MdiIdHighReg
+ );
+
+ PhyId = ((UINT32) MdiIdLowReg | ((UINT32) MdiIdHighReg << 16));
+
+ //
+ // And out the revsion field of the Phy ID so that we'll be able to detect
+ // future revs of the same Phy.
+ //
+ PhyId &= PHY_MODEL_REV_ID_MASK;
+
+ //
+ // Handle the National TX
+ //
+ if (PhyId == PHY_NSC_TX) {
+
+ MdiRead (
+ AdapterInfo,
+ NSC_CONG_CONTROL_REG,
+ AdapterInfo->PhyAddress,
+ &MdiMiscReg
+ );
+
+ MdiMiscReg |= (NSC_TX_CONG_TXREADY | NSC_TX_CONG_F_CONNECT);
+
+#if CONGESTION_CONTROL
+ //
+ // If we are configured to do congestion control, then enable the
+ // congestion control bit in the National Phy
+ //
+ if (AdapterInfo->Congest) {
+ MdiMiscReg |= NSC_TX_CONG_ENABLE;
+ } else {
+ MdiMiscReg &= ~NSC_TX_CONG_ENABLE;
+ }
+#endif
+ MdiWrite (
+ AdapterInfo,
+ NSC_CONG_CONTROL_REG,
+ AdapterInfo->PhyAddress,
+ MdiMiscReg
+ );
+ }
+
+ FindPhySpeedAndDpx (AdapterInfo, PhyId);
+
+ //
+ // We put a hardware fix on to our adapters to work-around the PHY_100 errata
+ // described below. The following code is only compiled in, if we wanted
+ // to attempt a software workaround to the PHY_100 A/B step problem.
+ //
+
+#if DO_PHY_100B_SOFTWARE_FIX
+ //
+ // Handle the Intel PHY_100 (A and B steps)
+ //
+ if ((PhyId == PHY_100_A) && (AdapterInfo->LinkSpeed == 100)) {
+ //
+ // The PHY_100 is very sensitive to collisions at 100mb, so increase
+ // the Adaptive IFS value with the intention of reducing the number of
+ // collisions that the adapter generates.
+ //
+ AdapterInfo->CurrentIFSValue = 0x18;
+ AdapterInfo->AdaptiveIFS = 0;
+ }
+#endif
+
+ return (TRUE);
+}
+
+VOID
+FindPhySpeedAndDpx (
+ IN NIC_DATA_INSTANCE *AdapterInfo,
+ IN UINT32 PhyId
+ )
+/*++
+
+Routine Description:
+ This routine will figure out what line speed and duplex mode
+ the PHY is currently using.
+
+Arguments:
+ AdapterInfo - pointer to the structure that contains the NIC's context.
+ PhyId - The ID of the PHY in question.
+
+Returns:
+ NOTHING
+--*/
+{
+ UINT16 MdiStatusReg;
+ UINT16 MdiMiscReg;
+ UINT16 MdiOwnAdReg;
+ UINT16 MdiLinkPartnerAdReg;
+
+ //
+ // If there was a speed and/or duplex override, then set our current
+ // value accordingly
+ //
+ AdapterInfo->LinkSpeed = AdapterInfo->LinkSpeedReq;
+ AdapterInfo->Duplex = (UINT8) ((AdapterInfo->DuplexReq & PXE_FORCE_FULL_DUPLEX) ?
+ FULL_DUPLEX : HALF_DUPLEX);
+
+ //
+ // If speed and duplex were forced, then we know our current settings, so
+ // we'll just return. Otherwise, we'll need to figure out what NWAY set
+ // us to.
+ //
+ if (AdapterInfo->LinkSpeed && AdapterInfo->Duplex) {
+ return ;
+
+ }
+ //
+ // If we didn't have a valid link, then we'll assume that our current
+ // speed is 10mb half-duplex.
+ //
+
+ //
+ // Read the status register twice because of sticky bits
+ //
+ MdiRead (
+ AdapterInfo,
+ MDI_STATUS_REG,
+ AdapterInfo->PhyAddress,
+ &MdiStatusReg
+ );
+ MdiRead (
+ AdapterInfo,
+ MDI_STATUS_REG,
+ AdapterInfo->PhyAddress,
+ &MdiStatusReg
+ );
+
+ //
+ // If there wasn't a valid link then use default speed & duplex
+ //
+ if (!(MdiStatusReg & MDI_SR_LINK_STATUS)) {
+
+ AdapterInfo->LinkSpeed = 10;
+ AdapterInfo->Duplex = HALF_DUPLEX;
+ return ;
+ }
+
+ //
+ // If this is an Intel PHY (a T4 PHY_100 or a TX PHY_TX), then read bits
+ // 1 and 0 of extended register 0, to get the current speed and duplex
+ // settings.
+ //
+ if ((PhyId == PHY_100_A) || (PhyId == PHY_100_C) || (PhyId == PHY_TX_ID)) {
+ //
+ // Read extended register 0
+ //
+ MdiRead (
+ AdapterInfo,
+ EXTENDED_REG_0,
+ AdapterInfo->PhyAddress,
+ &MdiMiscReg
+ );
+
+ //
+ // Get current speed setting
+ //
+ if (MdiMiscReg & PHY_100_ER0_SPEED_INDIC) {
+ AdapterInfo->LinkSpeed = 100;
+ } else {
+ AdapterInfo->LinkSpeed = 10;
+ }
+
+ //
+ // Get current duplex setting -- if bit is set then FDX is enabled
+ //
+ if (MdiMiscReg & PHY_100_ER0_FDX_INDIC) {
+ AdapterInfo->Duplex = FULL_DUPLEX;
+ } else {
+ AdapterInfo->Duplex = HALF_DUPLEX;
+ }
+
+ return ;
+ }
+ //
+ // Read our link partner's advertisement register
+ //
+ MdiRead (
+ AdapterInfo,
+ AUTO_NEG_LINK_PARTNER_REG,
+ AdapterInfo->PhyAddress,
+ &MdiLinkPartnerAdReg
+ );
+
+ //
+ // See if Auto-Negotiation was complete (bit 5, reg 1)
+ //
+ MdiRead (
+ AdapterInfo,
+ MDI_STATUS_REG,
+ AdapterInfo->PhyAddress,
+ &MdiStatusReg
+ );
+
+ //
+ // If a True NWAY connection was made, then we can detect speed/duplex by
+ // ANDing our adapter's advertised abilities with our link partner's
+ // advertised ablilities, and then assuming that the highest common
+ // denominator was chosed by NWAY.
+ //
+ if ((MdiLinkPartnerAdReg & NWAY_LP_ABILITY) &&
+ (MdiStatusReg & MDI_SR_AUTO_NEG_COMPLETE)) {
+
+ //
+ // Read our advertisement register
+ //
+ MdiRead (
+ AdapterInfo,
+ AUTO_NEG_ADVERTISE_REG,
+ AdapterInfo->PhyAddress,
+ &MdiOwnAdReg
+ );
+
+ //
+ // AND the two advertisement registers together, and get rid of any
+ // extraneous bits.
+ //
+ MdiOwnAdReg &= (MdiLinkPartnerAdReg & NWAY_LP_ABILITY);
+
+ //
+ // Get speed setting
+ //
+ if (MdiOwnAdReg & (NWAY_AD_TX_HALF_DPX | NWAY_AD_TX_FULL_DPX | NWAY_AD_T4_CAPABLE)) {
+ AdapterInfo->LinkSpeed = 100;
+ } else {
+ AdapterInfo->LinkSpeed = 10;
+ }
+
+ //
+ // Get duplex setting -- use priority resolution algorithm
+ //
+ if (MdiOwnAdReg & (NWAY_AD_T4_CAPABLE)) {
+ AdapterInfo->Duplex = HALF_DUPLEX;
+ return ;
+ } else if (MdiOwnAdReg & (NWAY_AD_TX_FULL_DPX)) {
+ AdapterInfo->Duplex = FULL_DUPLEX;
+ return ;
+ } else if (MdiOwnAdReg & (NWAY_AD_TX_HALF_DPX)) {
+ AdapterInfo->Duplex = HALF_DUPLEX;
+ return ;
+ } else if (MdiOwnAdReg & (NWAY_AD_10T_FULL_DPX)) {
+ AdapterInfo->Duplex = FULL_DUPLEX;
+ return ;
+ } else {
+ AdapterInfo->Duplex = HALF_DUPLEX;
+ return ;
+ }
+ }
+
+ //
+ // If we are connected to a dumb (non-NWAY) repeater or hub, and the line
+ // speed was determined automatically by parallel detection, then we have
+ // no way of knowing exactly what speed the PHY is set to unless that PHY
+ // has a propietary register which indicates speed in this situation. The
+ // NSC TX PHY does have such a register. Also, since NWAY didn't establish
+ // the connection, the duplex setting should HALF duplex.
+ //
+ AdapterInfo->Duplex = HALF_DUPLEX;
+
+ if (PhyId == PHY_NSC_TX) {
+ //
+ // Read register 25 to get the SPEED_10 bit
+ //
+ MdiRead (
+ AdapterInfo,
+ NSC_SPEED_IND_REG,
+ AdapterInfo->PhyAddress,
+ &MdiMiscReg
+ );
+
+ //
+ // If bit 6 was set then we're at 10mb
+ //
+ if (MdiMiscReg & NSC_TX_SPD_INDC_SPEED) {
+ AdapterInfo->LinkSpeed = 10;
+ } else {
+ AdapterInfo->LinkSpeed = 100;
+ }
+ }
+
+ //
+ // If we don't know what line speed we are set at, then we'll default to
+ // 10mbs
+ //
+ else {
+ AdapterInfo->LinkSpeed = 10;
+ }
+}
+
+VOID
+XmitWaitForCompletion (
+ NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AdapterInfo - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ TxCB *TxPtr;
+
+ if (AdapterInfo->FreeCBCount == AdapterInfo->TxBufCnt) {
+ return ;
+ }
+
+ //
+ // used xmit cb list starts right after the free tail (ends before the
+ // free head ptr)
+ //
+ TxPtr = AdapterInfo->FreeTxTailPtr->NextTCBVirtualLinkPtr;
+ while (TxPtr != AdapterInfo->FreeTxHeadPtr) {
+ CommandWaitForCompletion (TxPtr, AdapterInfo);
+ SetFreeCB (AdapterInfo, TxPtr);
+ TxPtr = TxPtr->NextTCBVirtualLinkPtr;
+ }
+}
+
+INT8
+CommandWaitForCompletion (
+ TxCB *cmd_ptr,
+ NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ cmd_ptr - TODO: add argument description
+ AdapterInfo - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ INT16 wait;
+ wait = 5000;
+ while ((cmd_ptr->cb_header.status == 0) && (--wait > 0)) {
+ DelayIt (AdapterInfo, 10);
+ }
+
+ if (cmd_ptr->cb_header.status == 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+INT8
+SoftwareReset (
+ NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AdapterInfo - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ UINT8 tco_stat;
+ UINT16 wait;
+
+ tco_stat = 0;
+
+ //
+ // Reset the chip: stop Tx and Rx processes and clear counters.
+ // This takes less than 10usec and will easily finish before the next
+ // action.
+ //
+
+ OutLong (AdapterInfo, PORT_RESET, AdapterInfo->ioaddr + SCBPort);
+ //
+ // wait for 5 milli seconds here!
+ //
+ DelayIt (AdapterInfo, 5000);
+ //
+ // TCO Errata work around for 559s only
+ // -----------------------------------------------------------------------------------
+ // TCO Workaround Code
+ // haifa workaround
+ // -----------------------------------------------------------------------------------
+ // 1. Issue SW-RST ^^^ (already done above)
+ // 2. Issue a redundant Set CU Base CMD immediately
+ // Do not set the General Pointer before the Set CU Base cycle
+ // Do not check the SCB CMD before the Set CU Base cycle
+ // 3. Wait for the SCB-CMD to be cleared
+ // this indicates the transition to post-driver
+ // 4. Poll the TCO-Req bit in the PMDR to be cleared
+ // this indicates the tco activity has stopped for real
+ // 5. Proceed with the nominal Driver Init:
+ // Actual Set CU & RU Base ...
+ //
+ // Check for ICH2 device ID. If this is an ICH2,
+ // do the TCO workaround code.
+ //
+ if (AdapterInfo->VendorID == D102_DEVICE_ID ||
+ AdapterInfo->VendorID == ICH3_DEVICE_ID_1 ||
+ AdapterInfo->VendorID == ICH3_DEVICE_ID_2 ||
+ AdapterInfo->VendorID == ICH3_DEVICE_ID_3 ||
+ AdapterInfo->VendorID == ICH3_DEVICE_ID_4 ||
+ AdapterInfo->VendorID == ICH3_DEVICE_ID_5 ||
+ AdapterInfo->VendorID == ICH3_DEVICE_ID_6 ||
+ AdapterInfo->VendorID == ICH3_DEVICE_ID_7 ||
+ AdapterInfo->VendorID == ICH3_DEVICE_ID_8 ||
+ AdapterInfo->RevID >= 8) { // do the TCO fix
+ //
+ // donot load the scb pointer but just give load_cu cmd.
+ //
+ OutByte (AdapterInfo, CU_CMD_BASE, AdapterInfo->ioaddr + SCBCmd);
+ //
+ // wait for command to be accepted.
+ //
+ wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd);
+ //
+ // read PMDR register and check bit 1 in it to see if TCO is active
+ //
+
+ //
+ // wait for 5 milli seconds
+ //
+ wait = 5000;
+ while (wait) {
+ tco_stat = InByte (AdapterInfo, AdapterInfo->ioaddr + 0x1b);
+ if ((tco_stat & 2) == 0) {
+ //
+ // is the activity bit clear??
+ //
+ break;
+ }
+
+ wait--;
+ DelayIt (AdapterInfo, 1);
+ }
+
+ if ((tco_stat & 2) != 0) {
+ //
+ // not zero??
+ //
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+UINT8
+SelectiveReset (
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AdapterInfo - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ UINT16 wait;
+ UINT32 stat;
+
+ wait = 10;
+ stat = 0;
+ OutLong (AdapterInfo, POR_SELECTIVE_RESET, AdapterInfo->ioaddr + SCBPort);
+ //
+ // wait for this to complete
+ //
+
+ //
+ // wait for 2 milli seconds here!
+ //
+ DelayIt (AdapterInfo, 2000);
+ while (wait > 0) {
+ wait--;
+ stat = InLong (AdapterInfo, AdapterInfo->ioaddr + SCBPort);
+ if (stat == 0) {
+ break;
+ }
+
+ //
+ // wait for 1 milli second
+ //
+ DelayIt (AdapterInfo, 1000);
+ }
+
+ if (stat != 0) {
+ return PXE_STATCODE_DEVICE_FAILURE;
+ }
+
+ return 0;
+}
+
+UINT16
+InitializeChip (
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+
+ TODO: Add function description
+
+Arguments:
+
+ AdapterInfo - TODO: add argument description
+
+Returns:
+
+ TODO: add return values
+
+--*/
+{
+ UINT16 ret_val;
+ if (SoftwareReset (AdapterInfo) != 0) {
+ return PXE_STATCODE_DEVICE_FAILURE;
+ }
+
+ //
+ // disable interrupts
+ //
+ OutWord (AdapterInfo, INT_MASK, AdapterInfo->ioaddr + SCBCmd);
+
+ //
+ // Load the base registers with 0s (we will give the complete address as
+ // offset later when we issue any command
+ //
+ if ((ret_val = Load_Base_Regs (AdapterInfo)) != 0) {
+ return ret_val;
+ }
+
+ if ((ret_val = SetupCBlink (AdapterInfo)) != 0) {
+ return ret_val;
+ }
+
+ if ((ret_val = SetupReceiveQueues (AdapterInfo)) != 0) {
+ return ret_val;
+ }
+
+ //
+ // detect the PHY only if we need to detect the cable as requested by the
+ // initialize parameters
+ //
+ AdapterInfo->PhyAddress = 0xFF;
+
+ if (AdapterInfo->CableDetect != 0) {
+ if (!PhyDetect (AdapterInfo)) {
+ return PXE_STATCODE_DEVICE_FAILURE;
+ }
+ }
+
+ if ((ret_val = E100bSetupIAAddr (AdapterInfo)) != 0) {
+ return ret_val;
+ }
+
+ if ((ret_val = Configure (AdapterInfo)) != 0) {
+ return ret_val;
+ }
+
+ return 0;
+}
+
+#pragma data_seg()
diff --git a/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/E100b.h b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/E100b.h
new file mode 100644
index 0000000..3a4127c
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/E100b.h
@@ -0,0 +1,668 @@
+/*++
+
+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:
+
+ E100B.H
+
+Abstract:
+
+
+Revision History
+
+--*/
+// pci config offsets:
+
+#define RX_BUFFER_COUNT 32
+#define TX_BUFFER_COUNT 32
+
+#define PCI_VENDOR_ID_INTEL 0x8086
+#define PCI_DEVICE_ID_INTEL_82557 0x1229
+#define D100_VENDOR_ID 0x8086
+#define D100_DEVICE_ID 0x1229
+#define D102_DEVICE_ID 0x2449
+
+#define ICH3_DEVICE_ID_1 0x1031
+#define ICH3_DEVICE_ID_2 0x1032
+#define ICH3_DEVICE_ID_3 0x1033
+#define ICH3_DEVICE_ID_4 0x1034
+#define ICH3_DEVICE_ID_5 0x1035
+#define ICH3_DEVICE_ID_6 0x1036
+#define ICH3_DEVICE_ID_7 0x1037
+#define ICH3_DEVICE_ID_8 0x1038
+
+#define SPEEDO_DEVICE_ID 0x1227
+#define SPLASH1_DEVICE_ID 0x1226
+
+
+// bit fields for the command
+#define PCI_COMMAND_MASTER 0x04 // bit 2
+#define PCI_COMMAND_IO 0x01 // bit 0
+#define PCI_COMMAND 0x04
+#define PCI_LATENCY_TIMER 0x0D
+
+#define ETHER_MAC_ADDR_LEN 6
+#ifdef AVL_XXX
+#define ETHER_HEADER_LEN 14
+// media interface type
+// #define INTERFACE_TYPE "
+
+// Hardware type values
+#define HW_ETHER_TYPE 1
+#define HW_EXPERIMENTAL_ETHER_TYPE 2
+#define HW_IEEE_TYPE 6
+#define HW_ARCNET_TYPE 7
+
+#endif // AVL_XXX
+
+#define MAX_ETHERNET_PKT_SIZE 1514 // including eth header
+#define RX_BUFFER_SIZE 1536 // including crc and padding
+#define TX_BUFFER_SIZE 64
+#define ETH_MTU 1500 // does not include ethernet header length
+
+#define SPEEDO3_TOTAL_SIZE 0x20
+
+#pragma pack(1)
+
+typedef struct eth {
+ UINT8 dest_addr[PXE_HWADDR_LEN_ETHER];
+ UINT8 src_addr[PXE_HWADDR_LEN_ETHER];
+ UINT16 type;
+} EtherHeader;
+
+#pragma pack(1)
+typedef struct CONFIG_HEADER {
+ UINT16 VendorID;
+ UINT16 DeviceID;
+ UINT16 Command;
+ UINT16 Status;
+ UINT16 RevID;
+ UINT16 ClassID;
+ UINT8 CacheLineSize;
+ UINT8 LatencyTimer;
+ UINT8 HeaderType; // must be zero to impose this structure...
+ UINT8 BIST; // built-in self test
+ UINT32 BaseAddressReg_0; // memory mapped address
+ UINT32 BaseAddressReg_1; //io mapped address, Base IO address
+ UINT32 BaseAddressReg_2; // option rom address
+ UINT32 BaseAddressReg_3;
+ UINT32 BaseAddressReg_4;
+ UINT32 BaseAddressReg_5;
+ UINT32 CardBusCISPtr;
+ UINT16 SubVendorID;
+ UINT16 SubSystemID;
+ UINT32 ExpansionROMBaseAddr;
+ UINT8 CapabilitiesPtr;
+ UINT8 reserved1;
+ UINT16 Reserved2;
+ UINT32 Reserved3;
+ UINT8 int_line;
+ UINT8 int_pin;
+ UINT8 Min_gnt;
+ UINT8 Max_lat;
+} PCI_CONFIG_HEADER;
+#pragma pack()
+
+//-------------------------------------------------------------------------
+// Offsets to the various registers.
+// All accesses need not be longword aligned.
+//-------------------------------------------------------------------------
+enum speedo_offsets {
+ SCBStatus = 0, SCBCmd = 2, // Rx/Command Unit command and status.
+ SCBPointer = 4, // General purpose pointer.
+ SCBPort = 8, // Misc. commands and operands.
+ SCBflash = 12, SCBeeprom = 14, // EEPROM and flash memory control.
+ SCBCtrlMDI = 16, // MDI interface control.
+ SCBEarlyRx = 20, // Early receive byte count.
+ SCBEarlyRxInt = 24, SCBFlowCtrlReg = 25, SCBPmdr = 27,
+ // offsets for general control registers (GCRs)
+ SCBGenCtrl = 28, SCBGenStatus = 29, SCBGenCtrl2 = 30, SCBRsvd = 31,
+};
+
+#define GCR2_EEPROM_ACCESS_SEMAPHORE 0x80 // bit offset into the gcr2
+
+//-------------------------------------------------------------------------
+// Action commands - Commands that can be put in a command list entry.
+//-------------------------------------------------------------------------
+enum commands {
+ CmdNOp = 0, CmdIASetup = 1, CmdConfigure = 2, CmdMulticastList = 3,
+ CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7,
+ CmdSuspend = 0x4000, /* Suspend after completion. */
+ CmdIntr = 0x2000, /* Interrupt after completion. */
+ CmdTxFlex = 0x0008, /* Use "Flexible mode" for CmdTx command. */
+};
+
+//-------------------------------------------------------------------------
+// port commands
+//-------------------------------------------------------------------------
+#define PORT_RESET 0
+#define PORT_SELF_TEST 1
+#define POR_SELECTIVE_RESET 2
+#define PORT_DUMP_POINTER 2
+
+//-------------------------------------------------------------------------
+// SCB Command Word bit definitions
+//-------------------------------------------------------------------------
+//- CUC fields
+#define CU_START 0x0010
+#define CU_RESUME 0x0020
+#define CU_STATSADDR 0x0040
+#define CU_SHOWSTATS 0x0050 /* Dump statistics counters. */
+#define CU_CMD_BASE 0x0060 /* Base address to add to add CU commands. */
+#define CU_DUMPSTATS 0x0070 /* Dump then reset stats counters. */
+
+//- RUC fields
+#define RX_START 0x0001
+#define RX_RESUME 0x0002
+#define RX_ABORT 0x0004
+#define RX_ADDR_LOAD 0x0006 /* load ru_base_reg */
+#define RX_RESUMENR 0x0007
+
+// Interrupt fields (assuming byte addressing)
+#define INT_MASK 0x0100
+#define DRVR_INT 0x0200 /* Driver generated interrupt. */
+
+//- CB Status Word
+#define CMD_STATUS_COMPLETE 0x8000
+#define RX_STATUS_COMPLETE 0x8000
+#define CMD_STATUS_MASK 0xF000
+
+//-------------------------------------------------------------------------
+//- SCB Status bits:
+// Interrupts are ACKed by writing to the upper 6 interrupt bits
+//-------------------------------------------------------------------------
+#define SCB_STATUS_MASK 0xFC00 // bits 2-7 - STATUS/ACK Mask
+#define SCB_STATUS_CX_TNO 0x8000 // BIT_15 - CX or TNO Interrupt
+#define SCB_STATUS_FR 0x4000 // BIT_14 - FR Interrupt
+#define SCB_STATUS_CNA 0x2000 // BIT_13 - CNA Interrupt
+#define SCB_STATUS_RNR 0x1000 // BIT_12 - RNR Interrupt
+#define SCB_STATUS_MDI 0x0800 // BIT_11 - MDI R/W Done Interrupt
+#define SCB_STATUS_SWI 0x0400 // BIT_10 - SWI Interrupt
+
+// CU STATUS: bits 6 & 7
+#define SCB_STATUS_CU_MASK 0x00C0 // bits 6 & 7
+#define SCB_STATUS_CU_IDLE 0x0000 // 00
+#define SCB_STATUS_CU_SUSPEND 0x0040 // 01
+#define SCB_STATUS_CU_ACTIVE 0x0080 // 10
+
+// RU STATUS: bits 2-5
+#define SCB_RUS_IDLE 0x0000
+#define SCB_RUS_SUSPENDED 0x0004 // bit 2
+#define SCB_RUS_NO_RESOURCES 0x0008 // bit 3
+#define SCB_RUS_READY 0x0010 // bit 4
+
+//-------------------------------------------------------------------------
+// Bit Mask definitions
+//-------------------------------------------------------------------------
+#define BIT_0 0x0001
+#define BIT_1 0x0002
+#define BIT_2 0x0004
+#define BIT_3 0x0008
+#define BIT_4 0x0010
+#define BIT_5 0x0020
+#define BIT_6 0x0040
+#define BIT_7 0x0080
+#define BIT_8 0x0100
+#define BIT_9 0x0200
+#define BIT_10 0x0400
+#define BIT_11 0x0800
+#define BIT_12 0x1000
+#define BIT_13 0x2000
+#define BIT_14 0x4000
+#define BIT_15 0x8000
+#define BIT_24 0x01000000
+#define BIT_28 0x10000000
+
+
+//-------------------------------------------------------------------------
+// MDI Control register bit definitions
+//-------------------------------------------------------------------------
+#define MDI_DATA_MASK BIT_0_15 // MDI Data port
+#define MDI_REG_ADDR BIT_16_20 // which MDI register to read/write
+#define MDI_PHY_ADDR BIT_21_25 // which PHY to read/write
+#define MDI_PHY_OPCODE BIT_26_27 // which PHY to read/write
+#define MDI_PHY_READY BIT_28 // PHY is ready for another MDI cycle
+#define MDI_PHY_INT_ENABLE BIT_29 // Assert INT at MDI cycle completion
+
+#define BIT_0_2 0x0007
+#define BIT_0_3 0x000F
+#define BIT_0_4 0x001F
+#define BIT_0_5 0x003F
+#define BIT_0_6 0x007F
+#define BIT_0_7 0x00FF
+#define BIT_0_8 0x01FF
+#define BIT_0_13 0x3FFF
+#define BIT_0_15 0xFFFF
+#define BIT_1_2 0x0006
+#define BIT_1_3 0x000E
+#define BIT_2_5 0x003C
+#define BIT_3_4 0x0018
+#define BIT_4_5 0x0030
+#define BIT_4_6 0x0070
+#define BIT_4_7 0x00F0
+#define BIT_5_7 0x00E0
+#define BIT_5_9 0x03E0
+#define BIT_5_12 0x1FE0
+#define BIT_5_15 0xFFE0
+#define BIT_6_7 0x00c0
+#define BIT_7_11 0x0F80
+#define BIT_8_10 0x0700
+#define BIT_9_13 0x3E00
+#define BIT_12_15 0xF000
+
+#define BIT_16_20 0x001F0000
+#define BIT_21_25 0x03E00000
+#define BIT_26_27 0x0C000000
+
+//-------------------------------------------------------------------------
+// MDI Control register opcode definitions
+//-------------------------------------------------------------------------
+#define MDI_WRITE 1 // Phy Write
+#define MDI_READ 2 // Phy read
+
+//-------------------------------------------------------------------------
+// PHY 100 MDI Register/Bit Definitions
+//-------------------------------------------------------------------------
+// MDI register set
+#define MDI_CONTROL_REG 0x00 // MDI control register
+#define MDI_STATUS_REG 0x01 // MDI Status regiser
+#define PHY_ID_REG_1 0x02 // Phy indentification reg (word 1)
+#define PHY_ID_REG_2 0x03 // Phy indentification reg (word 2)
+#define AUTO_NEG_ADVERTISE_REG 0x04 // Auto-negotiation advertisement
+#define AUTO_NEG_LINK_PARTNER_REG 0x05 // Auto-negotiation link partner ability
+#define AUTO_NEG_EXPANSION_REG 0x06 // Auto-negotiation expansion
+#define AUTO_NEG_NEXT_PAGE_REG 0x07 // Auto-negotiation next page transmit
+#define EXTENDED_REG_0 0x10 // Extended reg 0 (Phy 100 modes)
+#define EXTENDED_REG_1 0x14 // Extended reg 1 (Phy 100 error indications)
+#define NSC_CONG_CONTROL_REG 0x17 // National (TX) congestion control
+#define NSC_SPEED_IND_REG 0x19 // National (TX) speed indication
+
+// MDI Control register bit definitions
+#define MDI_CR_COLL_TEST_ENABLE BIT_7 // Collision test enable
+#define MDI_CR_FULL_HALF BIT_8 // FDX =1, half duplex =0
+#define MDI_CR_RESTART_AUTO_NEG BIT_9 // Restart auto negotiation
+#define MDI_CR_ISOLATE BIT_10 // Isolate PHY from MII
+#define MDI_CR_POWER_DOWN BIT_11 // Power down
+#define MDI_CR_AUTO_SELECT BIT_12 // Auto speed select enable
+#define MDI_CR_10_100 BIT_13 // 0 = 10Mbs, 1 = 100Mbs
+#define MDI_CR_LOOPBACK BIT_14 // 0 = normal, 1 = loopback
+#define MDI_CR_RESET BIT_15 // 0 = normal, 1 = PHY reset
+
+// MDI Status register bit definitions
+#define MDI_SR_EXT_REG_CAPABLE BIT_0 // Extended register capabilities
+#define MDI_SR_JABBER_DETECT BIT_1 // Jabber detected
+#define MDI_SR_LINK_STATUS BIT_2 // Link Status -- 1 = link
+#define MDI_SR_AUTO_SELECT_CAPABLE BIT_3 // Auto speed select capable
+#define MDI_SR_REMOTE_FAULT_DETECT BIT_4 // Remote fault detect
+#define MDI_SR_AUTO_NEG_COMPLETE BIT_5 // Auto negotiation complete
+#define MDI_SR_10T_HALF_DPX BIT_11 // 10BaseT Half Duplex capable
+#define MDI_SR_10T_FULL_DPX BIT_12 // 10BaseT full duplex capable
+#define MDI_SR_TX_HALF_DPX BIT_13 // TX Half Duplex capable
+#define MDI_SR_TX_FULL_DPX BIT_14 // TX full duplex capable
+#define MDI_SR_T4_CAPABLE BIT_15 // T4 capable
+
+// Auto-Negotiation advertisement register bit definitions
+#define NWAY_AD_SELCTOR_FIELD BIT_0_4 // identifies supported protocol
+#define NWAY_AD_ABILITY BIT_5_12 // technologies that are supported
+#define NWAY_AD_10T_HALF_DPX BIT_5 // 10BaseT Half Duplex capable
+#define NWAY_AD_10T_FULL_DPX BIT_6 // 10BaseT full duplex capable
+#define NWAY_AD_TX_HALF_DPX BIT_7 // TX Half Duplex capable
+#define NWAY_AD_TX_FULL_DPX BIT_8 // TX full duplex capable
+#define NWAY_AD_T4_CAPABLE BIT_9 // T4 capable
+#define NWAY_AD_REMOTE_FAULT BIT_13 // indicates local remote fault
+#define NWAY_AD_RESERVED BIT_14 // reserved
+#define NWAY_AD_NEXT_PAGE BIT_15 // Next page (not supported)
+
+// Auto-Negotiation link partner ability register bit definitions
+#define NWAY_LP_SELCTOR_FIELD BIT_0_4 // identifies supported protocol
+#define NWAY_LP_ABILITY BIT_5_9 // technologies that are supported
+#define NWAY_LP_REMOTE_FAULT BIT_13 // indicates partner remote fault
+#define NWAY_LP_ACKNOWLEDGE BIT_14 // acknowledge
+#define NWAY_LP_NEXT_PAGE BIT_15 // Next page (not supported)
+
+// Auto-Negotiation expansion register bit definitions
+#define NWAY_EX_LP_NWAY BIT_0 // link partner is NWAY
+#define NWAY_EX_PAGE_RECEIVED BIT_1 // link code word received
+#define NWAY_EX_NEXT_PAGE_ABLE BIT_2 // local is next page able
+#define NWAY_EX_LP_NEXT_PAGE_ABLE BIT_3 // partner is next page able
+#define NWAY_EX_PARALLEL_DET_FLT BIT_4 // parallel detection fault
+#define NWAY_EX_RESERVED BIT_5_15 // reserved
+
+
+// PHY 100 Extended Register 0 bit definitions
+#define PHY_100_ER0_FDX_INDIC BIT_0 // 1 = FDX, 0 = half duplex
+#define PHY_100_ER0_SPEED_INDIC BIT_1 // 1 = 100mbs, 0= 10mbs
+#define PHY_100_ER0_WAKE_UP BIT_2 // Wake up DAC
+#define PHY_100_ER0_RESERVED BIT_3_4 // Reserved
+#define PHY_100_ER0_REV_CNTRL BIT_5_7 // Revsion control (A step = 000)
+#define PHY_100_ER0_FORCE_FAIL BIT_8 // Force Fail is enabled
+#define PHY_100_ER0_TEST BIT_9_13 // Revsion control (A step = 000)
+#define PHY_100_ER0_LINKDIS BIT_14 // Link integrity test is disabled
+#define PHY_100_ER0_JABDIS BIT_15 // Jabber function is disabled
+
+
+// PHY 100 Extended Register 1 bit definitions
+#define PHY_100_ER1_RESERVED BIT_0_8 // Reserved
+#define PHY_100_ER1_CH2_DET_ERR BIT_9 // Channel 2 EOF detection error
+#define PHY_100_ER1_MANCH_CODE_ERR BIT_10 // Manchester code error
+#define PHY_100_ER1_EOP_ERR BIT_11 // EOP error
+#define PHY_100_ER1_BAD_CODE_ERR BIT_12 // bad code error
+#define PHY_100_ER1_INV_CODE_ERR BIT_13 // invalid code error
+#define PHY_100_ER1_DC_BAL_ERR BIT_14 // DC balance error
+#define PHY_100_ER1_PAIR_SKEW_ERR BIT_15 // Pair skew error
+
+// National Semiconductor TX phy congestion control register bit definitions
+#define NSC_TX_CONG_TXREADY BIT_10 // Makes TxReady an input
+#define NSC_TX_CONG_ENABLE BIT_8 // Enables congestion control
+#define NSC_TX_CONG_F_CONNECT BIT_5 // Enables congestion control
+
+// National Semiconductor TX phy speed indication register bit definitions
+#define NSC_TX_SPD_INDC_SPEED BIT_6 // 0 = 100mb, 1=10mb
+
+//-------------------------------------------------------------------------
+// Phy related constants
+//-------------------------------------------------------------------------
+#define PHY_503 0
+#define PHY_100_A 0x000003E0
+#define PHY_100_C 0x035002A8
+#define PHY_TX_ID 0x015002A8
+#define PHY_NSC_TX 0x5c002000
+#define PHY_OTHER 0xFFFF
+
+#define PHY_MODEL_REV_ID_MASK 0xFFF0FFFF
+#define PARALLEL_DETECT 0
+#define N_WAY 1
+
+#define RENEGOTIATE_TIME 35 // (3.5 Seconds)
+
+#define CONNECTOR_AUTO 0
+#define CONNECTOR_TPE 1
+#define CONNECTOR_MII 2
+
+//-------------------------------------------------------------------------
+
+/* The Speedo3 Rx and Tx frame/buffer descriptors. */
+#pragma pack(1)
+struct CB_Header { /* A generic descriptor. */
+ UINT16 status; /* Offset 0. */
+ UINT16 command; /* Offset 2. */
+ UINT32 link; /* struct descriptor * */
+};
+
+/* transmit command block structure */
+#pragma pack(1)
+typedef struct s_TxCB {
+ struct CB_Header cb_header;
+ UINT32 PhysTBDArrayAddres; /* address of an array that contains
+ physical TBD pointers */
+ UINT16 ByteCount; /* immediate data count = 0 always */
+ UINT8 Threshold;
+ UINT8 TBDCount;
+ UINT8 ImmediateData[TX_BUFFER_SIZE];
+ /* following fields are not seen by the 82557 */
+ struct TBD {
+ UINT32 phys_buf_addr;
+ UINT32 buf_len;
+ } TBDArray[MAX_XMIT_FRAGMENTS];
+ UINT32 PhysArrayAddr; /* in case the one in the header is lost */
+ UINT32 PhysTCBAddress; /* for this TCB */
+ struct s_TxCB *NextTCBVirtualLinkPtr;
+ struct s_TxCB *PrevTCBVirtualLinkPtr;
+ UINT64 free_data_ptr; // to be given to the upper layer when this xmit completes1
+}TxCB;
+
+/* The Speedo3 Rx and Tx buffer descriptors. */
+#pragma pack(1)
+typedef struct s_RxFD { /* Receive frame descriptor. */
+ struct CB_Header cb_header;
+ UINT32 rx_buf_addr; /* VOID * */
+ UINT16 ActualCount;
+ UINT16 RFDSize;
+ UINT8 RFDBuffer[RX_BUFFER_SIZE];
+ UINT8 forwarded;
+ UINT8 junk[3];
+}RxFD;
+
+/* Elements of the RxFD.status word. */
+#define RX_COMPLETE 0x8000
+#define RX_FRAME_OK 0x2000
+
+/* Elements of the dump_statistics block. This block must be lword aligned. */
+#pragma pack(1)
+struct speedo_stats {
+ UINT32 tx_good_frames;
+ UINT32 tx_coll16_errs;
+ UINT32 tx_late_colls;
+ UINT32 tx_underruns;
+ UINT32 tx_lost_carrier;
+ UINT32 tx_deferred;
+ UINT32 tx_one_colls;
+ UINT32 tx_multi_colls;
+ UINT32 tx_total_colls;
+ UINT32 rx_good_frames;
+ UINT32 rx_crc_errs;
+ UINT32 rx_align_errs;
+ UINT32 rx_resource_errs;
+ UINT32 rx_overrun_errs;
+ UINT32 rx_colls_errs;
+ UINT32 rx_runt_errs;
+ UINT32 done_marker;
+};
+#pragma pack()
+
+
+struct Krn_Mem{
+ RxFD rx_ring[RX_BUFFER_COUNT];
+ TxCB tx_ring[TX_BUFFER_COUNT];
+ struct speedo_stats statistics;
+};
+#define MEMORY_NEEDED sizeof(struct Krn_Mem)
+
+/* The parameters for a CmdConfigure operation.
+ There are so many options that it would be difficult to document each bit.
+ We mostly use the default or recommended settings.
+*/
+
+/*
+ *--------------------------------------------------------------------------
+ * Configuration CB Parameter Bit Definitions
+ *--------------------------------------------------------------------------
+ */
+// - Byte 0 (Default Value = 16h)
+#define CFIG_BYTE_COUNT 0x16 // 22 Configuration Bytes
+
+//- Byte 1 (Default Value = 88h)
+#define CFIG_TXRX_FIFO_LIMIT 0x88
+
+//- Byte 2 (Default Value = 0)
+#define CFIG_ADAPTIVE_IFS 0
+
+//- Byte 3 (Default Value = 0, ALWAYS. This byte is RESERVED)
+#define CFIG_RESERVED 0
+
+//- Byte 4 (Default Value = 0. Default implies that Rx DMA cannot be
+//- preempted).
+#define CFIG_RXDMA_BYTE_COUNT 0
+
+//- Byte 5 (Default Value = 80h. Default implies that Tx DMA cannot be
+//- preempted. However, setting these counters is enabled.)
+#define CFIG_DMBC_ENABLE 0x80
+
+//- Byte 6 (Default Value = 33h. Late SCB enabled, No TNO interrupts,
+//- CNA interrupts and do not save bad frames.)
+#define CFIG_LATE_SCB 1 // BIT 0
+#define CFIG_TNO_INTERRUPT 0x4 // BIT 2
+#define CFIG_CI_INTERRUPT 0x8 // BIT 3
+#define CFIG_SAVE_BAD_FRAMES 0x80 // BIT_7
+
+//- Byte 7 (Default Value = 7h. Discard short frames automatically and
+//- attempt upto 3 retries on transmit.)
+#define CFIG_DISCARD_SHORTRX 0x00001
+#define CFIG_URUN_RETRY BIT_1 OR BIT_2
+
+//- Byte 8 (Default Value = 1. Enable MII mode.)
+#define CFIG_503_MII BIT_0
+
+//- Byte 9 (Default Value = 0, ALWAYS)
+
+//- Byte 10 (Default Value = 2Eh)
+#define CFIG_NSAI BIT_3
+#define CFIG_PREAMBLE_LENGTH BIT_5 ;- Bit 5-4 = 1-0
+#define CFIG_NO_LOOPBACK 0
+#define CFIG_INTERNAL_LOOPBACK BIT_6
+#define CFIG_EXT_LOOPBACK BIT_7
+#define CFIG_EXT_PIN_LOOPBACK BIT_6 OR BIT_7
+
+//- Byte 11 (Default Value = 0)
+#define CFIG_LINEAR_PRIORITY 0
+
+//- Byte 12 (Default Value = 60h)
+#define CFIG_LPRIORITY_MODE 0
+#define CFIG_IFS 6 ;- 6 * 16 = 96
+
+//- Byte 13 (Default Value = 0, ALWAYS)
+
+//- Byte 14 (Default Value = 0F2h, ALWAYS)
+
+//- Byte 15 (Default Value = E8h)
+#define CFIG_PROMISCUOUS_MODE BIT_0
+#define CFIG_BROADCAST_DISABLE BIT_1
+#define CFIG_CRS_CDT BIT_7
+
+//- Byte 16 (Default Value = 0, ALWAYS)
+
+//- Byte 17 (Default Value = 40h, ALWAYS)
+
+//- Byte 18 (Default Value = F2h)
+#define CFIG_STRIPPING BIT_0
+#define CFIG_PADDING BIT_1
+#define CFIG_RX_CRC_TRANSFER BIT_2
+
+//- Byte 19 (Default Value = 80h)
+#define CFIG_FORCE_FDX BIT_6
+#define CFIG_FDX_PIN_ENABLE BIT_7
+
+//- Byte 20 (Default Value = 3Fh)
+#define CFIG_MULTI_IA BIT_6
+
+//- Byte 21 (Default Value = 05)
+#define CFIG_MC_ALL BIT_3
+
+/*-----------------------------------------------------------------------*/
+#define D102_REVID 0x0b
+
+#define HALF_DUPLEX 1
+#define FULL_DUPLEX 2
+
+typedef struct s_data_instance {
+
+ UINT16 State; // stopped, started or initialized
+ UINT16 Bus;
+ UINT8 Device;
+ UINT8 Function;
+ UINT16 VendorID;
+ UINT16 DeviceID;
+ UINT16 RevID;
+ UINT16 SubVendorID;
+ UINT16 SubSystemID;
+
+ UINT8 PermNodeAddress[PXE_MAC_LENGTH];
+ UINT8 CurrentNodeAddress[PXE_MAC_LENGTH];
+ UINT8 BroadcastNodeAddress[PXE_MAC_LENGTH];
+ UINT32 Config[MAX_PCI_CONFIG_LEN];
+ UINT32 NVData[MAX_EEPROM_LEN];
+
+ UINT32 ioaddr;
+ UINT32 flash_addr;
+
+ UINT16 LinkSpeed; // actual link speed setting
+ UINT16 LinkSpeedReq; // requested (forced) link speed
+ UINT8 DuplexReq; // requested duplex
+ UINT8 Duplex; // Duplex set
+ UINT8 CableDetect; // 1 to detect and 0 not to detect the cable
+ UINT8 LoopBack;
+
+ UINT16 TxBufCnt;
+ UINT16 TxBufSize;
+ UINT16 RxBufCnt;
+ UINT16 RxBufSize;
+ UINT32 RxTotals;
+ UINT32 TxTotals;
+
+ UINT16 int_mask;
+ UINT16 Int_Status;
+ UINT16 PhyRecord[2]; // primary and secondary PHY record registers from eeprom
+ UINT8 PhyAddress;
+ UINT8 int_num;
+ UINT16 NVData_Len;
+ UINT32 MemoryLength;
+
+ RxFD *rx_ring; // array of rx buffers
+ TxCB *tx_ring; // array of tx buffers
+ struct speedo_stats *statistics;
+ TxCB *FreeTxHeadPtr;
+ TxCB *FreeTxTailPtr;
+ RxFD *RFDTailPtr;
+
+ UINT64 rx_phy_addr; // physical addresses
+ UINT64 tx_phy_addr;
+ UINT64 stat_phy_addr;
+ UINT64 MemoryPtr;
+ UINT64 Mapped_MemoryPtr;
+
+ UINT64 xmit_done[TX_BUFFER_COUNT << 1]; // circular buffer
+ UINT16 xmit_done_head; // index into the xmit_done array
+ UINT16 xmit_done_tail; // where are we filling now (index into xmit_done)
+ UINT16 cur_rx_ind; // current RX Q head index
+ UINT16 FreeCBCount;
+
+ BOOLEAN in_interrupt;
+ BOOLEAN in_transmit;
+ BOOLEAN Receive_Started;
+ UINT8 Rx_Filter;
+ UINT8 VersionFlag; // UNDI30 or UNDI31??
+ UINT8 rsvd[3];
+
+ struct mc{
+ UINT16 reserved [3]; // padding for this structure to make it 8 byte aligned
+ UINT16 list_len;
+ UINT8 mc_list[MAX_MCAST_ADDRESS_CNT][PXE_MAC_LENGTH]; // 8*32 is the size
+ } mcast_list;
+
+ UINT64 Unique_ID;
+
+ EFI_PCI_IO_PROTOCOL *Io_Function;
+
+ VOID (*Delay_30)(UINTN); // call back routine
+ VOID (*Virt2Phys_30)(UINT64 virtual_addr, UINT64 physical_ptr); // call back routine
+ VOID (*Block_30)(UINT32 enable); // call back routine
+ VOID (*Mem_Io_30)(UINT8 read_write, UINT8 len, UINT64 port, UINT64 buf_addr);
+ VOID (*Delay)(UINT64, UINTN); // call back routine
+ VOID (*Virt2Phys)(UINT64 unq_id, UINT64 virtual_addr, UINT64 physical_ptr); // call back routine
+ VOID (*Block)(UINT64 unq_id, UINT32 enable); // call back routine
+ VOID (*Mem_Io)(UINT64 unq_id, UINT8 read_write, UINT8 len, UINT64 port,
+ UINT64 buf_addr);
+ VOID (*Map_Mem)(UINT64 unq_id, UINT64 virtual_addr, UINT32 size,
+ UINT32 Direction, UINT64 mapped_addr);
+ VOID (*UnMap_Mem)(UINT64 unq_id, UINT64 virtual_addr, UINT32 size,
+ UINT32 Direction, UINT64 mapped_addr);
+ VOID (*Sync_Mem)(UINT64 unq_id, UINT64 virtual_addr,
+ UINT32 size, UINT32 Direction, UINT64 mapped_addr);
+} NIC_DATA_INSTANCE;
+
+#pragma pack(1)
+struct MC_CB_STRUCT{
+ UINT16 count;
+ UINT8 m_list[MAX_MCAST_ADDRESS_CNT][ETHER_MAC_ADDR_LEN];
+};
+#pragma pack()
+
+#define FOUR_GIGABYTE (UINT64)0x100000000ULL
diff --git a/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Init.c b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Init.c
new file mode 100644
index 0000000..70982cb
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Init.c
@@ -0,0 +1,1162 @@
+/*++
+
+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:
+
+ init.c
+
+Abstract:
+
+ Initialization functions for EFI UNDI32 driver
+
+Revision History
+
+--*/
+
+#include "undi32.h"
+
+//
+// Global Variables
+//
+PXE_SW_UNDI *pxe = 0; // 3.0 entry point
+PXE_SW_UNDI *pxe_31 = 0; // 3.1 entry
+UNDI32_DEV *UNDI32DeviceList[MAX_NIC_INTERFACES];
+
+NII_TABLE *UnidiDataPointer=NULL;
+//
+// external Global Variables
+//
+extern UNDI_CALL_TABLE api_table[];
+
+//
+// function prototypes
+//
+EFI_STATUS
+InstallConfigTable (
+ IN VOID
+ );
+
+EFI_STATUS
+EFIAPI
+InitializeUNDIDriver (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+VOID
+UNDI_notify_virtual (
+ EFI_EVENT event,
+ VOID *context
+ );
+
+VOID
+EFIAPI
+UndiNotifyExitBs (
+ EFI_EVENT Event,
+ VOID *Context
+ );
+
+EFI_STATUS
+EFIAPI
+UndiDriverSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+EFIAPI
+UndiDriverStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ );
+
+EFI_STATUS
+EFIAPI
+UndiDriverStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+EFI_STATUS
+AppendMac2DevPath (
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **DevPtr,
+ IN EFI_DEVICE_PATH_PROTOCOL *BaseDevPtr,
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ );
+//
+// end function prototypes
+//
+VOID
+EFIAPI
+UndiNotifyVirtual (
+ EFI_EVENT Event,
+ VOID *Context
+ )
+/*++
+
+Routine Description:
+
+ When address mapping changes to virtual this should make the appropriate
+ address conversions.
+
+Arguments:
+
+ (Standard Event handler)
+
+Returns:
+
+ None
+
+--*/
+// TODO: Context - add argument and description to function comment
+{
+ UINT16 Index;
+ VOID *Pxe31Pointer;
+
+ if (pxe_31 != NULL) {
+ Pxe31Pointer = (VOID *) pxe_31;
+
+ EfiConvertPointer (
+ EFI_OPTIONAL_POINTER,
+ (void **) &Pxe31Pointer
+ );
+
+ //
+ // UNDI32DeviceList is an array of pointers
+ //
+ for (Index = 0; Index < pxe_31->IFcnt; Index++) {
+ UNDI32DeviceList[Index]->NIIProtocol_31.ID = (UINT64) (UINTN) Pxe31Pointer;
+ EfiConvertPointer (
+ EFI_OPTIONAL_POINTER,
+ (void **) &(UNDI32DeviceList[Index])
+ );
+ }
+
+ EfiConvertPointer (
+ EFI_OPTIONAL_POINTER,
+ (void **) &(pxe_31->EntryPoint)
+ );
+ pxe_31 = Pxe31Pointer;
+ }
+
+ for (Index = 0; Index <= PXE_OPCODE_LAST_VALID; Index++) {
+ EfiConvertPointer (
+ EFI_OPTIONAL_POINTER,
+ (void **) &api_table[Index].api_ptr
+ );
+ }
+}
+
+VOID
+EFIAPI
+UndiNotifyExitBs (
+ EFI_EVENT Event,
+ VOID *Context
+ )
+/*++
+
+Routine Description:
+
+ When EFI is shuting down the boot services, we need to install a
+ configuration table for UNDI to work at runtime!
+
+Arguments:
+
+ (Standard Event handler)
+
+Returns:
+
+ None
+
+--*/
+// TODO: Context - add argument and description to function comment
+{
+ InstallConfigTable ();
+}
+//
+// UNDI Class Driver Global Variables
+//
+EFI_DRIVER_BINDING_PROTOCOL gUndiDriverBinding = {
+ UndiDriverSupported,
+ UndiDriverStart,
+ UndiDriverStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+EFI_STATUS
+EFIAPI
+InitializeUNDIDriver (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ Register Driver Binding protocol for this driver.
+
+Arguments:
+
+ ImageHandle - Image Handle
+
+ SystemTable - Pointer to system table
+
+Returns:
+
+ EFI_SUCCESS - Driver loaded.
+
+ other - Driver not loaded.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_EVENT Event;
+
+ Status = gBS->CreateEvent (
+ EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES,
+ EFI_TPL_NOTIFY,
+ UndiNotifyExitBs,
+ NULL,
+ &Event
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+UndiDriverSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+Routine Description:
+
+ Test to see if this driver supports ControllerHandle. Any ControllerHandle
+ than contains a DevicePath, PciIo protocol, Class code of 2, Vendor ID of 0x8086,
+ and DeviceId of (D100_DEVICE_ID || D102_DEVICE_ID || ICH3_DEVICE_ID_1 ||
+ ICH3_DEVICE_ID_2 || ICH3_DEVICE_ID_3 || ICH3_DEVICE_ID_4 || ICH3_DEVICE_ID_5 ||
+ ICH3_DEVICE_ID_6 || ICH3_DEVICE_ID_7 || ICH3_DEVICE_ID_8) can be supported.
+
+Arguments:
+
+ This - Protocol instance pointer.
+
+ Controller - Handle of device to test.
+
+ RemainingDevicePath - Not used.
+
+Returns:
+
+ EFI_SUCCESS - This driver supports this device.
+
+ other - This driver does not support this device.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ 0,
+ sizeof (PCI_CONFIG_HEADER),
+ &Pci
+ );
+
+ if (!EFI_ERROR (Status)) {
+ Status = EFI_UNSUPPORTED;
+
+ if (Pci.Hdr.ClassCode[2] == 0x02 && Pci.Hdr.VendorId == PCI_VENDOR_ID_INTEL) {
+ switch (Pci.Hdr.DeviceId) {
+ case D100_DEVICE_ID:
+ case D102_DEVICE_ID:
+ case ICH3_DEVICE_ID_1:
+ case ICH3_DEVICE_ID_2:
+ case ICH3_DEVICE_ID_3:
+ case ICH3_DEVICE_ID_4:
+ case ICH3_DEVICE_ID_5:
+ case ICH3_DEVICE_ID_6:
+ case ICH3_DEVICE_ID_7:
+ case ICH3_DEVICE_ID_8:
+ case 0x1039:
+ case 0x103A:
+ case 0x103B:
+ case 0x103C:
+ case 0x103D:
+ case 0x103E:
+ case 0x1050:
+ case 0x1051:
+ case 0x1052:
+ case 0x1053:
+ case 0x1054:
+ case 0x1055:
+ case 0x1056:
+ case 0x1057:
+ case 0x1059:
+ case 0x1064:
+ Status = EFI_SUCCESS;
+ }
+ }
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+UndiDriverStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+/*++
+
+Routine Description:
+
+ Start this driver on Controller by opening PciIo and DevicePath protocol.
+ Initialize PXE structures, create a copy of the Controller Device Path with the
+ NIC's MAC address appended to it, install the NetworkInterfaceIdentifier protocol
+ on the newly created Device Path.
+
+Arguments:
+
+ This - Protocol instance pointer.
+
+ Controller - Handle of device to work with.
+
+ RemainingDevicePath - Not used, always produce all possible children.
+
+Returns:
+
+ EFI_SUCCESS - This driver is added to Controller.
+
+ other - This driver does not support this device.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *UndiDevicePath;
+ PCI_CONFIG_HEADER *CfgHdr;
+ UNDI32_DEV *UNDI32Device;
+ UINT16 NewCommand;
+ UINT8 *TmpPxePointer;
+ EFI_PCI_IO_PROTOCOL *PciIoFncs;
+ UINTN Len;
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIoFncs,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &UndiDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return Status;
+ }
+
+ Status = gBS->AllocatePool (
+ EfiRuntimeServicesData,
+ sizeof (UNDI32_DEV),
+ (VOID **) &UNDI32Device
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto UndiError;
+ }
+
+ ZeroMem ((CHAR8 *) UNDI32Device, sizeof (UNDI32_DEV));
+
+ //
+ // allocate and initialize both (old and new) the !pxe structures here,
+ // there should only be one copy of each of these structure for any number
+ // of NICs this undi supports. Also, these structures need to be on a
+ // paragraph boundary as per the spec. so, while allocating space for these,
+ // make sure that there is space for 2 !pxe structures (old and new) and a
+ // 32 bytes padding for alignment adjustment (in case)
+ //
+ TmpPxePointer = NULL;
+ if (pxe_31 == NULL) {
+ Status = gBS->AllocatePool (
+ EfiRuntimeServicesData,
+ (sizeof (PXE_SW_UNDI) + sizeof (PXE_SW_UNDI) + 32),
+ (VOID **) &TmpPxePointer
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto UndiErrorDeleteDevice;
+ }
+
+ ZeroMem (
+ TmpPxePointer,
+ sizeof (PXE_SW_UNDI) + sizeof (PXE_SW_UNDI) + 32
+ );
+ //
+ // check for paragraph alignment here, assuming that the pointer is
+ // already 8 byte aligned.
+ //
+ if (((UINTN) TmpPxePointer & 0x0F) != 0) {
+ pxe_31 = (PXE_SW_UNDI *) ((UINTN) (TmpPxePointer + 8));
+ } else {
+ pxe_31 = (PXE_SW_UNDI *) TmpPxePointer;
+ }
+ //
+ // assuming that the sizeof pxe_31 is a 16 byte multiple
+ //
+ pxe = (PXE_SW_UNDI *) ((CHAR8 *) (pxe_31) + sizeof (PXE_SW_UNDI));
+
+ PxeStructInit (pxe, 0x30);
+ PxeStructInit (pxe_31, 0x31);
+ }
+
+ UNDI32Device->NIIProtocol.ID = (UINT64) (UINTN) (pxe);
+ UNDI32Device->NIIProtocol_31.ID = (UINT64) (UINTN) (pxe_31);
+
+ Status = PciIoFncs->Attributes (
+ PciIoFncs,
+ EfiPciIoAttributeOperationEnable,
+ EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER,
+ NULL
+ );
+ //
+ // Read all the registers from device's PCI Configuration space
+ //
+ Status = PciIoFncs->Pci.Read (
+ PciIoFncs,
+ EfiPciIoWidthUint32,
+ 0,
+ MAX_PCI_CONFIG_LEN,
+ &UNDI32Device->NicInfo.Config
+ );
+
+ CfgHdr = (PCI_CONFIG_HEADER *) &(UNDI32Device->NicInfo.Config[0]);
+
+ //
+ // make sure that this device is a PCI bus master
+ //
+
+ NewCommand = (UINT16) (CfgHdr->Command | PCI_COMMAND_MASTER | PCI_COMMAND_IO);
+ if (CfgHdr->Command != NewCommand) {
+ PciIoFncs->Pci.Write (
+ PciIoFncs,
+ EfiPciIoWidthUint16,
+ PCI_COMMAND,
+ 1,
+ &NewCommand
+ );
+ CfgHdr->Command = NewCommand;
+ }
+
+ //
+ // make sure that the latency timer is at least 32
+ //
+ if (CfgHdr->LatencyTimer < 32) {
+ CfgHdr->LatencyTimer = 32;
+ PciIoFncs->Pci.Write (
+ PciIoFncs,
+ EfiPciIoWidthUint8,
+ PCI_LATENCY_TIMER,
+ 1,
+ &CfgHdr->LatencyTimer
+ );
+ }
+ //
+ // the IfNum index for the current interface will be the total number
+ // of interfaces initialized so far
+ //
+ UNDI32Device->NIIProtocol.IfNum = pxe->IFcnt;
+ UNDI32Device->NIIProtocol_31.IfNum = pxe_31->IFcnt;
+
+ PxeUpdate (&UNDI32Device->NicInfo, pxe);
+ PxeUpdate (&UNDI32Device->NicInfo, pxe_31);
+
+ UNDI32Device->NicInfo.Io_Function = PciIoFncs;
+ UNDI32DeviceList[UNDI32Device->NIIProtocol.IfNum] = UNDI32Device;
+ UNDI32Device->Undi32BaseDevPath = UndiDevicePath;
+
+ Status = AppendMac2DevPath (
+ &UNDI32Device->Undi32DevPath,
+ UNDI32Device->Undi32BaseDevPath,
+ &UNDI32Device->NicInfo
+ );
+
+ if (Status != 0) {
+ goto UndiErrorDeletePxe;
+ }
+
+ UNDI32Device->Signature = UNDI_DEV_SIGNATURE;
+
+ UNDI32Device->NIIProtocol.Revision = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION;
+ UNDI32Device->NIIProtocol.Type = EfiNetworkInterfaceUndi;
+ UNDI32Device->NIIProtocol.MajorVer = PXE_ROMID_MAJORVER;
+ UNDI32Device->NIIProtocol.MinorVer = PXE_ROMID_MINORVER;
+ UNDI32Device->NIIProtocol.ImageSize = 0;
+ UNDI32Device->NIIProtocol.ImageAddr = 0;
+ UNDI32Device->NIIProtocol.Ipv6Supported = FALSE;
+
+ UNDI32Device->NIIProtocol.StringId[0] = 'U';
+ UNDI32Device->NIIProtocol.StringId[1] = 'N';
+ UNDI32Device->NIIProtocol.StringId[2] = 'D';
+ UNDI32Device->NIIProtocol.StringId[3] = 'I';
+
+ UNDI32Device->NIIProtocol_31.Revision = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION_31;
+ UNDI32Device->NIIProtocol_31.Type = EfiNetworkInterfaceUndi;
+ UNDI32Device->NIIProtocol_31.MajorVer = PXE_ROMID_MAJORVER;
+ UNDI32Device->NIIProtocol_31.MinorVer = PXE_ROMID_MINORVER_31;
+ UNDI32Device->NIIProtocol_31.ImageSize = 0;
+ UNDI32Device->NIIProtocol_31.ImageAddr = 0;
+ UNDI32Device->NIIProtocol_31.Ipv6Supported = FALSE;
+
+ UNDI32Device->NIIProtocol_31.StringId[0] = 'U';
+ UNDI32Device->NIIProtocol_31.StringId[1] = 'N';
+ UNDI32Device->NIIProtocol_31.StringId[2] = 'D';
+ UNDI32Device->NIIProtocol_31.StringId[3] = 'I';
+
+ UNDI32Device->DeviceHandle = NULL;
+
+ //
+ // install both the 3.0 and 3.1 NII protocols.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &UNDI32Device->DeviceHandle,
+ &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
+ &UNDI32Device->NIIProtocol_31,
+ &gEfiNetworkInterfaceIdentifierProtocolGuid,
+ &UNDI32Device->NIIProtocol,
+ &gEfiDevicePathProtocolGuid,
+ UNDI32Device->Undi32DevPath,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto UndiErrorDeleteDevicePath;
+ }
+
+ //
+ // if the table exists, free it and alloc again, or alloc it directly
+ //
+ if (UnidiDataPointer != NULL) {
+ Status = gBS->FreePool(UnidiDataPointer);
+ }
+ if (EFI_ERROR (Status)) {
+ goto UndiErrorDeleteDevicePath;
+ }
+
+ Len = (pxe_31->IFcnt * sizeof (NII_ENTRY)) + sizeof (UnidiDataPointer);
+ Status = gBS->AllocatePool (EfiRuntimeServicesData, Len, (VOID **) &UnidiDataPointer);
+
+ if (EFI_ERROR (Status)) {
+ goto UndiErrorAllocDataPointer;
+ }
+
+ //
+ // Open For Child Device
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIoFncs,
+ This->DriverBindingHandle,
+ UNDI32Device->DeviceHandle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+
+ return EFI_SUCCESS;
+UndiErrorAllocDataPointer:
+ gBS->UninstallMultipleProtocolInterfaces (
+ &UNDI32Device->DeviceHandle,
+ &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
+ &UNDI32Device->NIIProtocol_31,
+ &gEfiNetworkInterfaceIdentifierProtocolGuid,
+ &UNDI32Device->NIIProtocol,
+ &gEfiDevicePathProtocolGuid,
+ UNDI32Device->Undi32DevPath,
+ NULL
+ );
+
+UndiErrorDeleteDevicePath:
+ UNDI32DeviceList[UNDI32Device->NIIProtocol.IfNum] = NULL;
+ gBS->FreePool (UNDI32Device->Undi32DevPath);
+
+UndiErrorDeletePxe:
+ PxeUpdate (NULL, pxe);
+ PxeUpdate (NULL, pxe_31);
+ if (TmpPxePointer != NULL) {
+ gBS->FreePool (TmpPxePointer);
+
+ }
+
+UndiErrorDeleteDevice:
+ gBS->FreePool (UNDI32Device);
+
+UndiError:
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+UndiDriverStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+/*++
+
+Routine Description:
+ Stop this driver on Controller by removing NetworkInterfaceIdentifier protocol and
+ closing the DevicePath and PciIo protocols on Controller.
+
+Arguments:
+ This - Protocol instance pointer.
+ Controller - Handle of device to stop driver on.
+ NumberOfChildren - How many children need to be stopped.
+ ChildHandleBuffer - Not used.
+
+Returns:
+ EFI_SUCCESS - This driver is removed Controller.
+ other - This driver was not removed from this device.
+
+--*/
+// TODO: EFI_DEVICE_ERROR - add return value to function comment
+{
+ EFI_STATUS Status;
+ BOOLEAN AllChildrenStopped;
+ UINTN Index;
+ UNDI32_DEV *UNDI32Device;
+ EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NIIProtocol;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ //
+ // Complete all outstanding transactions to Controller.
+ // Don't allow any new transaction to Controller to be started.
+ //
+ if (NumberOfChildren == 0) {
+
+ //
+ // Close the bus driver
+ //
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ return Status;
+ }
+
+ AllChildrenStopped = TRUE;
+
+ for (Index = 0; Index < NumberOfChildren; Index++) {
+
+ Status = gBS->OpenProtocol (
+ ChildHandleBuffer[Index],
+ &gEfiNetworkInterfaceIdentifierProtocolGuid,
+ (VOID **) &NIIProtocol,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+
+ UNDI32Device = UNDI_DEV_FROM_THIS (NIIProtocol);
+
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index]
+ );
+
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ ChildHandleBuffer[Index],
+ &gEfiDevicePathProtocolGuid,
+ UNDI32Device->Undi32DevPath,
+ &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
+ &UNDI32Device->NIIProtocol_31,
+ &gEfiNetworkInterfaceIdentifierProtocolGuid,
+ &UNDI32Device->NIIProtocol,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index],
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ } else {
+ gBS->FreePool (UNDI32Device->Undi32DevPath);
+ gBS->FreePool (UNDI32Device);
+ }
+ }
+
+ if (EFI_ERROR (Status)) {
+ AllChildrenStopped = FALSE;
+ }
+ }
+
+ if (!AllChildrenStopped) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+VOID
+TmpDelay (
+ IN UINT64 UnqId,
+ IN UINTN MicroSeconds
+ )
+/*++
+
+Routine Description:
+
+ Use the EFI boot services to produce a pause. This is also the routine which
+ gets replaced during RunTime by the O/S in the NIC_DATA_INSTANCE so it can
+ do it's own pause.
+
+Arguments:
+
+ UnqId - Runtime O/S routine might use this, this temp routine does not use it
+
+ MicroSeconds - Determines the length of pause.
+
+Returns:
+
+ none
+
+--*/
+{
+ gBS->Stall ((UINT32) MicroSeconds);
+}
+
+VOID
+TmpMemIo (
+ IN UINT64 UnqId,
+ IN UINT8 ReadWrite,
+ IN UINT8 Len,
+ IN UINT64 Port,
+ IN UINT64 BuffAddr
+ )
+/*++
+
+Routine Description:
+
+ Use the PCI IO abstraction to issue memory or I/O reads and writes. This is also the routine which
+ gets replaced during RunTime by the O/S in the NIC_DATA_INSTANCE so it can do it's own I/O abstractions.
+
+Arguments:
+
+ UnqId - Runtime O/S routine may use this field, this temp routine does not.
+
+ ReadWrite - Determine if it is an I/O or Memory Read/Write Operation.
+
+ Len - Determines the width of the data operation.
+
+ Port - What port to Read/Write from.
+
+ BuffAddr - Address to read to or write from.
+
+Returns:
+
+ none
+
+--*/
+{
+ EFI_PCI_IO_PROTOCOL_WIDTH Width;
+ NIC_DATA_INSTANCE *AdapterInfo;
+
+ Width = 0;
+ AdapterInfo = (NIC_DATA_INSTANCE *) (UINTN) UnqId;
+ switch (Len) {
+ case 2:
+ Width = 1;
+ break;
+
+ case 4:
+ Width = 2;
+ break;
+
+ case 8:
+ Width = 3;
+ break;
+ }
+
+ switch (ReadWrite) {
+ case PXE_IO_READ:
+ AdapterInfo->Io_Function->Io.Read (
+ AdapterInfo->Io_Function,
+ Width,
+ 1,
+ Port,
+ 1,
+ (VOID *) (UINTN) (BuffAddr)
+ );
+ break;
+
+ case PXE_IO_WRITE:
+ AdapterInfo->Io_Function->Io.Write (
+ AdapterInfo->Io_Function,
+ Width,
+ 1,
+ Port,
+ 1,
+ (VOID *) (UINTN) (BuffAddr)
+ );
+ break;
+
+ case PXE_MEM_READ:
+ AdapterInfo->Io_Function->Mem.Read (
+ AdapterInfo->Io_Function,
+ Width,
+ 0,
+ Port,
+ 1,
+ (VOID *) (UINTN) (BuffAddr)
+ );
+ break;
+
+ case PXE_MEM_WRITE:
+ AdapterInfo->Io_Function->Mem.Write (
+ AdapterInfo->Io_Function,
+ Width,
+ 0,
+ Port,
+ 1,
+ (VOID *) (UINTN) (BuffAddr)
+ );
+ break;
+ }
+
+ return ;
+}
+
+EFI_STATUS
+AppendMac2DevPath (
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **DevPtr,
+ IN EFI_DEVICE_PATH_PROTOCOL *BaseDevPtr,
+ IN NIC_DATA_INSTANCE *AdapterInfo
+ )
+/*++
+
+Routine Description:
+
+ Using the NIC data structure information, read the EEPROM to get the MAC address and then allocate space
+ for a new devicepath (**DevPtr) which will contain the original device path the NIC was found on (*BaseDevPtr)
+ and an added MAC node.
+
+Arguments:
+
+ DevPtr - Pointer which will point to the newly created device path with the MAC node attached.
+
+ BaseDevPtr - Pointer to the device path which the UNDI device driver is latching on to.
+
+ AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on..
+
+Returns:
+
+ EFI_SUCCESS - A MAC address was successfully appended to the Base Device Path.
+
+ other - Not enough resources available to create new Device Path node.
+
+--*/
+{
+ EFI_MAC_ADDRESS MACAddress;
+ PCI_CONFIG_HEADER *CfgHdr;
+ INT32 Val;
+ INT32 Index;
+ INT32 Index2;
+ UINT8 AddrLen;
+ MAC_ADDR_DEVICE_PATH MacAddrNode;
+ EFI_DEVICE_PATH_PROTOCOL *EndNode;
+ UINT8 *DevicePtr;
+ UINT16 TotalPathLen;
+ UINT16 BasePathLen;
+ EFI_STATUS Status;
+
+ //
+ // set the environment ready (similar to UNDI_Start call) so that we can
+ // execute the other UNDI_ calls to get the mac address
+ // we are using undi 3.1 style
+ //
+ AdapterInfo->Delay = TmpDelay;
+ AdapterInfo->Virt2Phys = (VOID *) 0;
+ AdapterInfo->Block = (VOID *) 0;
+ AdapterInfo->Map_Mem = (VOID *) 0;
+ AdapterInfo->UnMap_Mem = (VOID *) 0;
+ AdapterInfo->Sync_Mem = (VOID *) 0;
+ AdapterInfo->Mem_Io = TmpMemIo;
+ //
+ // these tmp call-backs follow 3.1 undi style
+ // i.e. they have the unique_id parameter.
+ //
+ AdapterInfo->VersionFlag = 0x31;
+ AdapterInfo->Unique_ID = (UINT64) (UINTN) AdapterInfo;
+
+ //
+ // undi init portion
+ //
+ CfgHdr = (PCI_CONFIG_HEADER *) &(AdapterInfo->Config[0]);
+ AdapterInfo->ioaddr = 0;
+ AdapterInfo->RevID = CfgHdr->RevID;
+
+ AddrLen = E100bGetEepromAddrLen (AdapterInfo);
+
+ for (Index = 0, Index2 = 0; Index < 3; Index++) {
+ Val = E100bReadEeprom (AdapterInfo, Index, AddrLen);
+ MACAddress.Addr[Index2++] = (UINT8) Val;
+ MACAddress.Addr[Index2++] = (UINT8) (Val >> 8);
+ }
+
+ SetMem (MACAddress.Addr + Index2, sizeof (EFI_MAC_ADDRESS) - Index2, 0);
+ //for (; Index2 < sizeof (EFI_MAC_ADDRESS); Index2++) {
+ // MACAddress.Addr[Index2] = 0;
+ //}
+ //
+ // stop undi
+ //
+ AdapterInfo->Delay = (VOID *) 0;
+ AdapterInfo->Mem_Io = (VOID *) 0;
+
+ //
+ // fill the mac address node first
+ //
+ ZeroMem ((CHAR8 *) &MacAddrNode, sizeof MacAddrNode);
+ CopyMem (
+ (CHAR8 *) &MacAddrNode.MacAddress,
+ (CHAR8 *) &MACAddress,
+ sizeof (EFI_MAC_ADDRESS)
+ );
+
+ MacAddrNode.Header.Type = MESSAGING_DEVICE_PATH;
+ MacAddrNode.Header.SubType = MSG_MAC_ADDR_DP;
+ MacAddrNode.Header.Length[0] = sizeof (MacAddrNode);
+ MacAddrNode.Header.Length[1] = 0;
+
+ //
+ // find the size of the base dev path.
+ //
+ EndNode = BaseDevPtr;
+
+ while (!IsDevicePathEnd (EndNode)) {
+ EndNode = NextDevicePathNode (EndNode);
+ }
+
+ BasePathLen = (UINT16) ((UINTN) (EndNode) - (UINTN) (BaseDevPtr));
+
+ //
+ // create space for full dev path
+ //
+ TotalPathLen = (UINT16) (BasePathLen + sizeof (MacAddrNode) + sizeof (EFI_DEVICE_PATH_PROTOCOL));
+
+ Status = gBS->AllocatePool (
+ EfiRuntimeServicesData,
+ TotalPathLen,
+ (VOID **) &DevicePtr
+ );
+
+ if (Status != EFI_SUCCESS) {
+ return Status;
+ }
+ //
+ // copy the base path, mac addr and end_dev_path nodes
+ //
+ *DevPtr = (EFI_DEVICE_PATH_PROTOCOL *) DevicePtr;
+ CopyMem (DevicePtr, (CHAR8 *) BaseDevPtr, BasePathLen);
+ DevicePtr += BasePathLen;
+ CopyMem (DevicePtr, (CHAR8 *) &MacAddrNode, sizeof (MacAddrNode));
+ DevicePtr += sizeof (MacAddrNode);
+ CopyMem (DevicePtr, (CHAR8 *) EndNode, sizeof (EFI_DEVICE_PATH_PROTOCOL));
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+InstallConfigTable (
+ IN VOID
+ )
+/*++
+
+Routine Description:
+
+ Install a GUID/Pointer pair into the system's configuration table.
+
+Arguments:
+
+ none
+
+Returns:
+
+ EFI_SUCCESS - Install a GUID/Pointer pair into the system's configuration table.
+
+ other - Did not successfully install the GUID/Pointer pair into the configuration table.
+
+--*/
+// TODO: VOID - add argument and description to function comment
+{
+ EFI_STATUS Status;
+ EFI_CONFIGURATION_TABLE *CfgPtr;
+ NII_TABLE *TmpData;
+ UINT16 Index;
+ NII_TABLE *UndiData;
+
+ if (pxe_31 == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ if(UnidiDataPointer == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ UndiData = (NII_TABLE *)UnidiDataPointer;
+
+ UndiData->NumEntries = pxe_31->IFcnt;
+ UndiData->NextLink = NULL;
+
+ for (Index = 0; Index < pxe_31->IFcnt; Index++) {
+ UndiData->NiiEntry[Index].InterfacePointer = &UNDI32DeviceList[Index]->NIIProtocol_31;
+ UndiData->NiiEntry[Index].DevicePathPointer = UNDI32DeviceList[Index]->Undi32DevPath;
+ }
+
+ //
+ // see if there is an entry in the config table already
+ //
+ CfgPtr = gST->ConfigurationTable;
+
+ for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
+ Status = CompareGuid (
+ &CfgPtr->VendorGuid,
+ &gEfiNetworkInterfaceIdentifierProtocolGuid_31
+ );
+ if (Status != EFI_SUCCESS) {
+ break;
+ }
+
+ CfgPtr++;
+ }
+
+ if (Index < gST->NumberOfTableEntries) {
+ TmpData = (NII_TABLE *) CfgPtr->VendorTable;
+
+ //
+ // go to the last link
+ //
+ while (TmpData->NextLink != NULL) {
+ TmpData = TmpData->NextLink;
+ }
+
+ TmpData->NextLink = UndiData;
+
+ //
+ // 1st one in chain
+ //
+ UndiData = (NII_TABLE *) CfgPtr->VendorTable;
+ }
+
+ //
+ // create an entry in the configuration table for our GUID
+ //
+ Status = gBS->InstallConfigurationTable (
+ &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
+ UndiData
+ );
+ return Status;
+}
diff --git a/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Undi.mbd b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Undi.mbd
new file mode 100644
index 0000000..d486d63
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Undi.mbd
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MbdHeader>
+ <BaseName>Undi</BaseName>
+ <Guid>A1f436EA-A127-4EF8-957C-8048606FF670</Guid>
+ <Version>0</Version>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Created>2006-03-12 17:09</Created>
+ <Modified>2006-03-19 15:18</Modified>
+ </MbdHeader>
+ <Libraries>
+ <Library>UefiBootServicesTableLib</Library>
+ <Library>BaseLib</Library>
+ <Library>BaseMemoryLib</Library>
+ <Library>UefiLib</Library>
+ <Library>UefiDriverEntryPoint</Library>
+ <Library>DxeReportStatusCodeLib</Library>
+ <Library>BaseDebugLibNull</Library>
+ <Library>BasePrintLib</Library>
+ <Library>EdkDxeRuntimeDriverLib</Library>
+ <Library>UefiDriverModelLib</Library>
+ <Library>DxeHobLib</Library>
+ <Library>DxeMemoryAllocationLib</Library>
+ <Arch ArchType="IPF">
+ <Library>EdkDxeSalLib</Library>
+ </Arch>
+ </Libraries>
+</ModuleBuildDescription>
diff --git a/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Undi.msa b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Undi.msa
new file mode 100644
index 0000000..dcf0238
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Undi.msa
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MsaHeader>
+ <BaseName>Undi</BaseName>
+ <ModuleType>DXE_RUNTIME_DRIVER</ModuleType>
+ <ComponentType>RT_DRIVER</ComponentType>
+ <Guid>A1f436EA-A127-4EF8-957C-8048606FF670</Guid>
+ <Version>0</Version>
+ <Abstract>Component description file for DiskIo module.</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Specification>0</Specification>
+ <Created>2006-03-12 17:09</Created>
+ <Updated>2006-03-19 15:18</Updated>
+ </MsaHeader>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverEntryPoint</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiDriverModelLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DxeRuntimeDriverLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">HobLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">MemoryAllocationLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiBootServicesTableLib</LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>Init.c</Filename>
+ <Filename>Decode.c</Filename>
+ <Filename>E100b.c</Filename>
+ <Filename>E100b.h</Filename>
+ <Filename>Undi32.h</Filename>
+ </SourceFiles>
+ <Includes>
+ <PackageName>MdePkg</PackageName>
+ <PackageName>EdkModulePkg</PackageName>
+ </Includes>
+ <Protocols>
+ <Protocol Usage="TO_START">DevicePath</Protocol>
+ <Protocol Usage="TO_START">PciIo</Protocol>
+ <Protocol Usage="BY_START">NetworkInterfaceIdentifier</Protocol>
+ <Protocol Usage="BY_START">NetworkInterfaceIdentifier31</Protocol>
+ </Protocols>
+ <Events>
+ <CreateEvents>
+ <Event Usage="ALWAYS_CONSUMED" EventGroup="EVENT_GROUP_VIRTUAL_ADDRESS_CHANGE">
+ <C_Name>gEfiEventVirtualAddressChangeGuid</C_Name>
+ <Guid>0x13fa7698, 0xc831, 0x49c7, 0x87, 0xea, 0x8f, 0x43, 0xfc, 0xc2, 0x51, 0x96</Guid>
+ </Event>
+ <Event Usage="ALWAYS_CONSUMED" EventGroup="EVENT_GROUP_EXIT_BOOT_SERVICES">
+ <C_Name>gEfiEventExitBootServicesGuid</C_Name>
+ <Guid>0x27abf055, 0xb1b8, 0x4c26, 0x80, 0x48, 0x74, 0x8f, 0x37, 0xba, 0xa2, 0xdf</Guid>
+ </Event>
+ </CreateEvents>
+ </Events>
+ <SystemTables>
+ <SystemTable Usage="SOMETIMES_PRODUCED">
+ <Entry>gEfiNetworkInterfaceIdentifierProtocolGuid_31</Entry>
+ </SystemTable>
+ </SystemTables>
+ <Externs>
+ <Extern>
+ <ModuleEntryPoint>InitializeUNDIDriver</ModuleEntryPoint>
+ </Extern>
+ <Extern>
+ <DriverBinding>gUndiDriverBinding</DriverBinding>
+ </Extern>
+ <Extern>
+ <SetVirtualAddressMapCallBack>UndiNotifyVirtual</SetVirtualAddressMapCallBack>
+ <ExitBootServicesCallBack></ExitBootServicesCallBack>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea>
diff --git a/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Undi32.h b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Undi32.h
new file mode 100644
index 0000000..5e00443
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Undi32.h
@@ -0,0 +1,208 @@
+
+/*++
+
+Copyright (c) 2004, 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:
+
+ undi32.h
+
+Abstract:
+
+ EFI internal structures for the EFI UNDI driver
+
+
+
+Revision History
+
+--*/
+
+#ifndef _UNDI_32_H_
+#define _UNDI_32_H_
+
+
+#include "E100b.h"
+#include <IndustryStandard\pci22.h>
+
+#define MAX_NIC_INTERFACES 16
+
+#define EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION_31 0x00010001
+#define PXE_ROMID_MINORVER_31 0x10
+#define PXE_STATFLAGS_DB_WRITE_TRUNCATED 0x2000
+
+//
+// UNDI_CALL_TABLE.state can have the following values
+//
+#define DONT_CHECK -1
+#define ANY_STATE -1
+#define MUST_BE_STARTED 1
+#define MUST_BE_INITIALIZED 2
+
+#define UNDI_DEV_SIGNATURE EFI_SIGNATURE_32('u','n','d','i')
+#define UNDI_DEV_FROM_THIS(a) CR(a, UNDI32_DEV, NIIProtocol, UNDI_DEV_SIGNATURE)
+#define UNDI_DEV_FROM_NIC(a) CR(a, UNDI32_DEV, NicInfo, UNDI_DEV_SIGNATURE)
+
+typedef struct {
+ UINTN Signature;
+ EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL NIIProtocol;
+ EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL NIIProtocol_31;
+ EFI_HANDLE DeviceHandle;
+ EFI_DEVICE_PATH_PROTOCOL *Undi32BaseDevPath;
+ EFI_DEVICE_PATH_PROTOCOL *Undi32DevPath;
+ NIC_DATA_INSTANCE NicInfo;
+} UNDI32_DEV;
+
+typedef struct {
+ UINT16 cpbsize;
+ UINT16 dbsize;
+ UINT16 opflags;
+ UINT16 state;
+ VOID (*api_ptr)();
+} UNDI_CALL_TABLE;
+
+typedef struct {
+ EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *InterfacePointer;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathPointer;
+} NII_ENTRY;
+
+typedef struct NII_CONFIG_ENTRY {
+ UINT32 NumEntries;
+ UINT32 Reserved; // padding for alignment
+ struct NII_CONFIG_ENTRY *NextLink;
+ NII_ENTRY NiiEntry[1];
+} NII_TABLE;
+
+typedef VOID (*ptr)(VOID);
+typedef VOID (*bsptr_30)(UINTN);
+typedef VOID (*virtphys_30)(UINT64, UINT64);
+typedef VOID (*block_30)(UINT32);
+typedef VOID (*mem_io_30)(UINT8, UINT8, UINT64, UINT64);
+
+typedef VOID (*bsptr)(UINT64, UINTN);
+typedef VOID (*virtphys)(UINT64, UINT64, UINT64);
+typedef VOID (*block)(UINT64, UINT32);
+typedef VOID (*mem_io)(UINT64, UINT8, UINT8, UINT64, UINT64);
+
+typedef VOID (*map_mem)(UINT64, UINT64, UINT32, UINT32, UINT64);
+typedef VOID (*unmap_mem)(UINT64, UINT64, UINT32, UINT32, UINT64);
+typedef VOID (*sync_mem)(UINT64, UINT64, UINT32, UINT32, UINT64);
+
+//
+// functions defined in e100b.c
+//
+UINT8 InByte (NIC_DATA_INSTANCE *AdapterInfo, UINT32 Port);
+UINT16 InWord (NIC_DATA_INSTANCE *AdapterInfo, UINT32 Port);
+UINT32 InLong (NIC_DATA_INSTANCE *AdapterInfo, UINT32 Port);
+VOID OutByte (NIC_DATA_INSTANCE *AdapterInfo, UINT8 Data, UINT32 Port);
+VOID OutWord (NIC_DATA_INSTANCE *AdapterInfo, UINT16 Data, UINT32 Port);
+VOID OutLong (NIC_DATA_INSTANCE *AdapterInfo, UINT32 Data, UINT32 Port);
+
+UINTN E100bInit (NIC_DATA_INSTANCE *AdapterInfo);
+UINTN E100bReset (NIC_DATA_INSTANCE *AdapterInfo, INT32 OpFlags);
+UINTN E100bShutdown (NIC_DATA_INSTANCE *AdapterInfo);
+UINTN E100bTransmit (NIC_DATA_INSTANCE *AdapterInfo, UINT64 cpb, UINT16 opflags);
+UINTN E100bReceive (NIC_DATA_INSTANCE *AdapterInfo, UINT64 cpb, UINT64 db);
+UINTN E100bSetfilter (NIC_DATA_INSTANCE *AdapterInfo, UINT16 New_filter,
+ UINT64 cpb, UINT32 cpbsize);
+UINTN E100bStatistics(NIC_DATA_INSTANCE *AdapterInfo, UINT64 db, UINT16 dbsize);
+UINT8 E100bSetupIAAddr (NIC_DATA_INSTANCE *AdapterInfo);
+UINT8 E100bSetInterruptState (NIC_DATA_INSTANCE *AdapterInfo);
+
+UINT8 E100bGetEepromAddrLen (NIC_DATA_INSTANCE *AdapterInfo);
+UINT16 E100bReadEeprom (NIC_DATA_INSTANCE *AdapterInfo, INT32 Location, UINT8 address_len);
+INT16 E100bReadEepromAndStationAddress (NIC_DATA_INSTANCE *AdapterInfo);
+
+UINT16 next(UINT16);
+UINT8 SetupCBlink (NIC_DATA_INSTANCE *AdapterInfo);
+VOID SetFreeCB (NIC_DATA_INSTANCE *AdapterInfo,TxCB *);
+TxCB *GetFreeCB (NIC_DATA_INSTANCE *AdapterInfo);
+UINT16 CheckCBList (NIC_DATA_INSTANCE *AdapterInfo);
+
+UINT8 SelectiveReset (NIC_DATA_INSTANCE *AdapterInfo);
+UINT16 InitializeChip (NIC_DATA_INSTANCE *AdapterInfo);
+UINT8 SetupReceiveQueues (NIC_DATA_INSTANCE *AdapterInfo);
+VOID Recycle_RFD (NIC_DATA_INSTANCE *AdapterInfo, UINT16);
+VOID XmitWaitForCompletion (NIC_DATA_INSTANCE *AdapterInfo);
+INT8 CommandWaitForCompletion (TxCB *cmd_ptr, NIC_DATA_INSTANCE *AdapterInfo);
+
+BOOLEAN PhyDetect (NIC_DATA_INSTANCE *AdapterInfo);
+VOID PhyReset (NIC_DATA_INSTANCE *AdapterInfo);
+VOID
+MdiWrite (
+ IN NIC_DATA_INSTANCE *AdapterInfo,
+ IN UINT8 RegAddress,
+ IN UINT8 PhyAddress,
+ IN UINT16 DataValue
+ );
+
+VOID
+MdiRead(
+ IN NIC_DATA_INSTANCE *AdapterInfo,
+ IN UINT8 RegAddress,
+ IN UINT8 PhyAddress,
+ IN OUT UINT16 *DataValue
+ );
+
+BOOLEAN SetupPhy (NIC_DATA_INSTANCE *AdapterInfo);
+VOID FindPhySpeedAndDpx (NIC_DATA_INSTANCE *AdapterInfo, UINT32 PhyId);
+
+
+
+//
+// functions defined in init.c
+//
+VOID
+TmpDelay (
+ IN UINT64 UnqId,
+ IN UINTN MicroSeconds
+ );
+
+VOID
+TmpMemIo (
+ IN UINT64 UnqId,
+ IN UINT8 ReadWrite,
+ IN UINT8 Len,
+ IN UINT64 Port,
+ IN UINT64 BufAddr
+ );
+
+//
+// functions defined in decode.c
+//
+VOID UNDI_GetState();
+VOID UNDI_Start();
+VOID UNDI_Stop();
+VOID UNDI_GetInitInfo();
+VOID UNDI_GetConfigInfo();
+VOID UNDI_Initialize();
+VOID UNDI_Reset();
+VOID UNDI_Shutdown();
+VOID UNDI_Interrupt();
+VOID UNDI_RecFilter();
+VOID UNDI_StnAddr();
+VOID UNDI_Statistics();
+VOID UNDI_ip2mac();
+VOID UNDI_NVData();
+VOID UNDI_Status();
+VOID UNDI_FillHeader();
+VOID UNDI_Transmit();
+VOID UNDI_Receive();
+
+VOID UNDI_APIEntry_new(UINT64);
+VOID UNDI_APIEntry_old(UINT64);
+VOID UNDI_APIEntry_Common(UINT64);
+
+PXE_IPV4 convert_mcip(PXE_MAC_ADDR *);
+INT32 validate_mcip (PXE_MAC_ADDR *MCastAddr);
+
+VOID PxeStructInit (PXE_SW_UNDI *PxePtr, UINTN VersionFlag);
+VOID PxeUpdate (NIC_DATA_INSTANCE *NicPtr, PXE_SW_UNDI *PxePtr);
+
+#endif
diff --git a/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/build.xml b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/build.xml
new file mode 100644
index 0000000..2375cd7
--- /dev/null
+++ b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/build.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- 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.-->
+<project basedir="." default="Undi"><!--Apply external ANT tasks-->
+ <taskdef resource="GenBuild.tasks"/>
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+ <property environment="env"/>
+ <property name="WORKSPACE_DIR" value="${env.WORKSPACE}"/>
+ <import file="${WORKSPACE_DIR}\Tools\Conf\BuildMacro.xml"/><!--MODULE_RELATIVE PATH is relative to PACKAGE_DIR-->
+ <property name="MODULE_RELATIVE_PATH" value="Bus\Pci\Undi\RuntimeDxe"/>
+ <property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
+ <property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
+ <target name="Undi">
+ <GenBuild baseName="Undi" mbdFilename="${MODULE_DIR}\Undi.mbd" msaFilename="${MODULE_DIR}\Undi.msa"/>
+ </target>
+ <target depends="Undi_clean" name="clean"/>
+ <target depends="Undi_cleanall" name="cleanall"/>
+ <target name="Undi_clean">
+ <OutputDirSetup baseName="Undi" mbdFilename="${MODULE_DIR}\Undi.mbd" msaFilename="${MODULE_DIR}\Undi.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\Undi_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\Undi_build.xml" target="clean"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
+ </target>
+ <target name="Undi_cleanall">
+ <OutputDirSetup baseName="Undi" mbdFilename="${MODULE_DIR}\Undi.mbd" msaFilename="${MODULE_DIR}\Undi.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\Undi_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\Undi_build.xml" target="cleanall"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}"/>
+ <delete dir="${DEST_DIR_DEBUG}"/>
+ <delete>
+ <fileset dir="${BIN_DIR}" includes="**Undi*"/>
+ </delete>
+ </target>
+</project> \ No newline at end of file