2 /*
3 Copyright (c) 2016, Texas Instruments Incorporated - http://www.ti.com/
4 All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the
16 * distribution.
17 *
18 * Neither the name of Texas Instruments Incorporated nor the names of
19 * its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 */
36 /*
37 * ======== dev2.c ========
38 */
40 #include <xdc/std.h>
41 #include <xdc/runtime/Error.h>
42 #include <xdc/runtime/Memory.h>
43 #include <xdc/runtime/Log.h>
44 #include <xdc/runtime/System.h>
45 #include <ti/sysbios/hal/Hwi.h>
46 #include <ti/sysbios/knl/Task.h>
48 #include "dev2.h"
50 #include <string.h>
52 Queue_Elem devList = {NULL, NULL};
54 DEV2_Attrs DEV2_ATTRS = {
55 NULL, /* dev ID */
56 NULL, /* params */
57 DEV2_SIOTYPE, /* TODO: Default was set to IOM(fxns) */
58 NULL /* devp */
59 };
61 static Bool devInit = FALSE;
63 /*
64 * ======== DEV2_createDevice ========
65 * Create a device(DEV2_Device) entry and add it to the list of devices.
66 * This API is not reentrant
67 */
68 Int DEV2_createDevice (String name, Void *fxns, Fxn initFxn,
69 DEV2_Attrs *attrs)
70 {
71 // DEV2_TableElem *objDevHead = (DEV2_TableElem*) &DEV2_table;
72 DEV2_TableElem *objDevHead = (DEV2_TableElem*) &devList;
73 DEV2_TableElem *objDev, *objEntry;
74 DEV2_Device *dptr, *entry;
75 // IOM_Fxns *iomfxns;
76 // Int status;
77 UInt key;
78 UInt taskKey;
79 Error_Block eb;
81 DEV2_init();
83 /* Crate a device entry */
84 Error_init(&eb);
85 objEntry = Memory_calloc(0, sizeof(DEV2_TableElem), 0, &eb);
87 if (objEntry == NULL) {
88 return(DEV2_ENOMEM);
89 }
91 taskKey = Task_disable();
93 /*
94 * Return error if device already exists in the Device table, or has
95 * already been created.
96 */
97 DEV2_find(name, &entry);
99 if (entry != NULL) {
100 Task_restore(taskKey);
101 Memory_free(0, objEntry, sizeof(DEV2_TableElem));
102 Log_error1("DEV2_createDevice: Device %s alread in table", (IArg)name);
103 return (DEV2_EINVAL);
104 }
106 /*
107 * Initialize new device entry(DEV2_Device) in the OBJ table with
108 * the parameters passed to API
109 */
110 entry = &objEntry->device;
111 entry->name = name;
112 entry->fxns = fxns;
114 if (attrs == NULL) {
115 attrs = &DEV2_ATTRS;
116 }
117 entry->devid = attrs->devid;
118 entry->params = attrs->params;
119 entry->type = attrs->type;
120 entry->devp = attrs->devp;
122 /*
123 * Call the Device init function if its not NULL, with interrupts
124 * disabled.
125 */
126 if (initFxn != NULL) {
127 key = Hwi_disable();
128 (*initFxn)();
129 Hwi_restore(key);
130 }
131 #if 0 // TODO
133 /*
134 * If device created is of type IOM then call mini driver function
135 * mdBindDev with interrupts disabled.
136 */
137 if (entry->type == DEV2_IOMTYPE) {
138 iomfxns = (IOM_Fxns *)entry->fxns;
140 key = HWI_disable();
141 status = iomfxns->mdBindDev(&entry->devp, entry->devid,
142 entry->params);
143 HWI_restore(key);
145 if (status != IOM_COMPLETED) {
147 TSK_enable();
149 /* Delete the just created device entry in device table */
150 Memory_free(NULL, objEntry, sizeof(DEV2_TableElem));
152 Log_error1("DEV2_createDevice: mdBindDev() failed (%d)",
153 (IArg)status);
155 return(status);
156 }
158 }
159 #endif // TODO
160 /*
161 * Device is ready for addition into the device. Check new device
162 * name length against existing device name lengths. If length of
163 * new device is greater than one in the table, mark the location
164 * and insert device ahead of device whose name length is shorter
165 * else add it to the end.
166 *
167 * This will keep all the devices sorted in descending order, which is
168 * required to pass additional parameters along with device name in
169 * DEV2_open()
170 */
172 objDev = (DEV2_TableElem *)Queue_next((Ptr)objDevHead);
173 while (objDev != objDevHead) {
174 dptr = &objDev->device;
175 if (strlen(name) > strlen(dptr->name)) {
176 break;
177 }
178 objDev = (DEV2_TableElem *)Queue_next((Ptr)objDev);
179 }
181 /* Insert objEntry ahead of objDev */
182 Queue_insert((Queue_Elem *)objDev, (Queue_Elem *)objEntry);
184 Task_restore(taskKey);
186 return (DEV2_OK);
187 }
189 /*
190 * DEV2_deleteDevice deletes device(DEV2_Device) entry in the OBJ table
191 * if device by that name exist in the system.
192 * This API is not reentrant
193 */
194 Int DEV2_deleteDevice (String name)
195 {
196 DEV2_TableElem *objDev;
197 DEV2_Device *entry;
198 // TODO IOM_Fxns *iomfxns;
199 Int status = DEV2_OK;
200 // Uns key;
202 DEV2_init();
204 /* Check if device exists in the Device table, if not return FALSE */
205 DEV2_find(name, &entry);
206 if (entry == NULL) {
207 Log_error1("DEV2_deleteDevice: Device %s not found", (IArg)name);
208 return (DEV2_ENODEV);
209 }
211 #if 0 // TODO
212 /*
213 * If device to be deleted is of type IOM call mdUnBindDev with
214 * interrupts disabled
215 */
216 if (entry->type == DEV2_IOMTYPE) {
217 iomfxns = (IOM_Fxns *)entry->fxns;
219 key = Hwi_disable();
220 status = iomfxns->mdUnBindDev(entry->devp);
221 Hwi_restore(key);
223 if (status != IOM_COMPLETED) {
224 Log_error1("DEV2_deleteDevice: mdUnBindDev failed (%d) ", status);
225 }
226 else {
227 status = DEV2_OK;
228 }
230 }
231 #endif // TODO
233 /* Free Device entry in the device table */
234 objDev = (DEV2_TableElem *)((char *)entry - sizeof(Queue_Elem));
235 Queue_remove((Queue_Elem *)objDev);
236 Memory_free(NULL, objDev, sizeof(DEV2_TableElem));
238 return (status);
239 }
241 /*
242 * ======== DEV2_ebadio ========
243 */
244 Int DEV2_ebadio(DEV2_Handle device)
245 {
246 Log_error1("DEV2_ebadio (0x%x)", (IArg)device);
248 return (DEV2_EBADIO);
249 }
251 /*
252 * ======== DEV2_find ========
253 */
254 Void DEV2_find(String name, DEV2_Device **driver)
255 {
256 DEV2_TableElem *objDevHead = (DEV2_TableElem*) &devList;
257 // DEV2_TableElem *objDevHead = (DEV2_TableElem*) &DEV2_table;
258 DEV2_TableElem *objDev;
259 DEV2_Device *dptr;
261 DEV2_init();
263 /*
264 * Do the exact match, return device entry if successfull.
265 */
266 for (objDev = (DEV2_TableElem *)Queue_next((Ptr)objDevHead);
267 objDev != objDevHead;
268 objDev = (DEV2_TableElem *)Queue_next((Ptr)objDev)) {
269 dptr = &objDev->device;
270 if (strcmp(name,dptr->name) == 0) {
271 /* If driver exists in the devicetable, point the *driver
272 to corresponding device entry */
273 *driver = dptr;
274 return;
275 }
276 }
278 *driver = NULL;
279 return;
280 }
282 /*
283 * ======== DEV2_init ========
284 */
285 Void DEV2_init()
286 {
287 UInt taskKey;
288 UInt numEntries = 0;
289 Int i;
291 if (!devInit) {
292 taskKey = Task_disable();
294 /* Count the number of devices and initialize next, prev pointers */
295 for (i = 0; DEV2_table[i].device.name != NULL; i++) {
296 DEV2_table[i].qElem.next = (Queue_Elem *)&DEV2_table[i + 1];
297 DEV2_table[i + 1].qElem.prev = (Queue_Elem *)&DEV2_table[i];
298 }
299 numEntries = i;
301 if (numEntries > 0) {
302 devList.next = (Queue_Elem *)&DEV2_table[0];
303 devList.prev = (Queue_Elem *)&DEV2_table[numEntries - 1];
304 DEV2_table[numEntries - 1].qElem.next = &devList;
305 }
306 else {
307 devList.next = devList.prev = &devList;
308 }
309 devInit = TRUE;
310 Task_restore(taskKey);
311 }
312 }
314 /*
315 * ======== DEV2_match ========
316 */
317 String DEV2_match(String name, DEV2_Device **driver)
318 {
319 DEV2_TableElem *objDevHead = (DEV2_TableElem*)&devList;
320 // DEV2_TableElem *objDevHead = (DEV2_TableElem*) &DEV2_table;
321 DEV2_TableElem *objDev;
322 DEV2_Device *dptr;
323 Int len;
325 DEV2_init();
327 /*
328 * Trace the existence of device through OBJ_table[OBJ_DEV].
329 * If successfull *dptr points to the device entry.
330 */
331 if(name[0] == '/') name ++;
333 if (strncmp(name, "SAP", 3) == 0)
334 name[0]='D';
336 for (objDev = (DEV2_TableElem *)Queue_next((Ptr)objDevHead);
337 objDev != objDevHead;
338 objDev = (DEV2_TableElem *)Queue_next((Ptr)objDev)) {
339 dptr = &objDev->device;
340 len = strlen(dptr->name);
341 if ((len == 0) || (strncmp(name,dptr->name,len) == 0) ) {
342 /* If driver exists in the devicetable, point the *driver
343 to corresponding device entry */
344 *driver = dptr;
345 return (name + len);
346 }
347 }
349 *driver = NULL;
350 return (name);
352 }
354 /*
355 * ======== DEV2_mkframe ========
356 */
357 DEV2_Frame *DEV2_mkframe(xdc_runtime_IHeap_Handle seg, Uns size, Uns align)
358 {
359 DEV2_Frame *frame;
360 Error_Block eb;
362 Error_init(&eb);
364 if ((frame = Memory_alloc(0, sizeof(DEV2_Frame), 0, &eb)) == NULL) {
365 return (NULL);
366 }
368 /* don't allocate frame buffer if size is zero */
369 if (size > 0) {
370 if ((frame->addr = Memory_alloc(seg, size, align, &eb)) == NULL) {
371 Memory_free(0, frame, sizeof(DEV2_Frame));
372 return (NULL);
373 }
374 }
376 frame->size = size;
378 return (frame);
379 }
381 /*
382 * ======== DEV2_one ========
383 */
384 Int DEV2_one(void)
385 {
386 return (1);
387 }
389 /*
390 * ======== DEV2_rmframe ========
391 */
392 Void DEV2_rmframe(DEV2_Frame *frame, xdc_runtime_IHeap_Handle seg, Uns size)
393 {
394 if (size > 0) {
395 /* free buffer */
396 Memory_free(seg, frame->addr, size);
397 }
399 /* free object */
400 Memory_free(0, frame, sizeof(DEV2_Frame));
401 }
403 /*
404 * ======== DEV2_zero ========
405 */
406 Int DEV2_zero(void)
407 {
408 return (0);
409 }