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