blob: c264e54f493579e22263e246ce01bcb7348413c5 [file] [log] [blame]
developer02e65912023-08-17 16:33:10 +08001/* device_generic.c
2 *
3 * This is the generic Driver Framework v4 Device API implementation.
4 */
5
6/*****************************************************************************
7* Copyright (c) 2017-2020 by Rambus, Inc. and/or its subsidiaries.
8*
9* This program is free software: you can redistribute it and/or modify
10* it under the terms of the GNU General Public License as published by
11* the Free Software Foundation, either version 2 of the License, or
12* any later version.
13*
14* This program is distributed in the hope that it will be useful,
15* but WITHOUT ANY WARRANTY; without even the implied warranty of
16* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17* GNU General Public License for more details.
18*
19* You should have received a copy of the GNU General Public License
20* along with this program. If not, see <http://www.gnu.org/licenses/>.
21*****************************************************************************/
22
23/*----------------------------------------------------------------------------
24 * This module implements (provides) the following interface(s):
25 */
26
27// Driver Framework Device API
28#include "device_mgmt.h" // API to implement
29
30
31/*----------------------------------------------------------------------------
32 * This module uses (requires) the following interface(s):
33 */
34
35// Driver Framework Basic Defs API
36#include "basic_defs.h" // IDENTIFIER_NOT_USED, NULL
37
38// Driver Framework C Run-time Library API
39#include "clib.h" // strlen, strcpy
40
41// Driver Framework Device Internal interface
42#include "device_internal.h" // Device_Internal_*
43
44
45/*----------------------------------------------------------------------------
46 * Definitions and macros
47 */
48
49// Default configuration
50#include "c_device_generic.h"
51
52// Logging API
53#include "log.h"
54
55
56/*----------------------------------------------------------------------------
57 * Local variables
58 */
59
60
61/*-----------------------------------------------------------------------------
62 * DeviceLib_Device_Exists
63 *
64 * Checks if a device with DeviceName_p is already present in the device list
65 *
66 */
67static bool
68DeviceLib_Device_Exists(
69 const char * DeviceName_p)
70{
71 unsigned int i = 0;
72 Device_Admin_t ** DevAdmin_pp = Device_Internal_Admin_Get();
73
74 if (DeviceName_p == NULL)
75 return false;
76
77 while(DevAdmin_pp[i])
78 {
79 if (strcmp(DevAdmin_pp[i]->DevName, DeviceName_p) == 0)
80 return true;
81 i++;
82 }
83
84 return false;
85}
86
87
88/*-----------------------------------------------------------------------------
89 * device_mgmt API
90 *
91 * These functions support finding a device given its name.
92 * A handle is returned that is needed in the device_rw API
93 * to read or write the device
94 */
95
96/*-----------------------------------------------------------------------------
97 * Device_Initialize
98 */
99int
100Device_Initialize(
101 void * CustomInitData_p)
102{
103 unsigned int res;
104 unsigned int DevStatCount = Device_Internal_Static_Count_Get();
105 unsigned int DevCount = Device_Internal_Count_Get();
106 const Device_Admin_Static_t * DevStatAdmin_p =
107 Device_Internal_Admin_Static_Get();
108 Device_Admin_t ** DevAdmin_pp = Device_Internal_Admin_Get();
109 Device_Global_Admin_t * DevGlobalAdmin_p =
110 Device_Internal_Admin_Global_Get();
111
112 if (DevGlobalAdmin_p->fInitialized)
113 return 0; // already initialized, success
114
115 if (DevStatCount > DevCount)
116 {
117 LOG_CRIT("%s: Invalid number of static devices (%d), max %d\n",
118 __func__,
119 (int)DevStatCount,
120 DevCount);
121 return -1; // failed
122 }
123
124 // Copy static devices
125 for (res = 0; res < DevStatCount; res++)
126 {
127 if (DeviceLib_Device_Exists(DevStatAdmin_p[res].DevName))
128 {
129 LOG_CRIT("%s: failed, device (index %d) with name %s exists\n",
130 __func__,
131 res,
132 DevStatAdmin_p[res].DevName);
133 goto error_exit;
134 }
135
136 // Allocate memory for device administration data
137 DevAdmin_pp[res] = Device_Internal_Alloc(sizeof(Device_Admin_t));
138 if (DevAdmin_pp[res] == NULL)
139 {
140 LOG_CRIT("%s: failed to allocate device (index %d, name %s)\n",
141 __func__,
142 res,
143 DevStatAdmin_p[res].DevName);
144 goto error_exit;
145 }
146
147 // Allocate and copy device name
148 DevAdmin_pp[res]->DevName =
149 Device_Internal_Alloc((unsigned int)strlen(DevStatAdmin_p[res].DevName)+1);
150 if (DevAdmin_pp[res]->DevName == NULL)
151 {
152 LOG_CRIT("%s: failed to allocate device (index %d) name %s\n",
153 __func__,
154 res,
155 DevStatAdmin_p[res].DevName);
156 goto error_exit;
157 }
158 strcpy(DevAdmin_pp[res]->DevName, DevStatAdmin_p[res].DevName);
159
160 // Copy the rest of device data
161 DevAdmin_pp[res]->DeviceNr = DevStatAdmin_p[res].DeviceNr;
162 DevAdmin_pp[res]->FirstOfs = DevStatAdmin_p[res].FirstOfs;
163 DevAdmin_pp[res]->LastOfs = DevStatAdmin_p[res].LastOfs;
164 DevAdmin_pp[res]->Flags = DevStatAdmin_p[res].Flags;
165
166#ifdef HWPAL_DEVICE_MAGIC
167 DevAdmin_pp[res]->Magic = HWPAL_DEVICE_MAGIC;
168#endif
169 DevAdmin_pp[res]->DeviceId = res;
170 }
171
172 res = (unsigned int)Device_Internal_Initialize(CustomInitData_p);
173 if (res != 0)
174 {
175 LOG_CRIT("%s: failed, error %d\n", __func__, res);
176 goto error_exit;
177 }
178
179 DevGlobalAdmin_p->fInitialized = true;
180 return 0; // success
181
182error_exit:
183 // Free all allocated memory
184 for (res = 0; res < DevStatCount; res++)
185 if (DevAdmin_pp[res])
186 {
187 Device_Internal_Free(DevAdmin_pp[res]->DevName);
188 Device_Internal_Free(DevAdmin_pp[res]);
189 DevAdmin_pp[res] = NULL;
190 }
191
192 return -1; // failed
193}
194
195
196/*-----------------------------------------------------------------------------
197 * Device_UnInitialize
198 */
199void
200Device_UnInitialize(void)
201{
202 unsigned int DevCount = Device_Internal_Count_Get();
203 Device_Admin_t ** DevAdmin_pp = Device_Internal_Admin_Get();
204 Device_Global_Admin_t * DevGlobalAdmin_p =
205 Device_Internal_Admin_Global_Get();
206
207 LOG_INFO("%s: unregister driver\n", __func__);
208
209 if (DevGlobalAdmin_p->fInitialized)
210 {
211 unsigned int i;
212
213 Device_Internal_UnInitialize();
214
215 // Free all allocated memory
216 for (i = 0; i < DevCount; i++)
217 if (DevAdmin_pp[i])
218 {
219 Device_Internal_Free(DevAdmin_pp[i]->DevName);
220 Device_Internal_Free(DevAdmin_pp[i]);
221 DevAdmin_pp[i] = NULL;
222 }
223
224 DevGlobalAdmin_p->fInitialized = false;
225 }
226}
227
228
229/*-----------------------------------------------------------------------------
230 * Device_Find
231 */
232Device_Handle_t
233Device_Find(
234 const char * DeviceName_p)
235{
236 unsigned int i;
237
238 unsigned int DevCount = Device_Internal_Count_Get();
239 Device_Admin_t ** DevAdmin_pp = Device_Internal_Admin_Get();
240 Device_Global_Admin_t * DevGlobalAdmin_p =
241 Device_Internal_Admin_Global_Get();
242
243 if (!DevGlobalAdmin_p->fInitialized)
244 {
245 LOG_CRIT("%s: failed, not initialized\n", __func__);
246 return NULL;
247 }
248
249#ifdef HWPAL_STRICT_ARGS_CHECK
250 if (DeviceName_p == NULL)
251 {
252 LOG_CRIT("%s: failed, invalid name\n", __func__);
253 return NULL; // not supported, thus not found
254 }
255#endif
256
257 // walk through the device list and compare the device name
258 for (i = 0; i < DevCount; i++)
259 if (DevAdmin_pp[i] &&
260 strcmp(DeviceName_p, DevAdmin_pp[i]->DevName) == 0)
261 return Device_Internal_Find(DeviceName_p, i);
262
263 LOG_CRIT("%s: failed to find device '%s'\n", __func__, DeviceName_p);
264
265 return NULL;
266}
267
268
269/*----------------------------------------------------------------------------
270 * Device_GetProperties
271 */
272int
273Device_GetProperties(
274 const unsigned int Index,
275 Device_Properties_t * const Props_p,
276 bool * const fValid_p)
277{
278 Device_Admin_t ** DevAdmin_pp = Device_Internal_Admin_Get();
279 Device_Global_Admin_t * DevGlobalAdmin_p =
280 Device_Internal_Admin_Global_Get();
281
282 if (!DevGlobalAdmin_p->fInitialized)
283 {
284 LOG_CRIT("%s: failed, not initialized\n", __func__);
285 return -1;
286 }
287
288#ifdef HWPAL_STRICT_ARGS_CHECK
289 if (Index >= Device_Internal_Count_Get())
290 {
291 LOG_CRIT("%s: failed, invalid index %d, max device count %d\n",
292 __func__,
293 Index,
294 Device_Internal_Count_Get());
295 return -1;
296 }
297
298 if (Props_p == NULL || fValid_p == NULL)
299 {
300 LOG_CRIT("%s: failed, invalid pointers for device index %d\n",
301 __func__,
302 Index);
303 return -1;
304 }
305#endif
306
307 if (!DevAdmin_pp[Index])
308 {
309 LOG_INFO("%s: device with index %d not present\n",
310 __func__,
311 Index);
312 *fValid_p = false;
313 }
314 else
315 {
316 Props_p->Name_p = DevAdmin_pp[Index]->DevName;
317 Props_p->StartByteOffset = DevAdmin_pp[Index]->FirstOfs;
318 Props_p->LastByteOffset = DevAdmin_pp[Index]->LastOfs;
319 Props_p->Flags = (char)DevAdmin_pp[Index]->Flags;
320 *fValid_p = true;
321 }
322 return 0;
323}
324
325
326/*----------------------------------------------------------------------------
327 * Device_Add
328 */
329int
330Device_Add(
331 const unsigned int Index,
332 const Device_Properties_t * const Props_p)
333{
334 Device_Admin_t ** DevAdmin_pp = Device_Internal_Admin_Get();
335 Device_Global_Admin_t * DevGlobalAdmin_p =
336 Device_Internal_Admin_Global_Get();
337
338 if (!DevGlobalAdmin_p->fInitialized)
339 {
340 LOG_CRIT("%s: failed, not initialized\n", __func__);
341 return -1;
342 }
343
344#ifdef HWPAL_STRICT_ARGS_CHECK
345 if (Index >= Device_Internal_Count_Get())
346 {
347 LOG_CRIT("%s: failed, invalid index %d, max device count %d\n",
348 __func__,
349 Index,
350 Device_Internal_Count_Get());
351 return -1;
352 }
353
354 if (Props_p == NULL || Props_p->Name_p == NULL)
355 {
356 LOG_CRIT("%s: failed, invalid properties for device index %d\n",
357 __func__,
358 Index);
359 return -1;
360 }
361#endif
362
363 if (DevAdmin_pp[Index])
364 {
365 LOG_CRIT("%s: device with index %d already added\n",
366 __func__,
367 Index);
368 return -1;
369 }
370
371 if (DeviceLib_Device_Exists(Props_p->Name_p))
372 {
373 LOG_CRIT("%s: device with name %s already added\n",
374 __func__,
375 Props_p->Name_p);
376 return -1;
377 }
378
379 // Allocate memory for device administration data
380 DevAdmin_pp[Index] = Device_Internal_Alloc(sizeof(Device_Admin_t));
381 if (DevAdmin_pp[Index] == NULL)
382 {
383 LOG_CRIT("%s: failed to allocate device (index %d, name %s)\n",
384 __func__,
385 Index,
386 Props_p->Name_p);
387 return -1;
388 }
389
390 // Allocate and copy device name
391 DevAdmin_pp[Index]->DevName =
392 Device_Internal_Alloc((unsigned int)strlen(Props_p->Name_p)+1);
393 if (DevAdmin_pp[Index]->DevName == NULL)
394 {
395 LOG_CRIT("%s: failed to allocate device (index %d) name %s\n",
396 __func__,
397 Index,
398 Props_p->Name_p);
399 Device_Internal_Free(DevAdmin_pp[Index]);
400 DevAdmin_pp[Index] = NULL;
401 return -1;
402 }
403 strcpy(DevAdmin_pp[Index]->DevName, Props_p->Name_p);
404
405 // Copy the rest
406 DevAdmin_pp[Index]->FirstOfs = Props_p->StartByteOffset;
407 DevAdmin_pp[Index]->LastOfs = Props_p->LastByteOffset;
408 DevAdmin_pp[Index]->Flags = (unsigned int)Props_p->Flags;
409
410 // Set default values
411 DevAdmin_pp[Index]->DeviceNr = 0;
412#ifdef HWPAL_DEVICE_MAGIC
413 DevAdmin_pp[Index]->Magic = HWPAL_DEVICE_MAGIC;
414#endif
415
416 DevAdmin_pp[Index]->DeviceId = Index;
417
418 return 0; // success
419}
420
421
422/*----------------------------------------------------------------------------
423 * Device_Remove
424 */
425int
426Device_Remove(
427 const unsigned int Index)
428{
429 Device_Admin_t ** DevAdmin_pp = Device_Internal_Admin_Get();
430 Device_Global_Admin_t * DevGlobalAdmin_p =
431 Device_Internal_Admin_Global_Get();
432
433 if (!DevGlobalAdmin_p->fInitialized)
434 {
435 LOG_CRIT("%s: failed, not initialized\n", __func__);
436 return -1;
437 }
438
439#ifdef HWPAL_STRICT_ARGS_CHECK
440 if (Index >= Device_Internal_Count_Get())
441 {
442 LOG_CRIT("%s: failed, invalid index %d, max device count %d\n",
443 __func__,
444 Index,
445 Device_Internal_Count_Get());
446 return -1;
447 }
448#endif
449
450 if (!DevAdmin_pp[Index])
451 {
452 LOG_CRIT("%s: device with index %d already removed\n",
453 __func__,
454 Index);
455 return -1;
456 }
457 else
458 {
459 // Free device memory
460 Device_Internal_Free(DevAdmin_pp[Index]->DevName);
461 Device_Internal_Free(DevAdmin_pp[Index]);
462 DevAdmin_pp[Index] = NULL;
463 }
464
465 return 0; // success
466}
467
468
469/*-----------------------------------------------------------------------------
470 * Device_GetName
471 */
472char *
473Device_GetName(
474 const unsigned int Index)
475{
476 Device_Admin_t ** DevAdmin_pp = Device_Internal_Admin_Get();
477 Device_Global_Admin_t * DevGlobalAdmin_p =
478 Device_Internal_Admin_Global_Get();
479
480 if (!DevGlobalAdmin_p->fInitialized)
481 {
482 LOG_CRIT("%s: failed, not initialized\n", __func__);
483 return NULL;
484 }
485
486#ifdef HWPAL_STRICT_ARGS_CHECK
487 if (Index >= Device_Internal_Count_Get())
488 {
489 LOG_CRIT("%s: failed, invalid index %d, max device count %d\n",
490 __func__,
491 Index,
492 Device_Internal_Count_Get());
493 return NULL;
494 }
495#endif
496
497 if (!DevAdmin_pp[Index])
498 {
499 LOG_CRIT("%s: device with index %d already removed\n",
500 __func__,
501 Index);
502 return NULL;
503 }
504
505 return DevAdmin_pp[Index]->DevName; // success
506}
507
508
509/*-----------------------------------------------------------------------------
510 * Device_GetIndex
511 */
512int
513Device_GetIndex(
514 const Device_Handle_t Device)
515{
516 Device_Global_Admin_t * DevGlobalAdmin_p =
517 Device_Internal_Admin_Global_Get();
518
519 if (!DevGlobalAdmin_p->fInitialized)
520 {
521 LOG_CRIT("%s: failed, not initialized\n", __func__);
522 return -1;
523 }
524
525 return Device_Internal_GetIndex(Device);
526}
527
528
529/*-----------------------------------------------------------------------------
530 * Device_GetCount
531 */
532unsigned int
533Device_GetCount(void)
534{
535 return Device_Internal_Count_Get();
536}
537
538
539/* end of file device_generic.c */