/** Allocates pages that are suitable for an EfiUfsHcOperationBusMasterCommonBuffer mapping. @param This A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance. @param Type This parameter is not used and must be ignored. @param MemoryType The type of memory to allocate, EfiBootServicesData or EfiRuntimeServicesData. @param Pages The number of pages to allocate. @param HostAddress A pointer to store the base system memory address of the allocated range. @param Attributes The requested bit mask of attributes for the allocated range. @retval EFI_SUCCESS The requested memory pages were allocated. @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are MEMORY_WRITE_COMBINE and MEMORY_CACHED. @retval EFI_INVALID_PARAMETER One or more parameters are invalid. @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. **/ EFI_STATUS EFIAPI UfsHcAllocateBuffer ( IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This, IN EFI_ALLOCATE_TYPE Type, IN EFI_MEMORY_TYPE MemoryType, IN UINTN Pages, OUT VOID **HostAddress, IN UINT64 Attributes ) { UFS_HOST_CONTROLLER_PRIVATE_DATA *Private; EFI_PCI_IO_PROTOCOL *PciIo; EFI_STATUS Status; if ((This == NULL) || (HostAddress == NULL)) { return EFI_INVALID_PARAMETER; } Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This); PciIo = Private->PciIo; Status = PciIo->AllocateBuffer (PciIo, Type, MemoryType, Pages, HostAddress, Attributes); return Status; }
/** Provides the UFS controller-specific addresses needed to access system memory. @param This A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance. @param Operation Indicates if the bus master is going to read or write to system memory. @param HostAddress The system memory address to map to the UFS controller. @param NumberOfBytes On input the number of bytes to map. On output the number of bytes that were mapped. @param DeviceAddress The resulting map address for the bus master UFS controller to use to access the hosts HostAddress. @param Mapping A resulting value to pass to Unmap(). @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer. @retval EFI_INVALID_PARAMETER One or more parameters are invalid. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. **/ EFI_STATUS EFIAPI UfsHcMap ( IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This, IN EDKII_UFS_HOST_CONTROLLER_OPERATION Operation, IN VOID *HostAddress, IN OUT UINTN *NumberOfBytes, OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, OUT VOID **Mapping ) { UFS_HOST_CONTROLLER_PRIVATE_DATA *Private; EFI_PCI_IO_PROTOCOL *PciIo; EFI_STATUS Status; if ((This == NULL) || (HostAddress == NULL) || (NumberOfBytes == NULL) || (DeviceAddress == NULL) || (Mapping == NULL)) { return EFI_INVALID_PARAMETER; } Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This); PciIo = Private->PciIo; Status = PciIo->Map (PciIo, (EFI_PCI_IO_PROTOCOL_OPERATION)Operation, HostAddress, NumberOfBytes, DeviceAddress, Mapping); return Status; }
/** After we've pronounced support for a specific device in DriverBindingSupported(), we start managing said device (passed in by the Driver Execution Environment) with the following service. See DriverBindingSupported() for specification references. @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object incorporating this driver (independently of any device). @param[in] DeviceHandle The supported device to drive. @param[in] RemainingDevicePath Relevant only for bus drivers, ignored. @retval EFI_SUCCESS The device was started. @retval EFI_OUT_OF_RESOURCES Memory allocation failed. @return Error codes from the OpenProtocol() boot service, the PciIo protocol or the InstallProtocolInterface() boot service. **/ STATIC EFI_STATUS EFIAPI XenIoPciDeviceBindingStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE DeviceHandle, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; XENIO_PROTOCOL *XenIo; EFI_PCI_IO_PROTOCOL *PciIo; EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarDesc; XenIo = (XENIO_PROTOCOL *) AllocateZeroPool (sizeof *XenIo); if (XenIo == NULL) { return EFI_OUT_OF_RESOURCES; } Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, (VOID **)&PciIo, This->DriverBindingHandle, DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER); if (EFI_ERROR (Status)) { goto FreeXenIo; } // // The BAR1 of this PCI device is used for shared memory and is supposed to // look like MMIO. The address space of the BAR1 will be used to map the // Grant Table. // Status = PciIo->GetBarAttributes (PciIo, PCI_BAR_IDX1, NULL, (VOID**) &BarDesc); ASSERT_EFI_ERROR (Status); ASSERT (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM); /* Get a Memory address for mapping the Grant Table. */ DEBUG ((EFI_D_INFO, "XenIoPci: BAR at %LX\n", BarDesc->AddrRangeMin)); XenIo->GrantTableAddress = BarDesc->AddrRangeMin; FreePool (BarDesc); Status = gBS->InstallProtocolInterface (&DeviceHandle, &gXenIoProtocolGuid, EFI_NATIVE_INTERFACE, XenIo); if (!EFI_ERROR (Status)) { return EFI_SUCCESS; } gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, This->DriverBindingHandle, DeviceHandle); FreeXenIo: FreePool (XenIo); return Status; }
/** Flushes all posted write transactions from the UFS bus to attached UFS device. @param This A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance. @retval EFI_SUCCESS The posted write transactions were flushed from the UFS bus to attached UFS device. @retval EFI_DEVICE_ERROR The posted write transactions were not flushed from the UFS bus to attached UFS device due to a hardware error. **/ EFI_STATUS EFIAPI UfsHcFlush ( IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This ) { UFS_HOST_CONTROLLER_PRIVATE_DATA *Private; EFI_PCI_IO_PROTOCOL *PciIo; EFI_STATUS Status; Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This); PciIo = Private->PciIo; Status = PciIo->Flush (PciIo); return Status; }
/** Get the NIC's PCI location and return it accroding to the composited format defined in iSCSI Boot Firmware Table. @param[in] Controller The handle of the controller. @return UINT16 The composited representation of the NIC PCI location. @retval 0 Other errors as indicated. **/ UINT16 IScsiGetNICPciLocation ( IN EFI_HANDLE Controller ) { EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_HANDLE PciIoHandle; EFI_PCI_IO_PROTOCOL *PciIo; UINTN Segment; UINTN Bus; UINTN Device; UINTN Function; Status = gBS->HandleProtocol ( Controller, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath ); if (EFI_ERROR (Status)) { return 0; } Status = gBS->LocateDevicePath ( &gEfiPciIoProtocolGuid, &DevicePath, &PciIoHandle ); if (EFI_ERROR (Status)) { return 0; } Status = gBS->HandleProtocol (PciIoHandle, &gEfiPciIoProtocolGuid, (VOID **)&PciIo); if (EFI_ERROR (Status)) { return 0; } Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function); if (EFI_ERROR (Status)) { return 0; } return (UINT16) ((Bus << 8) | (Device << 3) | Function); }
/** Completes the Map() operation and releases any corresponding resources. @param This A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance. @param Mapping The mapping value returned from Map(). @retval EFI_SUCCESS The range was unmapped. @retval EFI_DEVICE_ERROR The data was not committed to the target system memory. **/ EFI_STATUS EFIAPI UfsHcUnmap ( IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This, IN VOID *Mapping ) { UFS_HOST_CONTROLLER_PRIVATE_DATA *Private; EFI_PCI_IO_PROTOCOL *PciIo; EFI_STATUS Status; if ((This == NULL) || (Mapping == NULL)) { return EFI_INVALID_PARAMETER; } Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This); PciIo = Private->PciIo; Status = PciIo->Unmap (PciIo, Mapping); return Status; }
/** Free the memory block from the memory pool. @param Pool The memory pool to free the block from. @param Block The memory block to free. **/ VOID UsbHcFreeMemBlock ( IN USBHC_MEM_POOL *Pool, IN USBHC_MEM_BLOCK *Block ) { EFI_PCI_IO_PROTOCOL *PciIo; ASSERT ((Pool != NULL) && (Block != NULL)); PciIo = Pool->PciIo; // // Unmap the common buffer then free the structures // PciIo->Unmap (PciIo, Block->Mapping); PciIo->FreeBuffer (PciIo, EFI_SIZE_TO_PAGES (Block->BufLen), Block->BufHost); gBS->FreePool (Block->Bits); gBS->FreePool (Block); }
/** Frees memory that was allocated with AllocateBuffer(). @param This A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance. @param Pages The number of pages to free. @param HostAddress The base system memory address of the allocated range. @retval EFI_SUCCESS The requested memory pages were freed. @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages was not allocated with AllocateBuffer(). **/ EFI_STATUS EFIAPI UfsHcFreeBuffer ( IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This, IN UINTN Pages, IN VOID *HostAddress ) { UFS_HOST_CONTROLLER_PRIVATE_DATA *Private; EFI_PCI_IO_PROTOCOL *PciIo; EFI_STATUS Status; if ((This == NULL) || (HostAddress == NULL)) { return EFI_INVALID_PARAMETER; } Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This); PciIo = Private->PciIo; Status = PciIo->FreeBuffer (PciIo, Pages, HostAddress); return Status; }
/** Get the MMIO base of the UFS host controller. @param[in] This A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance. @param[out] MmioBar The MMIO base address of UFS host controller. @retval EFI_SUCCESS The operation succeeds. @retval others The operation fails. **/ EFI_STATUS EFIAPI UfsHcGetMmioBar ( IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This, OUT UINTN *MmioBar ) { UFS_HOST_CONTROLLER_PRIVATE_DATA *Private; EFI_PCI_IO_PROTOCOL *PciIo; EFI_STATUS Status; UINT8 BarIndex; EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarDesc; if ((This == NULL) || (MmioBar == NULL)) { return EFI_INVALID_PARAMETER; } BarDesc = NULL; Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This); PciIo = Private->PciIo; BarIndex = Private->BarIndex; Status = PciIo->GetBarAttributes ( PciIo, BarIndex, NULL, (VOID**) &BarDesc ); if (EFI_ERROR (Status)) { return Status; } *MmioBar = (UINTN)BarDesc->AddrRangeMin; FreePool (BarDesc); return Status; }
EFI_STATUS EFIAPI GetPciRom ( IN CONST EFI_PCI_PLATFORM_PROTOCOL *This, IN EFI_HANDLE PciHandle, OUT VOID **RomImage, OUT UINTN *RomSize ) { EFI_STATUS Status; EFI_PCI_IO_PROTOCOL *PciIo; EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; UINTN Segment; UINTN Bus; UINTN Device; UINTN Function; UINT16 VendorId; UINT16 DeviceId; UINT16 DeviceClass; UINTN TableIndex; UINT8 Data8; BOOLEAN MfgMode; EFI_PLATFORM_SETUP_ID *BootModeBuffer; EFI_PEI_HOB_POINTERS GuidHob; MfgMode = FALSE; // // Check if system is in manufacturing mode. // GuidHob.Raw = GetHobList (); if (GuidHob.Raw == NULL) { return EFI_NOT_FOUND; } if ((GuidHob.Raw = GetNextGuidHob (&gEfiPlatformBootModeGuid, GuidHob.Raw)) != NULL) { BootModeBuffer = GET_GUID_HOB_DATA (GuidHob.Guid); if (!CompareMem (&BootModeBuffer->SetupName, MANUFACTURE_SETUP_NAME, StrSize (MANUFACTURE_SETUP_NAME))) { // // System is in manufacturing mode. // MfgMode = TRUE; } } Status = gBS->HandleProtocol ( PciHandle, &gEfiPciIoProtocolGuid, (void **)&PciIo ); if (EFI_ERROR (Status)) { return EFI_NOT_FOUND; } Status = gBS->LocateProtocol ( &gEfiPciRootBridgeIoProtocolGuid, NULL, (void **)&PciRootBridgeIo ); if (EFI_ERROR (Status)) { return EFI_NOT_FOUND; } PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, 0x0A, 1, &DeviceClass); PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function); PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, 0, 1, &VendorId); PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, 2, 1, &DeviceId); // // WA for PCIe SATA card (SYBA SY-PEX400-40) // if ((VendorId == 0x1B21) && (DeviceId == 0x0612)) { Data8 = 0x07; PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 4, 1, &Data8); } // // Do not run RAID or AHCI Option ROM if IDE // if ( (DeviceClass == ((PCI_CLASS_MASS_STORAGE << 8 ) | PCI_CLASS_MASS_STORAGE_IDE)) ) { return EFI_NOT_FOUND; } // // Run PXE ROM only if Boot network is enabled and not in MFG mode // if (DeviceClass == ((PCI_CLASS_NETWORK << 8 ) | PCI_CLASS_NETWORK_ETHERNET)) { if (((mSystemConfiguration.BootNetwork == 0) && (MfgMode == FALSE )) || (mSystemConfiguration.FastBoot == 1)) { return EFI_NOT_FOUND; } } // // Loop through table of Onboard option rom descriptions // for (TableIndex = 0; mPciOptionRomTable[TableIndex].VendorId != 0xffff; TableIndex++) { // // See if the PCI device specified by PciHandle matches at device in mPciOptionRomTable // if (VendorId != mPciOptionRomTable[TableIndex].VendorId || DeviceId != mPciOptionRomTable[TableIndex].DeviceId || ((DeviceClass == ((PCI_CLASS_NETWORK << 8 ) | PCI_CLASS_NETWORK_ETHERNET)) && (mPciOptionRomTable[TableIndex].Flag != mSystemConfiguration.BootNetwork)) ) { continue; } Status = GetRawImage( &mPciOptionRomTable[TableIndex].FileName, RomImage, RomSize ); if ((VendorId == IGD_VID) && (DeviceId == IGD_DID_VLV_A0)) { *(UINT16 *)(((UINTN) *RomImage) + OPROM_DID_OFFSET) = IGD_DID_VLV_A0; } if ((VendorId == IGD_VID) && (DeviceId == IGD_DID_II)) { *(UINT16 *)(((UINTN) *RomImage) + OPROM_DID_OFFSET) = IGD_DID_II; } if ((VendorId == IGD_VID) && (DeviceId == IGD_DID_0BE4)) { *(UINT16 *)(((UINTN) *RomImage) + OPROM_DID_OFFSET) = IGD_DID_0BE4; } if ((VendorId == IGD_VID) && (DeviceId == IGD_DID_QS)) { *(UINT16 *)(((UINTN) *RomImage) + OPROM_DID_OFFSET) = IGD_DID_QS; } if (EFI_ERROR (Status)) { continue; } return EFI_SUCCESS; } return EFI_NOT_FOUND; }
/** Stop this driver on ControllerHandle. This service is called by the EFI boot service DisconnectController(). In order to make drivers as small as possible, there are a few calling restrictions for this service. DisconnectController() must follow these calling restrictions. If any other agent wishes to call Stop() it must also follow these calling restrictions. @param This Protocol instance pointer. @param ControllerHandle Handle of device to stop driver on @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of children is zero stop the entire bus driver. @param ChildHandleBuffer List of Child Handles to Stop. @retval EFI_SUCCESS This driver is removed ControllerHandle @retval other This driver was not removed from this device **/ EFI_STATUS EFIAPI SimpleNetworkDriverStop ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer ) { EFI_STATUS Status; EFI_SIMPLE_NETWORK_PROTOCOL *SnpProtocol; SNP_DRIVER *Snp; EFI_PCI_IO_PROTOCOL *PciIo; // // Get our context back. // Status = gBS->OpenProtocol ( Controller, &gEfiSimpleNetworkProtocolGuid, (VOID **) &SnpProtocol, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { return EFI_UNSUPPORTED; } Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SnpProtocol); Status = gBS->UninstallProtocolInterface ( Controller, &gEfiSimpleNetworkProtocolGuid, &Snp->Snp ); if (EFI_ERROR (Status)) { return Status; } // // Close EXIT_BOOT_SERIVES Event // gBS->CloseEvent (Snp->ExitBootServicesEvent); Status = gBS->CloseProtocol ( Controller, &gEfiNetworkInterfaceIdentifierProtocolGuid_31, This->DriverBindingHandle, Controller ); Status = gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); PxeShutdown (Snp); PxeStop (Snp); FreePool (Snp->RecycledTxBuf); PciIo = Snp->PciIo; PciIo->FreeBuffer ( PciIo, SNP_MEM_PAGES (4096), Snp->Cpb ); PciIo->FreeBuffer ( PciIo, SNP_MEM_PAGES (sizeof (SNP_DRIVER)), Snp ); return Status; }
/** ControllerDriver Protocol Method @param This Driver Binding protocol instance pointer. @param Controller Handle of device to test. @param RemainingDevicePath Optional parameter use to pick a specific child device to start. @retval EFI_SUCCESS This driver supports this device. @retval other This driver does not support this device. **/ EFI_STATUS EFIAPI PcatIsaAcpiDriverBindingSupported ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; EFI_PCI_IO_PROTOCOL *PciIo; PCI_TYPE00 Pci; UINTN SegmentNumber; UINTN BusNumber; UINTN DeviceNumber; UINTN FunctionNumber; // // Get PciIo protocol instance // 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, EfiPciIoWidthUint32, 0, sizeof(Pci) / sizeof(UINT32), &Pci); if (!EFI_ERROR (Status)) { Status = EFI_UNSUPPORTED; if ((Pci.Hdr.Command & 0x03) == 0x03) { if (Pci.Hdr.ClassCode[2] == PCI_CLASS_BRIDGE) { // // See if this is a standard PCI to ISA Bridge from the Base Code and Class Code // if (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA) { Status = EFI_SUCCESS; } // // See if this is an Intel PCI to ISA bridge in Positive Decode Mode // if (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA_PDECODE && Pci.Hdr.VendorId == 0x8086 ) { // // See if this is on Function #0 to avoid false positives on // PCI_CLASS_BRIDGE_OTHER that has the same value as // PCI_CLASS_BRIDGE_ISA_PDECODE // Status = PciIo->GetLocation ( PciIo, &SegmentNumber, &BusNumber, &DeviceNumber, &FunctionNumber ); if (!EFI_ERROR (Status) && FunctionNumber == 0) { Status = EFI_SUCCESS; } else { Status = EFI_UNSUPPORTED; } } } } } gBS->CloseProtocol ( Controller, &gEfiPciIoProtocolGuid, This->DriverBindingHandle, Controller ); return Status; }
// //TDS 4.3.2 // EFI_STATUS GetAndSetBarAttributes_Stress ( IN EFI_BB_TEST_PROTOCOL *This, IN VOID *ClientInterface, IN EFI_TEST_LEVEL TestLevel, IN EFI_HANDLE SupportHandle ) { EFI_STATUS Status; PCI_IO_PROTOCOL_DEVICE *PciIoDevice; EFI_PCI_IO_PROTOCOL *PciIo; EFI_STANDARD_TEST_LIBRARY_PROTOCOL *StandardLib; EFI_TEST_ASSERTION AssertionType; UINTN Index; UINTN SubIndex; UINT8 BarIndex; UINT64 DevSupportedAttributes; UINT64 BarOriginalAttributes; UINT64 AddressOffset; UINT64 AddressLength; VOID *Resources; UINTN PciIoAttributesNumber; UINT64 ThisAttribute; // //get tested interface. // PciIo = (EFI_PCI_IO_PROTOCOL *)ClientInterface; // // Get the Standard Library Interface // Status = gtBS->HandleProtocol ( SupportHandle, &gEfiStandardTestLibraryGuid, &StandardLib ); if (EFI_ERROR(Status)) { return Status; } // //get PciIoDevice struct pointer. // PciIoDevice = NULL; PciIoDevice = GetPciIoDevice (PciIo); if (PciIoDevice == NULL) { return EFI_ABORTED; } InitializeCaseEnvironment (); // //print the device path of pci device. // Status = PrintPciIoDevice (PciIoDevice->DevicePath); if (EFI_ERROR(Status)) { return Status; } Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationSupported, 0, &DevSupportedAttributes ); if (!EFI_ERROR(Status)) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } // //record assertion // StandardLib->RecordAssertion ( StandardLib, AssertionType, gTestGenericFailureGuid, L"EFI_PCI_IO_PROTOCOL.Attributes - return status must be EFI_SUCCESS.", L"%a:%d:Status - %r", __FILE__, __LINE__, Status ); for (Index = 0; Index < REGNUM; Index++) { BarIndex = (UINT8)Index; Resources = 0; Status = PciIo->GetBarAttributes ( PciIo, BarIndex, &BarOriginalAttributes, &Resources ); if (!EFI_ERROR(Status)) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } // //record assertion // StandardLib->RecordAssertion ( StandardLib, AssertionType, gPciIoBBTestStressAssertionGuid019, L"EFI_PCI_IO_PROTOCOL.GetBarAttributes - return status must be EFI_SUCCESS.", L"%a:%d:Status - %r, BarIndex - %d", __FILE__, __LINE__, Status, BarIndex ); if (IsValidResourceDescrptor (Resources)) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } // //record assertion // StandardLib->RecordAssertion ( StandardLib, AssertionType, gPciIoBBTestStressAssertionGuid020, L"EFI_PCI_IO_PROTOCOL.GetBarAttributes - the Resource Descriptor List must be valid", L"%a:%d", __FILE__, __LINE__ ); // //free the resources if necessory. // if (Status == EFI_SUCCESS) { gtBS->FreePool (Resources); } // //the attribute supported by this bar must be in the device supported attributes range. // if ((BarOriginalAttributes & DevSupportedAttributes) == BarOriginalAttributes) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } // //record assertion // StandardLib->RecordAssertion ( StandardLib, AssertionType, gPciIoBBTestStressAssertionGuid021, L"EFI_PCI_IO_PROTOCOL.GetBarAttributes - Bar supported attributes must in the range of Device supproted attributes", L"%a:%d:Bar Supported - %lXh, Dev Supported - %lXh", __FILE__, __LINE__, BarOriginalAttributes, DevSupportedAttributes ); // //Invalid bar then continue; // if (!PciIoDevice->BarHasEffect[BarIndex]) { continue; } AddressOffset = 0; AddressLength = PciIoDevice->BarLength[BarIndex]; PciIoAttributesNumber = 19; // //for each attributes call SetBarAttributes // for (SubIndex = 0; SubIndex < PciIoAttributesNumber; SubIndex++) { ThisAttribute = 1 << SubIndex; Status = PciIo->SetBarAttributes ( PciIo, ThisAttribute, BarIndex, &AddressOffset, &AddressLength ); if ((ThisAttribute & BarOriginalAttributes) == ThisAttribute) { if (!EFI_ERROR(Status)) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } // //record assertion // StandardLib->RecordAssertion ( StandardLib, AssertionType, gPciIoBBTestStressAssertionGuid022, L"EFI_PCI_IO_PROTOCOL.SetBarAttributes - Set Bar supported attributes return Staus Must be EFI_SUCCESS", L"%a:%d:Set Attribute - %lXh, Supported Attributes - %lXh", __FILE__, __LINE__, ThisAttribute, BarOriginalAttributes ); } else { // //Unsupported attributes // if (Status == EFI_UNSUPPORTED) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } // //record assertion // StandardLib->RecordAssertion ( StandardLib, AssertionType, gPciIoBBTestStressAssertionGuid023, L"EFI_PCI_IO_PROTOCOL.SetBarAttributes - Set Unsupported attributes status must be EFI_UNSUPPORTED.", L"%a:%d:Set Attribute - %lXh, Supported Attributes - %lXh", __FILE__, __LINE__, ThisAttribute, BarOriginalAttributes ); } } } // //done successfully // return EFI_SUCCESS; }
/** Stops a device controller or a bus controller. The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). As a result, much of the error checking on the parameters to Stop() has been moved into this common boot service. It is legal to call Stop() from other locations, but the following calling restrictions must be followed or the system behavior will not be deterministic. 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this same driver's Start() function. 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid EFI_HANDLE. In addition, all of these handles must have been created in this driver's Start() function, and the Start() function must have called OpenProtocol() on ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. @param[in] ControllerHandle A handle to the device being stopped. The handle must support a bus specific I/O protocol for the driver to use to stop the device. @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL if NumberOfChildren is 0. @retval EFI_SUCCESS The device was stopped. @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. **/ EFI_STATUS EFIAPI SdMmcPciHcDriverBindingStop ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer ) { EFI_STATUS Status; EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru; SD_MMC_HC_PRIVATE_DATA *Private; EFI_PCI_IO_PROTOCOL *PciIo; LIST_ENTRY *Link; LIST_ENTRY *NextLink; SD_MMC_HC_TRB *Trb; DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStop: Start\n")); Status = gBS->OpenProtocol ( Controller, &gEfiSdMmcPassThruProtocolGuid, (VOID**) &PassThru, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { return Status; } Private = SD_MMC_HC_PRIVATE_FROM_THIS (PassThru); // // Close Non-Blocking timer and free Task list. // if (Private->TimerEvent != NULL) { gBS->CloseEvent (Private->TimerEvent); Private->TimerEvent = NULL; } if (Private->ConnectEvent != NULL) { gBS->CloseEvent (Private->ConnectEvent); Private->ConnectEvent = NULL; } // // As the timer is closed, there is no needs to use TPL lock to // protect the critical region "queue". // for (Link = GetFirstNode (&Private->Queue); !IsNull (&Private->Queue, Link); Link = NextLink) { NextLink = GetNextNode (&Private->Queue, Link); RemoveEntryList (Link); Trb = SD_MMC_HC_TRB_FROM_THIS (Link); Trb->Packet->TransactionStatus = EFI_ABORTED; gBS->SignalEvent (Trb->Event); SdMmcFreeTrb (Trb); } // // Uninstall Block I/O protocol from the device handle // Status = gBS->UninstallProtocolInterface ( Controller, &gEfiSdMmcPassThruProtocolGuid, &(Private->PassThru) ); if (EFI_ERROR (Status)) { return Status; } gBS->CloseProtocol ( Controller, &gEfiPciIoProtocolGuid, This->DriverBindingHandle, Controller ); // // Restore original PCI attributes // PciIo = Private->PciIo; Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationSet, Private->PciAttributes, NULL ); ASSERT_EFI_ERROR (Status); FreePool (Private); DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStop: End with %r\n", Status)); return Status; }
/** Starts a device controller or a bus controller. The Start() function is designed to be invoked from the EFI boot service ConnectController(). As a result, much of the error checking on the parameters to Start() has been moved into this common boot service. It is legal to call Start() from other locations, but the following calling restrictions must be followed or the system behavior will not be deterministic. 1. ControllerHandle must be a valid EFI_HANDLE. 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned EFI_DEVICE_PATH_PROTOCOL. 3. Prior to calling Start(), the Supported() function for the driver specified by This must have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. @param[in] ControllerHandle The handle of the controller to start. This handle must support a protocol interface that supplies an I/O abstraction to the driver. @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This parameter is ignored by device drivers, and is optional for bus drivers. For a bus driver, if this parameter is NULL, then handles for all the children of Controller are created by this driver. If this parameter is not NULL and the first Device Path Node is not the End of Device Path Node, then only the handle for the child device specified by the first Device Path Node of RemainingDevicePath is created by this driver. If the first Device Path Node of RemainingDevicePath is the End of Device Path Node, no child handle is created by this driver. @retval EFI_SUCCESS The device was started. @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. @retval Others The driver failded to start the device. **/ EFI_STATUS EFIAPI SdMmcPciHcDriverBindingStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; SD_MMC_HC_PRIVATE_DATA *Private; EFI_PCI_IO_PROTOCOL *PciIo; UINT64 Supports; UINT64 PciAttributes; UINT8 SlotNum; UINT8 FirstBar; UINT8 Slot; UINT8 Index; CARD_TYPE_DETECT_ROUTINE *Routine; UINT32 RoutineNum; BOOLEAN MediaPresent; BOOLEAN Support64BitDma; DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStart: Start\n")); // // Open PCI I/O Protocol and save pointer to open protocol // in private data area. // PciIo = NULL; Status = gBS->OpenProtocol ( Controller, &gEfiPciIoProtocolGuid, (VOID **) &PciIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { return Status; } // // Enable the SD Host Controller MMIO space // Private = NULL; Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationGet, 0, &PciAttributes ); if (EFI_ERROR (Status)) { goto Done; } Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationSupported, 0, &Supports ); if (!EFI_ERROR (Status)) { Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE; Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationEnable, Supports, NULL ); } else { goto Done; } Private = AllocateCopyPool (sizeof (SD_MMC_HC_PRIVATE_DATA), &gSdMmcPciHcTemplate); if (Private == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Done; } Private->ControllerHandle = Controller; Private->PciIo = PciIo; Private->PciAttributes = PciAttributes; InitializeListHead (&Private->Queue); // // Get SD/MMC Pci Host Controller Slot info // Status = SdMmcHcGetSlotInfo (PciIo, &FirstBar, &SlotNum); if (EFI_ERROR (Status)) { goto Done; } Support64BitDma = TRUE; for (Slot = FirstBar; Slot < (FirstBar + SlotNum); Slot++) { Private->Slot[Slot].Enable = TRUE; Status = SdMmcHcGetCapability (PciIo, Slot, &Private->Capability[Slot]); if (EFI_ERROR (Status)) { continue; } DumpCapabilityReg (Slot, &Private->Capability[Slot]); Support64BitDma &= Private->Capability[Slot].SysBus64; Status = SdMmcHcGetMaxCurrent (PciIo, Slot, &Private->MaxCurrent[Slot]); if (EFI_ERROR (Status)) { continue; } Private->Slot[Slot].SlotType = Private->Capability[Slot].SlotType; if ((Private->Slot[Slot].SlotType != RemovableSlot) && (Private->Slot[Slot].SlotType != EmbeddedSlot)) { DEBUG ((DEBUG_INFO, "SdMmcPciHcDxe doesn't support the slot type [%d]!!!\n", Private->Slot[Slot].SlotType)); continue; } // // Reset the specified slot of the SD/MMC Pci Host Controller // Status = SdMmcHcReset (PciIo, Slot); if (EFI_ERROR (Status)) { continue; } // // Check whether there is a SD/MMC card attached // Status = SdMmcHcCardDetect (PciIo, Slot, &MediaPresent); if (EFI_ERROR (Status) && (Status != EFI_MEDIA_CHANGED)) { continue; } else if (!MediaPresent) { DEBUG ((DEBUG_INFO, "SdMmcHcCardDetect: No device attached in Slot[%d]!!!\n", Slot)); continue; } Status = SdMmcHcInitHost (PciIo, Slot, Private->Capability[Slot]); if (EFI_ERROR (Status)) { continue; } Private->Slot[Slot].MediaPresent = TRUE; Private->Slot[Slot].Initialized = TRUE; RoutineNum = sizeof (mCardTypeDetectRoutineTable) / sizeof (CARD_TYPE_DETECT_ROUTINE); for (Index = 0; Index < RoutineNum; Index++) { Routine = &mCardTypeDetectRoutineTable[Index]; if (*Routine != NULL) { Status = (*Routine) (Private, Slot); if (!EFI_ERROR (Status)) { break; } } } // // This card doesn't get initialized correctly. // if (Index == RoutineNum) { Private->Slot[Slot].Initialized = FALSE; } } // // Enable 64-bit DMA support in the PCI layer if this controller // supports it. // if (Support64BitDma) { Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationEnable, EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE, NULL ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_WARN, "SdMmcPciHcDriverBindingStart: failed to enable 64-bit DMA (%r)\n", Status)); } } // // Start the asynchronous I/O monitor // Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_NOTIFY, ProcessAsyncTaskList, Private, &Private->TimerEvent ); if (EFI_ERROR (Status)) { goto Done; } Status = gBS->SetTimer (Private->TimerEvent, TimerPeriodic, SD_MMC_HC_ASYNC_TIMER); if (EFI_ERROR (Status)) { goto Done; } // // Start the Sd removable device connection enumeration // Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, SdMmcPciHcEnumerateDevice, Private, &Private->ConnectEvent ); if (EFI_ERROR (Status)) { goto Done; } Status = gBS->SetTimer (Private->ConnectEvent, TimerPeriodic, SD_MMC_HC_ENUM_TIMER); if (EFI_ERROR (Status)) { goto Done; } Status = gBS->InstallMultipleProtocolInterfaces ( &Controller, &gEfiSdMmcPassThruProtocolGuid, &(Private->PassThru), NULL ); DEBUG ((DEBUG_INFO, "SdMmcPciHcDriverBindingStart: %r End on %x\n", Status, Controller)); Done: if (EFI_ERROR (Status)) { if ((Private != NULL) && (Private->PciAttributes != 0)) { // // Restore original PCI attributes // PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationSet, Private->PciAttributes, NULL ); } gBS->CloseProtocol ( Controller, &gEfiPciIoProtocolGuid, This->DriverBindingHandle, Controller ); if ((Private != NULL) && (Private->TimerEvent != NULL)) { gBS->CloseEvent (Private->TimerEvent); } if ((Private != NULL) && (Private->ConnectEvent != NULL)) { gBS->CloseEvent (Private->ConnectEvent); } if (Private != NULL) { FreePool (Private); } } return Status; }
/** Starts a device controller or a bus controller. The Start() function is designed to be invoked from the EFI boot service ConnectController(). As a result, much of the error checking on the parameters to Start() has been moved into this common boot service. It is legal to call Start() from other locations, but the following calling restrictions must be followed or the system behavior will not be deterministic. 1. ControllerHandle must be a valid EFI_HANDLE. 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned EFI_DEVICE_PATH_PROTOCOL. 3. Prior to calling Start(), the Supported() function for the driver specified by This must have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. @param[in] ControllerHandle The handle of the controller to start. This handle must support a protocol interface that supplies an I/O abstraction to the driver. @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This parameter is ignored by device drivers, and is optional for bus drivers. For a bus driver, if this parameter is NULL, then handles for all the children of Controller are created by this driver. If this parameter is not NULL and the first Device Path Node is not the End of Device Path Node, then only the handle for the child device specified by the first Device Path Node of RemainingDevicePath is created by this driver. If the first Device Path Node of RemainingDevicePath is the End of Device Path Node, no child handle is created by this driver. @retval EFI_SUCCESS The device was started. @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. @retval Others The driver failded to start the device. **/ EFI_STATUS EFIAPI NvmExpressDriverBindingStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; EFI_PCI_IO_PROTOCOL *PciIo; NVME_CONTROLLER_PRIVATE_DATA *Private; EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; UINT32 NamespaceId; EFI_PHYSICAL_ADDRESS MappedAddr; UINTN Bytes; EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *Passthru; DEBUG ((EFI_D_INFO, "NvmExpressDriverBindingStart: start\n")); Private = NULL; Passthru = NULL; ParentDevicePath = NULL; 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; } Status = gBS->OpenProtocol ( Controller, &gEfiPciIoProtocolGuid, (VOID **) &PciIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) { return Status; } // // Check EFI_ALREADY_STARTED to reuse the original NVME_CONTROLLER_PRIVATE_DATA. // if (Status != EFI_ALREADY_STARTED) { Private = AllocateZeroPool (sizeof (NVME_CONTROLLER_PRIVATE_DATA)); if (Private == NULL) { DEBUG ((EFI_D_ERROR, "NvmExpressDriverBindingStart: allocating pool for Nvme Private Data failed!\n")); Status = EFI_OUT_OF_RESOURCES; goto Exit; } // // 6 x 4kB aligned buffers will be carved out of this buffer. // 1st 4kB boundary is the start of the admin submission queue. // 2nd 4kB boundary is the start of the admin completion queue. // 3rd 4kB boundary is the start of I/O submission queue #1. // 4th 4kB boundary is the start of I/O completion queue #1. // 5th 4kB boundary is the start of I/O submission queue #2. // 6th 4kB boundary is the start of I/O completion queue #2. // // Allocate 6 pages of memory, then map it for bus master read and write. // Status = PciIo->AllocateBuffer ( PciIo, AllocateAnyPages, EfiBootServicesData, 6, (VOID**)&Private->Buffer, 0 ); if (EFI_ERROR (Status)) { goto Exit; } Bytes = EFI_PAGES_TO_SIZE (6); Status = PciIo->Map ( PciIo, EfiPciIoOperationBusMasterCommonBuffer, Private->Buffer, &Bytes, &MappedAddr, &Private->Mapping ); if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (6))) { goto Exit; } Private->BufferPciAddr = (UINT8 *)(UINTN)MappedAddr; Private->Signature = NVME_CONTROLLER_PRIVATE_DATA_SIGNATURE; Private->ControllerHandle = Controller; Private->ImageHandle = This->DriverBindingHandle; Private->DriverBindingHandle = This->DriverBindingHandle; Private->PciIo = PciIo; Private->ParentDevicePath = ParentDevicePath; Private->Passthru.Mode = &Private->PassThruMode; Private->Passthru.PassThru = NvmExpressPassThru; Private->Passthru.GetNextNamespace = NvmExpressGetNextNamespace; Private->Passthru.BuildDevicePath = NvmExpressBuildDevicePath; Private->Passthru.GetNamespace = NvmExpressGetNamespace; CopyMem (&Private->PassThruMode, &gEfiNvmExpressPassThruMode, sizeof (EFI_NVM_EXPRESS_PASS_THRU_MODE)); InitializeListHead (&Private->AsyncPassThruQueue); InitializeListHead (&Private->UnsubmittedSubtasks); Status = NvmeControllerInit (Private); if (EFI_ERROR(Status)) { goto Exit; } // // Start the asynchronous I/O completion monitor // Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_NOTIFY, ProcessAsyncTaskList, Private, &Private->TimerEvent ); if (EFI_ERROR (Status)) { goto Exit; } Status = gBS->SetTimer ( Private->TimerEvent, TimerPeriodic, NVME_HC_ASYNC_TIMER ); if (EFI_ERROR (Status)) { goto Exit; } Status = gBS->InstallMultipleProtocolInterfaces ( &Controller, &gEfiNvmExpressPassThruProtocolGuid, &Private->Passthru, NULL ); if (EFI_ERROR (Status)) { goto Exit; } NvmeRegisterShutdownNotification (); } else { Status = gBS->OpenProtocol ( Controller, &gEfiNvmExpressPassThruProtocolGuid, (VOID **) &Passthru, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { goto Exit; } Private = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (Passthru); } if (RemainingDevicePath == NULL) { // // Enumerate all NVME namespaces in the controller // Status = DiscoverAllNamespaces ( Private ); } else if (!IsDevicePathEnd (RemainingDevicePath)) { // // Enumerate the specified NVME namespace // Status = Private->Passthru.GetNamespace ( &Private->Passthru, RemainingDevicePath, &NamespaceId ); if (!EFI_ERROR (Status)) { Status = EnumerateNvmeDevNamespace ( Private, NamespaceId ); } } DEBUG ((EFI_D_INFO, "NvmExpressDriverBindingStart: end successfully\n")); return EFI_SUCCESS; Exit: if ((Private != NULL) && (Private->Mapping != NULL)) { PciIo->Unmap (PciIo, Private->Mapping); } if ((Private != NULL) && (Private->Buffer != NULL)) { PciIo->FreeBuffer (PciIo, 6, Private->Buffer); } if ((Private != NULL) && (Private->ControllerData != NULL)) { FreePool (Private->ControllerData); } if (Private != NULL) { if (Private->TimerEvent != NULL) { gBS->CloseEvent (Private->TimerEvent); } FreePool (Private); } gBS->CloseProtocol ( Controller, &gEfiPciIoProtocolGuid, This->DriverBindingHandle, Controller ); gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); DEBUG ((EFI_D_INFO, "NvmExpressDriverBindingStart: end with %r\n", Status)); return Status; }
// //TDS 4.3.1 // EFI_STATUS Attributes_Stress ( IN EFI_BB_TEST_PROTOCOL *This, IN VOID *ClientInterface, IN EFI_TEST_LEVEL TestLevel, IN EFI_HANDLE SupportHandle ) { EFI_STATUS Status; EFI_STATUS Status1; PCI_IO_PROTOCOL_DEVICE *PciIoDevice; EFI_PCI_IO_PROTOCOL *PciIo; EFI_STANDARD_TEST_LIBRARY_PROTOCOL *StandardLib; EFI_TEST_ASSERTION AssertionType; UINT64 SupportedAttributes; UINT64 CurrentAttributes; UINT64 OriginalAttributes; UINT64 CommonAttributes; UINTN Index; UINTN PciIoAttributesNumber; UINT64 ThisAttribute; CHAR16 *DevicePathStr; // //get tested interface. // PciIo = (EFI_PCI_IO_PROTOCOL *)ClientInterface; // // Get the Standard Library Interface // Status = gtBS->HandleProtocol ( SupportHandle, &gEfiStandardTestLibraryGuid, &StandardLib ); if (EFI_ERROR(Status)) { return Status; } InitializeCaseEnvironment (); // //get PciIoDevice struct pointer. // PciIoDevice = NULL; PciIoDevice = GetPciIoDevice (PciIo); if (PciIoDevice == NULL) { return EFI_ABORTED; } // //print the device path of pci device. // // Status = PrintPciIoDevice (PciIoDevice->DevicePath); // if (EFI_ERROR(Status)) { // return Status; // } DevicePathStr = DevicePathToStr (PciIoDevice->DevicePath); if (DevicePathStr == NULL) { StandardLib->RecordMessage ( StandardLib, EFI_VERBOSE_LEVEL_DEFAULT, L"\r\nCannot get DevicePath" ); } else { StandardLib->RecordMessage ( StandardLib, EFI_VERBOSE_LEVEL_DEFAULT, L"\r\nCurrent Device: %s", DevicePathStr ); gtBS->FreePool (DevicePathStr); } // //call Attributes with operation EfiPciIoAttributeOperationGet to //get current attributes. // PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationGet, 0, &OriginalAttributes ); // //call Attribtes with operation EfiPciIoAttributeOperationSupported to //get the supported attributes of the pci controller. // PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationSupported, 0, &SupportedAttributes ); // //for each pci io attributes call Attributes with EfiPciIoAttributeOperationSet // PciIoAttributesNumber = 19; for (Index = 0; Index < PciIoAttributesNumber; Index++) { // //first get current attributes. // PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationGet, 0, &CurrentAttributes ); ThisAttribute = 1 << Index; Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationSet, ThisAttribute, NULL ); // //get current attributes after Call Set // PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationGet, 0, &CommonAttributes ); // //call Attributes to set the orininal value before output to console // Status1 = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationSet, OriginalAttributes, NULL ); if (EFI_ERROR(Status1)) { AssertionType = EFI_TEST_ASSERTION_FAILED; // //record assertion // StandardLib->RecordAssertion ( StandardLib, AssertionType, gPciIoBBTestStressAssertionGuid017, L"EFI_PCI_IO_PROTOCOL.Attributes - Set Original Supported attribute the Status Must be EFI_SUCCESS", L"%a:%d:Status - %r", __FILE__, __LINE__, Status1 ); return Status1; } else { AssertionType = EFI_TEST_ASSERTION_PASSED; } if (ThisAttribute & SupportedAttributes) { if (!EFI_ERROR(Status) || (Status == EFI_UNSUPPORTED)) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } // //record assertion // StandardLib->RecordAssertion ( StandardLib, AssertionType, gPciIoBBTestStressAssertionGuid001, L"EFI_PCI_IO_PROTOCOL.Attributes - Set Supported attribute status must be EFI_SUCCESS or EFI_UNSUPPORTED.", L"%a:%d:Status - %r, Set Attributes - %lXh, Supported Attributes - %lXh", __FILE__, __LINE__, Status, ThisAttribute, SupportedAttributes ); if (!EFI_ERROR(Status)) { // //verify the attributes was really set. // if (CommonAttributes == ThisAttribute) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } // //record assertion // StandardLib->RecordAssertion ( StandardLib, AssertionType, gPciIoBBTestStressAssertionGuid002, L"EFI_PCI_IO_PROTOCOL.Attributes - Supported attribute are really set", L"%a:%d:Set Attributes - %lXh, Supported Attributes - %lXh, Original Attribute - %lXh, Current Attributes - %lXh", __FILE__, __LINE__, ThisAttribute, SupportedAttributes, CurrentAttributes, CommonAttributes ); } } else { // //unsupported attributes. // if (Status == EFI_UNSUPPORTED) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } // //record assertion // StandardLib->RecordAssertion ( StandardLib, AssertionType, gPciIoBBTestStressAssertionGuid003, L"EFI_PCI_IO_PROTOCOL.Attributes - Set UnSupported attribute status must be EFI_UNSUPPORTED", L"%a:%d:Status - %r", __FILE__, __LINE__, Status ); // //verify the attributes remain unchanged // if (CommonAttributes == CurrentAttributes) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } // //record assertion // StandardLib->RecordAssertion ( StandardLib, AssertionType, gPciIoBBTestStressAssertionGuid004, L"EFI_PCI_IO_PROTOCOL.Attributes - set UnSupported attribute the Attributes can not been changed", L"%a:%d:Set Attributes - %lXh, Supported Attributes - %lXh, Original Attribute - %lXh, Current Attributes - %lXh", __FILE__, __LINE__, ThisAttribute, SupportedAttributes, CurrentAttributes, CommonAttributes ); } } // //call Attributes to set the orininal value // Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationSet, OriginalAttributes, NULL ); if (!EFI_ERROR(Status)) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } // //record assertion // StandardLib->RecordAssertion ( StandardLib, AssertionType, gPciIoBBTestStressAssertionGuid005, L"EFI_PCI_IO_PROTOCOL.Attributes - Set Original Supported attribute the Status Must be EFI_SUCCESS", L"%a:%d:Status - %r", __FILE__, __LINE__, Status ); // //call get attributes to verify. // PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationGet, 0, &CommonAttributes ); if (CommonAttributes == OriginalAttributes) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } // //record assertion // StandardLib->RecordAssertion ( StandardLib, AssertionType, gPciIoBBTestStressAssertionGuid006, L"EFI_PCI_IO_PROTOCOL.Attributes - Set Original Supported attribute the Attributes must be really set.", L"%a:%d:Set attributes - %lXh, gotted attributes - %lXh", __FILE__, __LINE__, OriginalAttributes, CommonAttributes ); // //for each pci io attributes call Attributes with EfiPciIoAttributeOperationDisable. // PciIoAttributesNumber = 19; for (Index = 0; Index < PciIoAttributesNumber; Index++) { // //first get current attributes. // PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationGet, 0, &CurrentAttributes ); ThisAttribute = 1 << Index; Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationDisable, ThisAttribute, NULL ); // //get current attributes // PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationGet, 0, &CommonAttributes ); // //call Attributes to set the orininal value before output to console // Status1 = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationSet, OriginalAttributes, NULL ); if (EFI_ERROR(Status1)) { AssertionType = EFI_TEST_ASSERTION_FAILED; // //record assertion // StandardLib->RecordAssertion ( StandardLib, AssertionType, gPciIoBBTestStressAssertionGuid017, L"EFI_PCI_IO_PROTOCOL.Attributes - Set Original Supported attribute the Status Must be EFI_SUCCESS", L"%a:%d:Status - %r", __FILE__, __LINE__, Status1 ); return Status; } else { AssertionType = EFI_TEST_ASSERTION_PASSED; } if ((ThisAttribute & SupportedAttributes) == ThisAttribute) { if (!EFI_ERROR(Status)) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } // //record assertion // StandardLib->RecordAssertion ( StandardLib, AssertionType, gPciIoBBTestStressAssertionGuid007, L"EFI_PCI_IO_PROTOCOL.Attributes - disable Supported attribute status must be EFI_SUCCESS", L"%a:%d:Status - %r, Disabled Attributes - %lXh, Supported Attributes - %lXh", __FILE__, __LINE__, Status, ThisAttribute, SupportedAttributes ); // //verify the attributes really disabled // if ((ThisAttribute & CommonAttributes) != ThisAttribute) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } // //record assertion // StandardLib->RecordAssertion ( StandardLib, AssertionType, gPciIoBBTestStressAssertionGuid008, L"EFI_PCI_IO_PROTOCOL.Attributes - disable Supported attribute are really diabled", L"%a:%d:Disable Attributes - %lXh, Supported Attributes - %lXh, Original Attribute - %lXh, Current Attributes - %lXh", __FILE__, __LINE__, ThisAttribute, SupportedAttributes, CurrentAttributes, CommonAttributes ); } else { // //unsupported attributes // if (Status == EFI_UNSUPPORTED) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } // //record assertion // StandardLib->RecordAssertion ( StandardLib, AssertionType, gPciIoBBTestStressAssertionGuid009, L"EFI_PCI_IO_PROTOCOL.Attributes - disable UnSupported attribute status must be EFI_UNSUPPORTED", L"%a:%d:Status - %r, Disabled Attributes - %lXh, Supported Attributes - %lXh", __FILE__, __LINE__, Status, ThisAttribute, SupportedAttributes ); // //verify the attributes remain unchanged after Disable operation // if (CommonAttributes == CurrentAttributes) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } // //record assertion // StandardLib->RecordAssertion ( StandardLib, AssertionType, gPciIoBBTestStressAssertionGuid010, L"EFI_PCI_IO_PROTOCOL.Attributes - disable UnSupported attribute the Attributes can not been changed", L"%a:%d:Disable Attributes - %lXh, Supported Attributes - %lXh, Original Attribute - %lXh, Current Attributes - %lXh", __FILE__, __LINE__, ThisAttribute, SupportedAttributes, CurrentAttributes, CommonAttributes ); } } // //call Attributes to set the orininal value // Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationSet, OriginalAttributes, NULL ); if (!EFI_ERROR(Status)) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } // //record assertion // StandardLib->RecordAssertion ( StandardLib, AssertionType, gPciIoBBTestStressAssertionGuid011, L"EFI_PCI_IO_PROTOCOL.Attributes - Set Original Supported attribute the Status Must be EFI_SUCCESS", L"%a:%d:Status - %r", __FILE__, __LINE__, Status ); // //call get attributes to verify. // PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationGet, 0, &CommonAttributes ); if (CommonAttributes == OriginalAttributes) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } // //record assertion // StandardLib->RecordAssertion ( StandardLib, AssertionType, gPciIoBBTestStressAssertionGuid012, L"EFI_PCI_IO_PROTOCOL.Attributes - Set Original Supported attribute the Attributes must be really set.", L"%a:%d:Set Attributes - %lXh, gotted attributes - %lXh", __FILE__, __LINE__, OriginalAttributes, CommonAttributes ); // //for each pci io attributes call Attributes with EfiPciIoAttributeOperationEnable. // PciIoAttributesNumber = 19; for (Index = 1; Index <= PciIoAttributesNumber; Index++) { // //first get current attributes. // PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationGet, 0, &CurrentAttributes ); ThisAttribute = 1 << Index; Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationEnable, ThisAttribute, &CommonAttributes ); // //get current attributes after Enable // PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationGet, 0, &CommonAttributes ); // //call Attributes to set the orininal value before output to console // Status1 = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationSet, OriginalAttributes, NULL ); if (EFI_ERROR(Status1)) { AssertionType = EFI_TEST_ASSERTION_FAILED; // //record assertion // StandardLib->RecordAssertion ( StandardLib, AssertionType, gPciIoBBTestStressAssertionGuid017, L"EFI_PCI_IO_PROTOCOL.Attributes - Set Original Supported attribute the Status Must be EFI_SUCCESS", L"%a:%d:Status - %r", __FILE__, __LINE__, Status1 ); return Status1; } else { AssertionType = EFI_TEST_ASSERTION_PASSED; } if ((ThisAttribute & SupportedAttributes) == ThisAttribute) { if (!EFI_ERROR(Status) || (Status == EFI_UNSUPPORTED)) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } // //record assertion // StandardLib->RecordAssertion ( StandardLib, AssertionType, gPciIoBBTestStressAssertionGuid013, L"EFI_PCI_IO_PROTOCOL.Attributes - enable Supported attribute status must be EFI_SUCCESS or EFI_UNSUPPORTED", L"%a:%d:Status - %r, Enabled Attributes - %lXh, Supported Attributes - %lXh", __FILE__, __LINE__, Status, ThisAttribute, SupportedAttributes ); if (!EFI_ERROR(Status)) { // //verify the attributes really enabled // if ((ThisAttribute & CommonAttributes) == ThisAttribute) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } // //record assertion // StandardLib->RecordAssertion ( StandardLib, AssertionType, gPciIoBBTestStressAssertionGuid014, L"EFI_PCI_IO_PROTOCOL.Attributes - enable Supported attribute are really enabled", L"%a:%d:Enable Attributes - %lXh, Supported Attributes - %lXh, Original Attribute - %lXh, Current Attributes - %lXh", __FILE__, __LINE__, ThisAttribute, SupportedAttributes, CurrentAttributes, CommonAttributes ); } } else { // //unsupported attributes // if (Status == EFI_UNSUPPORTED) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } // //record assertion // StandardLib->RecordAssertion ( StandardLib, AssertionType, gPciIoBBTestStressAssertionGuid015, L"EFI_PCI_IO_PROTOCOL.Attributes - enable UnSupported attribute status must be EFI_UNSUPPORTED", L"%a:%d:Status - %r, Enabled Attributes - %lXh, Supported Attributes - %lXh", __FILE__, __LINE__, Status, ThisAttribute, SupportedAttributes ); // //verify the attributes remain unchanged // if (CommonAttributes == CurrentAttributes) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } // //record assertion // StandardLib->RecordAssertion ( StandardLib, AssertionType, gPciIoBBTestStressAssertionGuid016, L"EFI_PCI_IO_PROTOCOL.Attributes - enable UnSupported attribute the Attributes can not been changed", L"%a:%d:Enalbe Attributes - %lXh, Supported Attributes - %lXh, Original Attribute - %lXh, Current Attributes - %lXh", __FILE__, __LINE__, ThisAttribute, SupportedAttributes, CurrentAttributes, CommonAttributes ); } } // //call Attributes to set the orininal value // Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationSet, OriginalAttributes, NULL ); if (!EFI_ERROR(Status)) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } // //record assertion // StandardLib->RecordAssertion ( StandardLib, AssertionType, gPciIoBBTestStressAssertionGuid017, L"EFI_PCI_IO_PROTOCOL.Attributes - Set Original Supported attribute the Status Must be EFI_SUCCESS", L"%a:%d:Status - %r", __FILE__, __LINE__, Status ); // //call get attributes to verify. // Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationGet, 0, &CommonAttributes ); if (CommonAttributes == OriginalAttributes) { AssertionType = EFI_TEST_ASSERTION_PASSED; } else { AssertionType = EFI_TEST_ASSERTION_FAILED; } // //record assertion // StandardLib->RecordAssertion ( StandardLib, AssertionType, gPciIoBBTestStressAssertionGuid018, L"EFI_PCI_IO_PROTOCOL.Attributes - Set Original Supported attribute the Attributes must be really set.", L"%a:%d:Set Attributes - %lXh, gotted attributes - %lXh", __FILE__, __LINE__, OriginalAttributes, CommonAttributes ); // //done successfully // return EFI_SUCCESS; }
VOID EFIAPI SEnvPciIo ( IN EFI_HANDLE h, IN VOID *Interface ) /*++ Routine Description: Arguments: h - An EFI handle Interface - The interface Returns: --*/ { EFI_PCI_IO_PROTOCOL *PciIo; PCI_TYPE00 Pci; UINTN Segment; UINTN Bus; UINTN Device; UINTN Function; UINTN Index; PciIo = Interface; PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0, sizeof (Pci), &Pci); PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function); // // Dump PciIo Info // Print (L"\n"); PrintToken (STRING_TOKEN (STR_SHELLENV_DPROT_SEGMENT_2), HiiEnvHandle, Segment); PrintToken (STRING_TOKEN (STR_SHELLENV_DPROT_BUS_2), HiiEnvHandle, Bus); PrintToken (STRING_TOKEN (STR_SHELLENV_DPROT_DEVICE_NUMBER), HiiEnvHandle, Device); PrintToken (STRING_TOKEN (STR_SHELLENV_DPROT_FUNCTION_NUMBER_2), HiiEnvHandle, Function); PrintToken (STRING_TOKEN (STR_SHELLENV_DPROT_ROM_SIZE_2), HiiEnvHandle, PciIo->RomSize); PrintToken (STRING_TOKEN (STR_SHELLENV_DPROT_ROM_LOCATION), HiiEnvHandle, PciIo->RomImage); PrintToken (STRING_TOKEN (STR_SHELLENV_DPROT_VENDOR_ID), HiiEnvHandle, Pci.Hdr.VendorId); PrintToken (STRING_TOKEN (STR_SHELLENV_DPROT_DEVICE_ID_2), HiiEnvHandle, Pci.Hdr.DeviceId); PrintToken ( STRING_TOKEN (STR_SHELLENV_DPROT_CLASS_CODE), HiiEnvHandle, Pci.Hdr.ClassCode[0], Pci.Hdr.ClassCode[1], Pci.Hdr.ClassCode[2] ); PrintToken (STRING_TOKEN (STR_SHELLENV_DPROT_CONFIG_HEADER), HiiEnvHandle); for (Index = 0; Index < sizeof (Pci); Index++) { if ((Index % 0x10) == 0) { Print (L"\n "); } PrintToken (STRING_TOKEN (STR_SHELLENV_DPROT_ONE_VAR_X), HiiEnvHandle, *((UINT8 *) (&Pci) + Index)); } Print (L"\n"); }
/** Install EFI_ISA_ACPI_PROTOCOL. @param This Driver Binding protocol instance pointer. @param ControllerHandle Handle of device to bind driver to. @param RemainingDevicePath Optional parameter use to pick a specific child device to start. @retval EFI_SUCCESS This driver is added to ControllerHandle @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle @retval other This driver does not support this device **/ EFI_STATUS EFIAPI PcatIsaAcpiDriverBindingStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; EFI_PCI_IO_PROTOCOL *PciIo; PCAT_ISA_ACPI_DEV *PcatIsaAcpiDev; UINT64 Supports; BOOLEAN Enabled; Enabled = FALSE; Supports = 0; PcatIsaAcpiDev = NULL; // // Open the PCI I/O Protocol Interface // PciIo = NULL; Status = gBS->OpenProtocol ( Controller, &gEfiPciIoProtocolGuid, (VOID**)&PciIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto Done; } // // Get supported PCI attributes // Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationSupported, 0, &Supports ); if (EFI_ERROR (Status)) { goto Done; } Supports &= (EFI_PCI_IO_ATTRIBUTE_ISA_IO | EFI_PCI_IO_ATTRIBUTE_ISA_IO_16); if (Supports == 0 || Supports == (EFI_PCI_IO_ATTRIBUTE_ISA_IO | EFI_PCI_IO_ATTRIBUTE_ISA_IO_16)) { Status = EFI_UNSUPPORTED; goto Done; } Enabled = TRUE; Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationEnable, EFI_PCI_DEVICE_ENABLE | Supports | EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO, NULL ); if (EFI_ERROR (Status)) { goto Done; } // // Allocate memory for the PCAT ISA ACPI Device structure // PcatIsaAcpiDev = NULL; Status = gBS->AllocatePool ( EfiBootServicesData, sizeof(PCAT_ISA_ACPI_DEV), (VOID**)&PcatIsaAcpiDev ); if (EFI_ERROR (Status)) { goto Done; } // // Initialize the PCAT ISA ACPI Device structure // PcatIsaAcpiDev->Signature = PCAT_ISA_ACPI_DEV_SIGNATURE; PcatIsaAcpiDev->Handle = Controller; PcatIsaAcpiDev->PciIo = PciIo; // // Initialize PcatIsaAcpiDeviceList // InitializePcatIsaAcpiDeviceList (); // // IsaAcpi interface // (PcatIsaAcpiDev->IsaAcpi).DeviceEnumerate = IsaDeviceEnumerate; (PcatIsaAcpiDev->IsaAcpi).SetPower = IsaDeviceSetPower; (PcatIsaAcpiDev->IsaAcpi).GetCurResource = IsaGetCurrentResource; (PcatIsaAcpiDev->IsaAcpi).GetPosResource = IsaGetPossibleResource; (PcatIsaAcpiDev->IsaAcpi).SetResource = IsaSetResource; (PcatIsaAcpiDev->IsaAcpi).EnableDevice = IsaEnableDevice; (PcatIsaAcpiDev->IsaAcpi).InitDevice = IsaInitDevice; (PcatIsaAcpiDev->IsaAcpi).InterfaceInit = IsaInterfaceInit; // // Install the ISA ACPI Protocol interface // Status = gBS->InstallMultipleProtocolInterfaces ( &Controller, &gEfiIsaAcpiProtocolGuid, &PcatIsaAcpiDev->IsaAcpi, NULL ); Done: if (EFI_ERROR (Status)) { if (PciIo != NULL && Enabled) { PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationDisable, EFI_PCI_DEVICE_ENABLE | Supports | EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO, NULL ); } gBS->CloseProtocol ( Controller, &gEfiPciIoProtocolGuid, This->DriverBindingHandle, Controller ); if (PcatIsaAcpiDev != NULL) { gBS->FreePool (PcatIsaAcpiDev); } return Status; } return EFI_SUCCESS; }
/** Starts a device controller or a bus controller. The Start() function is designed to be invoked from the EFI boot service ConnectController(). As a result, much of the error checking on the parameters to Start() has been moved into this common boot service. It is legal to call Start() from other locations, but the following calling restrictions must be followed or the system behavior will not be deterministic. 1. ControllerHandle must be a valid EFI_HANDLE. 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned EFI_DEVICE_PATH_PROTOCOL. 3. Prior to calling Start(), the Supported() function for the driver specified by This must have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. @param[in] ControllerHandle The handle of the controller to start. This handle must support a protocol interface that supplies an I/O abstraction to the driver. @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This parameter is ignored by device drivers, and is optional for bus drivers. For a bus driver, if this parameter is NULL, then handles for all the children of Controller are created by this driver. If this parameter is not NULL and the first Device Path Node is not the End of Device Path Node, then only the handle for the child device specified by the first Device Path Node of RemainingDevicePath is created by this driver. If the first Device Path Node of RemainingDevicePath is the End of Device Path Node, no child handle is created by this driver. @retval EFI_SUCCESS The device was started. @retval EFI_DEVICE_ERROR The device could not be started due to a device error. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. @retval Others The driver failded to start the device. **/ EFI_STATUS EFIAPI SioBusDriverBindingStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; EFI_PCI_IO_PROTOCOL *PciIo; EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; UINT64 Supports; UINT64 OriginalAttributes; UINT64 Attributes; BOOLEAN Enabled; SIO_BUS_DRIVER_PRIVATE_DATA *Private; UINT32 ChildDeviceNumber; Enabled = FALSE; Supports = 0; OriginalAttributes = 0; Private = NULL; // // Open the PCI I/O Protocol Interface // PciIo = NULL; Status = gBS->OpenProtocol ( Controller, &gEfiPciIoProtocolGuid, (VOID**) &PciIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { return Status; } // // Open Device Path Protocol // Status = gBS->OpenProtocol ( Controller, &gEfiDevicePathProtocolGuid, (VOID **) &ParentDevicePath, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { gBS->CloseProtocol ( Controller, &gEfiPciIoProtocolGuid, This->DriverBindingHandle, Controller ); return Status; } // // Get supported PCI attributes // Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationSupported, 0, &Supports ); if (EFI_ERROR (Status)) { goto Done; } Supports &= (UINT64) (EFI_PCI_IO_ATTRIBUTE_ISA_IO | EFI_PCI_IO_ATTRIBUTE_ISA_IO_16); if (Supports == 0 || Supports == (EFI_PCI_IO_ATTRIBUTE_ISA_IO | EFI_PCI_IO_ATTRIBUTE_ISA_IO_16)) { Status = EFI_UNSUPPORTED; goto Done; } Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationGet, 0, &OriginalAttributes ); if (EFI_ERROR (Status)) { goto Done; } Attributes = EFI_PCI_DEVICE_ENABLE | Supports | EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO; Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationEnable, Attributes, NULL ); if (EFI_ERROR (Status)) { goto Done; } Enabled = TRUE; // // Store the OriginalAttributes for the restore in BindingStop() // Private = AllocateZeroPool (sizeof (SIO_BUS_DRIVER_PRIVATE_DATA)); if (Private == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Done; } Private->PciIo = PciIo; Private->OriginalAttributes = OriginalAttributes; Status = gBS->InstallProtocolInterface ( &Controller, &gEfiCallerIdGuid, EFI_NATIVE_INTERFACE, Private ); if (EFI_ERROR (Status)) { goto Done; } // // Report status code for the start of general controller initialization // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_IO_BUS_LPC | EFI_IOB_PC_INIT), ParentDevicePath ); // // Report status code for the start of enabling devices on the bus // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, (EFI_IO_BUS_LPC | EFI_IOB_PC_ENABLE), ParentDevicePath ); // // Create all the children upon the first entrance // ChildDeviceNumber = SioCreateAllChildDevices ( This, Controller, PciIo, ParentDevicePath ); if (ChildDeviceNumber == 0) { Status = EFI_DEVICE_ERROR; } Done: if (EFI_ERROR (Status)) { if (PciIo != NULL && Enabled) { PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationSet, OriginalAttributes, NULL ); } gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); gBS->CloseProtocol ( Controller, &gEfiPciIoProtocolGuid, This->DriverBindingHandle, Controller ); if (Private != NULL) { gBS->UninstallMultipleProtocolInterfaces ( Controller, &gEfiCallerIdGuid, Private, NULL ); FreePool (Private); } return Status; } return EFI_SUCCESS; }
/** Start this driver on ControllerHandle. This service is called by the EFI boot service ConnectController(). In order to make drivers as small as possible, there are a few calling restrictions for this service. ConnectController() must follow these calling restrictions. If any other agent wishes to call Start() it must also follow these calling restrictions. @param This Protocol instance pointer. @param ControllerHandle Handle of device to bind driver to. @param RemainingDevicePath Optional parameter use to pick a specific child device to start. @retval EFI_SUCCESS This driver is added to ControllerHandle @retval EFI_DEVICE_ERROR This driver could not be started due to a device error @retval other This driver does not support this device **/ EFI_STATUS EFIAPI SimpleNetworkDriverStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *Nii; EFI_DEVICE_PATH_PROTOCOL *NiiDevicePath; EFI_STATUS Status; PXE_UNDI *Pxe; SNP_DRIVER *Snp; VOID *Address; EFI_HANDLE Handle; UINT8 BarIndex; PXE_STATFLAGS InitStatFlags; EFI_PCI_IO_PROTOCOL *PciIo; EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarDesc; BOOLEAN FoundIoBar; BOOLEAN FoundMemoryBar; DEBUG ((EFI_D_NET, "\nSnpNotifyNetworkInterfaceIdentifier() ")); Status = gBS->OpenProtocol ( Controller, &gEfiDevicePathProtocolGuid, (VOID **) &NiiDevicePath, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { return Status; } Status = gBS->LocateDevicePath ( &gEfiPciIoProtocolGuid, &NiiDevicePath, &Handle ); if (EFI_ERROR (Status)) { return Status; } Status = gBS->OpenProtocol ( Handle, &gEfiPciIoProtocolGuid, (VOID **) &PciIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { return Status; } // // Get the NII interface. // Status = gBS->OpenProtocol ( Controller, &gEfiNetworkInterfaceIdentifierProtocolGuid_31, (VOID **) &Nii, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); return Status; } DEBUG ((EFI_D_INFO, "Start(): UNDI3.1 found\n")); Pxe = (PXE_UNDI *) (UINTN) (Nii->Id); if (Calc8BitCksum (Pxe, Pxe->hw.Len) != 0) { DEBUG ((EFI_D_NET, "\n!PXE checksum is not correct.\n")); goto NiiError; } if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) { // // We can get any packets. // } else if ((Pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) { // // We need to be able to get broadcast packets for DHCP. // If we do not have promiscuous support, we must at least have // broadcast support or we cannot do DHCP! // } else { DEBUG ((EFI_D_NET, "\nUNDI does not have promiscuous or broadcast support.")); goto NiiError; } // // OK, we like this UNDI, and we know snp is not already there on this handle // Allocate and initialize a new simple network protocol structure. // Status = PciIo->AllocateBuffer ( PciIo, AllocateAnyPages, EfiBootServicesData, SNP_MEM_PAGES (sizeof (SNP_DRIVER)), &Address, 0 ); if (Status != EFI_SUCCESS) { DEBUG ((EFI_D_NET, "\nCould not allocate SNP_DRIVER structure.\n")); goto NiiError; } Snp = (SNP_DRIVER *) (UINTN) Address; ZeroMem (Snp, sizeof (SNP_DRIVER)); Snp->PciIo = PciIo; Snp->Signature = SNP_DRIVER_SIGNATURE; EfiInitializeLock (&Snp->Lock, TPL_NOTIFY); Snp->Snp.Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION; Snp->Snp.Start = SnpUndi32Start; Snp->Snp.Stop = SnpUndi32Stop; Snp->Snp.Initialize = SnpUndi32Initialize; Snp->Snp.Reset = SnpUndi32Reset; Snp->Snp.Shutdown = SnpUndi32Shutdown; Snp->Snp.ReceiveFilters = SnpUndi32ReceiveFilters; Snp->Snp.StationAddress = SnpUndi32StationAddress; Snp->Snp.Statistics = SnpUndi32Statistics; Snp->Snp.MCastIpToMac = SnpUndi32McastIpToMac; Snp->Snp.NvData = SnpUndi32NvData; Snp->Snp.GetStatus = SnpUndi32GetStatus; Snp->Snp.Transmit = SnpUndi32Transmit; Snp->Snp.Receive = SnpUndi32Receive; Snp->Snp.WaitForPacket = NULL; Snp->Snp.Mode = &Snp->Mode; Snp->TxRxBufferSize = 0; Snp->TxRxBuffer = NULL; Snp->RecycledTxBuf = AllocatePool (sizeof (UINT64) * SNP_TX_BUFFER_INCREASEMENT); if (Snp->RecycledTxBuf == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Error_DeleteSNP; } Snp->MaxRecycledTxBuf = SNP_TX_BUFFER_INCREASEMENT; Snp->RecycledTxBufCount = 0; if (Nii->Revision >= EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION) { Snp->IfNum = Nii->IfNum; } else { Snp->IfNum = (UINT8) (Nii->IfNum & 0xFF); } if ((Pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) != 0) { Snp->IsSwUndi = FALSE; Snp->IssueUndi32Command = &IssueHwUndiCommand; } else { Snp->IsSwUndi = TRUE; if ((Pxe->sw.Implementation & PXE_ROMID_IMP_SW_VIRT_ADDR) != 0) { Snp->IssueUndi32Command = (ISSUE_UNDI32_COMMAND) (UINTN) Pxe->sw.EntryPoint; } else { Snp->IssueUndi32Command = (ISSUE_UNDI32_COMMAND) (UINTN) ((UINT8) (UINTN) Pxe + Pxe->sw.EntryPoint); } } // // Allocate a global CPB and DB buffer for this UNDI interface. // we do this because: // // -UNDI 3.0 wants all the addresses passed to it (even the cpb and db) to be // within 2GB limit, create them here and map them so that when undi calls // v2p callback to check if the physical address is < 2gb, we will pass. // // -This is not a requirement for 3.1 or later UNDIs but the code looks // simpler if we use the same cpb, db variables for both old and new undi // interfaces from all the SNP interface calls (we don't map the buffers // for the newer undi interfaces though) // . // -it is OK to allocate one global set of CPB, DB pair for each UNDI // interface as EFI does not multi-task and so SNP will not be re-entered! // Status = PciIo->AllocateBuffer ( PciIo, AllocateAnyPages, EfiBootServicesData, SNP_MEM_PAGES (4096), &Address, 0 ); if (Status != EFI_SUCCESS) { DEBUG ((EFI_D_NET, "\nCould not allocate CPB and DB structures.\n")); goto Error_DeleteSNP; } Snp->Cpb = (VOID *) (UINTN) Address; Snp->Db = (VOID *) ((UINTN) Address + 2048); // // Find the correct BAR to do IO. // // Enumerate through the PCI BARs for the device to determine which one is // the IO BAR. Save the index of the BAR into the adapter info structure. // for regular 32bit BARs, 0 is memory mapped, 1 is io mapped // Snp->MemoryBarIndex = 0; Snp->IoBarIndex = 1; FoundMemoryBar = FALSE; FoundIoBar = FALSE; for (BarIndex = 0; BarIndex < PCI_MAX_BAR; BarIndex++) { Status = PciIo->GetBarAttributes ( PciIo, BarIndex, NULL, (VOID**) &BarDesc ); if (Status == EFI_UNSUPPORTED) { continue; } else if (EFI_ERROR (Status)) { goto Error_DeleteSNP; } if ((!FoundMemoryBar) && (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM)) { Snp->MemoryBarIndex = BarIndex; FoundMemoryBar = TRUE; } else if ((!FoundIoBar) && (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_IO)) { Snp->IoBarIndex = BarIndex; FoundIoBar = TRUE; } FreePool (BarDesc); if (FoundMemoryBar && FoundIoBar) { break; } } Status = PxeStart (Snp); if (Status != EFI_SUCCESS) { goto Error_DeleteSNP; } Snp->Cdb.OpCode = PXE_OPCODE_GET_INIT_INFO; Snp->Cdb.OpFlags = PXE_OPFLAGS_NOT_USED; Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED; Snp->Cdb.CPBaddr = PXE_DBADDR_NOT_USED; Snp->Cdb.DBsize = (UINT16) sizeof (Snp->InitInfo); Snp->Cdb.DBaddr = (UINT64)(UINTN) (&Snp->InitInfo); Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE; Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; Snp->Cdb.IFnum = Snp->IfNum; Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST; DEBUG ((EFI_D_NET, "\nSnp->undi.get_init_info() ")); (*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb); // // Save the INIT Stat Code... // InitStatFlags = Snp->Cdb.StatFlags; if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) { DEBUG ((EFI_D_NET, "\nSnp->undi.init_info() %xh:%xh\n", Snp->Cdb.StatFlags, Snp->Cdb.StatCode)); PxeStop (Snp); goto Error_DeleteSNP; } // // Initialize simple network protocol mode structure // Snp->Mode.State = EfiSimpleNetworkStopped; Snp->Mode.HwAddressSize = Snp->InitInfo.HWaddrLen; Snp->Mode.MediaHeaderSize = Snp->InitInfo.MediaHeaderLen; Snp->Mode.MaxPacketSize = Snp->InitInfo.FrameDataLen; Snp->Mode.NvRamAccessSize = Snp->InitInfo.NvWidth; Snp->Mode.NvRamSize = Snp->InitInfo.NvCount * Snp->Mode.NvRamAccessSize; Snp->Mode.IfType = Snp->InitInfo.IFtype; Snp->Mode.MaxMCastFilterCount = Snp->InitInfo.MCastFilterCnt; Snp->Mode.MCastFilterCount = 0; switch (InitStatFlags & PXE_STATFLAGS_CABLE_DETECT_MASK) { case PXE_STATFLAGS_CABLE_DETECT_SUPPORTED: Snp->CableDetectSupported = TRUE; break; case PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED: default: Snp->CableDetectSupported = FALSE; } switch (InitStatFlags & PXE_STATFLAGS_GET_STATUS_NO_MEDIA_MASK) { case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED: Snp->MediaStatusSupported = TRUE; break; case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_NOT_SUPPORTED: default: Snp->MediaStatusSupported = FALSE; } if (Snp->CableDetectSupported || Snp->MediaStatusSupported) { Snp->Mode.MediaPresentSupported = TRUE; } if ((Pxe->hw.Implementation & PXE_ROMID_IMP_STATION_ADDR_SETTABLE) != 0) { Snp->Mode.MacAddressChangeable = TRUE; } else { Snp->Mode.MacAddressChangeable = FALSE; } if ((Pxe->hw.Implementation & PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED) != 0) { Snp->Mode.MultipleTxSupported = TRUE; } else { Snp->Mode.MultipleTxSupported = FALSE; } Snp->Mode.ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST; if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) != 0) { Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST; } if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) { Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS; } if ((Pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) { Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST; } if ((Pxe->hw.Implementation & PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED) != 0) { Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST; } if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) != 0) { Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST; } Snp->Mode.ReceiveFilterSetting = 0; // // need to get the station address to save in the mode structure. we need to // initialize the UNDI first for this. // Snp->TxRxBufferSize = Snp->InitInfo.MemoryRequired; Status = PxeInit (Snp, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE); if (EFI_ERROR (Status)) { PxeStop (Snp); goto Error_DeleteSNP; } Status = PxeGetStnAddr (Snp); if (Status != EFI_SUCCESS) { DEBUG ((EFI_D_ERROR, "\nSnp->undi.get_station_addr() failed.\n")); PxeShutdown (Snp); PxeStop (Snp); goto Error_DeleteSNP; } Snp->Mode.MediaPresent = FALSE; // // We should not leave UNDI started and initialized here. this DriverStart() // routine must only find and attach the SNP interface to UNDI layer that it // finds on the given handle! // The UNDI layer will be started when upper layers call Snp->start. // How ever, this DriverStart() must fill up the snp mode structure which // contains the MAC address of the NIC. For this reason we started and // initialized UNDI here, now we are done, do a shutdown and stop of the // UNDI interface! // PxeShutdown (Snp); PxeStop (Snp); // // Create EXIT_BOOT_SERIVES Event // Status = gBS->CreateEventEx ( EVT_NOTIFY_SIGNAL, TPL_NOTIFY, SnpNotifyExitBootServices, Snp, &gEfiEventExitBootServicesGuid, &Snp->ExitBootServicesEvent ); if (EFI_ERROR (Status)) { goto Error_DeleteSNP; } // // add SNP to the undi handle // Status = gBS->InstallProtocolInterface ( &Controller, &gEfiSimpleNetworkProtocolGuid, EFI_NATIVE_INTERFACE, &(Snp->Snp) ); if (!EFI_ERROR (Status)) { return Status; } PciIo->FreeBuffer ( PciIo, SNP_MEM_PAGES (4096), Snp->Cpb ); Error_DeleteSNP: if (Snp->RecycledTxBuf != NULL) { FreePool (Snp->RecycledTxBuf); } PciIo->FreeBuffer ( PciIo, SNP_MEM_PAGES (sizeof (SNP_DRIVER)), Snp ); NiiError: gBS->CloseProtocol ( Controller, &gEfiNetworkInterfaceIdentifierProtocolGuid_31, This->DriverBindingHandle, Controller ); gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); // // If we got here that means we are in error state. // if (!EFI_ERROR (Status)) { Status = EFI_DEVICE_ERROR; } return Status; }
/** Starting the Pci SATA Driver. @param This Protocol instance pointer. @param Controller Handle of device to test. @param RemainingDevicePath Not used. @return EFI_SUCCESS supports this device. @return EFI_UNSUPPORTED do not support this device. @return EFI_DEVICE_ERROR cannot be started due to device Error. @return EFI_OUT_OF_RESOURCES cannot allocate resources. **/ EFI_STATUS EFIAPI SataSiI3132DriverBindingStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; EFI_PCI_IO_PROTOCOL *PciIo; UINT64 Supports; UINT64 OriginalPciAttributes; BOOLEAN PciAttributesSaved; UINT32 PciID; SATA_SI3132_INSTANCE *SataSiI3132Instance = NULL; SATA_TRACE ("SataSiI3132DriverBindingStart()"); //TODO: Find a nicer way to do it ! if (mbStarted) { return EFI_SUCCESS; // Don't restart me ! } // // Open the PciIo Protocol // Status = gBS->OpenProtocol ( Controller, &gEfiPciIoProtocolGuid, (VOID **) &PciIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { return Status; } PciAttributesSaved = FALSE; // // Save original PCI attributes // Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationGet, 0, &OriginalPciAttributes ); if (EFI_ERROR (Status)) { goto CLOSE_PCIIO; } PciAttributesSaved = TRUE; Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationSupported, 0, &Supports ); if (!EFI_ERROR (Status)) { Supports &= EFI_PCI_DEVICE_ENABLE; Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationEnable, Supports, NULL ); } if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "SataSiI3132DriverBindingStart: failed to enable controller\n")); goto CLOSE_PCIIO; } // // Get the Pci device class code. // Status = PciIo->Pci.Read ( PciIo, EfiPciIoWidthUint32, PCI_VENDOR_ID_OFFSET, 1, &PciID ); if (EFI_ERROR (Status)) { Status = EFI_UNSUPPORTED; goto CLOSE_PCIIO; } // // Test whether the controller belongs to SATA Mass Storage type // if (PciID != ((SATA_SII3132_DEVICE_ID << 16) | SATA_SII3132_VENDOR_ID)) { Status = EFI_UNSUPPORTED; goto CLOSE_PCIIO; } // Create SiI3132 Sata Instance Status = SataSiI3132Constructor (PciIo, &SataSiI3132Instance); if (EFI_ERROR (Status)) { return Status; } // Initialize SiI3132 Sata Controller Status = SataSiI3132Initialization (SataSiI3132Instance); if (EFI_ERROR (Status)) { return Status; } // Install Ata Pass Thru Protocol Status = gBS->InstallProtocolInterface ( &Controller, &gEfiAtaPassThruProtocolGuid, EFI_NATIVE_INTERFACE, &(SataSiI3132Instance->AtaPassThruProtocol) ); if (EFI_ERROR (Status)) { goto FREE_POOL; } /* // // Create event to stop the HC when exit boot service. // Status = gBS->CreateEventEx ( EVT_NOTIFY_SIGNAL, TPL_NOTIFY, EhcExitBootService, Ehc, &gEfiEventExitBootServicesGuid, &Ehc->ExitBootServiceEvent ); if (EFI_ERROR (Status)) { goto UNINSTALL_USBHC; }*/ mbStarted = TRUE; SATA_TRACE ("SataSiI3132DriverBindingStart() Success!"); return EFI_SUCCESS; FREE_POOL: //TODO: Free SATA Instance CLOSE_PCIIO: if (PciAttributesSaved) { // // Restore original PCI attributes // PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationSet, OriginalPciAttributes, NULL ); } gBS->CloseProtocol ( Controller, &gEfiPciIoProtocolGuid, This->DriverBindingHandle, Controller ); return Status; }
/** Complete build of BBS TABLE. @param Private Legacy BIOS Instance data @param BbsTable BBS Table passed to 16-bit code @retval EFI_SUCCESS Removable media not present **/ EFI_STATUS LegacyBiosBuildBbs ( IN LEGACY_BIOS_INSTANCE *Private, IN BBS_TABLE *BbsTable ) { UINTN BbsIndex; HDD_INFO *HddInfo; UINTN HddIndex; UINTN Index; // // First entry is floppy. // Next 2*MAX_IDE_CONTROLLER entries are for onboard IDE. // Next n entries are filled in after each ROM is dispatched. // Entry filled in if follow BBS spec. See LegacyPci.c // Next entries are for non-BBS compliant ROMS. They are filled in by // 16-bit code during Legacy16UpdateBbs invocation. Final BootPriority // occurs after that invocation. // // Floppy // Set default state. // IsHaveMediaInFloppy = HasMediaInFloppy (); if (IsHaveMediaInFloppy == FLOPPY_PRESENT_WITH_MEDIA) { BbsTable[0].BootPriority = BBS_UNPRIORITIZED_ENTRY; } else { if (IsHaveMediaInFloppy == FLOPPY_PRESENT_NO_MEDIA) { BbsTable[0].BootPriority = BBS_LOWEST_PRIORITY; } else { BbsTable[0].BootPriority = BBS_IGNORE_ENTRY; } } BbsTable[0].Bus = 0xff; BbsTable[0].Device = 0xff; BbsTable[0].Function = 0xff; BbsTable[0].DeviceType = BBS_FLOPPY; BbsTable[0].Class = 01; BbsTable[0].SubClass = 02; BbsTable[0].StatusFlags.OldPosition = 0; BbsTable[0].StatusFlags.Reserved1 = 0; BbsTable[0].StatusFlags.Enabled = 0; BbsTable[0].StatusFlags.Failed = 0; BbsTable[0].StatusFlags.MediaPresent = 0; BbsTable[0].StatusFlags.Reserved2 = 0; // // Onboard HDD - Note Each HDD controller controls 2 drives // Master & Slave // HddInfo = &Private->IntThunk->EfiToLegacy16BootTable.HddInfo[0]; // // Get IDE Drive Info // LegacyBiosBuildIdeData (Private, &HddInfo, 0); for (HddIndex = 0; HddIndex < MAX_IDE_CONTROLLER; HddIndex++) { BbsIndex = HddIndex * 2 + 1; for (Index = 0; Index < 2; ++Index) { BbsTable[BbsIndex + Index].Bus = HddInfo[HddIndex].Bus; BbsTable[BbsIndex + Index].Device = HddInfo[HddIndex].Device; BbsTable[BbsIndex + Index].Function = HddInfo[HddIndex].Function; BbsTable[BbsIndex + Index].Class = 01; BbsTable[BbsIndex + Index].SubClass = 01; BbsTable[BbsIndex + Index].StatusFlags.OldPosition = 0; BbsTable[BbsIndex + Index].StatusFlags.Reserved1 = 0; BbsTable[BbsIndex + Index].StatusFlags.Enabled = 0; BbsTable[BbsIndex + Index].StatusFlags.Failed = 0; BbsTable[BbsIndex + Index].StatusFlags.MediaPresent = 0; BbsTable[BbsIndex + Index].StatusFlags.Reserved2 = 0; // // If no controller found or no device found set to ignore // else set to unprioritized and set device type // if (HddInfo[HddIndex].CommandBaseAddress == 0) { BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY; } else { if (Index == 0) { if ((HddInfo[HddIndex].Status & (HDD_MASTER_IDE | HDD_MASTER_ATAPI_CDROM | HDD_MASTER_ATAPI_ZIPDISK)) != 0) { BbsTable[BbsIndex + Index].BootPriority = BBS_UNPRIORITIZED_ENTRY; if ((HddInfo[HddIndex].Status & HDD_MASTER_IDE) != 0) { BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK; } else if ((HddInfo[HddIndex].Status & HDD_MASTER_ATAPI_CDROM) != 0) { BbsTable[BbsIndex + Index].DeviceType = BBS_CDROM; } else { // // for ZIPDISK // BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK; } } else { BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY; } } else { if ((HddInfo[HddIndex].Status & (HDD_SLAVE_IDE | HDD_SLAVE_ATAPI_CDROM | HDD_SLAVE_ATAPI_ZIPDISK)) != 0) { BbsTable[BbsIndex + Index].BootPriority = BBS_UNPRIORITIZED_ENTRY; if ((HddInfo[HddIndex].Status & HDD_SLAVE_IDE) != 0) { BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK; } else if ((HddInfo[HddIndex].Status & HDD_SLAVE_ATAPI_CDROM) != 0) { BbsTable[BbsIndex + Index].DeviceType = BBS_CDROM; } else { // // for ZIPDISK // BbsTable[BbsIndex + Index].DeviceType = BBS_HARDDISK; } } else { BbsTable[BbsIndex + Index].BootPriority = BBS_IGNORE_ENTRY; } } } } } // // add virtio-blk devices // { EFI_STATUS Status; UINTN NumPciIoHandles; EFI_HANDLE *PciIoHandles; BbsIndex = HddIndex * 2 + 1; // // scan all handles supporting the PCI IO protocol // Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiPciIoProtocolGuid, NULL, &NumPciIoHandles, &PciIoHandles ); if (Status == EFI_SUCCESS) { UINTN CurPciIo; for (CurPciIo = 0; CurPciIo < NumPciIoHandles; ++CurPciIo) { EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *References; UINTN NumReferences; UINTN CurRef; // // on each handle supporting the PCI IO protocol, see which drivers // (agents) have a PCI IO protocol interface actually opened // Status = gBS->OpenProtocolInformation ( PciIoHandles[CurPciIo], &gEfiPciIoProtocolGuid, &References, &NumReferences ); if (EFI_ERROR (Status)) { continue; } for (CurRef = 0; CurRef < NumReferences; ++CurRef) { if (References[CurRef].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) { EFI_COMPONENT_NAME2_PROTOCOL *ComponentName; CHAR16 *DriverName; // // OpenProtocol() enforced non-NULL AgentHandle for this case // ASSERT (References[CurRef].AgentHandle != NULL); // // Check if the agent owning the open protocol interface can // provide its name, and if so, whether it's VirtioBlkDxe. For this // check we don't want a persistent reference to the agent's // EFI_COMPONENT_NAME2_PROTOCOL instance, therefore we use // HandleProtocol() instead of OpenProtocol(). // Status = gBS->HandleProtocol ( References[CurRef].AgentHandle, &gEfiComponentName2ProtocolGuid, (VOID **) &ComponentName ); if (EFI_ERROR (Status)) { continue; } Status = ComponentName->GetDriverName ( ComponentName, "en", &DriverName ); if (Status == EFI_SUCCESS && StrCmp (DriverName, L"Virtio Block Driver") == 0) { break; } } } if (CurRef < NumReferences) { EFI_PCI_IO_PROTOCOL *PciIo; UINTN Segment; UINTN Bus; UINTN Device; UINTN Function; // // reference by VirtioBlkDxe found, produce boot entry for device // Status = gBS->HandleProtocol ( PciIoHandles[CurPciIo], &gEfiPciIoProtocolGuid, (VOID **) &PciIo ); ASSERT (Status == EFI_SUCCESS); Status = PciIo->GetLocation ( PciIo, &Segment, &Bus, &Device, &Function ); ASSERT (Status == EFI_SUCCESS); if (Segment == 0) { BbsTable[BbsIndex].Bus = (UINT32) Bus; BbsTable[BbsIndex].Device = (UINT32) Device; BbsTable[BbsIndex].Function = (UINT32) Function; BbsTable[BbsIndex].Class = 1; BbsTable[BbsIndex].SubClass = 0x80; BbsTable[BbsIndex].StatusFlags.OldPosition = 0; BbsTable[BbsIndex].StatusFlags.Reserved1 = 0; BbsTable[BbsIndex].StatusFlags.Enabled = 0; BbsTable[BbsIndex].StatusFlags.Failed = 0; BbsTable[BbsIndex].StatusFlags.MediaPresent = 0; BbsTable[BbsIndex].StatusFlags.Reserved2 = 0; BbsTable[BbsIndex].DeviceType = BBS_HARDDISK; BbsTable[BbsIndex].BootPriority = BBS_UNPRIORITIZED_ENTRY; ++BbsIndex; } } FreePool (References); } FreePool (PciIoHandles); } } return EFI_SUCCESS; }
/** Initialize the Nvm Express controller. @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. @retval EFI_SUCCESS The NVM Express Controller is initialized successfully. @retval Others A device error occurred while initializing the controller. **/ EFI_STATUS NvmeControllerInit ( IN NVME_CONTROLLER_PRIVATE_DATA *Private ) { EFI_STATUS Status; EFI_PCI_IO_PROTOCOL *PciIo; UINT64 Supports; NVME_AQA Aqa; NVME_ASQ Asq; NVME_ACQ Acq; UINT8 Sn[21]; UINT8 Mn[41]; // // Save original PCI attributes and enable this controller. // PciIo = Private->PciIo; Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationGet, 0, &Private->PciAttributes ); if (EFI_ERROR (Status)) { return Status; } Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationSupported, 0, &Supports ); if (!EFI_ERROR (Status)) { Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE; Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationEnable, Supports, NULL ); } if (EFI_ERROR (Status)) { DEBUG ((EFI_D_INFO, "NvmeControllerInit: failed to enable controller\n")); return Status; } // // Read the Controller Capabilities register and verify that the NVM command set is supported // Status = ReadNvmeControllerCapabilities (Private, &Private->Cap); if (EFI_ERROR (Status)) { return Status; } if (Private->Cap.Css != 0x01) { DEBUG ((EFI_D_INFO, "NvmeControllerInit: the controller doesn't support NVMe command set\n")); return EFI_UNSUPPORTED; } // // Currently the driver only supports 4k page size. // ASSERT ((Private->Cap.Mpsmin + 12) <= EFI_PAGE_SHIFT); Private->Cid[0] = 0; Private->Cid[1] = 0; Private->Cid[2] = 0; Private->Pt[0] = 0; Private->Pt[1] = 0; Private->Pt[2] = 0; Private->SqTdbl[0].Sqt = 0; Private->SqTdbl[1].Sqt = 0; Private->SqTdbl[2].Sqt = 0; Private->CqHdbl[0].Cqh = 0; Private->CqHdbl[1].Cqh = 0; Private->CqHdbl[2].Cqh = 0; Private->AsyncSqHead = 0; Status = NvmeDisableController (Private); if (EFI_ERROR(Status)) { return Status; } // // set number of entries admin submission & completion queues. // Aqa.Asqs = NVME_ASQ_SIZE; Aqa.Rsvd1 = 0; Aqa.Acqs = NVME_ACQ_SIZE; Aqa.Rsvd2 = 0; // // Address of admin submission queue. // Asq = (UINT64)(UINTN)(Private->BufferPciAddr) & ~0xFFF; // // Address of admin completion queue. // Acq = (UINT64)(UINTN)(Private->BufferPciAddr + EFI_PAGE_SIZE) & ~0xFFF; // // Address of I/O submission & completion queue. // ZeroMem (Private->Buffer, EFI_PAGES_TO_SIZE (6)); Private->SqBuffer[0] = (NVME_SQ *)(UINTN)(Private->Buffer); Private->SqBufferPciAddr[0] = (NVME_SQ *)(UINTN)(Private->BufferPciAddr); Private->CqBuffer[0] = (NVME_CQ *)(UINTN)(Private->Buffer + 1 * EFI_PAGE_SIZE); Private->CqBufferPciAddr[0] = (NVME_CQ *)(UINTN)(Private->BufferPciAddr + 1 * EFI_PAGE_SIZE); Private->SqBuffer[1] = (NVME_SQ *)(UINTN)(Private->Buffer + 2 * EFI_PAGE_SIZE); Private->SqBufferPciAddr[1] = (NVME_SQ *)(UINTN)(Private->BufferPciAddr + 2 * EFI_PAGE_SIZE); Private->CqBuffer[1] = (NVME_CQ *)(UINTN)(Private->Buffer + 3 * EFI_PAGE_SIZE); Private->CqBufferPciAddr[1] = (NVME_CQ *)(UINTN)(Private->BufferPciAddr + 3 * EFI_PAGE_SIZE); Private->SqBuffer[2] = (NVME_SQ *)(UINTN)(Private->Buffer + 4 * EFI_PAGE_SIZE); Private->SqBufferPciAddr[2] = (NVME_SQ *)(UINTN)(Private->BufferPciAddr + 4 * EFI_PAGE_SIZE); Private->CqBuffer[2] = (NVME_CQ *)(UINTN)(Private->Buffer + 5 * EFI_PAGE_SIZE); Private->CqBufferPciAddr[2] = (NVME_CQ *)(UINTN)(Private->BufferPciAddr + 5 * EFI_PAGE_SIZE); DEBUG ((EFI_D_INFO, "Private->Buffer = [%016X]\n", (UINT64)(UINTN)Private->Buffer)); DEBUG ((EFI_D_INFO, "Admin Submission Queue size (Aqa.Asqs) = [%08X]\n", Aqa.Asqs)); DEBUG ((EFI_D_INFO, "Admin Completion Queue size (Aqa.Acqs) = [%08X]\n", Aqa.Acqs)); DEBUG ((EFI_D_INFO, "Admin Submission Queue (SqBuffer[0]) = [%016X]\n", Private->SqBuffer[0])); DEBUG ((EFI_D_INFO, "Admin Completion Queue (CqBuffer[0]) = [%016X]\n", Private->CqBuffer[0])); DEBUG ((EFI_D_INFO, "Sync I/O Submission Queue (SqBuffer[1]) = [%016X]\n", Private->SqBuffer[1])); DEBUG ((EFI_D_INFO, "Sync I/O Completion Queue (CqBuffer[1]) = [%016X]\n", Private->CqBuffer[1])); DEBUG ((EFI_D_INFO, "Async I/O Submission Queue (SqBuffer[2]) = [%016X]\n", Private->SqBuffer[2])); DEBUG ((EFI_D_INFO, "Async I/O Completion Queue (CqBuffer[2]) = [%016X]\n", Private->CqBuffer[2])); // // Program admin queue attributes. // Status = WriteNvmeAdminQueueAttributes (Private, &Aqa); if (EFI_ERROR(Status)) { return Status; } // // Program admin submission queue address. // Status = WriteNvmeAdminSubmissionQueueBaseAddress (Private, &Asq); if (EFI_ERROR(Status)) { return Status; } // // Program admin completion queue address. // Status = WriteNvmeAdminCompletionQueueBaseAddress (Private, &Acq); if (EFI_ERROR(Status)) { return Status; } Status = NvmeEnableController (Private); if (EFI_ERROR(Status)) { return Status; } // // Allocate buffer for Identify Controller data // if (Private->ControllerData == NULL) { Private->ControllerData = (NVME_ADMIN_CONTROLLER_DATA *)AllocateZeroPool (sizeof(NVME_ADMIN_CONTROLLER_DATA)); if (Private->ControllerData == NULL) { return EFI_OUT_OF_RESOURCES; } } // // Get current Identify Controller Data // Status = NvmeIdentifyController (Private, Private->ControllerData); if (EFI_ERROR(Status)) { FreePool(Private->ControllerData); Private->ControllerData = NULL; return EFI_NOT_FOUND; } // // Dump NvmExpress Identify Controller Data // CopyMem (Sn, Private->ControllerData->Sn, sizeof (Private->ControllerData->Sn)); Sn[20] = 0; CopyMem (Mn, Private->ControllerData->Mn, sizeof (Private->ControllerData->Mn)); Mn[40] = 0; DEBUG ((EFI_D_INFO, " == NVME IDENTIFY CONTROLLER DATA ==\n")); DEBUG ((EFI_D_INFO, " PCI VID : 0x%x\n", Private->ControllerData->Vid)); DEBUG ((EFI_D_INFO, " PCI SSVID : 0x%x\n", Private->ControllerData->Ssvid)); DEBUG ((EFI_D_INFO, " SN : %a\n", Sn)); DEBUG ((EFI_D_INFO, " MN : %a\n", Mn)); DEBUG ((EFI_D_INFO, " FR : 0x%x\n", *((UINT64*)Private->ControllerData->Fr))); DEBUG ((EFI_D_INFO, " RAB : 0x%x\n", Private->ControllerData->Rab)); DEBUG ((EFI_D_INFO, " IEEE : 0x%x\n", *(UINT32*)Private->ControllerData->Ieee_oui)); DEBUG ((EFI_D_INFO, " AERL : 0x%x\n", Private->ControllerData->Aerl)); DEBUG ((EFI_D_INFO, " SQES : 0x%x\n", Private->ControllerData->Sqes)); DEBUG ((EFI_D_INFO, " CQES : 0x%x\n", Private->ControllerData->Cqes)); DEBUG ((EFI_D_INFO, " NN : 0x%x\n", Private->ControllerData->Nn)); // // Create two I/O completion queues. // One for blocking I/O, one for non-blocking I/O. // Status = NvmeCreateIoCompletionQueue (Private); if (EFI_ERROR(Status)) { return Status; } // // Create two I/O Submission queues. // One for blocking I/O, one for non-blocking I/O. // Status = NvmeCreateIoSubmissionQueue (Private); if (EFI_ERROR(Status)) { return Status; } return Status; }
/** Starts the device with this driver. @param This The driver binding instance. @param Controller Handle of device to bind driver to. @param RemainingDevicePath Optional parameter use to pick a specific child device to start. @retval EFI_SUCCESS The controller is controlled by the driver. @retval Other This controller cannot be started. **/ EFI_STATUS EFIAPI BiosBlockIoDriverBindingStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; // EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; EFI_PCI_IO_PROTOCOL *PciIo; UINT8 DiskStart = 0x80; UINT8 DiskEnd = 0xFF; BIOS_BLOCK_IO_DEV *BiosBlockIoPrivate; EFI_DEVICE_PATH_PROTOCOL *PciDevPath; UINTN Index; // UINTN Flags; UINTN TmpAddress; BOOLEAN DeviceEnable; // // Initialize variables // PciIo = NULL; PciDevPath = NULL; DeviceEnable = FALSE; // // See if the Legacy BIOS Protocol is available // /* Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **) &LegacyBios); if (EFI_ERROR (Status)) { goto Error; } */ if (mLegacy8259 == NULL) { Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **) &mLegacy8259); if (EFI_ERROR (Status)) { goto Error; } InitializeBiosIntCaller(&mThunkContext); InitializeInterruptRedirection(mLegacy8259); } // // Open the IO Abstraction(s) needed // Status = gBS->OpenProtocol ( Controller, &gEfiPciIoProtocolGuid, (VOID **) &PciIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto Error; } Status = gBS->OpenProtocol ( Controller, &gEfiDevicePathProtocolGuid, (VOID **) &PciDevPath, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto Error; } // // Enable the device and make sure VGA cycles are being forwarded to this VGA device // Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationEnable, EFI_PCI_DEVICE_ENABLE, NULL ); if (EFI_ERROR (Status)) { goto Error; } DeviceEnable = TRUE; // // Check to see if there is a legacy option ROM image associated with this PCI device // //Slice - something for replacement? /* Status = LegacyBios->CheckPciRom ( LegacyBios, Controller, NULL, NULL, &Flags ); if (EFI_ERROR (Status)) { goto Error; } // // Post the legacy option ROM if it is available. // Status = LegacyBios->InstallPciRom ( LegacyBios, Controller, NULL, &Flags, &DiskStart, &DiskEnd, NULL, NULL ); if (EFI_ERROR (Status)) { goto Error; } */ // // All instances share a buffer under 1MB to put real mode thunk code in // If it has not been allocated, then we allocate it. // if (mBufferUnder1Mb == 0) { // // Should only be here if there are no active instances // // ASSERT (mActiveInstances == 0); if (mActiveInstances) { Status = EFI_OUT_OF_RESOURCES; goto Error; } // // Acquire the lock // EfiAcquireLock (&mGlobalDataLock); // // Allocate below 1MB // mBufferUnder1Mb = 0x00000000000FFFFF; Status = gBS->AllocatePages (AllocateMaxAddress, EfiBootServicesData, BLOCK_IO_BUFFER_PAGE_SIZE, &mBufferUnder1Mb); // // Release the lock // EfiReleaseLock (&mGlobalDataLock); // // Check memory allocation success // if (EFI_ERROR (Status)) { // // In checked builds we want to assert if the allocate failed. // // ASSERT_EFI_ERROR (Status); Status = EFI_OUT_OF_RESOURCES; mBufferUnder1Mb = 0; goto Error; } TmpAddress = (UINTN) mBufferUnder1Mb; // // Adjusting the value to be on proper boundary // mEdd11Buffer = (VOID *) ALIGN_VARIABLE (TmpAddress); TmpAddress = (UINTN) mEdd11Buffer + MAX_EDD11_XFER; // // Adjusting the value to be on proper boundary // mLegacyDriverUnder1Mb = (BIOS_LEGACY_DRIVE *) ALIGN_VARIABLE (TmpAddress); TmpAddress = (UINTN) mLegacyDriverUnder1Mb + sizeof (BIOS_LEGACY_DRIVE); // // Adjusting the value to be on proper boundary // mEddBufferUnder1Mb = (EDD_DEVICE_ADDRESS_PACKET *) ALIGN_VARIABLE (TmpAddress); } // // Allocate the private device structure for each disk // for (Index = DiskStart; Index <= DiskEnd; Index++) { Status = gBS->AllocatePool ( EfiBootServicesData, sizeof (BIOS_BLOCK_IO_DEV), (VOID **) &BiosBlockIoPrivate ); if (EFI_ERROR (Status)) { goto Error; } // // Zero the private device structure // ZeroMem (BiosBlockIoPrivate, sizeof (BIOS_BLOCK_IO_DEV)); // // Initialize the private device structure // BiosBlockIoPrivate->Signature = BIOS_CONSOLE_BLOCK_IO_DEV_SIGNATURE; BiosBlockIoPrivate->ControllerHandle = Controller; // BiosBlockIoPrivate->LegacyBios = LegacyBios; BiosBlockIoPrivate->Legacy8259 = mLegacy8259; BiosBlockIoPrivate->ThunkContext = &mThunkContext; BiosBlockIoPrivate->PciIo = PciIo; BiosBlockIoPrivate->Bios.Floppy = FALSE; BiosBlockIoPrivate->Bios.Number = (UINT8) Index; BiosBlockIoPrivate->Bios.Letter = (UINT8) (Index - 0x80 + 'C'); BiosBlockIoPrivate->BlockMedia.RemovableMedia = FALSE; if (BiosInitBlockIo (BiosBlockIoPrivate)) { SetBiosInitBlockIoDevicePath (PciDevPath, &BiosBlockIoPrivate->Bios, &BiosBlockIoPrivate->DevicePath); // // Install the Block Io Protocol onto a new child handle // Status = gBS->InstallMultipleProtocolInterfaces ( &BiosBlockIoPrivate->Handle, &gEfiBlockIoProtocolGuid, &BiosBlockIoPrivate->BlockIo, &gEfiDevicePathProtocolGuid, BiosBlockIoPrivate->DevicePath, NULL ); if (EFI_ERROR (Status)) { gBS->FreePool (BiosBlockIoPrivate); } // // Open For Child Device // Status = gBS->OpenProtocol ( Controller, &gEfiPciIoProtocolGuid, (VOID **) &BiosBlockIoPrivate->PciIo, This->DriverBindingHandle, BiosBlockIoPrivate->Handle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); } else { gBS->FreePool (BiosBlockIoPrivate); } } mBiosDrivesEnumerated = TRUE; Error: if (EFI_ERROR (Status)) { if (PciIo != NULL) { if (DeviceEnable) { PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationDisable, EFI_PCI_DEVICE_ENABLE, NULL ); } gBS->CloseProtocol ( Controller, &gEfiPciIoProtocolGuid, This->DriverBindingHandle, Controller ); if (PciDevPath != NULL) { gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); } if (mBufferUnder1Mb != 0 && mActiveInstances == 0) { gBS->FreePages (mBufferUnder1Mb, BLOCK_IO_BUFFER_PAGE_SIZE); // // Clear the buffer back to 0 // EfiAcquireLock (&mGlobalDataLock); mBufferUnder1Mb = 0; EfiReleaseLock (&mGlobalDataLock); } } } else { // // Successfully installed, so increment the number of active instances // EfiAcquireLock (&mGlobalDataLock); mActiveInstances++; EfiReleaseLock (&mGlobalDataLock); } return Status; }
/** Start function of Driver binding protocol which start this driver on Controller by detecting all disks and installing BlockIo protocol on them. @param This Protocol instance pointer. @param Controller Handle of device to bind driver to. @param RemainingDevicePath produce all possible children. @retval EFI_SUCCESS This driver is added to ControllerHandle. @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle. @retval other This driver does not support this device. **/ EFI_STATUS EFIAPI IDEBusDriverBindingStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { 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; IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData; UINT64 Supports; // // Local variables declaration for IdeControllerInit support // EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit; BOOLEAN EnumAll; BOOLEAN ChannelEnabled; 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. Step7.2 // EnumAll = IdeInit->EnumAll; // // 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, EfiPciIoAttributeOperationSupported, 0, &Supports ); if (!EFI_ERROR (Status)) { Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE; Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationEnable, Supports, 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, NULL, &DataSize, &ConfigurationOptions ); if (EFI_ERROR (Status)) { ConfigurationOptions = 0x0f; } if (EnumAll || RemainingDevicePath == NULL) { // // If IdeInit->EnumAll is TRUE or RemainingDevicePath is NULL, // must enumerate all IDE devices anyway // BeginningIdeChannel = IdePrimary; EndIdeChannel = IdeSecondary; BeginningIdeDevice = IdeMaster; EndIdeDevice = IdeSlave; } else if (!IsDevicePathEnd (RemainingDevicePath)) { // // If RemainingDevicePath isn't the End of Device Path Node, // only scan the specified device by RemainingDevicePath // Node = (EFI_DEV_PATH *) RemainingDevicePath; BeginningIdeChannel = Node->Atapi.PrimarySecondary; EndIdeChannel = BeginningIdeChannel; BeginningIdeDevice = Node->Atapi.SlaveMaster; EndIdeDevice = BeginningIdeDevice; if (BeginningIdeChannel >= IdeMaxChannel || EndIdeChannel >= IdeMaxChannel) { Status = EFI_INVALID_PARAMETER; goto ErrorExit; } if (BeginningIdeDevice >= IdeMaxDevice|| EndIdeDevice >= IdeMaxDevice) { Status = EFI_INVALID_PARAMETER; goto ErrorExit; } } else { // // If RemainingDevicePath is the End of Device Path Node, // skip enumerate any device and return EFI_SUCESSS // BeginningIdeChannel = IdeMaxChannel; EndIdeChannel = IdeMaxChannel - 1; BeginningIdeDevice = IdeMaxDevice; EndIdeDevice = IdeMaxDevice - 1; } // // 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) MIN ((MaxDevices - 1), EndIdeDevice); ASSERT (EndIdeDevice < IdeMaxDevice); // // 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 ); // // Prepare to detect IDE device of this channel // InitializeIDEChannelData (); // // -- 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))) == 0) { 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 = (EFI_IDE_CHANNEL) IdeChannel; IdeBlkIoDevicePtr->Device = (EFI_IDE_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_EX ( EFI_PROGRESS_CODE, (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_PRESENCE_DETECT), 0, &gEfiCallerIdGuid, NULL, NULL, 0 ); // // Discover device, now! // PERF_START (NULL, "DiscoverIdeDevice", "IDE", 0); Status = DiscoverIdeDevice (IdeBlkIoDevicePtr); PERF_END (NULL, "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->IdData, sizeof (IdentifyData)); 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++) { ASSERT (IdeChannel * 2 + IdeDevice < MAX_IDE_DEVICE); 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; } ASSERT (IdeChannel < IdeMaxChannel && IdeDevice < IdeMaxDevice); IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice]; // // Set best supported PIO mode on this IDE device // if (SupportedModes->PioMode.Mode <= AtaPioMode2) { 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; } // // Record Udma Mode // IdeBlkIoDevicePtr->UdmaMode.Valid = TRUE; IdeBlkIoDevicePtr->UdmaMode.Mode = SupportedModes->UdmaMode.Mode; 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) ((ATA5_IDENTIFY_DATA *) IdeBlkIoDevicePtr->IdData)->sectors_per_track; DriveParameters.Heads = (UINT8) (((ATA5_IDENTIFY_DATA *) IdeBlkIoDevicePtr->IdData)->heads - 1); DriveParameters.MultipleSector = (UINT8) IdeBlkIoDevicePtr->IdData->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 = (ATA_PIO_MODE) 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_IDE_ATAPI_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 ); // // Create event to clear pending IDE interrupt // Status = gBS->CreateEventEx ( EVT_NOTIFY_SIGNAL, TPL_NOTIFY, ClearInterrupt, IdeBlkIoDevicePtr, &gEfiEventExitBootServicesGuid, &IdeBlkIoDevicePtr->ExitBootServiceEvent ); // // 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) { FreePool (SupportedModes); } PERF_START (NULL, "Finish IDE detection", "IDE", 1); PERF_END (NULL, "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; }
STATIC UINT16 IScsiGetNICPciLocation ( IN EFI_HANDLE Controller ) /*++ Routine Description: Get the NIC's PCI location and return it accroding to the composited format defined in iSCSI Boot Firmware Table. Arguments: Controller - The handle of the controller. Returns: UINT16 - The composited representation of the NIC PCI location. --*/ { EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_HANDLE PciIoHandle; EFI_PCI_IO_PROTOCOL *PciIo; UINTN Segment; UINTN Bus; UINTN Device; UINTN Function; Status = gBS->HandleProtocol ( Controller, &gEfiDevicePathProtocolGuid, &DevicePath ); if (EFI_ERROR (Status)) { return 0; } Status = gBS->LocateDevicePath ( &gEfiPciIoProtocolGuid, &DevicePath, &PciIoHandle ); if (EFI_ERROR (Status)) { return 0; } Status = gBS->HandleProtocol (PciIoHandle, &gEfiPciIoProtocolGuid, &PciIo); if (EFI_ERROR (Status)) { return 0; } Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function); if (EFI_ERROR (Status)) { return 0; } return (UINT16) ((Bus << 8) | (Device << 3) | Function); }
/** Stop function of Driver Binding Protocol which is to stop the driver on Controller Handle and all child handle attached to the controller handle if there are. @param This Protocol instance pointer. @param Controller Handle of device to stop driver on @param NumberOfChildren Not used @param ChildHandleBuffer Not used @retval EFI_SUCCESS This driver is removed DeviceHandle @retval other This driver was not removed from this device **/ EFI_STATUS EFIAPI IDEBusDriverBindingStop ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer ) { EFI_STATUS Status; EFI_PCI_IO_PROTOCOL *PciIo; BOOLEAN AllChildrenStopped; UINTN Index; IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData; UINT64 Supports; IdeBusDriverPrivateData = NULL; if (NumberOfChildren == 0) { Status = gBS->OpenProtocol ( Controller, &gEfiPciIoProtocolGuid, (VOID **) &PciIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (!EFI_ERROR (Status)) { Status = PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationSupported, 0, &Supports ); if (!EFI_ERROR (Status)) { Supports &= (UINT64)(EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE); PciIo->Attributes ( PciIo, EfiPciIoAttributeOperationDisable, Supports, 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; }
/** Allocate a block of memory to be used by the buffer pool. @param Pool The buffer pool to allocate memory for. @param Pages How many pages to allocate. @return The allocated memory block or NULL if failed. **/ USBHC_MEM_BLOCK * UsbHcAllocMemBlock ( IN USBHC_MEM_POOL *Pool, IN UINTN Pages ) { USBHC_MEM_BLOCK *Block; EFI_PCI_IO_PROTOCOL *PciIo; VOID *BufHost; VOID *Mapping; EFI_PHYSICAL_ADDRESS MappedAddr; UINTN Bytes; EFI_STATUS Status; PciIo = Pool->PciIo; Block = AllocateZeroPool (sizeof (USBHC_MEM_BLOCK)); if (Block == NULL) { return NULL; } // // each bit in the bit array represents USBHC_MEM_UNIT // bytes of memory in the memory block. // ASSERT (USBHC_MEM_UNIT * 8 <= EFI_PAGE_SIZE); Block->BufLen = EFI_PAGES_TO_SIZE (Pages); Block->BitsLen = Block->BufLen / (USBHC_MEM_UNIT * 8); Block->Bits = AllocateZeroPool (Block->BitsLen); if (Block->Bits == NULL) { gBS->FreePool (Block); return NULL; } // // Allocate the number of Pages of memory, then map it for // bus master read and write. // Status = PciIo->AllocateBuffer ( PciIo, AllocateAnyPages, EfiBootServicesData, Pages, &BufHost, 0 ); if (EFI_ERROR (Status)) { goto FREE_BITARRAY; } Bytes = EFI_PAGES_TO_SIZE (Pages); Status = PciIo->Map ( PciIo, EfiPciIoOperationBusMasterCommonBuffer, BufHost, &Bytes, &MappedAddr, &Mapping ); if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (Pages))) { goto FREE_BUFFER; } Block->BufHost = BufHost; Block->Buf = (UINT8 *) ((UINTN) MappedAddr); Block->Mapping = Mapping; return Block; FREE_BUFFER: PciIo->FreeBuffer (PciIo, Pages, BufHost); FREE_BITARRAY: gBS->FreePool (Block->Bits); gBS->FreePool (Block); return NULL; }
/** Call back function when the timer event is signaled. @param[in] Event The Event this notify function registered to. @param[in] Context Pointer to the context data registered to the Event. **/ VOID EFIAPI ProcessAsyncTaskList ( IN EFI_EVENT Event, IN VOID* Context ) { NVME_CONTROLLER_PRIVATE_DATA *Private; EFI_PCI_IO_PROTOCOL *PciIo; NVME_CQ *Cq; UINT16 QueueId; UINT32 Data; LIST_ENTRY *Link; LIST_ENTRY *NextLink; NVME_PASS_THRU_ASYNC_REQ *AsyncRequest; NVME_BLKIO2_SUBTASK *Subtask; NVME_BLKIO2_REQUEST *BlkIo2Request; EFI_BLOCK_IO2_TOKEN *Token; BOOLEAN HasNewItem; EFI_STATUS Status; Private = (NVME_CONTROLLER_PRIVATE_DATA*)Context; QueueId = 2; Cq = Private->CqBuffer[QueueId] + Private->CqHdbl[QueueId].Cqh; HasNewItem = FALSE; PciIo = Private->PciIo; // // Submit asynchronous subtasks to the NVMe Submission Queue // for (Link = GetFirstNode (&Private->UnsubmittedSubtasks); !IsNull (&Private->UnsubmittedSubtasks, Link); Link = NextLink) { NextLink = GetNextNode (&Private->UnsubmittedSubtasks, Link); Subtask = NVME_BLKIO2_SUBTASK_FROM_LINK (Link); BlkIo2Request = Subtask->BlockIo2Request; Token = BlkIo2Request->Token; RemoveEntryList (Link); BlkIo2Request->UnsubmittedSubtaskNum--; // // If any previous subtask fails, do not process subsequent ones. // if (Token->TransactionStatus != EFI_SUCCESS) { if (IsListEmpty (&BlkIo2Request->SubtasksQueue) && BlkIo2Request->LastSubtaskSubmitted && (BlkIo2Request->UnsubmittedSubtaskNum == 0)) { // // Remove the BlockIo2 request from the device asynchronous queue. // RemoveEntryList (&BlkIo2Request->Link); FreePool (BlkIo2Request); gBS->SignalEvent (Token->Event); } FreePool (Subtask->CommandPacket->NvmeCmd); FreePool (Subtask->CommandPacket->NvmeCompletion); FreePool (Subtask->CommandPacket); FreePool (Subtask); continue; } Status = Private->Passthru.PassThru ( &Private->Passthru, Subtask->NamespaceId, Subtask->CommandPacket, Subtask->Event ); if (Status == EFI_NOT_READY) { InsertHeadList (&Private->UnsubmittedSubtasks, Link); BlkIo2Request->UnsubmittedSubtaskNum++; break; } else if (EFI_ERROR (Status)) { Token->TransactionStatus = EFI_DEVICE_ERROR; if (IsListEmpty (&BlkIo2Request->SubtasksQueue) && Subtask->IsLast) { // // Remove the BlockIo2 request from the device asynchronous queue. // RemoveEntryList (&BlkIo2Request->Link); FreePool (BlkIo2Request); gBS->SignalEvent (Token->Event); } FreePool (Subtask->CommandPacket->NvmeCmd); FreePool (Subtask->CommandPacket->NvmeCompletion); FreePool (Subtask->CommandPacket); FreePool (Subtask); } else { InsertTailList (&BlkIo2Request->SubtasksQueue, Link); if (Subtask->IsLast) { BlkIo2Request->LastSubtaskSubmitted = TRUE; } } } while (Cq->Pt != Private->Pt[QueueId]) { ASSERT (Cq->Sqid == QueueId); HasNewItem = TRUE; // // Find the command with given Command Id. // for (Link = GetFirstNode (&Private->AsyncPassThruQueue); !IsNull (&Private->AsyncPassThruQueue, Link); Link = NextLink) { NextLink = GetNextNode (&Private->AsyncPassThruQueue, Link); AsyncRequest = NVME_PASS_THRU_ASYNC_REQ_FROM_THIS (Link); if (AsyncRequest->CommandId == Cq->Cid) { // // Copy the Respose Queue entry for this command to the callers // response buffer. // CopyMem ( AsyncRequest->Packet->NvmeCompletion, Cq, sizeof(EFI_NVM_EXPRESS_COMPLETION) ); // // Free the resources allocated before cmd submission // if (AsyncRequest->MapData != NULL) { PciIo->Unmap (PciIo, AsyncRequest->MapData); } if (AsyncRequest->MapMeta != NULL) { PciIo->Unmap (PciIo, AsyncRequest->MapMeta); } if (AsyncRequest->MapPrpList != NULL) { PciIo->Unmap (PciIo, AsyncRequest->MapPrpList); } if (AsyncRequest->PrpListHost != NULL) { PciIo->FreeBuffer ( PciIo, AsyncRequest->PrpListNo, AsyncRequest->PrpListHost ); } RemoveEntryList (Link); gBS->SignalEvent (AsyncRequest->CallerEvent); FreePool (AsyncRequest); // // Update submission queue head. // Private->AsyncSqHead = Cq->Sqhd; break; } } Private->CqHdbl[QueueId].Cqh++; if (Private->CqHdbl[QueueId].Cqh > NVME_ASYNC_CCQ_SIZE) { Private->CqHdbl[QueueId].Cqh = 0; Private->Pt[QueueId] ^= 1; } Cq = Private->CqBuffer[QueueId] + Private->CqHdbl[QueueId].Cqh; } if (HasNewItem) { Data = ReadUnaligned32 ((UINT32*)&Private->CqHdbl[QueueId]); PciIo->Mem.Write ( PciIo, EfiPciIoWidthUint32, NVME_BAR, NVME_CQHDBL_OFFSET(QueueId, Private->Cap.Dstrd), 1, &Data ); } }