!484 Uploading PCIE framework code to the Library

Merge pull request !484 from liangxuewu/lxw_pcie_1211
This commit is contained in:
openharmony_ci 2021-12-28 15:04:57 +00:00 committed by Gitee
commit 08db5ad015
13 changed files with 1248 additions and 0 deletions

101
include/platform/pcie_if.h Normal file
View File

@ -0,0 +1,101 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
/**
* @addtogroup PCIE
* @{
*
* @brief Declares standard APIs of basic Peripheral Component Interconnect Express (PCIE) capabilities.
*
* You can use this module to access the PCIE and enable the driver to operate an PCIE device.
* These capabilities include read and write the PCIE configuration Space.
*
* @since 1.0
*/
/**
* @file pcie_if.h
*
* @brief Declares the standard PCIE interface functions.
*
* @since 1.0
*/
#ifndef PCIE_IF_H
#define PCIE_IF_H
#include "platform_if.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
/**
* @brief Opens an PCIE controller with a specified bus number.
*
* Before using the PCIE interface, you can obtain the device handle of the PCIE controller
* by calling {@link PcieOpen}. This function is used in pair with {@link PcieClose}.
*
* @param busNum Indicates the bus number.
*
* @return Returns the device handle {@link DevHandle} of the PCIE controller if the operation is successful;
* returns <b>NULL</b> otherwise.
*
* @since 1.0
*/
DevHandle PcieOpen(uint16_t busNum);
/**
* @brief Reads a given length of data from the PCIE configuration Space.
*
* @param handle Indicates the pointer to the device handle of the PCIE controller obtained by {@link PcieOpen}.
* @param pos Indicates the start address of the data to read.
* @param data Indicates the pointer to the data to read.
* @param len Indicates the length of the data to read.
*
* @return Returns <b>0</b> if the operation is successful; returns a negative value if the operation fails.
*
* @since 1.0
*/
int32_t PcieRead(DevHandle handle, uint32_t pos, uint8_t *data, uint32_t len);
/**
* @brief Writes a given length of data into the PCIE configuration Space.
*
* @param handle Indicates the pointer to the device handle of the PCIE controller obtained by {@link PcieOpen}.
* @param pos Indicates the start address of the data to write.
* @param data Indicates the pointer to the data to write.
* @param len Indicates the length of the data to write.
*
* @return Returns <b>0</b> if the operation is successful; returns a negative value if the operation fails.
*
* @since 1.0
*/
int32_t PcieWrite(DevHandle handle, uint32_t pos, uint8_t *data, uint32_t len);
/**
* @brief Closes an PCIE controller.
*
* After the PCIE interface is used, you can close the PCIE controller by calling {@link PcieClose}.
* This function is used in pair with {@link PcieOpen}.
*
* @param handle Indicates the pointer to the device handle of the PCIE controller.
*
* @since 1.0
*/
void PcieClose(DevHandle handle);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */
#endif /* PCIE_IF_H */

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#ifndef PCIE_CORE_H
#define PCIE_CORE_H
#include "hdf_base.h"
#include "hdf_device_desc.h"
#include "osal_mutex.h"
#include "platform_core.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
struct PcieCntlr;
struct PcieCntlrOps {
int32_t (*read)(struct PcieCntlr *cntlr, uint32_t pos, uint8_t *data, uint32_t len);
int32_t (*write)(struct PcieCntlr *cntlr, uint32_t pos, uint8_t *data, uint32_t len);
};
struct PcieDevCfgInfo {
uint32_t busNum;
uint32_t vendorId;
uint32_t devId;
};
struct PcieCntlr {
struct IDeviceIoService service;
struct HdfDeviceObject *hdfDevObj;
struct PlatformDevice device;
struct OsalMutex mutex;
struct PcieCntlrOps *ops;
struct PcieDevCfgInfo devInfo;
void *priv;
};
static inline void PcieCntlrLock(struct PcieCntlr *cntlr)
{
if (cntlr != NULL) {
(void)OsalMutexLock(&cntlr->mutex);
}
}
static inline void PcieCntlrUnlock(struct PcieCntlr *cntlr)
{
if (cntlr != NULL) {
(void)OsalMutexUnlock(&cntlr->mutex);
}
}
static inline struct PcieCntlr *PcieCntlrGetByBusNum(uint16_t num)
{
struct PlatformDevice *device = PlatformManagerGetDeviceByNumber(PlatformManagerGet(PLATFORM_MODULE_PCIE), num);
if (device == NULL) {
return NULL;
}
return CONTAINER_OF(device, struct PcieCntlr, device);
}
int32_t PcieCntlrParse(struct PcieCntlr *cntlr, struct HdfDeviceObject *obj);
int32_t PcieCntlrAdd(struct PcieCntlr *cntlr);
void PcieCntlrRemove(struct PcieCntlr *cntlr);
int32_t PcieCntlrRead(struct PcieCntlr *cntlr, uint32_t pos, uint8_t *data, uint32_t len);
int32_t PcieCntlrWrite(struct PcieCntlr *cntlr, uint32_t pos, uint8_t *data, uint32_t len);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */
#endif /* PCIE_CORE_H */

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#ifndef PCIE_DISPATCH_H
#define PCIE_DISPATCH_H
#include "hdf_base.h"
#ifndef __USER__
#include "devsvc_manager_clnt.h"
#endif
#ifdef __USER__
#include "hdf_io_service_if.h"
#endif
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */
#ifndef __USER__
int32_t PcieIoDispatch(struct HdfDeviceIoClient *client, int cmd, struct HdfSBuf *data, struct HdfSBuf *reply);
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */
#endif /* PCIE_DISPATCH_H */

View File

@ -0,0 +1,156 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include "pcie_core.h"
#include "device_resource_if.h"
#include "hdf_log.h"
#include "osal_mem.h"
#include "osal_time.h"
#include "pcie_dispatch.h"
#include "securec.h"
#define HDF_LOG_TAG pcie_core_c
static int32_t PcieCntlrInit(struct PcieCntlr *cntlr)
{
int32_t ret;
if (cntlr == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
if (cntlr->hdfDevObj == NULL) {
HDF_LOGE("PcieCntlrInit: no HdfDeviceObject attached!");
return HDF_ERR_INVALID_OBJECT;
}
ret = OsalMutexInit(&cntlr->mutex);
if (ret != HDF_SUCCESS) {
HDF_LOGE("PcieCntlrInit: mutex init fail!");
return ret;
}
cntlr->service.Dispatch = PcieIoDispatch;
cntlr->hdfDevObj->service = &(cntlr->service);
cntlr->device.number = cntlr->devInfo.busNum;
cntlr->device.hdfDev = cntlr->hdfDevObj;
return HDF_SUCCESS;
}
static void PcieCntlrUninit(struct PcieCntlr *cntlr)
{
if (cntlr != NULL) {
(void)OsalMutexDestroy(&cntlr->mutex);
}
}
int32_t PcieCntlrAdd(struct PcieCntlr *cntlr)
{
int32_t ret;
if (cntlr == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
ret = PcieCntlrInit(cntlr);
if (ret != HDF_SUCCESS) {
return ret;
}
cntlr->device.manager = PlatformManagerGet(PLATFORM_MODULE_PCIE);
ret = PlatformDeviceAdd(&cntlr->device);
if (ret != HDF_SUCCESS) {
HDF_LOGE("PcieCntlrAdd: device add fail!");
PcieCntlrUninit(cntlr);
return ret;
}
return HDF_SUCCESS;
}
void PcieCntlrRemove(struct PcieCntlr *cntlr)
{
if (cntlr != NULL) {
PlatformDeviceDel(&cntlr->device);
PcieCntlrUninit(cntlr);
}
}
int32_t PcieCntlrParse(struct PcieCntlr *cntlr, struct HdfDeviceObject *obj)
{
const struct DeviceResourceNode *node = NULL;
struct DeviceResourceIface *drsOps = NULL;
int32_t ret;
if (obj == NULL || cntlr == NULL) {
HDF_LOGE("PcieCntlrParse: input param is NULL.");
return HDF_FAILURE;
}
node = obj->property;
if (node == NULL) {
HDF_LOGE("PcieCntlrParse: drs node is NULL.");
return HDF_FAILURE;
}
drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
if (drsOps == NULL || drsOps->GetUint32 == NULL) {
HDF_LOGE("PcieCntlrParse: invalid drs ops fail.");
return HDF_FAILURE;
}
ret = drsOps->GetUint32(node, "busNum", &(cntlr->devInfo.busNum), 0);
if (ret != HDF_SUCCESS) {
HDF_LOGE("PcieCntlrParse: read busNum fail!");
return ret;
}
ret = drsOps->GetUint32(node, "vendorId", &(cntlr->devInfo.vendorId), 0);
if (ret != HDF_SUCCESS) {
HDF_LOGE("PcieCntlrParse: read vendorId fail!");
return HDF_FAILURE;
}
ret = drsOps->GetUint32(node, "devId", &(cntlr->devInfo.devId), 0);
if (ret != HDF_SUCCESS) {
HDF_LOGE("PcieCntlrParse: read devId fail!");
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
int32_t PcieCntlrRead(struct PcieCntlr *cntlr, uint32_t pos, uint8_t *data, uint32_t len)
{
int32_t ret;
if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->read == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
if (data == NULL || len == 0) {
return HDF_ERR_INVALID_PARAM;
}
PcieCntlrLock(cntlr);
ret = cntlr->ops->read(cntlr, pos, data, len);
PcieCntlrUnlock(cntlr);
return ret;
}
int32_t PcieCntlrWrite(struct PcieCntlr *cntlr, uint32_t pos, uint8_t *data, uint32_t len)
{
int32_t ret;
if (cntlr == NULL || cntlr->ops == NULL || cntlr->ops->write == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
if (data == NULL || len == 0) {
return HDF_ERR_INVALID_PARAM;
}
PcieCntlrLock(cntlr);
ret = cntlr->ops->write(cntlr, pos, data, len);
PcieCntlrUnlock(cntlr);
return ret;
}

View File

@ -0,0 +1,115 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include "pcie_dispatch.h"
#include "hdf_log.h"
#include "osal_mem.h"
#include "pcie_core.h"
#include "pcie_if.h"
#define HDF_LOG_TAG pcie_dispatch_c
enum PcieIoCmd {
PCIE_CMD_READ,
PCIE_CMD_WRITE,
PCIE_CMD_BUTT,
};
struct PcieDispatchFunc {
int32_t cmd;
int32_t (*func)(struct PcieCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply);
};
static int32_t PcieCmdRead(struct PcieCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply)
{
uint32_t len, pos;
uint8_t *buf = NULL;
int32_t ret;
if (!HdfSbufReadUint32(data, &len)) {
HDF_LOGE("PcieCmdRead: read len fail");
return HDF_ERR_IO;
}
if (len == 0) {
return HDF_ERR_INVALID_PARAM;
}
if (!HdfSbufReadUint32(data, &pos)) {
HDF_LOGE("PcieCmdRead: read pos fail");
return HDF_ERR_IO;
}
buf = (uint8_t *)OsalMemCalloc(sizeof(*buf) * len);
if (buf == NULL) {
HDF_LOGE("PcieCmdRead: OsalMemCalloc error");
return HDF_ERR_MALLOC_FAIL;
}
ret = PcieCntlrRead(cntlr, pos, buf, len);
if (ret != HDF_SUCCESS) {
HDF_LOGE("PcieCntlrRead: error, ret is %d", ret);
goto EXIT;
}
if (!HdfSbufWriteBuffer(reply, buf, len)) {
HDF_LOGE("PcieCntlrRead: sbuf write buffer failed");
ret = HDF_ERR_IO;
goto EXIT;
}
ret = HDF_SUCCESS;
EXIT:
OsalMemFree(buf);
return ret;
}
static int32_t PcieCmdWrite(struct PcieCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply)
{
uint32_t size, pos;
uint8_t *buf = NULL;
(void)reply;
if (!HdfSbufReadUint32(data, &pos)) {
HDF_LOGE("PcieCmdWrite: read pos fail");
return HDF_ERR_IO;
}
if (!HdfSbufReadBuffer(data, (const void **)&buf, &size)) {
HDF_LOGE("PcieCmdWrite: sbuf read buffer failed");
return HDF_ERR_IO;
}
return PcieCntlrWrite(cntlr, pos, buf, size);
}
int32_t PcieIoDispatch(struct HdfDeviceIoClient *client, int32_t cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
{
struct PcieCntlr *cntlr = NULL;
uint32_t i;
uint32_t len;
struct PcieDispatchFunc dispatchFunc[] = {
{ PCIE_CMD_READ, PcieCmdRead },
{ PCIE_CMD_WRITE, PcieCmdWrite },
};
if (client == NULL || client->device == NULL) {
HDF_LOGE("PcieIoDispatch: client or hdf dev obj is NULL");
return HDF_ERR_INVALID_OBJECT;
}
cntlr = (struct PcieCntlr *)client->device->service;
if (cntlr == NULL) {
HDF_LOGE("PcieIoDispatch: service is NULL");
return HDF_ERR_INVALID_OBJECT;
}
len = sizeof(dispatchFunc) / sizeof(dispatchFunc[0]);
for (i = 0; i < len; i++) {
if (dispatchFunc[i].cmd == cmd) {
return dispatchFunc[i].func(cntlr, data, reply);
}
}
HDF_LOGE("PcieIoDispatch: cmd %d is not support", cmd);
return HDF_ERR_NOT_SUPPORT;
}

View File

@ -0,0 +1,203 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include "pcie_if.h"
#ifndef __USER__
#include "devsvc_manager_clnt.h"
#include "pcie_core.h"
#endif
#include "hdf_base.h"
#include "hdf_log.h"
#ifdef __USER__
#include "hdf_io_service_if.h"
#endif
#include "osal_mem.h"
#include "securec.h"
#define HDF_LOG_TAG pcie_if_c
#define PCIE_SERVICE_NAME_LEN 32
#ifdef __USER__
enum PcieIoCmd {
PCIE_CMD_READ,
PCIE_CMD_WRITE,
PCIE_CMD_BUTT,
};
static int32_t PcieGetDataFromReply(struct HdfSBuf *reply, uint8_t *data, uint32_t size)
{
uint32_t rLen;
const void *rBuf = NULL;
if (HdfSbufReadBuffer(reply, &rBuf, &rLen) == false) {
HDF_LOGE("PcieGetDataFromReply: read rBuf fail!");
return HDF_ERR_IO;
}
if (size != rLen) {
HDF_LOGE("PcieGetDataFromReply: err len:%u, rLen:%u", size, rLen);
if (rLen > size) {
rLen = size;
}
}
if (memcpy_s(data, size, rBuf, rLen) != EOK) {
HDF_LOGE("PcieGetDataFromReply: memcpy rBuf fail!");
return HDF_ERR_IO;
}
return HDF_SUCCESS;
}
static int32_t PcieUserRead(DevHandle handle, uint32_t pos, uint8_t *data, uint32_t len)
{
int32_t ret;
struct HdfSBuf *reply = NULL;
struct HdfSBuf *buf = NULL;
struct HdfIoService *service = (struct HdfIoService *)handle;
if (service == NULL || service->dispatcher == NULL || service->dispatcher->Dispatch == NULL) {
HDF_LOGE("PcieUserRead: service is invalid");
return HDF_ERR_INVALID_PARAM;
}
if (data == NULL || len == 0) {
return HDF_ERR_INVALID_PARAM;
}
buf = HdfSBufObtainDefaultSize();
if (buf == NULL) {
HDF_LOGE("PcieUserRead: failed to obtain buf");
ret = HDF_ERR_MALLOC_FAIL;
goto EXIT;
}
if (!HdfSbufWriteUint32(buf, len)) {
HDF_LOGE("PcieUserRead: sbuf write uint32 failed");
ret = HDF_ERR_IO;
goto EXIT;
}
if (!HdfSbufWriteUint32(buf, pos)) {
HDF_LOGE("PcieUserRead: sbuf write uint32 failed");
ret = HDF_ERR_IO;
goto EXIT;
}
reply = HdfSBufObtainDefaultSize();
if (reply == NULL) {
HDF_LOGE("PcieUserRead: failed to obtain reply");
ret = HDF_ERR_MALLOC_FAIL;
goto EXIT;
}
ret = service->dispatcher->Dispatch(&service->object, PCIE_CMD_READ, buf, reply);
if (ret != HDF_SUCCESS) {
HDF_LOGE("PcieUserRead: failed to write, ret %d", ret);
} else {
ret = PcieGetDataFromReply(reply, data, len);
}
EXIT :
if (reply != NULL) {
HdfSBufRecycle(reply);
}
if (buf != NULL) {
HdfSBufRecycle(buf);
}
return ret;
}
static int32_t PcieUserWrite(DevHandle handle, uint32_t pos, uint8_t *data, uint32_t len)
{
int32_t ret;
struct HdfSBuf *buf = NULL;
struct HdfIoService *service = (struct HdfIoService *)handle;
if (service == NULL || service->dispatcher == NULL || service->dispatcher->Dispatch == NULL) {
HDF_LOGE("PcieUserWrite: service is invalid");
return HDF_ERR_INVALID_PARAM;
}
buf = HdfSBufObtainDefaultSize();
if (buf == NULL) {
HDF_LOGE("PcieUserWrite: failed to obtain buf");
return HDF_ERR_MALLOC_FAIL;
}
if (!HdfSbufWriteUint32(buf, pos)) {
HDF_LOGE("PcieUserWrite: sbuf write uint32 failed");
ret = HDF_ERR_IO;
goto EXIT;
}
if (!HdfSbufWriteBuffer(buf, data, len)) {
HDF_LOGE("PcieUserWrite: sbuf write buffer failed");
ret = HDF_ERR_IO;
goto EXIT;
}
ret = service->dispatcher->Dispatch(&service->object, PCIE_CMD_WRITE, buf, NULL);
if (ret != HDF_SUCCESS) {
HDF_LOGE("PcieUserWrite: failed to write, ret %d", ret);
}
EXIT:
HdfSBufRecycle(buf);
return ret;
}
#endif
static void *PcieCntlrObjGet(uint16_t busNum)
{
char *serviceName = NULL;
void *obj = NULL;
serviceName = (char *)OsalMemCalloc(PCIE_SERVICE_NAME_LEN + 1);
if (serviceName == NULL) {
HDF_LOGE("HDMI service name malloc fail.");
return NULL;
}
if (snprintf_s(serviceName, (PCIE_SERVICE_NAME_LEN + 1),
PCIE_SERVICE_NAME_LEN, "HDF_PLATFORM_PCIE_%d", busNum) < 0) {
HDF_LOGE("get PCIE service name fail.");
goto EXIT;
}
#ifdef __USER__
obj = (void *)HdfIoServiceBind(serviceName);
#else
obj = (void *)PcieCntlrGetByBusNum(busNum);
#endif
EXIT:
OsalMemFree(serviceName);
return obj;
}
DevHandle PcieOpen(uint16_t busNum)
{
return (DevHandle)PcieCntlrObjGet(busNum);
}
int32_t PcieRead(DevHandle handle, uint32_t pos, uint8_t *data, uint32_t len)
{
#ifdef __USER__
return PcieUserRead(handle, pos, data, len);
#else
return PcieCntlrRead((struct PcieCntlr *)handle, pos, data, len);
#endif
}
int32_t PcieWrite(DevHandle handle, uint32_t pos, uint8_t *data, uint32_t len)
{
#ifdef __USER__
return PcieUserWrite(handle, pos, data, len);
#else
return PcieCntlrWrite((struct PcieCntlr *)handle, pos, data, len);
#endif
}
void PcieClose(DevHandle handle)
{
if (handle != NULL) {
#ifdef __USER__
HdfIoServiceRecycle((struct HdfIoService *)handle);
#endif
}
}

View File

@ -0,0 +1,128 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <fcntl.h>
#include <gtest/gtest.h>
#include <string>
#include <unistd.h>
#include "hdf_io_service_if.h"
#include "hdf_uhdf_test.h"
#include "pcie_if.h"
using namespace testing::ext;
#define PCIE_DISABLE_ADDR 0xB7
#define PCIE_UPPER_ADDR 0x28
#define PCIE_CMD_ADDR 0x04
enum PcieTestCmd {
PCIE_READ_AND_WRITE_01 = 0,
};
class HdfPcieTest : public testing::Test {
public:
static void SetUpTestCase();
static void TearDownTestCase();
void SetUp();
void TearDown();
};
void HdfPcieTest::SetUpTestCase()
{
HdfTestOpenService();
}
void HdfPcieTest::TearDownTestCase()
{
HdfTestCloseService();
}
void HdfPcieTest::SetUp()
{
}
void HdfPcieTest::TearDown()
{
}
static void PcieUserTest(void)
{
DevHandle handle = NULL;
int32_t ret;
uint8_t disable;
uint32_t upper;
uint16_t cmd;
handle = PcieOpen(0);
if (handle == NULL) {
printf("PcieOpen fail.");
}
ret = PcieRead(handle, PCIE_DISABLE_ADDR, &disable, sizeof(disable));
if (ret != HDF_SUCCESS) {
printf("PcieRead failed ret = %d.", ret);
return;
}
printf("disable is %d", disable);
ret = PcieWrite(handle, PCIE_DISABLE_ADDR, &disable, sizeof(disable));
if (ret != HDF_SUCCESS) {
printf("PcieWrite failed ret = %d.", ret);
return;
}
ret = PcieRead(handle, PCIE_UPPER_ADDR, (uint8_t *)&upper, sizeof(upper));
if (ret != HDF_SUCCESS) {
printf("PcieRead failed ret = %d.", ret);
return;
}
printf("upper is 0x%x", upper);
ret = PcieWrite(handle, PCIE_UPPER_ADDR, (uint8_t *)&upper, sizeof(upper));
if (ret != HDF_SUCCESS) {
printf("PcieWrite failed ret = %d.", ret);
return;
}
ret = PcieRead(handle, PCIE_CMD_ADDR, (uint8_t *)&cmd, sizeof(cmd));
if (ret != HDF_SUCCESS) {
printf("PcieRead failed ret = %d.", ret);
return;
}
printf("cmd is 0x%x", cmd);
ret = PcieWrite(handle, PCIE_CMD_ADDR, (uint8_t *)&cmd, sizeof(cmd));
if (ret != HDF_SUCCESS) {
printf("PcieWrite failed ret = %d.", ret);
return;
}
PcieClose(handle);
}
/**
* @tc.name: PcieReadAndWrite001
* @tc.desc: test PcieRead/PcieWrite interface in kernel status.
* @tc.type: FUNC
* @tc.require:
*/
HWTEST_F(HdfPcieTest, PcieReadAndWrite001, TestSize.Level1)
{
struct HdfTestMsg msg = { TEST_PAL_PCIE_TYPE, PCIE_READ_AND_WRITE_01, -1 };
EXPECT_EQ(0, HdfTestSendMsgToService(&msg));
}
/**
* @tc.name: PcieUserTest001
* @tc.desc: test pcie all interface in user status.
* @tc.type: FUNC
* @tc.require:
*/
HWTEST_F(HdfPcieTest, PcieUserTest001, TestSize.Level1)
{
PcieUserTest();
}

View File

@ -44,6 +44,9 @@
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_SDIO) || defined(CONFIG_DRIVERS_HDF_PLATFORM_SDIO)
#include "hdf_sdio_entry_test.h"
#endif
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_PCIE) || defined(CONFIG_DRIVERS_HDF_PLATFORM_PCIE)
#include "hdf_pcie_entry_test.h"
#endif
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_UART) || defined(CONFIG_DRIVERS_HDF_PLATFORM_UART)
#include "hdf_uart_entry_test.h"
#endif
@ -131,6 +134,9 @@ HdfTestFuncList g_hdfTestFuncList[] = {
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_SDIO) || defined(CONFIG_DRIVERS_HDF_PLATFORM_SDIO)
{ TEST_PAL_SDIO_TYPE, HdfSdioUnitTestEntry },
#endif
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_PCIE) || defined(CONFIG_DRIVERS_HDF_PLATFORM_PCIE)
{ TEST_PAL_PCIE_TYPE, HdfPcieUnitTestEntry },
#endif
#if (defined(LOSCFG_STORAGE_EMMC) && defined(LOSCFG_DRIVERS_HDF_PLATFORM_EMMC)) || \
defined(CONFIG_DRIVERS_HDF_PLATFORM_EMMC)
{ TEST_PAL_EMMC_TYPE, HdfEmmcUnitTestEntry },

View File

@ -0,0 +1,197 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include "device_resource_if.h"
#include "hdf_base.h"
#include "hdf_log.h"
#include "osal_time.h"
#include "pcie_if.h"
#include "pcie_test.h"
#define HDF_LOG_TAG pcie_test_c
#define PCIE_TEST_DISABLE_ADDR 0xB7
#define PCIE_TEST_UPPER_ADDR 0x28
#define PCIE_TEST_CMD_ADDR 0x04
struct PcieTestFunc {
enum PcieTestCmd type;
int32_t (*Func)(struct PcieTester *tester);
};
static DevHandle PcieTestGetHandle(struct PcieTester *tester)
{
if (tester == NULL) {
HDF_LOGE("%s: tester is null", __func__);
return NULL;
}
return PcieOpen(tester->busNum);
}
static void PcieTestReleaseHandle(DevHandle handle)
{
if (handle == NULL) {
HDF_LOGE("%s: pcie handle is null", __func__);
return;
}
PcieClose(handle);
}
static int32_t TestPcieReadAndWrite(struct PcieTester *tester)
{
int32_t ret;
uint8_t disable;
uint32_t upper;
uint16_t cmd;
ret = PcieRead(tester->handle, PCIE_TEST_DISABLE_ADDR, &disable, sizeof(disable));
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: PcieRead failed ret = %d.", __func__, ret);
return ret;
}
HDF_LOGD("%s: disable is %d", __func__, disable);
ret = PcieWrite(tester->handle, PCIE_TEST_DISABLE_ADDR, &disable, sizeof(disable));
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: PcieWrite failed ret = %d.", __func__, ret);
return ret;
}
ret = PcieRead(tester->handle, PCIE_TEST_UPPER_ADDR, (uint8_t *)&upper, sizeof(upper));
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: PcieRead failed ret = %d.", __func__, ret);
return ret;
}
HDF_LOGD("%s: upper is 0x%x", __func__, upper);
ret = PcieWrite(tester->handle, PCIE_TEST_UPPER_ADDR, (uint8_t *)&upper, sizeof(upper));
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: PcieWrite failed ret = %d.", __func__, ret);
return ret;
}
ret = PcieRead(tester->handle, PCIE_TEST_CMD_ADDR, (uint8_t *)&cmd, sizeof(cmd));
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: PcieRead failed ret = %d.", __func__, ret);
return ret;
}
HDF_LOGD("%s: cmd is 0x%x", __func__, cmd);
ret = PcieWrite(tester->handle, PCIE_TEST_CMD_ADDR, (uint8_t *)&cmd, sizeof(cmd));
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: PcieWrite failed ret = %d.", __func__, ret);
}
return ret;
}
struct PcieTestFunc g_pcieTestFunc[] = {
{ PCIE_READ_AND_WRITE_01, TestPcieReadAndWrite },
};
static int32_t PcieTestEntry(struct PcieTester *tester, int32_t cmd)
{
int32_t i;
int32_t ret = HDF_SUCCESS;
bool isFind = false;
if (tester == NULL) {
HDF_LOGE("%s: tester is NULL", __func__);
return HDF_ERR_INVALID_OBJECT;
}
tester->handle = PcieTestGetHandle(tester);
if (tester->handle == NULL) {
HDF_LOGE("%s: pcie test get handle failed", __func__);
return HDF_FAILURE;
}
for (i = 0; i < sizeof(g_pcieTestFunc) / sizeof(g_pcieTestFunc[0]); i++) {
if (cmd == g_pcieTestFunc[i].type && g_pcieTestFunc[i].Func != NULL) {
ret = g_pcieTestFunc[i].Func(tester);
isFind = true;
break;
}
}
if (!isFind) {
ret = HDF_ERR_NOT_SUPPORT;
HDF_LOGE("%s: cmd %d not supported", __func__, cmd);
}
PcieTestReleaseHandle(tester->handle);
return ret;
}
static int32_t PcieTestFillConfig(struct PcieTester *tester, const struct DeviceResourceNode *node)
{
int32_t ret;
struct DeviceResourceIface *drsOps = NULL;
drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
if (drsOps == NULL || drsOps->GetUint32 == NULL) {
HDF_LOGE("%s: invalid drs ops", __func__);
return HDF_FAILURE;
}
ret = drsOps->GetUint32(node, "busNum", &(tester->busNum), 0);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: fill bus num failed", __func__);
return ret;
}
HDF_LOGE("%s: busNum:%d.", __func__, tester->busNum);
return HDF_SUCCESS;
}
static int32_t PcieTestBind(struct HdfDeviceObject *device)
{
static struct PcieTester tester;
if (device == NULL) {
HDF_LOGE("%s: device or config is null!", __func__);
return HDF_ERR_IO;
}
device->service = &tester.service;
HDF_LOGE("%s: PCIE_TEST service init success!", __func__);
return HDF_SUCCESS;
}
static int32_t PcieTestInit(struct HdfDeviceObject *device)
{
struct PcieTester *tester = NULL;
int32_t ret;
if (device == NULL || device->service == NULL || device->property == NULL) {
HDF_LOGE("%s: invalid parameter", __func__);
return HDF_ERR_INVALID_PARAM;
}
tester = (struct PcieTester *)device->service;
if (tester == NULL) {
HDF_LOGE("%s: tester is NULL", __func__);
return HDF_ERR_INVALID_PARAM;
}
ret = PcieTestFillConfig(tester, device->property);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: read config failed", __func__);
return ret;
}
tester->TestEntry = PcieTestEntry;
HDF_LOGE("%s: success", __func__);
return HDF_SUCCESS;
}
static void PcieTestRelease(struct HdfDeviceObject *device)
{
if (device != NULL) {
device->service = NULL;
}
}
struct HdfDriverEntry g_pcieTestEntry = {
.moduleVersion = 1,
.Bind = PcieTestBind,
.Init = PcieTestInit,
.Release = PcieTestRelease,
.moduleName = "PLATFORM_PCIE_TEST",
};
HDF_INIT(g_pcieTestEntry);

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#ifndef PCIE_TEST_H
#define PCIE_TEST_H
#include "hdf_device_desc.h"
#include "platform_if.h"
enum PcieTestCmd {
PCIE_READ_AND_WRITE_01 = 0,
};
struct PcieTester {
struct IDeviceIoService service;
struct HdfDeviceObject *device;
int32_t (*TestEntry)(struct PcieTester *tester, int32_t cmd);
uint32_t busNum;
DevHandle handle;
};
static inline struct PcieTester *GetPcieTester(void)
{
return (struct PcieTester *)DevSvcManagerClntGetService("PCIE_TEST");
}
#endif /* PCIE_TEST_H */

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include "hdf_log.h"
#include "hdf_pcie_entry_test.h"
#include "pcie_if.h"
#include "pcie_test.h"
#define HDF_LOG_TAG hdf_pcie_entry_test
int32_t HdfPcieUnitTestEntry(HdfTestMsg *msg)
{
struct PcieTester *tester = NULL;
if (msg == NULL) {
HDF_LOGE("HdfPcieUnitTestEntry: msg is NULL");
return HDF_FAILURE;
}
tester = GetPcieTester();
if (tester == NULL || tester->TestEntry == NULL) {
HDF_LOGE("HdfPcieUnitTestEntry: tester/TestEntry is NULL");
msg->result = HDF_FAILURE;
return HDF_FAILURE;
}
msg->result = tester->TestEntry(tester, msg->subCmd);
return msg->result;
}

View File

@ -0,0 +1,16 @@
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#ifndef HDF_PCIE_ENTRY_TEST_H
#define HDF_PCIE_ENTRY_TEST_H
#include "hdf_main_test.h"
int32_t HdfPcieUnitTestEntry(HdfTestMsg *msg);
#endif // HDF_PCIE_ENTRY_TEST_H

View File

@ -0,0 +1,141 @@
/*
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/
#include "device_resource_if.h"
#include "hdf_log.h"
#include "osal_mem.h"
#include "pcie_core.h"
#define HDF_LOG_TAG pcie_virtual_c
#define PCIE_VIRTUAL_ADAPTER_ONE_BYTE 1
#define PCIE_VIRTUAL_ADAPTER_TWO_BYTE 2
#define PCIE_VIRTUAL_ADAPTER_FOUR_BYTE 4
#define PCIE_VIRTUAL_ADAPTER_READ_DATA_1 0x95
#define PCIE_VIRTUAL_ADAPTER_READ_DATA_2 0x27
#define PCIE_VIRTUAL_ADAPTER_READ_DATA_3 0x89
struct PcieVirtualAdapterHost {
struct PcieCntlr cntlr;
};
static int32_t PcieVirtualAdapterRead(struct PcieCntlr *cntlr, uint32_t pos, uint8_t *data, uint32_t len)
{
if (cntlr == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
HDF_LOGD("PcieVirtualAdapterRead: pos = 0x%x, data = 0x%x, data val = %u, len = %d",
pos, (uint32_t)data, *data, len);
if (len == PCIE_VIRTUAL_ADAPTER_ONE_BYTE) {
*data = PCIE_VIRTUAL_ADAPTER_READ_DATA_1;
} else if (len == PCIE_VIRTUAL_ADAPTER_TWO_BYTE) {
*data = PCIE_VIRTUAL_ADAPTER_READ_DATA_1;
data++;
*data = PCIE_VIRTUAL_ADAPTER_READ_DATA_2;
} else {
*data = PCIE_VIRTUAL_ADAPTER_READ_DATA_1;
data++;
*data = PCIE_VIRTUAL_ADAPTER_READ_DATA_2;
data++;
*data = PCIE_VIRTUAL_ADAPTER_READ_DATA_2;
data++;
*data = PCIE_VIRTUAL_ADAPTER_READ_DATA_3;
}
return HDF_SUCCESS;
}
static int32_t PcieVirtualAdapterWrite(struct PcieCntlr *cntlr, uint32_t pos, uint8_t *data, uint32_t len)
{
if (cntlr == NULL) {
return HDF_ERR_INVALID_OBJECT;
}
HDF_LOGD("PcieVirtualAdapterWrite: pos = 0x%x, data = 0x%x, data val = %u, len = %d", pos, (uint32_t)data,
*data, len);
return HDF_SUCCESS;
}
static struct PcieCntlrOps g_pcieVirtualAdapterHostOps = {
.read = PcieVirtualAdapterRead,
.write = PcieVirtualAdapterWrite,
};
static int32_t PcieVirtualAdapterBind(struct HdfDeviceObject *obj)
{
struct PcieVirtualAdapterHost *host = NULL;
int32_t ret;
if (obj == NULL) {
HDF_LOGE("PcieVirtualAdapterBind: Fail, device is NULL.");
return HDF_ERR_INVALID_OBJECT;
}
host = (struct PcieVirtualAdapterHost *)OsalMemCalloc(sizeof(struct PcieVirtualAdapterHost));
if (host == NULL) {
HDF_LOGE("PcieVirtualAdapterBind: no mem for PcieAdapterHost.");
return HDF_ERR_MALLOC_FAIL;
}
host->cntlr.ops = &g_pcieVirtualAdapterHostOps;
host->cntlr.hdfDevObj = obj;
obj->service = &(host->cntlr.service);
ret = PcieCntlrParse(&(host->cntlr), obj);
if (ret != HDF_SUCCESS) {
goto ERR;
}
ret = PcieCntlrAdd(&(host->cntlr));
if (ret != HDF_SUCCESS) {
goto ERR;
}
HDF_LOGD("PcieVirtualAdapterBind: success.");
return HDF_SUCCESS;
ERR:
PcieCntlrRemove(&(host->cntlr));
OsalMemFree(host);
HDF_LOGD("PcieAdapterBind: fail, err = %d.", ret);
return ret;
}
static int32_t PcieVirtualAdapterInit(struct HdfDeviceObject *obj)
{
(void)obj;
HDF_LOGD("PcieVirtualAdapterInit: success.");
return HDF_SUCCESS;
}
static void PcieVirtualAdapterRelease(struct HdfDeviceObject *obj)
{
struct PcieCntlr *cntlr = NULL;
struct PcieVirtualAdapterHost *host = NULL;
if (obj == NULL) {
return;
}
cntlr = (struct PcieCntlr *)obj->service;
if (cntlr == NULL) {
return;
}
PcieCntlrRemove(cntlr);
host = (struct PcieVirtualAdapterHost *)cntlr;
OsalMemFree(host);
HDF_LOGD("PcieAdapterRelease: success.");
}
struct HdfDriverEntry g_pcieVirtualDriverEntry = {
.moduleVersion = 1,
.Bind = PcieVirtualAdapterBind,
.Init = PcieVirtualAdapterInit,
.Release = PcieVirtualAdapterRelease,
.moduleName = "PLATFORM_PCIE_VIRTUAL",
};
HDF_INIT(g_pcieVirtualDriverEntry);