1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492 |
- /** @file
- This file implements I2C IO Protocol which enables the user to manipulate a single
- I2C device independent of the host controller and I2C design.
- Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "I2cDxe.h"
- //
- // EFI_DRIVER_BINDING_PROTOCOL instance
- //
- EFI_DRIVER_BINDING_PROTOCOL gI2cBusDriverBinding = {
- I2cBusDriverSupported,
- I2cBusDriverStart,
- I2cBusDriverStop,
- 0x10,
- NULL,
- NULL
- };
- //
- // Template for I2C Bus Child Device.
- //
- I2C_DEVICE_CONTEXT gI2cDeviceContextTemplate = {
- I2C_DEVICE_SIGNATURE,
- NULL,
- { // I2cIo Protocol
- I2cBusQueueRequest, // QueueRequest
- NULL, // DeviceGuid
- 0, // DeviceIndex
- 0, // HardwareRevision
- NULL // I2cControllerCapabilities
- },
- NULL, // DevicePath
- NULL, // I2cDevice
- NULL, // I2cBusContext
- };
- //
- // Template for controller device path node.
- //
- CONTROLLER_DEVICE_PATH gControllerDevicePathTemplate = {
- {
- HARDWARE_DEVICE_PATH,
- HW_CONTROLLER_DP,
- {
- (UINT8) (sizeof (CONTROLLER_DEVICE_PATH)),
- (UINT8) ((sizeof (CONTROLLER_DEVICE_PATH)) >> 8)
- }
- },
- 0
- };
- //
- // Template for vendor device path node.
- //
- VENDOR_DEVICE_PATH gVendorDevicePathTemplate = {
- {
- HARDWARE_DEVICE_PATH,
- HW_VENDOR_DP,
- {
- (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
- (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
- }
- },
- { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }}
- };
- //
- // Driver name table
- //
- GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mI2cBusDriverNameTable[] = {
- { "eng;en", (CHAR16 *) L"I2C Bus Driver" },
- { NULL , NULL }
- };
- //
- // EFI Component Name Protocol
- //
- GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gI2cBusComponentName = {
- (EFI_COMPONENT_NAME_GET_DRIVER_NAME) I2cBusComponentNameGetDriverName,
- (EFI_COMPONENT_NAME_GET_CONTROLLER_NAME) I2cBusComponentNameGetControllerName,
- "eng"
- };
- //
- // EFI Component Name 2 Protocol
- //
- GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gI2cBusComponentName2 = {
- I2cBusComponentNameGetDriverName,
- I2cBusComponentNameGetControllerName,
- "en"
- };
- /**
- Retrieves a Unicode string that is the user readable name of the driver.
- This function retrieves the user readable name of a driver in the form of a
- Unicode string. If the driver specified by This has a user readable name in
- the language specified by Language, then a pointer to the driver name is
- returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
- by This does not support the language specified by Language,
- then EFI_UNSUPPORTED is returned.
- @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
- EFI_COMPONENT_NAME_PROTOCOL instance.
- @param Language[in] A pointer to a Null-terminated ASCII string
- array indicating the language. This is the
- language of the driver name that the caller is
- requesting, and it must match one of the
- languages specified in SupportedLanguages. The
- number of languages supported by a driver is up
- to the driver writer. Language is specified
- in RFC 4646 or ISO 639-2 language code format.
- @param DriverName[out] A pointer to the Unicode string to return.
- This Unicode string is the name of the
- driver specified by This in the language
- specified by Language.
- @retval EFI_SUCCESS The Unicode string for the Driver specified by
- This and the language specified by Language was
- returned in DriverName.
- @retval EFI_INVALID_PARAMETER Language is NULL.
- @retval EFI_INVALID_PARAMETER DriverName is NULL.
- @retval EFI_UNSUPPORTED The driver specified by This does not support
- the language specified by Language.
- **/
- EFI_STATUS
- EFIAPI
- I2cBusComponentNameGetDriverName (
- IN EFI_COMPONENT_NAME2_PROTOCOL *This,
- IN CHAR8 *Language,
- OUT CHAR16 **DriverName
- )
- {
- return LookupUnicodeString2 (
- Language,
- This->SupportedLanguages,
- mI2cBusDriverNameTable,
- DriverName,
- (BOOLEAN)(This != &gI2cBusComponentName2)
- );
- }
- /**
- Retrieves a Unicode string that is the user readable name of the controller
- that is being managed by a driver.
- This function retrieves the user readable name of the controller specified by
- ControllerHandle and ChildHandle in the form of a Unicode string. If the
- driver specified by This has a user readable name in the language specified by
- Language, then a pointer to the controller name is returned in ControllerName,
- and EFI_SUCCESS is returned. If the driver specified by This is not currently
- managing the controller specified by ControllerHandle and ChildHandle,
- then EFI_UNSUPPORTED is returned. If the driver specified by This does not
- support the language specified by Language, then EFI_UNSUPPORTED is returned.
- @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
- EFI_COMPONENT_NAME_PROTOCOL instance.
- @param ControllerHandle[in] The handle of a controller that the driver
- specified by This is managing. This handle
- specifies the controller whose name is to be
- returned.
- @param ChildHandle[in] The handle of the child controller to retrieve
- the name of. This is an optional parameter that
- may be NULL. It will be NULL for device
- drivers. It will also be NULL for a bus drivers
- that wish to retrieve the name of the bus
- controller. It will not be NULL for a bus
- driver that wishes to retrieve the name of a
- child controller.
- @param Language[in] A pointer to a Null-terminated ASCII string
- array indicating the language. This is the
- language of the driver name that the caller is
- requesting, and it must match one of the
- languages specified in SupportedLanguages. The
- number of languages supported by a driver is up
- to the driver writer. Language is specified in
- RFC 4646 or ISO 639-2 language code format.
- @param ControllerName[out] A pointer to the Unicode string to return.
- This Unicode string is the name of the
- controller specified by ControllerHandle and
- ChildHandle in the language specified by
- Language from the point of view of the driver
- specified by This.
- @retval EFI_SUCCESS The Unicode string for the user readable name in
- the language specified by Language for the
- driver specified by This was returned in
- DriverName.
- @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
- @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
- EFI_HANDLE.
- @retval EFI_INVALID_PARAMETER Language is NULL.
- @retval EFI_INVALID_PARAMETER ControllerName is NULL.
- @retval EFI_UNSUPPORTED The driver specified by This is not currently
- managing the controller specified by
- ControllerHandle and ChildHandle.
- @retval EFI_UNSUPPORTED The driver specified by This does not support
- the language specified by Language.
- **/
- EFI_STATUS
- EFIAPI
- I2cBusComponentNameGetControllerName (
- IN EFI_COMPONENT_NAME2_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN EFI_HANDLE ChildHandle OPTIONAL,
- IN CHAR8 *Language,
- OUT CHAR16 **ControllerName
- )
- {
- return EFI_UNSUPPORTED;
- }
- /**
- Check if the child of I2C controller has been created.
- @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
- @param[in] Controller I2C controller handle.
- @param[in] RemainingDevicePath A pointer to the remaining portion of a device path.
- @param[in] RemainingHasControllerNode Indicate if RemainingDevicePath contains CONTROLLER_DEVICE_PATH.
- @param[in] RemainingControllerNumber Controller number in CONTROLLER_DEVICE_PATH.
- @retval EFI_SUCCESS The child of I2C controller is not created.
- @retval Others The child of I2C controller has been created or other errors happen.
- **/
- EFI_STATUS
- CheckRemainingDevicePath (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE Controller,
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath,
- IN BOOLEAN RemainingHasControllerNode,
- IN UINT32 RemainingControllerNumber
- )
- {
- EFI_STATUS Status;
- EFI_DEVICE_PATH_PROTOCOL *SystemDevicePath;
- EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
- UINTN EntryCount;
- UINTN Index;
- BOOLEAN SystemHasControllerNode;
- UINT32 SystemControllerNumber;
- SystemHasControllerNode = FALSE;
- SystemControllerNumber = 0;
- Status = gBS->OpenProtocolInformation (
- Controller,
- &gEfiI2cHostProtocolGuid,
- &OpenInfoBuffer,
- &EntryCount
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- for (Index = 0; Index < EntryCount; Index++) {
- if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
- Status = gBS->OpenProtocol (
- OpenInfoBuffer[Index].ControllerHandle,
- &gEfiDevicePathProtocolGuid,
- (VOID **) &SystemDevicePath,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (!EFI_ERROR (Status)) {
- //
- // Find vendor device path node and compare
- //
- while (!IsDevicePathEnd (SystemDevicePath)) {
- if ((DevicePathType (SystemDevicePath) == HARDWARE_DEVICE_PATH) &&
- (DevicePathSubType (SystemDevicePath) == HW_VENDOR_DP)) {
- //
- // Check if vendor device path is same between system device path and remaining device path
- //
- if (CompareMem (SystemDevicePath, RemainingDevicePath, sizeof (VENDOR_DEVICE_PATH)) == 0) {
- //
- // Get controller node appended after vendor node
- //
- SystemDevicePath = NextDevicePathNode (SystemDevicePath);
- if ((DevicePathType (SystemDevicePath) == HARDWARE_DEVICE_PATH) &&
- (DevicePathSubType (SystemDevicePath) == HW_CONTROLLER_DP)) {
- SystemHasControllerNode = TRUE;
- SystemControllerNumber = ((CONTROLLER_DEVICE_PATH *) SystemDevicePath)->ControllerNumber;
- } else {
- SystemHasControllerNode = FALSE;
- SystemControllerNumber = 0;
- }
- if (((SystemHasControllerNode) && (!RemainingHasControllerNode) && (SystemControllerNumber == 0)) ||
- ((!SystemHasControllerNode) && (RemainingHasControllerNode) && (RemainingControllerNumber == 0)) ||
- ((SystemHasControllerNode) && (RemainingHasControllerNode) && (SystemControllerNumber == RemainingControllerNumber)) ||
- ((!SystemHasControllerNode) && (!RemainingHasControllerNode))) {
- DEBUG ((EFI_D_ERROR, "This I2C device has been already started.\n"));
- Status = EFI_UNSUPPORTED;
- break;
- }
- }
- }
- SystemDevicePath = NextDevicePathNode (SystemDevicePath);
- }
- if (EFI_ERROR (Status)) {
- break;
- }
- }
- }
- }
- FreePool (OpenInfoBuffer);
- return Status;
- }
- /**
- Tests to see if this driver supports a given controller. If a child device is provided,
- it further tests to see if this driver supports creating a handle for the specified child device.
- This function checks to see if the driver specified by This supports the device specified by
- ControllerHandle. Drivers will typically use the device path attached to
- ControllerHandle and/or the services from the bus I/O abstraction attached to
- ControllerHandle to determine if the driver supports ControllerHandle. This function
- may be called many times during platform initialization. In order to reduce boot times, the tests
- performed by this function must be very small, and take as little time as possible to execute. This
- function must not change the state of any hardware devices, and this function must be aware that the
- device specified by ControllerHandle may already be managed by the same driver or a
- different driver. This function must match its calls to AllocatePages() with FreePages(),
- AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
- Since ControllerHandle may have been previously started by the same driver, if a protocol is
- already in the opened state, then it must not be closed with CloseProtocol(). This is required
- to guarantee the state of ControllerHandle is not modified by this function.
- @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
- @param[in] ControllerHandle The handle of the controller to test. 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 bus drivers, if this parameter is not NULL, then
- the bus driver must determine if the bus controller specified
- by ControllerHandle and the child controller specified
- by RemainingDevicePath are both supported by this
- bus driver.
- @retval EFI_SUCCESS The device specified by ControllerHandle and
- RemainingDevicePath is supported by the driver specified by This.
- @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
- RemainingDevicePath is already being managed by the driver
- specified by This.
- @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
- RemainingDevicePath is already being managed by a different
- driver or an application that requires exclusive access.
- Currently not implemented.
- @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
- RemainingDevicePath is not supported by the driver specified by This.
- **/
- EFI_STATUS
- EFIAPI
- I2cBusDriverSupported (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE Controller,
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
- )
- {
- EFI_STATUS Status;
- EFI_I2C_ENUMERATE_PROTOCOL *I2cEnumerate;
- EFI_I2C_HOST_PROTOCOL *I2cHost;
- EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
- EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
- BOOLEAN RemainingHasControllerNode;
- UINT32 RemainingControllerNumber;
- RemainingHasControllerNode = FALSE;
- RemainingControllerNumber = 0;
- //
- // Determine if the I2c Enumerate Protocol is available
- //
- Status = gBS->OpenProtocol (
- Controller,
- &gEfiI2cEnumerateProtocolGuid,
- (VOID **) &I2cEnumerate,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
- return Status;
- }
- if (!EFI_ERROR (Status)) {
- gBS->CloseProtocol (
- Controller,
- &gEfiI2cEnumerateProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
- }
- 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;
- }
- if (!EFI_ERROR (Status)) {
- gBS->CloseProtocol (
- Controller,
- &gEfiDevicePathProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
- }
- if ((RemainingDevicePath != NULL) && !IsDevicePathEnd (RemainingDevicePath)) {
- //
- // Check if the first node of RemainingDevicePath is a hardware vendor device path
- //
- if ((DevicePathType (RemainingDevicePath) != HARDWARE_DEVICE_PATH) ||
- (DevicePathSubType (RemainingDevicePath) != HW_VENDOR_DP)) {
- return EFI_UNSUPPORTED;
- }
- //
- // Check if the second node of RemainingDevicePath is a controller node
- //
- DevPathNode = NextDevicePathNode (RemainingDevicePath);
- if (!IsDevicePathEnd (DevPathNode)) {
- if ((DevicePathType (DevPathNode) != HARDWARE_DEVICE_PATH) ||
- (DevicePathSubType (DevPathNode) != HW_CONTROLLER_DP)) {
- return EFI_UNSUPPORTED;
- } else {
- RemainingHasControllerNode = TRUE;
- RemainingControllerNumber = ((CONTROLLER_DEVICE_PATH *) DevPathNode)->ControllerNumber;
- }
- }
- }
- //
- // Determine if the I2C Host Protocol is available
- //
- Status = gBS->OpenProtocol (
- Controller,
- &gEfiI2cHostProtocolGuid,
- (VOID **) &I2cHost,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- if (!EFI_ERROR (Status)) {
- gBS->CloseProtocol (
- Controller,
- &gEfiI2cHostProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
- }
- if (Status == EFI_ALREADY_STARTED) {
- if ((RemainingDevicePath == NULL) ||
- ((RemainingDevicePath != NULL) && IsDevicePathEnd (RemainingDevicePath))) {
- //
- // If RemainingDevicePath is NULL or is the End of Device Path Node, return EFI_SUCCESS.
- //
- Status = EFI_SUCCESS;
- } else {
- //
- // Test if the child with the RemainingDevicePath has already been created.
- //
- Status = CheckRemainingDevicePath (
- This,
- Controller,
- RemainingDevicePath,
- RemainingHasControllerNode,
- RemainingControllerNumber
- );
- }
- }
- 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
- I2cBusDriverStart (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE Controller,
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
- )
- {
- EFI_I2C_ENUMERATE_PROTOCOL *I2cEnumerate;
- EFI_I2C_HOST_PROTOCOL *I2cHost;
- I2C_BUS_CONTEXT *I2cBusContext;
- EFI_STATUS Status;
- EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
- I2cBusContext = NULL;
- ParentDevicePath = NULL;
- I2cEnumerate = NULL;
- I2cHost = NULL;
- //
- // Determine if the I2C controller is available
- //
- Status = gBS->OpenProtocol (
- Controller,
- &gEfiI2cHostProtocolGuid,
- (VOID**)&I2cHost,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
- DEBUG ((EFI_D_ERROR, "I2cBus: open I2C host error, Status = %r\n", Status));
- return Status;
- }
- if (Status == EFI_ALREADY_STARTED) {
- Status = gBS->OpenProtocol (
- Controller,
- &gEfiCallerIdGuid,
- (VOID **) &I2cBusContext,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "I2cBus: open private protocol error, Status = %r.\n", Status));
- return Status;
- }
- }
- //
- // Get the I2C bus enumeration API
- //
- Status = gBS->OpenProtocol (
- Controller,
- &gEfiI2cEnumerateProtocolGuid,
- (VOID**)&I2cEnumerate,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
- DEBUG ((EFI_D_ERROR, "I2cBus: open I2C enumerate error, Status = %r\n", Status));
- goto Error;
- }
- Status = gBS->OpenProtocol (
- Controller,
- &gEfiDevicePathProtocolGuid,
- (VOID **) &ParentDevicePath,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
- DEBUG ((EFI_D_ERROR, "I2cBus: open device path error, Status = %r\n", Status));
- goto Error;
- }
- if ((RemainingDevicePath != NULL) && IsDevicePathEnd (RemainingDevicePath)) {
- //
- // If RemainingDevicePath is the End of Device Path Node,
- // don't create any child device and return EFI_SUCESS
- //
- return EFI_SUCCESS;
- }
- //
- // Allocate the buffer for I2C_BUS_CONTEXT if it is not allocated before.
- //
- if (I2cBusContext == NULL) {
- //
- // Allocate the I2C context structure for the current I2C controller
- //
- I2cBusContext = AllocateZeroPool (sizeof (I2C_BUS_CONTEXT));
- if (I2cBusContext == NULL) {
- DEBUG ((EFI_D_ERROR, "I2cBus: there is no enough memory to allocate.\n"));
- Status = EFI_OUT_OF_RESOURCES;
- goto Error;
- }
- /*
- +----------------+
- .->| I2C_BUS_CONTEXT|<----- This file Protocol (gEfiCallerIdGuid) installed on I2C Controller handle
- | +----------------+
- |
- | +----------------------------+
- | | I2C_DEVICE_CONTEXT |
- `--| |
- | |
- | I2C IO Protocol Structure | <----- I2C IO Protocol
- | |
- +----------------------------+
- */
- I2cBusContext->I2cHost = I2cHost;
- I2cBusContext->I2cEnumerate = I2cEnumerate;
- //
- // Parent controller used to create children
- //
- I2cBusContext->Controller = Controller;
- //
- // Parent controller device path used to create children device path
- //
- I2cBusContext->ParentDevicePath = ParentDevicePath;
- I2cBusContext->DriverBindingHandle = This->DriverBindingHandle;
- Status = gBS->InstallMultipleProtocolInterfaces (
- &Controller,
- &gEfiCallerIdGuid,
- I2cBusContext,
- NULL
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "I2cBus: install private protocol error, Status = %r.\n", Status));
- goto Error;
- }
- }
- //
- // Start the driver
- //
- Status = RegisterI2cDevice (I2cBusContext, Controller, RemainingDevicePath);
- return Status;
- Error:
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "I2cBus: Start() function failed, Status = %r\n", Status));
- if (ParentDevicePath != NULL) {
- gBS->CloseProtocol (
- Controller,
- &gEfiDevicePathProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
- }
- if (I2cHost != NULL) {
- gBS->CloseProtocol (
- Controller,
- &gEfiI2cHostProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
- }
- if (I2cEnumerate != NULL) {
- gBS->CloseProtocol (
- Controller,
- &gEfiI2cEnumerateProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
- }
- if (I2cBusContext != NULL) {
- Status = gBS->UninstallMultipleProtocolInterfaces (
- &Controller,
- gEfiCallerIdGuid,
- I2cBusContext,
- NULL
- );
- FreePool (I2cBusContext);
- }
- }
- //
- // Return the operation status.
- //
- return Status;
- }
- /**
- 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
- I2cBusDriverStop (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE Controller,
- IN UINTN NumberOfChildren,
- IN EFI_HANDLE *ChildHandleBuffer
- )
- {
- I2C_BUS_CONTEXT *I2cBusContext;
- EFI_STATUS Status;
- BOOLEAN AllChildrenStopped;
- UINTN Index;
- if (NumberOfChildren == 0) {
- gBS->CloseProtocol (
- Controller,
- &gEfiDevicePathProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
- gBS->CloseProtocol (
- Controller,
- &gEfiI2cHostProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
- gBS->CloseProtocol (
- Controller,
- &gEfiI2cEnumerateProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
- Status = gBS->OpenProtocol (
- Controller,
- &gEfiCallerIdGuid,
- (VOID **) &I2cBusContext,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (!EFI_ERROR (Status)) {
- gBS->UninstallMultipleProtocolInterfaces (
- Controller,
- &gEfiCallerIdGuid,
- I2cBusContext,
- NULL
- );
- //
- // No more child now, free bus context data.
- //
- FreePool (I2cBusContext);
- }
- return Status;
- }
- AllChildrenStopped = TRUE;
- for (Index = 0; Index < NumberOfChildren; Index++) {
- Status = UnRegisterI2cDevice (This, Controller, ChildHandleBuffer[Index]);
- if (EFI_ERROR (Status)) {
- AllChildrenStopped = FALSE;
- }
- }
- if (!AllChildrenStopped) {
- return EFI_DEVICE_ERROR;
- }
- return EFI_SUCCESS;
- }
- /**
- Enumerate the I2C bus
- This routine walks the platform specific data describing the
- I2C bus to create the I2C devices where driver GUIDs were
- specified.
- @param[in] I2cBusContext Address of an I2C_BUS_CONTEXT structure
- @param[in] Controller Handle to the controller
- @param[in] RemainingDevicePath A pointer to the remaining portion of a device path.
- @retval EFI_SUCCESS The bus is successfully configured
- **/
- EFI_STATUS
- RegisterI2cDevice (
- IN I2C_BUS_CONTEXT *I2cBusContext,
- IN EFI_HANDLE Controller,
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
- )
- {
- I2C_DEVICE_CONTEXT *I2cDeviceContext;
- EFI_STATUS Status;
- CONST EFI_I2C_DEVICE *Device;
- CONST EFI_I2C_DEVICE *TempDevice;
- UINT32 RemainingPathDeviceIndex;
- EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
- BOOLEAN BuildControllerNode;
- UINTN Count;
- Status = EFI_SUCCESS;
- BuildControllerNode = TRUE;
- //
- // Default DeviceIndex
- //
- RemainingPathDeviceIndex = 0;
- //
- // Determine the controller number in Controller Node Device Path when RemainingDevicePath is not NULL.
- //
- if (RemainingDevicePath != NULL) {
- //
- // Check if there is a controller node appended after vendor node
- //
- DevPathNode = NextDevicePathNode (RemainingDevicePath);
- if ((DevicePathType (DevPathNode) == HARDWARE_DEVICE_PATH) &&
- (DevicePathSubType(DevPathNode) == HW_CONTROLLER_DP)) {
- //
- // RemainingDevicePath != NULL and RemainingDevicePath contains Controller Node,
- // add Controller Node to Device Path on child handle.
- //
- RemainingPathDeviceIndex = ((CONTROLLER_DEVICE_PATH *) DevPathNode)->ControllerNumber;
- } else {
- //
- // RemainingDevicePath != NULL and RemainingDevicePath does not contain Controller Node,
- // do not add controller node to Device Path on child handle.
- //
- BuildControllerNode = FALSE;
- }
- }
- //
- // Walk the list of I2C devices on this bus
- //
- Device = NULL;
- while (TRUE) {
- //
- // Get the next I2C device
- //
- Status = I2cBusContext->I2cEnumerate->Enumerate (I2cBusContext->I2cEnumerate, &Device);
- if (EFI_ERROR (Status) || Device == NULL) {
- if (RemainingDevicePath != NULL) {
- Status = EFI_NOT_FOUND;
- } else {
- Status = EFI_SUCCESS;
- }
- break;
- }
- //
- // Determine if the device info is valid
- //
- if ((Device->DeviceGuid == NULL) || (Device->SlaveAddressCount == 0) || (Device->SlaveAddressArray == NULL)) {
- DEBUG ((EFI_D_ERROR, "Invalid EFI_I2C_DEVICE reported by I2c Enumerate protocol.\n"));
- continue;
- }
- if (RemainingDevicePath == NULL) {
- if (Device->DeviceIndex == 0) {
- //
- // Determine if the controller node is necessary when controller number is zero in I2C device
- //
- TempDevice = NULL;
- Count = 0;
- while (TRUE) {
- //
- // Get the next I2C device
- //
- Status = I2cBusContext->I2cEnumerate->Enumerate (I2cBusContext->I2cEnumerate, &TempDevice);
- if (EFI_ERROR (Status) || TempDevice == NULL) {
- Status = EFI_SUCCESS;
- break;
- }
- if (CompareGuid (Device->DeviceGuid, TempDevice->DeviceGuid)) {
- Count++;
- }
- }
- if (Count == 1) {
- //
- // RemainingDevicePath == NULL and only DeviceIndex 0 is present on the I2C bus,
- // do not add Controller Node to Device Path on child handle.
- //
- BuildControllerNode = FALSE;
- }
- }
- } else {
- //
- // Find I2C device reported in Remaining Device Path
- //
- if ((!CompareGuid (&((VENDOR_DEVICE_PATH *)RemainingDevicePath)->Guid, Device->DeviceGuid)) ||
- (RemainingPathDeviceIndex != Device->DeviceIndex)) {
- continue;
- }
- }
- //
- // Build the device context for current I2C device.
- //
- I2cDeviceContext = NULL;
- I2cDeviceContext = AllocateCopyPool (sizeof (I2C_DEVICE_CONTEXT), &gI2cDeviceContextTemplate);
- ASSERT (I2cDeviceContext != NULL);
- if (I2cDeviceContext == NULL) {
- continue;
- }
- //
- // Initialize the specific device context
- //
- I2cDeviceContext->I2cBusContext = I2cBusContext;
- I2cDeviceContext->I2cDevice = Device;
- I2cDeviceContext->I2cIo.DeviceGuid = Device->DeviceGuid;
- I2cDeviceContext->I2cIo.DeviceIndex = Device->DeviceIndex;
- I2cDeviceContext->I2cIo.HardwareRevision = Device->HardwareRevision;
- I2cDeviceContext->I2cIo.I2cControllerCapabilities = I2cBusContext->I2cHost->I2cControllerCapabilities;
- //
- // Build the device path
- //
- Status = I2cBusDevicePathAppend (I2cDeviceContext, BuildControllerNode);
- ASSERT_EFI_ERROR (Status);
- if (EFI_ERROR (Status)) {
- continue;
- }
- //
- // Install the protocol
- //
- Status = gBS->InstallMultipleProtocolInterfaces (
- &I2cDeviceContext->Handle,
- &gEfiI2cIoProtocolGuid,
- &I2cDeviceContext->I2cIo,
- &gEfiDevicePathProtocolGuid,
- I2cDeviceContext->DevicePath,
- NULL );
- if (EFI_ERROR (Status)) {
- //
- // Free resources for this I2C device
- //
- ReleaseI2cDeviceContext (I2cDeviceContext);
- continue;
- }
- //
- // Create the child handle
- //
- Status = gBS->OpenProtocol (
- Controller,
- &gEfiI2cHostProtocolGuid,
- (VOID **) &I2cBusContext->I2cHost,
- I2cBusContext->DriverBindingHandle,
- I2cDeviceContext->Handle,
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
- );
- if (EFI_ERROR (Status)) {
- Status = gBS->UninstallMultipleProtocolInterfaces (
- I2cDeviceContext->Handle,
- &gEfiDevicePathProtocolGuid,
- I2cDeviceContext->DevicePath,
- &gEfiI2cIoProtocolGuid,
- &I2cDeviceContext->I2cIo,
- NULL
- );
- //
- // Free resources for this I2C device
- //
- ReleaseI2cDeviceContext (I2cDeviceContext);
- continue;
- }
- if (RemainingDevicePath != NULL) {
- //
- // Child has been created successfully
- //
- break;
- }
- }
- return Status;
- }
- /**
- Queue an I2C transaction for execution on the I2C device.
- This routine must be called at or below TPL_NOTIFY. For synchronous
- requests this routine must be called at or below TPL_CALLBACK.
- This routine queues an I2C transaction to the I2C controller for
- execution on the I2C bus.
- When Event is NULL, QueueRequest() operates synchronously and returns
- the I2C completion status as its return value.
- When Event is not NULL, QueueRequest() synchronously returns EFI_SUCCESS
- indicating that the asynchronous I2C transaction was queued. The values
- above are returned in the buffer pointed to by I2cStatus upon the
- completion of the I2C transaction when I2cStatus is not NULL.
- The upper layer driver writer provides the following to the platform
- vendor:
- 1. Vendor specific GUID for the I2C part
- 2. Guidance on proper construction of the slave address array when the
- I2C device uses more than one slave address. The I2C bus protocol
- uses the SlaveAddressIndex to perform relative to physical address
- translation to access the blocks of hardware within the I2C device.
- @param[in] This Pointer to an EFI_I2C_IO_PROTOCOL structure.
- @param[in] SlaveAddressIndex Index value into an array of slave addresses
- for the I2C device. The values in the array
- are specified by the board designer, with the
- third party I2C device driver writer providing
- the slave address order.
- For devices that have a single slave address,
- this value must be zero. If the I2C device
- uses more than one slave address then the
- third party (upper level) I2C driver writer
- needs to specify the order of entries in the
- slave address array.
- \ref ThirdPartyI2cDrivers "Third Party I2C
- Drivers" section in I2cMaster.h.
- @param[in] Event Event to signal for asynchronous transactions,
- NULL for synchronous transactions
- @param[in] RequestPacket Pointer to an EFI_I2C_REQUEST_PACKET structure
- describing the I2C transaction
- @param[out] I2cStatus Optional buffer to receive the I2C transaction
- completion status
- @retval EFI_SUCCESS The asynchronous transaction was successfully
- queued when Event is not NULL.
- @retval EFI_SUCCESS The transaction completed successfully when
- Event is NULL.
- @retval EFI_BAD_BUFFER_SIZE The RequestPacket->LengthInBytes value is too
- large.
- @retval EFI_DEVICE_ERROR There was an I2C error (NACK) during the
- transaction.
- @retval EFI_INVALID_PARAMETER RequestPacket is NULL
- @retval EFI_NO_MAPPING The EFI_I2C_HOST_PROTOCOL could not set the
- bus configuration required to access this I2C
- device.
- @retval EFI_NO_RESPONSE The I2C device is not responding to the slave
- address selected by SlaveAddressIndex.
- EFI_DEVICE_ERROR will be returned if the
- controller cannot distinguish when the NACK
- occurred.
- @retval EFI_OUT_OF_RESOURCES Insufficient memory for I2C transaction
- @retval EFI_UNSUPPORTED The controller does not support the requested
- transaction.
- **/
- EFI_STATUS
- EFIAPI
- I2cBusQueueRequest (
- IN CONST EFI_I2C_IO_PROTOCOL *This,
- IN UINTN SlaveAddressIndex,
- IN EFI_EVENT Event OPTIONAL,
- IN EFI_I2C_REQUEST_PACKET *RequestPacket,
- OUT EFI_STATUS *I2cStatus OPTIONAL
- )
- {
- CONST EFI_I2C_DEVICE *I2cDevice;
- I2C_BUS_CONTEXT *I2cBusContext;
- CONST EFI_I2C_HOST_PROTOCOL *I2cHost;
- I2C_DEVICE_CONTEXT *I2cDeviceContext;
- EFI_STATUS Status;
- if (RequestPacket == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- //
- // Validate the I2C slave index
- //
- I2cDeviceContext = I2C_DEVICE_CONTEXT_FROM_PROTOCOL (This);
- I2cDevice = I2cDeviceContext->I2cDevice;
- if ( SlaveAddressIndex >= I2cDevice->SlaveAddressCount ) {
- return EFI_INVALID_PARAMETER;
- }
- //
- // Locate the I2c Host Protocol to queue request
- //
- I2cBusContext = I2cDeviceContext->I2cBusContext;
- I2cHost = I2cBusContext->I2cHost;
- //
- // Start the I2C operation
- //
- Status = I2cHost->QueueRequest (
- I2cHost,
- I2cDevice->I2cBusConfiguration,
- I2cDevice->SlaveAddressArray [SlaveAddressIndex],
- Event,
- RequestPacket,
- I2cStatus
- );
- return Status;
- }
- /**
- Release all the resources allocated for the I2C device.
- This function releases all the resources allocated for the I2C device.
- @param I2cDeviceContext The I2C child device involved for the operation.
- **/
- VOID
- ReleaseI2cDeviceContext (
- IN I2C_DEVICE_CONTEXT *I2cDeviceContext
- )
- {
- if (I2cDeviceContext == NULL) {
- return;
- }
- if (I2cDeviceContext->DevicePath != NULL) {
- FreePool (I2cDeviceContext->DevicePath);
- }
- FreePool (I2cDeviceContext);
- }
- /**
- Unregister an I2C device.
- This function removes the protocols installed on the controller handle and
- frees the resources allocated for the I2C device.
- @param This The pointer to EFI_DRIVER_BINDING_PROTOCOL instance.
- @param Controller The controller handle of the I2C device.
- @param Handle The child handle.
- @retval EFI_SUCCESS The I2C device is successfully unregistered.
- @return Others Some error occurs when unregistering the I2C device.
- **/
- EFI_STATUS
- UnRegisterI2cDevice (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE Controller,
- IN EFI_HANDLE Handle
- )
- {
- EFI_STATUS Status;
- I2C_DEVICE_CONTEXT *I2cDeviceContext;
- EFI_I2C_IO_PROTOCOL *I2cIo;
- EFI_I2C_HOST_PROTOCOL *I2cHost;
- I2cIo = NULL;
- Status = gBS->OpenProtocol (
- Handle,
- &gEfiI2cIoProtocolGuid,
- (VOID **) &I2cIo,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- //
- // Get I2c device context data.
- //
- I2cDeviceContext = I2C_DEVICE_CONTEXT_FROM_PROTOCOL (I2cIo);
- //
- // Close the child handle
- //
- gBS->CloseProtocol (
- Controller,
- &gEfiI2cHostProtocolGuid,
- This->DriverBindingHandle,
- Handle
- );
- //
- // The I2C Bus driver installs the I2C Io and Device Path Protocol in the DriverBindingStart().
- // Here should uninstall them.
- //
- Status = gBS->UninstallMultipleProtocolInterfaces (
- Handle,
- &gEfiDevicePathProtocolGuid,
- I2cDeviceContext->DevicePath,
- &gEfiI2cIoProtocolGuid,
- &I2cDeviceContext->I2cIo,
- NULL
- );
- if (EFI_ERROR (Status)) {
- //
- // Keep parent and child relationship
- //
- gBS->OpenProtocol (
- Controller,
- &gEfiI2cHostProtocolGuid,
- (VOID **) &I2cHost,
- This->DriverBindingHandle,
- Handle,
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
- );
- return Status;
- }
- //
- // Free resources for this I2C device
- //
- ReleaseI2cDeviceContext (I2cDeviceContext);
- return EFI_SUCCESS;
- }
- /**
- Create a path for the I2C device
- Append the I2C slave path to the I2C master controller path.
- @param[in] I2cDeviceContext Address of an I2C_DEVICE_CONTEXT structure.
- @param[in] BuildControllerNode Flag to build controller node in device path.
- @retval EFI_SUCCESS The I2C device path is built successfully.
- @return Others It is failed to built device path.
- **/
- EFI_STATUS
- I2cBusDevicePathAppend (
- IN I2C_DEVICE_CONTEXT *I2cDeviceContext,
- IN BOOLEAN BuildControllerNode
- )
- {
- EFI_DEVICE_PATH_PROTOCOL *PreviousDevicePath;
- PreviousDevicePath = NULL;
- //
- // Build vendor device path
- //
- CopyMem (&gVendorDevicePathTemplate.Guid, I2cDeviceContext->I2cDevice->DeviceGuid, sizeof (EFI_GUID));
- I2cDeviceContext->DevicePath = AppendDevicePathNode (
- I2cDeviceContext->I2cBusContext->ParentDevicePath,
- (EFI_DEVICE_PATH_PROTOCOL *) &gVendorDevicePathTemplate
- );
- ASSERT (I2cDeviceContext->DevicePath != NULL);
- if (I2cDeviceContext->DevicePath == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- if ((BuildControllerNode) && (I2cDeviceContext->DevicePath != NULL)) {
- //
- // Build the final I2C device path with controller node
- //
- PreviousDevicePath = I2cDeviceContext->DevicePath;
- gControllerDevicePathTemplate.ControllerNumber = I2cDeviceContext->I2cDevice->DeviceIndex;
- I2cDeviceContext->DevicePath = AppendDevicePathNode (
- I2cDeviceContext->DevicePath,
- (EFI_DEVICE_PATH_PROTOCOL *) &gControllerDevicePathTemplate
- );
- gBS->FreePool (PreviousDevicePath);
- ASSERT (I2cDeviceContext->DevicePath != NULL);
- if (I2cDeviceContext->DevicePath == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- }
- return EFI_SUCCESS;
- }
- /**
- The user entry point for the I2C bus module. The user code starts with
- this function.
- @param[in] ImageHandle The firmware allocated handle for the EFI image.
- @param[in] SystemTable A pointer to the EFI System Table.
- @retval EFI_SUCCESS The entry point is executed successfully.
- @retval other Some error occurs when executing this entry point.
- **/
- EFI_STATUS
- EFIAPI
- InitializeI2cBus(
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
- {
- EFI_STATUS Status;
- //
- // Install driver model protocol(s).
- //
- Status = EfiLibInstallDriverBindingComponentName2 (
- ImageHandle,
- SystemTable,
- &gI2cBusDriverBinding,
- NULL,
- &gI2cBusComponentName,
- &gI2cBusComponentName2
- );
- ASSERT_EFI_ERROR (Status);
- return Status;
- }
- /**
- This is the unload handle for I2C bus module.
- Disconnect the driver specified by ImageHandle from all the devices in the handle database.
- Uninstall all the protocols installed in the driver entry point.
- @param[in] ImageHandle The drivers' driver image.
- @retval EFI_SUCCESS The image is unloaded.
- @retval Others Failed to unload the image.
- **/
- EFI_STATUS
- EFIAPI
- I2cBusUnload (
- IN EFI_HANDLE ImageHandle
- )
- {
- EFI_STATUS Status;
- EFI_HANDLE *DeviceHandleBuffer;
- UINTN DeviceHandleCount;
- UINTN Index;
- EFI_COMPONENT_NAME_PROTOCOL *ComponentName;
- EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2;
- //
- // Get the list of all I2C Controller handles in the handle database.
- // If there is an error getting the list, then the unload
- // operation fails.
- //
- Status = gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiI2cHostProtocolGuid,
- NULL,
- &DeviceHandleCount,
- &DeviceHandleBuffer
- );
- if (!EFI_ERROR (Status)) {
- //
- // Disconnect the driver specified by Driver BindingHandle from all
- // the devices in the handle database.
- //
- for (Index = 0; Index < DeviceHandleCount; Index++) {
- Status = gBS->DisconnectController (
- DeviceHandleBuffer[Index],
- gI2cBusDriverBinding.DriverBindingHandle,
- NULL
- );
- if (EFI_ERROR (Status)) {
- goto Done;
- }
- }
- }
- //
- // Uninstall all the protocols installed in the driver entry point
- //
- Status = gBS->UninstallMultipleProtocolInterfaces (
- gI2cBusDriverBinding.DriverBindingHandle,
- &gEfiDriverBindingProtocolGuid,
- &gI2cBusDriverBinding,
- NULL
- );
- ASSERT_EFI_ERROR (Status);
- //
- // Note we have to one by one uninstall the following protocols.
- // It's because some of them are optionally installed based on
- // the following PCD settings.
- // gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable
- // gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable
- // gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable
- // gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable
- //
- Status = gBS->HandleProtocol (
- gI2cBusDriverBinding.DriverBindingHandle,
- &gEfiComponentNameProtocolGuid,
- (VOID **) &ComponentName
- );
- if (!EFI_ERROR (Status)) {
- gBS->UninstallProtocolInterface (
- gI2cBusDriverBinding.DriverBindingHandle,
- &gEfiComponentNameProtocolGuid,
- ComponentName
- );
- }
- Status = gBS->HandleProtocol (
- gI2cBusDriverBinding.DriverBindingHandle,
- &gEfiComponentName2ProtocolGuid,
- (VOID **) &ComponentName2
- );
- if (!EFI_ERROR (Status)) {
- gBS->UninstallProtocolInterface (
- gI2cBusDriverBinding.DriverBindingHandle,
- &gEfiComponentName2ProtocolGuid,
- ComponentName2
- );
- }
- Status = EFI_SUCCESS;
- Done:
- //
- // Free the buffer containing the list of handles from the handle database
- //
- if (DeviceHandleBuffer != NULL) {
- gBS->FreePool (DeviceHandleBuffer);
- }
- return Status;
- }
|