1 /*
2 * Copyright (c) 2020--2023 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 "device_resource_if.h"
10 #include "hdf_log.h"
11 #include "osal_mem.h"
12 #include "pcie_core.h"
13
14 #define HDF_LOG_TAG pcie_virtual_c
15
16 #define PCIE_VIRTUAL_ADAPTER_ONE_BYTE 1
17 #define PCIE_VIRTUAL_ADAPTER_TWO_BYTE 2
18 #define PCIE_VIRTUAL_ADAPTER_FOUR_BYTE 4
19 #define PCIE_VIRTUAL_ADAPTER_READ_DATA_1 0x95
20 #define PCIE_VIRTUAL_ADAPTER_READ_DATA_2 0x27
21 #define PCIE_VIRTUAL_ADAPTER_READ_DATA_3 0x89
22 #define PCIE_VIRTUAL_DIR_MAX 1
23
24 struct PcieVirtualAdapterHost {
25 struct PcieCntlr cntlr;
26 uintptr_t dmaData;
27 uint32_t len;
28 uint8_t dir;
29 bool irqRegistered;
30 };
31
PcieVirtualAdapterRead(struct PcieCntlr * cntlr,uint32_t mode,uint32_t pos,uint8_t * data,uint32_t len)32 static int32_t PcieVirtualAdapterRead(struct PcieCntlr *cntlr, uint32_t mode,
33 uint32_t pos, uint8_t *data, uint32_t len)
34 {
35 (void)mode;
36 (void)pos;
37 if (cntlr == NULL) {
38 HDF_LOGE("PcieVirtualAdapterRead: cntlr is null!");
39 return HDF_ERR_INVALID_OBJECT;
40 }
41 if (len == PCIE_VIRTUAL_ADAPTER_ONE_BYTE) {
42 *data = PCIE_VIRTUAL_ADAPTER_READ_DATA_1;
43 } else if (len == PCIE_VIRTUAL_ADAPTER_TWO_BYTE) {
44 *data = PCIE_VIRTUAL_ADAPTER_READ_DATA_1;
45 data++;
46 *data = PCIE_VIRTUAL_ADAPTER_READ_DATA_2;
47 } else {
48 *data = PCIE_VIRTUAL_ADAPTER_READ_DATA_1;
49 data++;
50 *data = PCIE_VIRTUAL_ADAPTER_READ_DATA_2;
51 data++;
52 *data = PCIE_VIRTUAL_ADAPTER_READ_DATA_2;
53 data++;
54 *data = PCIE_VIRTUAL_ADAPTER_READ_DATA_3;
55 }
56 return HDF_SUCCESS;
57 }
58
PcieVirtualAdapterWrite(struct PcieCntlr * cntlr,uint32_t mode,uint32_t pos,uint8_t * data,uint32_t len)59 static int32_t PcieVirtualAdapterWrite(struct PcieCntlr *cntlr, uint32_t mode,
60 uint32_t pos, uint8_t *data, uint32_t len)
61 {
62 (void)mode;
63 (void)pos;
64 (void)data;
65 (void)len;
66 if (cntlr == NULL) {
67 HDF_LOGE("PcieVirtualAdapterWrite: cntlr is null!");
68 return HDF_ERR_INVALID_OBJECT;
69 }
70 return HDF_SUCCESS;
71 }
72
PcieVirtualAdapterDmaMap(struct PcieCntlr * cntlr,uintptr_t addr,uint32_t len,uint8_t dir)73 static int32_t PcieVirtualAdapterDmaMap(struct PcieCntlr *cntlr, uintptr_t addr,
74 uint32_t len, uint8_t dir)
75 {
76 struct PcieVirtualAdapterHost *host = (struct PcieVirtualAdapterHost *)cntlr;
77
78 if (host == NULL) {
79 HDF_LOGE("PcieVirtualAdapterDmaMap: host is null!");
80 return HDF_ERR_INVALID_OBJECT;
81 }
82 if (addr == 0 || dir > PCIE_DMA_TO_DEVICE) {
83 HDF_LOGE("PcieVirtualAdapterDmaMap: addr or dir is invaild!");
84 return HDF_ERR_INVALID_PARAM;
85 }
86 if (host->dmaData != 0) {
87 HDF_LOGE("PcieVirtualAdapterDmaMap: pcie dma has been mapped!");
88 return HDF_ERR_DEVICE_BUSY;
89 }
90 host->dmaData = addr;
91 host->len = len;
92 host->dir = dir;
93
94 return PcieCntlrDmaCallback(cntlr);
95 }
96
PcieVirtualAdapterDmaUnmap(struct PcieCntlr * cntlr,uintptr_t addr,uintptr_t len,uint8_t dir)97 static void PcieVirtualAdapterDmaUnmap(struct PcieCntlr *cntlr, uintptr_t addr, uintptr_t len, uint8_t dir)
98 {
99 struct PcieVirtualAdapterHost *host = (struct PcieVirtualAdapterHost *)cntlr;
100
101 if (host == NULL || dir > PCIE_VIRTUAL_DIR_MAX) {
102 HDF_LOGE("PcieVirtualAdapterDmaUnmap: host is NULL or dir is invalid!");
103 return;
104 }
105 if (addr != host->dmaData || len != host->len || dir != host->dir) {
106 HDF_LOGE("PcieVirtualAdapterDmaUnmap: invalid addr or len or dir!");
107 return;
108 }
109 host->dmaData = 0;
110 host->len = 0;
111 host->dir = 0;
112 }
113
PcieVirtualRegIrq(struct PcieCntlr * cntlr)114 int32_t PcieVirtualRegIrq(struct PcieCntlr *cntlr)
115 {
116 struct PcieVirtualAdapterHost *host = (struct PcieVirtualAdapterHost *)cntlr;
117
118 if (host == NULL) {
119 HDF_LOGE("PcieVirtualRegIrq: host is null!");
120 return HDF_ERR_INVALID_OBJECT;
121 }
122 if (host->irqRegistered == true) {
123 HDF_LOGE("PcieVirtualRegIrq: irq has been registered!");
124 return HDF_ERR_DEVICE_BUSY;
125 }
126 host->irqRegistered = true;
127 return PcieCntlrCallback(cntlr); // test interrupt callback access
128 }
129
PcieVirtualUnregIrq(struct PcieCntlr * cntlr)130 void PcieVirtualUnregIrq(struct PcieCntlr *cntlr)
131 {
132 struct PcieVirtualAdapterHost *host = (struct PcieVirtualAdapterHost *)cntlr;
133
134 if (host == NULL) {
135 HDF_LOGE("PcieVirtualUnregIrq: host is null!");
136 return;
137 }
138 host->irqRegistered = false;
139 }
140
141 static struct PcieCntlrOps g_pcieVirtualAdapterHostOps = {
142 .read = PcieVirtualAdapterRead,
143 .write = PcieVirtualAdapterWrite,
144 .dmaMap = PcieVirtualAdapterDmaMap,
145 .dmaUnmap = PcieVirtualAdapterDmaUnmap,
146 .registerIrq = PcieVirtualRegIrq,
147 .unregisterIrq = PcieVirtualUnregIrq,
148 };
149
PcieVirtualAdapterBind(struct HdfDeviceObject * obj)150 static int32_t PcieVirtualAdapterBind(struct HdfDeviceObject *obj)
151 {
152 struct PcieVirtualAdapterHost *host = NULL;
153 int32_t ret;
154
155 if (obj == NULL) {
156 HDF_LOGE("PcieVirtualAdapterBind: fail, device is null!");
157 return HDF_ERR_INVALID_OBJECT;
158 }
159
160 host = (struct PcieVirtualAdapterHost *)OsalMemCalloc(sizeof(struct PcieVirtualAdapterHost));
161 if (host == NULL) {
162 HDF_LOGE("PcieVirtualAdapterBind: no mem for PcieAdapterHost!");
163 return HDF_ERR_MALLOC_FAIL;
164 }
165 host->cntlr.ops = &g_pcieVirtualAdapterHostOps;
166 host->cntlr.hdfDevObj = obj;
167 obj->service = &(host->cntlr.service);
168
169 ret = PcieCntlrParse(&(host->cntlr), obj);
170 if (ret != HDF_SUCCESS) {
171 goto ERR;
172 }
173
174 ret = PcieCntlrAdd(&(host->cntlr));
175 if (ret != HDF_SUCCESS) {
176 goto ERR;
177 }
178
179 HDF_LOGI("PcieVirtualAdapterBind: success.");
180 return HDF_SUCCESS;
181 ERR:
182 PcieCntlrRemove(&(host->cntlr));
183 OsalMemFree(host);
184 HDF_LOGE("PcieVirtualAdapterBind: fail, err = %d.", ret);
185 return ret;
186 }
187
PcieVirtualAdapterInit(struct HdfDeviceObject * obj)188 static int32_t PcieVirtualAdapterInit(struct HdfDeviceObject *obj)
189 {
190 (void)obj;
191
192 HDF_LOGI("PcieVirtualAdapterInit: success.");
193 return HDF_SUCCESS;
194 }
195
PcieVirtualAdapterRelease(struct HdfDeviceObject * obj)196 static void PcieVirtualAdapterRelease(struct HdfDeviceObject *obj)
197 {
198 struct PcieCntlr *cntlr = NULL;
199 struct PcieVirtualAdapterHost *host = NULL;
200
201 if (obj == NULL) {
202 HDF_LOGE("PcieVirtualAdapterRelease: obj is null!");
203 return;
204 }
205
206 cntlr = (struct PcieCntlr *)obj->service;
207 if (cntlr == NULL) {
208 HDF_LOGE("PcieVirtualAdapterRelease: cntlr is null!");
209 return;
210 }
211 PcieCntlrRemove(cntlr);
212 host = (struct PcieVirtualAdapterHost *)cntlr;
213 OsalMemFree(host);
214 HDF_LOGI("PcieVirtualAdapterRelease: success.");
215 }
216
217 struct HdfDriverEntry g_pcieVirtualDriverEntry = {
218 .moduleVersion = 1,
219 .Bind = PcieVirtualAdapterBind,
220 .Init = PcieVirtualAdapterInit,
221 .Release = PcieVirtualAdapterRelease,
222 .moduleName = "PLATFORM_PCIE_VIRTUAL",
223 };
224 HDF_INIT(g_pcieVirtualDriverEntry);
225