1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #include "pcie_dispatch.h"
10 #include "hdf_log.h"
11 #include "osal_mem.h"
12 #include "pcie_core.h"
13 #include "pcie_if.h"
14
15 #define HDF_LOG_TAG pcie_dispatch_c
16
17 enum PcieIoCmd {
18 PCIE_CMD_READ,
19 PCIE_CMD_WRITE,
20 PCIE_CMD_BUTT,
21 };
22
23 struct PcieDispatchFunc {
24 uint32_t cmd;
25 int32_t (*func)(struct PcieCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply);
26 };
27
PcieCmdRead(struct PcieCntlr * cntlr,struct HdfSBuf * data,struct HdfSBuf * reply)28 static int32_t PcieCmdRead(struct PcieCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply)
29 {
30 uint32_t len, pos;
31 uint8_t *buf = NULL;
32 int32_t ret;
33
34 if (!HdfSbufReadUint32(data, &len)) {
35 HDF_LOGE("PcieCmdRead: read len fail");
36 return HDF_ERR_IO;
37 }
38 if (len == 0) {
39 return HDF_ERR_INVALID_PARAM;
40 }
41 if (!HdfSbufReadUint32(data, &pos)) {
42 HDF_LOGE("PcieCmdRead: read pos fail");
43 return HDF_ERR_IO;
44 }
45
46 buf = (uint8_t *)OsalMemCalloc(sizeof(*buf) * len);
47 if (buf == NULL) {
48 HDF_LOGE("PcieCmdRead: OsalMemCalloc error");
49 return HDF_ERR_MALLOC_FAIL;
50 }
51
52 ret = PcieCntlrRead(cntlr, pos, buf, len);
53 if (ret != HDF_SUCCESS) {
54 HDF_LOGE("PcieCntlrRead: error, ret is %d", ret);
55 goto EXIT;
56 }
57 if (!HdfSbufWriteBuffer(reply, buf, len)) {
58 HDF_LOGE("PcieCntlrRead: sbuf write buffer failed");
59 ret = HDF_ERR_IO;
60 goto EXIT;
61 }
62 ret = HDF_SUCCESS;
63 EXIT:
64 OsalMemFree(buf);
65 return ret;
66 }
67
PcieCmdWrite(struct PcieCntlr * cntlr,struct HdfSBuf * data,struct HdfSBuf * reply)68 static int32_t PcieCmdWrite(struct PcieCntlr *cntlr, struct HdfSBuf *data, struct HdfSBuf *reply)
69 {
70 uint32_t size, pos;
71 uint8_t *buf = NULL;
72 (void)reply;
73
74 if (!HdfSbufReadUint32(data, &pos)) {
75 HDF_LOGE("PcieCmdWrite: read pos fail");
76 return HDF_ERR_IO;
77 }
78 if (!HdfSbufReadBuffer(data, (const void **)&buf, &size)) {
79 HDF_LOGE("PcieCmdWrite: sbuf read buffer failed");
80 return HDF_ERR_IO;
81 }
82 return PcieCntlrWrite(cntlr, pos, buf, size);
83 }
84
PcieIoDispatch(struct HdfDeviceIoClient * client,int32_t cmd,struct HdfSBuf * data,struct HdfSBuf * reply)85 int32_t PcieIoDispatch(struct HdfDeviceIoClient *client, int32_t cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
86 {
87 struct PcieCntlr *cntlr = NULL;
88 uint32_t i;
89 uint32_t len;
90 struct PcieDispatchFunc dispatchFunc[] = {
91 { PCIE_CMD_READ, PcieCmdRead },
92 { PCIE_CMD_WRITE, PcieCmdWrite },
93 };
94
95 if (client == NULL || client->device == NULL) {
96 HDF_LOGE("PcieIoDispatch: client or hdf dev obj is NULL");
97 return HDF_ERR_INVALID_OBJECT;
98 }
99
100 cntlr = (struct PcieCntlr *)client->device->service;
101 if (cntlr == NULL) {
102 HDF_LOGE("PcieIoDispatch: service is NULL");
103 return HDF_ERR_INVALID_OBJECT;
104 }
105
106 len = sizeof(dispatchFunc) / sizeof(dispatchFunc[0]);
107 for (i = 0; i < len; i++) {
108 if (dispatchFunc[i].cmd == cmd) {
109 return dispatchFunc[i].func(cntlr, data, reply);
110 }
111 }
112
113 HDF_LOGE("PcieIoDispatch: cmd %d is not support", cmd);
114 return HDF_ERR_NOT_SUPPORT;
115 }
116