Initial import into "quilt"
[bridge-dev.git] / 0008-TI-DSP-BRIDGE-Services.patch
blob92713822168ef9b2c0a7c7369641ada3ffc06a61
1 From d1f74c03f166bf92278642867607111e21d68130 Mon Sep 17 00:00:00 2001
2 From: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
3 Date: Fri, 15 Aug 2008 01:55:54 +0300
4 Subject: [PATCH 08/10] TI DSP BRIDGE: Services
6 Initial port from omapzoom
7 http://omapzoom.org/gf/project/omapbridge
9 For details,
10 http://omapzoom.org/gf/project/omapbridge/docman/?subdir=3
12 Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
13 ---
14 drivers/dsp/bridge/services/cfg.c | 484 +++++++++++++++++++++++++
15 drivers/dsp/bridge/services/clk.c | 376 ++++++++++++++++++++
16 drivers/dsp/bridge/services/csl.c | 274 ++++++++++++++
17 drivers/dsp/bridge/services/dbg.c | 119 +++++++
18 drivers/dsp/bridge/services/dpc.c | 275 ++++++++++++++
19 drivers/dsp/bridge/services/isr.c | 261 ++++++++++++++
20 drivers/dsp/bridge/services/kfile.c | 336 ++++++++++++++++++
21 drivers/dsp/bridge/services/list.c | 285 +++++++++++++++
22 drivers/dsp/bridge/services/mem.c | 594 +++++++++++++++++++++++++++++++
23 drivers/dsp/bridge/services/ntfy.c | 329 +++++++++++++++++
24 drivers/dsp/bridge/services/prcs.c | 119 +++++++
25 drivers/dsp/bridge/services/reg.c | 196 ++++++++++
26 drivers/dsp/bridge/services/regsup.c | 367 +++++++++++++++++++
27 drivers/dsp/bridge/services/regsup.h | 58 +++
28 drivers/dsp/bridge/services/services.c | 205 +++++++++++
29 drivers/dsp/bridge/services/sync.c | 610 ++++++++++++++++++++++++++++++++
30 16 files changed, 4888 insertions(+), 0 deletions(-)
31 create mode 100644 drivers/dsp/bridge/services/cfg.c
32 create mode 100644 drivers/dsp/bridge/services/clk.c
33 create mode 100644 drivers/dsp/bridge/services/csl.c
34 create mode 100644 drivers/dsp/bridge/services/dbg.c
35 create mode 100644 drivers/dsp/bridge/services/dpc.c
36 create mode 100644 drivers/dsp/bridge/services/isr.c
37 create mode 100644 drivers/dsp/bridge/services/kfile.c
38 create mode 100644 drivers/dsp/bridge/services/list.c
39 create mode 100644 drivers/dsp/bridge/services/mem.c
40 create mode 100644 drivers/dsp/bridge/services/ntfy.c
41 create mode 100644 drivers/dsp/bridge/services/prcs.c
42 create mode 100644 drivers/dsp/bridge/services/reg.c
43 create mode 100644 drivers/dsp/bridge/services/regsup.c
44 create mode 100644 drivers/dsp/bridge/services/regsup.h
45 create mode 100644 drivers/dsp/bridge/services/services.c
46 create mode 100644 drivers/dsp/bridge/services/sync.c
48 diff --git a/drivers/dsp/bridge/services/cfg.c b/drivers/dsp/bridge/services/cfg.c
49 new file mode 100644
50 index 0000000..1614d80
51 --- /dev/null
52 +++ b/drivers/dsp/bridge/services/cfg.c
53 @@ -0,0 +1,484 @@
54 +/*
55 + * linux/drivers/dsp/bridge/services/cfg.c
56 + *
57 + * DSP-BIOS Bridge driver support functions for TI OMAP processors.
58 + *
59 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
60 + *
61 + * This package is free software; you can redistribute it and/or modify
62 + * it under the terms of the GNU General Public License version 2 as
63 + * published by the Free Software Foundation.
64 + *
65 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
66 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
67 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
68 + */
71 +/*
72 + * ======== cfgce.c ========
73 + * Purpose:
74 + * Implementation of platform specific config services.
75 + *
76 + * Private Functions:
77 + * CFG_Exit
78 + * CFG_GetAutoStart
79 + * CFG_GetDevObject
80 + * CFG_GetDSPResources
81 + * CFG_GetExecFile
82 + * CFG_GetHostResources
83 + * CFG_GetObject
84 + * CFG_Init
85 + * CFG_SetDevObject
86 + * CFG_SetObject
87 + *
88 + *
89 + *! Revision History:
90 + *! ================
91 + *! 26-Arp-2004 hp Support for handling more than one Device.
92 + *! 26-Feb-2003 kc Removed unused CFG fxns.
93 + *! 10-Nov-2000 rr: CFG_GetBoardName local var initialized.
94 + *! 30-Oct-2000 kc: Changed local var. names to use Hungarian notation.
95 + *! 10-Aug-2000 rr: Cosmetic changes.
96 + *! 26-Jul-2000 rr: Added CFG_GetDCDName. CFG_Get/SetObject(based on a flag)
97 + *! replaces CFG_GetMgrObject & CFG_SetMgrObject.
98 + *! 17-Jul-2000 rr: Added CFG_GetMgrObject & CFG_SetMgrObject.
99 + *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
100 + *! GT Changes.
101 + *! 31-Jan-2000 rr: Comments and bugfixes: modified after code review
102 + *! 07-Jan-2000 rr: CFG_GetBoardName Ensure class checks CSL_Strlen of the
103 + *! read value from the registry against the passed in BufSize;
104 + *! CFG_GetZLFile,CFG_GetWMDFileName and
105 + *! CFG_GetExecFile also modified same way.
106 + *! 06-Jan-2000 rr: CFG_GetSearchPath & CFG_GetWinBRIDGEDir removed.
107 + *! 09-Dec-1999 rr: CFG_SetDevObject stores the DevNodeString pointer.
108 + *! 03-Dec-1999 rr: CFG_GetDevObject reads stored DevObject from Registry.
109 + *! CFG_GetDevNode reads the Devnodestring from the registry.
110 + *! CFG_SetDevObject stores the registry path as
111 + *! DevNodestring in the registry.
112 + *! 02-Dec-1999 rr: CFG_debugMask is declared static now. stdwin.h included
113 + *! 22-Nov-1999 kc: Added windows.h to remove warnings.
114 + *! 25-Oct-1999 rr: CFG_GetHostResources reads the HostResource structure
115 + *! from the registry which was set by the DRV Request
116 + *! Resources.
117 + *! 15-Oct-1999 rr: Changes in CFG_SetPrivateDword & HostResources reflecting
118 + *! changes for drv.h resource structure and wsxreg.h new
119 + *! entry(DevObject) Hard coded entries removed for those items
120 + *! 08-Oct-1999 rr: CFG_SetPrivateDword modified. it sets devobject into the
121 + *! registry. CFG_Get HostResources modified for opening up
122 + *! two mem winodws.
123 + *! 24-Sep-1999 rr: CFG_GetHostResources uses hardcoded Registry calls,uses NT
124 + *! type of Resource Structure.
125 + *! 19-Jul-1999 a0216266: Stubbed from cfgnt.c.
126 + */
128 +/* ----------------------------------- DSP/BIOS Bridge */
129 +#include <std.h>
130 +#include <dbdefs.h>
131 +#include <errbase.h>
133 +/* ----------------------------------- Trace & Debug */
134 +#include <dbc.h>
135 +#include <gt.h>
137 +/* ----------------------------------- OS Adaptation Layer */
138 +#include <csl.h>
139 +#include <reg.h>
141 +/* ----------------------------------- Others */
142 +#include <dbreg.h>
144 +/* ----------------------------------- This */
145 +#include <cfg.h>
146 +#include <list.h>
148 +struct DRV_EXT {
149 + struct LST_ELEM link;
150 + char szString[MAXREGPATHLENGTH];
153 +/* ----------------------------------- Globals */
154 +#if GT_TRACE
155 +static struct GT_Mask CFG_debugMask = { NULL, NULL }; /* CFG debug Mask */
156 +#endif
159 + * ======== CFG_Exit ========
160 + * Purpose:
161 + * Discontinue usage of the CFG module.
162 + */
163 +void CFG_Exit(void)
165 + GT_0trace(CFG_debugMask, GT_5CLASS, "Entered CFG_Exit\n");
169 + * ======== CFG_GetAutoStart ========
170 + * Purpose:
171 + * Retreive the autostart mask, if any, for this board.
172 + */
173 +DSP_STATUS CFG_GetAutoStart(struct CFG_DEVNODE *hDevNode,
174 + OUT u32 *pdwAutoStart)
176 + DSP_STATUS status = DSP_SOK;
177 + u32 dwBufSize;
178 + GT_2trace(CFG_debugMask, GT_ENTER,
179 + "Entered CFG_GetAutoStart: \n\thDevNode:"
180 + "0x%x\n\tpdwAutoStart: 0x%x\n", hDevNode, pdwAutoStart);
181 + dwBufSize = sizeof(*pdwAutoStart);
182 + if (!hDevNode)
183 + status = CFG_E_INVALIDHDEVNODE;
184 + if (!pdwAutoStart)
185 + status = CFG_E_INVALIDPOINTER;
186 + if (DSP_SUCCEEDED(status)) {
187 + status = REG_GetValue(NULL, (char *)hDevNode, AUTOSTART,
188 + (u8 *)pdwAutoStart, &dwBufSize);
189 + if (DSP_FAILED(status))
190 + status = CFG_E_RESOURCENOTAVAIL;
192 +#ifdef DEBUG
193 + if (DSP_SUCCEEDED(status)) {
194 + GT_0trace(CFG_debugMask, GT_1CLASS,
195 + "CFG_GetAutoStart SUCCESS \n");
196 + } else {
197 + GT_0trace(CFG_debugMask, GT_6CLASS,
198 + "CFG_GetAutoStart Failed \n");
200 +#endif
201 + DBC_Ensure((status == DSP_SOK &&
202 + (*pdwAutoStart == 0 || *pdwAutoStart == 1))
203 + || status != DSP_SOK);
204 + return status;
208 + * ======== CFG_GetDevObject ========
209 + * Purpose:
210 + * Retrieve the Device Object handle for a given devnode.
211 + */
212 +DSP_STATUS CFG_GetDevObject(struct CFG_DEVNODE *hDevNode, OUT u32 *pdwValue)
214 + DSP_STATUS status = DSP_SOK;
215 + u32 dwBufSize;
216 + GT_2trace(CFG_debugMask, GT_ENTER, "Entered CFG_GetDevObject, args: "
217 + "\n\thDevNode: 0x%x\n\tpdwValue: 0x%x\n", hDevNode,
218 + *pdwValue);
219 + if (!hDevNode)
220 + status = CFG_E_INVALIDHDEVNODE;
222 + if (!pdwValue)
223 + status = CFG_E_INVALIDHDEVNODE;
225 + dwBufSize = sizeof(pdwValue);
226 + if (DSP_SUCCEEDED(status)) {
228 + /* check the device string and then call the REG_SetValue*/
229 + if (!(CSL_Strcmp((char *)((struct DRV_EXT *)hDevNode)->szString,
230 + "TIOMAP1510"))) {
231 + GT_0trace(CFG_debugMask, GT_1CLASS,
232 + "Fetching DSP Device from "
233 + "Registry \n");
234 + status = REG_GetValue(NULL, (char *)hDevNode,
235 + "DEVICE_DSP",
236 + (u8 *)pdwValue, &dwBufSize);
237 + } else {
238 + GT_0trace(CFG_debugMask, GT_6CLASS,
239 + "Failed to Identify the Device to Fetch \n");
242 +#ifdef DEBUG
243 + if (DSP_SUCCEEDED(status)) {
244 + GT_1trace(CFG_debugMask, GT_1CLASS,
245 + "CFG_GetDevObject SUCCESS DevObject"
246 + ": 0x%x\n ", *pdwValue);
247 + } else {
248 + GT_0trace(CFG_debugMask, GT_6CLASS,
249 + "CFG_GetDevObject Failed \n");
251 +#endif
252 + return status;
256 + * ======== CFG_GetDSPResources ========
257 + * Purpose:
258 + * Get the DSP resources available to a given device.
259 + */
260 +DSP_STATUS CFG_GetDSPResources(struct CFG_DEVNODE *hDevNode,
261 + OUT struct CFG_DSPRES *pDSPResTable)
263 + DSP_STATUS status = DSP_SOK; /* return value */
264 + u32 dwResSize;
265 + GT_2trace(CFG_debugMask, GT_ENTER,
266 + "Entered CFG_GetDSPResources, args: "
267 + "\n\thDevNode: 0x%x\n\tpDSPResTable: 0x%x\n",
268 + hDevNode, pDSPResTable);
269 + if (!hDevNode) {
270 + status = CFG_E_INVALIDHDEVNODE;
271 + } else if (!pDSPResTable) {
272 + status = CFG_E_INVALIDPOINTER;
273 + } else {
274 + status = REG_GetValue(NULL, CONFIG, DSPRESOURCES,
275 + (u8 *)pDSPResTable,
276 + &dwResSize);
278 + if (DSP_SUCCEEDED(status)) {
279 + GT_0trace(CFG_debugMask, GT_1CLASS,
280 + "CFG_GetDSPResources SUCCESS\n");
281 + } else {
282 + status = CFG_E_RESOURCENOTAVAIL;
283 + GT_0trace(CFG_debugMask, GT_6CLASS,
284 + "CFG_GetDSPResources Failed \n");
286 +#ifdef DEBUG
287 + /* assert that resource values are reasonable */
288 + DBC_Assert(pDSPResTable->uChipType < 256);
289 + DBC_Assert(pDSPResTable->uWordSize > 0);
290 + DBC_Assert(pDSPResTable->uWordSize < 32);
291 + DBC_Assert(pDSPResTable->cChips > 0);
292 + DBC_Assert(pDSPResTable->cChips < 256);
293 +#endif
294 + return status;
298 + * ======== CFG_GetExecFile ========
299 + * Purpose:
300 + * Retreive the default executable, if any, for this board.
301 + */
302 +DSP_STATUS CFG_GetExecFile(struct CFG_DEVNODE *hDevNode, u32 ulBufSize,
303 + OUT char *pstrExecFile)
305 + DSP_STATUS status = DSP_SOK;
306 + u32 cExecSize = ulBufSize;
307 + GT_3trace(CFG_debugMask, GT_ENTER,
308 + "Entered CFG_GetExecFile:\n\tthDevNode: "
309 + "0x%x\n\tulBufSize: 0x%x\n\tpstrExecFile: 0x%x\n", hDevNode,
310 + ulBufSize, pstrExecFile);
311 + if (!hDevNode)
312 + status = CFG_E_INVALIDHDEVNODE;
314 + if (!pstrExecFile)
315 + status = CFG_E_INVALIDPOINTER;
317 + if (DSP_SUCCEEDED(status)) {
318 + status = REG_GetValue(NULL, (char *)hDevNode, DEFEXEC,
319 + (u8 *)pstrExecFile, &cExecSize);
320 + if (DSP_FAILED(status))
321 + status = CFG_E_RESOURCENOTAVAIL;
322 + else if (cExecSize > ulBufSize)
323 + status = DSP_ESIZE;
326 +#ifdef DEBUG
327 + if (DSP_SUCCEEDED(status)) {
328 + GT_1trace(CFG_debugMask, GT_1CLASS,
329 + "CFG_GetExecFile SUCCESS Exec File"
330 + "name : %s\n ", pstrExecFile);
331 + } else {
332 + GT_0trace(CFG_debugMask, GT_6CLASS,
333 + "CFG_GetExecFile Failed \n");
335 +#endif
336 + DBC_Ensure(((status == DSP_SOK) &&
337 + (CSL_Strlen(pstrExecFile) <= ulBufSize))
338 + || (status != DSP_SOK));
339 + return status;
343 + * ======== CFG_GetHostResources ========
344 + * Purpose:
345 + * Get the Host allocated resources assigned to a given device.
346 + */
347 +DSP_STATUS CFG_GetHostResources(struct CFG_DEVNODE *hDevNode,
348 + OUT struct CFG_HOSTRES *pHostResTable)
350 + DSP_STATUS status = DSP_SOK;
351 + u32 dwBufSize;
352 + GT_2trace(CFG_debugMask, GT_ENTER,
353 + "Entered CFG_GetHostResources, args:\n\t"
354 + "pHostResTable: 0x%x\n\thDevNode: 0x%x\n",
355 + pHostResTable, hDevNode);
356 + if (!hDevNode)
357 + status = CFG_E_INVALIDHDEVNODE;
359 + if (!pHostResTable)
360 + status = CFG_E_INVALIDPOINTER;
362 + if (DSP_SUCCEEDED(status)) {
363 + dwBufSize = sizeof(struct CFG_HOSTRES);
364 + if (DSP_FAILED(REG_GetValue(NULL, (char *)hDevNode,
365 + CURRENTCONFIG,
366 + (u8 *)pHostResTable, &dwBufSize))) {
367 + status = CFG_E_RESOURCENOTAVAIL;
370 +#ifdef DEBUG
371 + if (DSP_SUCCEEDED(status)) {
372 + GT_0trace(CFG_debugMask, GT_1CLASS,
373 + "CFG_GetHostResources SUCCESS \n");
374 + } else {
375 + GT_0trace(CFG_debugMask, GT_6CLASS,
376 + "CFG_GetHostResources Failed \n");
378 +#endif
379 + return status;
383 + * ======== CFG_GetObject ========
384 + * Purpose:
385 + * Retrieve the Object handle from the Registry
386 + */
387 +DSP_STATUS CFG_GetObject(OUT u32 *pdwValue, u32 dwType)
389 + DSP_STATUS status = DSP_EINVALIDARG;
390 + u32 dwBufSize;
391 + DBC_Require(pdwValue != NULL);
392 + GT_1trace(CFG_debugMask, GT_ENTER,
393 + "Entered CFG_GetObject, args:pdwValue: "
394 + "0x%x\n", *pdwValue);
395 + dwBufSize = sizeof(pdwValue);
396 + switch (dwType) {
397 + case (REG_DRV_OBJECT):
398 + status = REG_GetValue(NULL, CONFIG, DRVOBJECT,
399 + (u8 *)pdwValue,
400 + &dwBufSize);
401 + break;
402 + case (REG_MGR_OBJECT):
403 + status = REG_GetValue(NULL, CONFIG, MGROBJECT,
404 + (u8 *)pdwValue,
405 + &dwBufSize);
406 + break;
407 + default:
408 + break;
410 + if (DSP_SUCCEEDED(status)) {
411 + GT_1trace(CFG_debugMask, GT_1CLASS,
412 + "CFG_GetObject SUCCESS DrvObject: "
413 + "0x%x\n ", *pdwValue);
414 + } else {
415 + status = CFG_E_RESOURCENOTAVAIL;
416 + *pdwValue = 0;
417 + GT_0trace(CFG_debugMask, GT_6CLASS, "CFG_GetObject Failed \n");
419 + DBC_Ensure((DSP_SUCCEEDED(status) && *pdwValue != 0) ||
420 + (DSP_FAILED(status) && *pdwValue == 0));
421 + return status;
425 + * ======== CFG_Init ========
426 + * Purpose:
427 + * Initialize the CFG module's private state.
428 + */
429 +bool CFG_Init(void)
431 + struct CFG_DSPRES dspResources;
432 + GT_create(&CFG_debugMask, "CF"); /* CF for ConFig */
433 + GT_0trace(CFG_debugMask, GT_5CLASS, "Entered CFG_Init\n");
434 + GT_0trace(CFG_debugMask, GT_5CLASS, "Intializing DSP Registry Info \n");
436 + dspResources.uChipType = DSPTYPE_64;
437 + dspResources.cChips = 1;
438 + dspResources.uWordSize = DSPWORDSIZE;
439 + dspResources.cMemTypes = 0;
440 + dspResources.aMemDesc[0].uMemType = 0;
441 + dspResources.aMemDesc[0].ulMin = 0;
442 + dspResources.aMemDesc[0].ulMax = 0;
443 + if (DSP_SUCCEEDED(REG_SetValue(NULL, CONFIG, DSPRESOURCES, REG_BINARY,
444 + (u8 *)&dspResources, sizeof(struct CFG_DSPRES)))) {
445 + GT_0trace(CFG_debugMask, GT_5CLASS,
446 + "Initialized DSP resources in "
447 + "Registry \n");
448 + } else
449 + GT_0trace(CFG_debugMask, GT_5CLASS,
450 + "Failed to Initialize DSP resources"
451 + " in Registry \n");
452 + return true;
456 + * ======== CFG_SetDevObject ========
457 + * Purpose:
458 + * Store the Device Object handle and devNode pointer for a given devnode.
459 + */
460 +DSP_STATUS CFG_SetDevObject(struct CFG_DEVNODE *hDevNode, u32 dwValue)
462 + DSP_STATUS status = DSP_SOK;
463 + u32 dwBuffSize;
464 + GT_2trace(CFG_debugMask, GT_ENTER,
465 + "Entered CFG_SetDevObject, args: \n\t"
466 + "hDevNode: 0x%x\n\tdwValue: 0x%x\n", hDevNode, dwValue);
467 + if (!hDevNode)
468 + status = CFG_E_INVALIDHDEVNODE;
470 + dwBuffSize = sizeof(dwValue);
471 + if (DSP_SUCCEEDED(status)) {
472 + /* Store the WCD device object in the Registry */
474 + if (!(CSL_Strcmp((char *)hDevNode, "TIOMAP1510"))) {
475 + GT_0trace(CFG_debugMask, GT_1CLASS,
476 + "Registering the DSP Device \n");
477 + status = REG_SetValue(NULL, (char *)hDevNode,
478 + "DEVICE_DSP", REG_DWORD,\
479 + (u8 *)&dwValue, dwBuffSize);
480 + if (DSP_SUCCEEDED(status)) {
481 + dwBuffSize = sizeof(hDevNode);
482 + status = REG_SetValue(NULL,
483 + (char *)hDevNode, "DEVNODESTRING_DSP",
484 + REG_DWORD, (u8 *)&hDevNode,
485 + dwBuffSize);
487 + } else {
488 + GT_0trace(CFG_debugMask, GT_6CLASS,
489 + "Failed to Register Device \n");
492 +#ifdef DEBUG
493 + if (DSP_SUCCEEDED(status)) {
494 + GT_0trace(CFG_debugMask, GT_1CLASS,
495 + "CFG_SetDevObject SUCCESS \n");
496 + } else {
497 + GT_0trace(CFG_debugMask, GT_6CLASS,
498 + "CFG_SetDevObject Failed \n");
500 +#endif
501 + return status;
505 + * ======== CFG_SetObject ========
506 + * Purpose:
507 + * Store the Driver Object handle
508 + */
509 +DSP_STATUS CFG_SetObject(u32 dwValue, u32 dwType)
511 + DSP_STATUS status = DSP_EINVALIDARG;
512 + u32 dwBuffSize;
513 + GT_1trace(CFG_debugMask, GT_ENTER,
514 + "Entered CFG_SetObject, args: dwValue: "
515 + "0x%x\n", dwValue);
516 + dwBuffSize = sizeof(dwValue);
517 + switch (dwType) {
518 + case (REG_DRV_OBJECT):
519 + status = REG_SetValue(NULL, CONFIG, DRVOBJECT, REG_DWORD,
520 + (u8 *)&dwValue, dwBuffSize);
521 + break;
522 + case (REG_MGR_OBJECT):
523 + status = REG_SetValue(NULL, CONFIG, MGROBJECT, REG_DWORD,
524 + (u8 *) &dwValue, dwBuffSize);
525 + break;
526 + default:
527 + break;
529 +#ifdef DEBUG
530 + if (DSP_SUCCEEDED(status))
531 + GT_0trace(CFG_debugMask, GT_1CLASS, "CFG_SetObject SUCCESS \n");
532 + else
533 + GT_0trace(CFG_debugMask, GT_6CLASS, "CFG_SetObject Failed \n");
535 +#endif
536 + return status;
538 diff --git a/drivers/dsp/bridge/services/clk.c b/drivers/dsp/bridge/services/clk.c
539 new file mode 100644
540 index 0000000..dfe3e4f
541 --- /dev/null
542 +++ b/drivers/dsp/bridge/services/clk.c
543 @@ -0,0 +1,376 @@
545 + * linux/drivers/dsp/bridge/services/clk.c
547 + * DSP-BIOS Bridge driver support functions for TI OMAP processors.
549 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
551 + * This package is free software; you can redistribute it and/or modify
552 + * it under the terms of the GNU General Public License version 2 as
553 + * published by the Free Software Foundation.
555 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
556 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
557 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
558 + */
561 + * ======== clk.c ========
562 + * Purpose:
563 + * Clock and Timer services.
565 + * Public Functions:
566 + * CLK_Exit
567 + * CLK_Init
568 + * CLK_Enable
569 + * CLK_Disable
570 + * CLK_GetRate
571 + * CLK_Set_32KHz
572 + *! Revision History:
573 + *! ================
574 + *! 08-May-2007 rg: moved all clock functions from sync module.
575 + * And added CLK_Set_32KHz, CLK_Set_SysClk.
576 + */
578 +/* ----------------------------------- Host OS */
579 +#include <host_os.h>
581 +/* ----------------------------------- DSP/BIOS Bridge */
582 +#include <std.h>
583 +#include <dbdefs.h>
584 +#include <errbase.h>
586 +/* ----------------------------------- Trace & Debug */
587 +#include <dbc.h>
588 +#include <gt.h>
590 +/* ----------------------------------- OS Adaptation Layer */
591 +#include <csl.h>
592 +#include <mem.h>
594 +/* ----------------------------------- This */
595 +#include <clk.h>
596 +#include <util.h>
599 +/* ----------------------------------- Defines, Data Structures, Typedefs */
601 +typedef volatile unsigned long REG_UWORD32;
603 +#define SSI_Base 0x48058000
605 +#define SSI_BASE IO_ADDRESS(SSI_Base)
608 +struct SERVICES_Clk_t {
609 + struct clk *clk_handle;
610 + const char *clk_name;
613 +/* The row order of the below array needs to match with the clock enumerations
614 + * 'SERVICES_ClkId' provided in the header file.. any changes in the
615 + * enumerations needs to be fixed in the array as well */
616 +static struct SERVICES_Clk_t SERVICES_Clks[] = {
617 + {NULL, "iva2_ck"},
618 + {NULL, "mailboxes_ick"},
619 + {NULL, "gpt5_fck"},
620 + {NULL, "gpt5_ick"},
621 + {NULL, "gpt6_fck"},
622 + {NULL, "gpt6_ick"},
623 + {NULL, "gpt7_fck"},
624 + {NULL, "gpt7_ick"},
625 + {NULL, "gpt8_fck"},
626 + {NULL, "gpt8_ick"},
627 + {NULL, "wdt_fck"},
628 + {NULL, "wdt_ick"},
629 + {NULL, "mcbsp1_fck"},
630 + {NULL, "mcbsp1_ick"},
631 + {NULL, "mcbsp2_fck"},
632 + {NULL, "mcbsp2_ick"},
633 + {NULL, "mcbsp3_fck"},
634 + {NULL, "mcbsp3_ick"},
635 + {NULL, "mcbsp4_fck"},
636 + {NULL, "mcbsp4_ick"},
637 + {NULL, "mcbsp5_fck"},
638 + {NULL, "mcbsp5_ick"},
639 + {NULL, "ssi_ssr_sst_fck"},
640 + {NULL, "ssi_ick"},
641 + {NULL, "omap_32k_fck"},
642 + {NULL, "sys_ck"},
643 + {NULL, ""}
647 +#ifndef CONFIG_DISABLE_BRIDGE_PM
648 +extern struct platform_device dspbridge_device;
649 +#endif
653 +/* Generic TIMER object: */
654 +struct TIMER_OBJECT {
655 + struct timer_list timer;
658 +/* ----------------------------------- Globals */
659 +#if GT_TRACE
660 +static struct GT_Mask CLK_debugMask = { NULL, NULL }; /* GT trace variable */
661 +#endif
663 +struct GPT6_configuration {
664 + u32 config;
665 + u32 tier;
666 + u32 twer;
667 + u32 tclr;
668 + u32 tldr;
669 + u32 ttgr;
671 +/* Shadow settings to save the GPT6 timer settings */
672 +struct GPT6_configuration gpt6_config;
675 + * ======== CLK_Exit ========
676 + * Purpose:
677 + * Cleanup CLK module.
678 + */
679 +void CLK_Exit(void)
681 + int i = 0;
683 + GT_0trace(CLK_debugMask, GT_5CLASS, "CLK_Exit\n");
684 + /* Relinquish the clock handles */
685 + while (i < SERVICESCLK_NOT_DEFINED) {
686 + if (SERVICES_Clks[i].clk_handle)
687 + clk_put(SERVICES_Clks[i].clk_handle);
689 + SERVICES_Clks[i].clk_handle = NULL;
690 + i++;
696 + * ======== CLK_Init ========
697 + * Purpose:
698 + * Initialize CLK module.
699 + */
700 +bool CLK_Init(void)
702 + struct clk *clk_handle;
703 + int i = 0;
704 + GT_create(&CLK_debugMask, "CK"); /* CK for CLK */
705 + GT_0trace(CLK_debugMask, GT_5CLASS, "CLK_Init\n");
707 + /* Get the clock handles from base port and store locally */
708 + while (i < SERVICESCLK_NOT_DEFINED) {
709 + /* get the handle from BP */
710 +#ifndef CONFIG_DISABLE_BRIDGE_PM
711 + clk_handle = clk_get(&dspbridge_device.dev,
712 + SERVICES_Clks[i].clk_name);
713 +#else
714 + clk_handle = clk_get(NULL, SERVICES_Clks[i].clk_name);
715 +#endif
717 + if (!clk_handle) {
718 + GT_1trace(CLK_debugMask, GT_7CLASS,
719 + "CLK_Init: failed to get Clk "
720 + "handle %s \n", SERVICES_Clks[i].clk_name);
721 + /* should we fail here?? */
722 + } else {
723 + GT_1trace(CLK_debugMask, GT_7CLASS,
724 + "CLK_Init: PASS and Clk handle"
725 + "%s \n", SERVICES_Clks[i].clk_name);
727 + SERVICES_Clks[i].clk_handle = clk_handle;
728 + i++;
731 + return true;
735 + * ======== CLK_Enable ========
736 + * Purpose:
737 + * Enable Clock .
740 +DSP_STATUS CLK_Enable(IN enum SERVICES_ClkId clk_id)
742 + DSP_STATUS status = DSP_SOK;
743 + struct clk *pClk;
745 + DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
746 + GT_1trace(CLK_debugMask, GT_6CLASS,
747 + "CLK_Enable: CLK Id = 0x%x \n", clk_id);
749 + pClk = SERVICES_Clks[clk_id].clk_handle;
750 + if (pClk) {
751 + if (clk_enable(pClk) == 0x0) {
752 + /* Success ? */
753 + } else {
754 + GT_1trace(CLK_debugMask, GT_7CLASS,
755 + "CLK_Enable: failed to Enable "
756 + "CLK %s \n", SERVICES_Clks[clk_id].clk_name);
757 + status = DSP_EFAIL;
759 + } else {
760 + GT_1trace(CLK_debugMask, GT_7CLASS,
761 + "CLK_Enable: failed to get "
762 + "CLK %s \n", SERVICES_Clks[clk_id].clk_name);
763 + status = DSP_EFAIL;
765 + /* The SSI module need to configured not to have the Forced idle for
766 + * master interface. If it is set to forced idle, the SSI module is
767 + * transitioning to standby thereby causing the client in the DSP hang
768 + * waiting for the SSI module to be active after enabling the clocks
769 + */
770 + if (clk_id == SERVICESCLK_ssi_fck)
771 + SSI_Clk_Prepare(true);
773 + return status;
776 + * ======== CLK_Set_32KHz ========
777 + * Purpose:
778 + * To Set parent of a clock to 32KHz.
779 + */
781 +DSP_STATUS CLK_Set_32KHz(IN enum SERVICES_ClkId clk_id)
783 + DSP_STATUS status = DSP_SOK;
784 + struct clk *pClk;
785 + struct clk *pClkParent;
786 + enum SERVICES_ClkId sys_32k_id = SERVICESCLK_sys_32k_ck;
787 + pClkParent = SERVICES_Clks[sys_32k_id].clk_handle;
789 + DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
790 + GT_1trace(CLK_debugMask, GT_6CLASS, "CLK_Set_32KHz: CLK Id = 0x%x is "
791 + "setting to 32KHz \n", clk_id);
792 + pClk = SERVICES_Clks[clk_id].clk_handle;
793 + if (pClk) {
794 + if (!(clk_set_parent(pClk, pClkParent) == 0x0)) {
795 + GT_1trace(CLK_debugMask, GT_7CLASS,
796 + "CLK_Set_32KHz: Failed to "
797 + "set to 32KHz %s \n",
798 + SERVICES_Clks[clk_id].clk_name);
799 + status = DSP_EFAIL;
802 + return status;
806 + * ======== CLK_Disable ========
807 + * Purpose:
808 + * Disable the clock.
811 +DSP_STATUS CLK_Disable(IN enum SERVICES_ClkId clk_id)
813 + DSP_STATUS status = DSP_SOK;
814 + struct clk *pClk;
815 + s32 clkUseCnt;
817 + DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
818 + GT_1trace(CLK_debugMask, GT_6CLASS,
819 + "CLK_Disable: CLK Id = 0x%x \n", clk_id);
821 + pClk = SERVICES_Clks[clk_id].clk_handle;
823 + clkUseCnt = CLK_Get_UseCnt(clk_id);
824 + if (clkUseCnt == -1) {
825 + GT_1trace(CLK_debugMask, GT_7CLASS,
826 + "CLK_Disable: failed to get "
827 + "CLK Use count for Clk %s \n",
828 + SERVICES_Clks[clk_id].clk_name);
829 + } else if (clkUseCnt == 0) {
830 + GT_1trace(CLK_debugMask, GT_7CLASS,
831 + "CLK_Disable: Clk %s is already"
832 + "disabled\n", SERVICES_Clks[clk_id].clk_name);
833 + return status;
835 + if (clk_id == SERVICESCLK_ssi_ick)
836 + SSI_Clk_Prepare(false);
838 + if (pClk) {
839 + clk_disable(pClk);
840 + } else {
841 + GT_1trace(CLK_debugMask, GT_7CLASS,
842 + "CLK_Disable: failed to get "
843 + "CLK %s \n", SERVICES_Clks[clk_id].clk_name);
844 + status = DSP_EFAIL;
846 + return status;
850 + * ======== CLK_GetRate ========
851 + * Purpose:
852 + * GetClock Speed.
854 + */
856 +DSP_STATUS CLK_GetRate(IN enum SERVICES_ClkId clk_id, u32 *speedKhz)
858 + DSP_STATUS status = DSP_SOK;
859 + struct clk *pClk;
860 + u32 clkSpeedHz;
862 + DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
863 + *speedKhz = 0x0;
865 + GT_1trace(CLK_debugMask, GT_7CLASS,
866 + "CLK_GetRate: CLK Id = 0x%x \n", clk_id);
867 + pClk = SERVICES_Clks[clk_id].clk_handle;
868 + if (pClk) {
869 + clkSpeedHz = clk_get_rate(pClk);
870 + *speedKhz = clkSpeedHz / 1000;
871 + GT_2trace(CLK_debugMask, GT_6CLASS,
872 + "CLK_GetRate: clkSpeedHz = %d , "
873 + "speedinKhz=%d \n", clkSpeedHz, *speedKhz);
874 + } else {
875 + GT_1trace(CLK_debugMask, GT_7CLASS,
876 + "CLK_GetRate: failed to get CLK %s\n",
877 + SERVICES_Clks[clk_id].clk_name);
878 + status = DSP_EFAIL;
880 + return status;
883 +s32 CLK_Get_UseCnt(IN enum SERVICES_ClkId clk_id)
885 + DSP_STATUS status = DSP_SOK;
886 + struct clk *pClk;
887 + s32 useCount = -1;
888 + DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
890 + pClk = SERVICES_Clks[clk_id].clk_handle;
892 + if (pClk) {
893 + useCount = clk_get_usecount(pClk);
894 + } else {
895 + GT_1trace(CLK_debugMask, GT_7CLASS,
896 + "CLK_GetRate: failed to get "
897 + "CLK %s \n", SERVICES_Clks[clk_id].clk_name);
898 + status = DSP_EFAIL;
900 + return useCount;
903 +void SSI_Clk_Prepare(bool FLAG)
905 + u32 ssi_sysconfig;
906 + ssi_sysconfig = __raw_readl((SSI_BASE) + 0x10);
909 + if (FLAG) {
910 + /* Set Autoidle, SIDLEMode to smart idle, and MIDLEmode to
911 + * no idle */
912 + ssi_sysconfig = 0x1011;
913 + } else {
914 + /* Set Autoidle, SIDLEMode to forced idle, and MIDLEmode to
915 + * forced idle*/
916 + ssi_sysconfig = 0x1;
918 + __raw_writel((u32)ssi_sysconfig, SSI_BASE + 0x10);
920 diff --git a/drivers/dsp/bridge/services/csl.c b/drivers/dsp/bridge/services/csl.c
921 new file mode 100644
922 index 0000000..a8b2ec8
923 --- /dev/null
924 +++ b/drivers/dsp/bridge/services/csl.c
925 @@ -0,0 +1,274 @@
927 + * linux/drivers/dsp/bridge/services/csl.c
929 + * DSP-BIOS Bridge driver support functions for TI OMAP processors.
931 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
933 + * This package is free software; you can redistribute it and/or modify
934 + * it under the terms of the GNU General Public License version 2 as
935 + * published by the Free Software Foundation.
937 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
938 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
939 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
940 + */
944 + * ======== cslce.c ========
945 + * Purpose:
946 + * Provides platform independent C Standard library functions.
948 + * Public Functions:
949 + * CSL_Atoi
950 + * CSL_Exit
951 + * CSL_Init
952 + * CSL_NumToAscii
953 + * CSL_Strcmp
954 + * CSL_Strstr
955 + * CSL_Strcpyn
956 + * CSL_Strlen
957 + * CSL_Strncat
958 + * CSL_Strncmp
959 + * CSL_Strtokr
961 + *! Revision History:
962 + *! ================
963 + *! 07-Aug-2002 jeh: Added CSL_Strtokr().
964 + *! 21-Sep-2001 jeh: Added CSL_Strncmp(). Alphabetized functions.
965 + *! 22-Nov-2000 map: Added CSL_Atoi and CSL_Strtok
966 + *! 19-Nov-2000 kc: Added CSL_ByteSwap.
967 + *! 09-Nov-2000 kc: Added CSL_Strncat.
968 + *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
969 + *! GT Changes.
970 + *! 15-Dec-1999 ag: Removed incorrect assertion CSL_NumToAscii()
971 + *! 29-Oct-1999 kc: Added CSL_Wstrlen for UNICODE strings.
972 + *! 30-Sep-1999 ag: Removed DBC assertion (!CSL_DebugMask.flags) in
973 + * CSP_Init().
974 + *! 20-Sep-1999 ag: Added CSL_WcharToAnsi().
975 + *! Removed call to GT_set().
976 + *! 19-Jan-1998 cr: Code review cleanup.
977 + *! 29-Dec-1997 cr: Made platform independant, using MS CRT code, and
978 + *! combined csl32.c csl95.c and cslnt.c into csl.c. Also
979 + *! changed CSL_lowercase to CSL_Uppercase.
980 + *! 21-Aug-1997 gp: Fix to CSL_strcpyn to initialize Source string, the NT way.
981 + *! 25-Jun-1997 cr: Created from csl95, added CSL_strcmp.
982 + */
984 +/* ----------------------------------- Host OS */
985 +#include <host_os.h>
987 +/* ----------------------------------- DSP/BIOS Bridge */
988 +#include <std.h>
989 +#include <dbdefs.h>
991 +/* ----------------------------------- Trace & Debug */
992 +#include <dbc.h>
993 +#include <gt.h>
995 +/* ----------------------------------- This */
996 +#include <csl.h>
998 +/* Is character c in the string pstrDelim? */
999 +#define IsDelimiter(c, pstrDelim) ((c != '\0') && \
1000 + (strchr(pstrDelim, c) != NULL))
1002 +/* ----------------------------------- Globals */
1003 +#if GT_TRACE
1004 +static struct GT_Mask CSL_DebugMask = { NULL, NULL }; /* GT trace var. */
1005 +#endif
1008 + * ======= CSL_Atoi =======
1009 + * Purpose:
1010 + * Convert a string to an integer
1011 + */
1012 +s32 CSL_Atoi(IN CONST char *ptstrSrc)
1014 + char *end_position;
1016 + DBC_Require(ptstrSrc);
1018 + return simple_strtol(ptstrSrc, &end_position, 10);
1022 + * ======== CSL_Exit ========
1023 + * Purpose:
1024 + * Discontinue usage of the CSL module.
1025 + */
1026 +void CSL_Exit(void)
1028 + GT_0trace(CSL_DebugMask, GT_5CLASS, "CSL_Exit\n");
1032 + * ======== CSL_Init ========
1033 + * Purpose:
1034 + * Initialize the CSL module's private state.
1035 + */
1036 +bool CSL_Init(void)
1038 + GT_create(&CSL_DebugMask, "CS");
1040 + GT_0trace(CSL_DebugMask, GT_5CLASS, "CSL_Init\n");
1042 + return true;
1046 + * ======== CSL_NumToAscii ========
1047 + * Purpose:
1048 + * Convert a 1 or 2 digit number to a 2 digit string.
1049 + */
1050 +void CSL_NumToAscii(OUT char *pstrNumber, u32 dwNum)
1052 + char tens;
1054 + DBC_Require(dwNum < 100);
1056 + if (dwNum < 100) {
1057 + tens = (char) dwNum / 10;
1058 + dwNum = dwNum % 10;
1060 + if (tens) {
1061 + pstrNumber[0] = tens + '0';
1062 + pstrNumber[1] = (char) dwNum + '0';
1063 + pstrNumber[2] = '\0';
1064 + } else {
1065 + pstrNumber[0] = (char) dwNum + '0';
1066 + pstrNumber[1] = '\0';
1068 + } else {
1069 + pstrNumber[0] = '\0';
1074 + * ======== CSL_Strcmp ========
1075 + * Purpose:
1076 + * Compare 2 ASCII strings. Works the same was as stdio's strcmp.
1077 + */
1078 +s32 CSL_Strcmp(IN CONST char *pstrStr1, IN CONST char *pstrStr2)
1080 + return strcmp(pstrStr1, pstrStr2);
1084 + * ======== CSL_Strstr ========
1085 + * Purpose:
1086 + * Find substring in a stringn.
1087 + * Parameters:
1088 + * haystack: Ptr to string1.
1089 + * needle: Ptr to substring to catch.
1090 + * Returns:
1091 + * Ptr to first char matching the substring in the main string.
1092 + * Requires:
1093 + * CSL initialized.
1094 + * haystack is valid.
1095 + * needle is valid.
1096 + * Ensures:
1097 + */
1099 +char *CSL_Strstr(IN CONST char *haystack, IN CONST char *needle)
1101 + return strstr(haystack, needle);
1105 + * ======== CSL_Strcpyn ========
1106 + * Purpose:
1107 + * Safe strcpy function.
1108 + */
1109 +char *CSL_Strcpyn(OUT char *pstrDest, IN CONST char *pstrSrc, u32 cMax)
1111 + return strncpy(pstrDest, pstrSrc, cMax);
1115 + * ======== CSL_Strlen ========
1116 + * Purpose:
1117 + * Determine the length of a null terminated ASCII string.
1118 + */
1119 +u32 CSL_Strlen(IN CONST char *pstrSrc)
1121 + CONST char *pStr = pstrSrc;
1122 + u32 retVal;
1124 + DBC_Require(pstrSrc);
1126 + while (*pStr++)
1127 + ;;
1129 + retVal = (u32) (pStr - pstrSrc - 1);
1130 + return retVal;
1134 + * ======== CSL_Strncat ========
1135 + * Purpose:
1136 + * Concatenate two strings together
1137 + */
1138 +char *CSL_Strncat(IN char *pszDest, IN char *pszSrc, IN u32 dwSize)
1141 + DBC_Require(pszDest && pszSrc);
1143 + return strncat(pszDest, pszSrc, dwSize);
1147 + * ======== CSL_Strncmp ========
1148 + * Purpose:
1149 + * Compare at most n characters of two ASCII strings. Works the same
1150 + * way as stdio's strncmp.
1151 + */
1152 +s32 CSL_Strncmp(IN CONST char *pstrStr1, IN CONST char *pstrStr2, u32 n)
1154 + return strncmp(pstrStr1, pstrStr2, n);
1158 + * ======= CSL_Strtokr =======
1159 + * Purpose:
1160 + * Re-entrant version of strtok.
1161 + */
1162 +char *CSL_Strtokr(IN char *pstrSrc, IN CONST char *szSeparators,
1163 + OUT char **ppstrLast)
1165 + char *pstrTemp;
1166 + char *pstrToken;
1168 + DBC_Require(szSeparators != NULL);
1169 + DBC_Require(ppstrLast != NULL);
1170 + DBC_Require(pstrSrc != NULL || *ppstrLast != NULL);
1172 + /*
1173 + * Set string location to beginning (pstrSrc != NULL) or to the
1174 + * beginning of the next token.
1175 + */
1176 + pstrTemp = (pstrSrc != NULL) ? pstrSrc : *ppstrLast;
1177 + if (*pstrTemp == '\0') {
1178 + pstrToken = NULL;
1179 + } else {
1180 + pstrToken = pstrTemp;
1181 + while (*pstrTemp != '\0' && !IsDelimiter(*pstrTemp,
1182 + szSeparators)) {
1183 + pstrTemp++;
1185 + if (*pstrTemp != '\0') {
1186 + while (IsDelimiter(*pstrTemp, szSeparators)) {
1187 + /* TODO: Shouldn't we do this for
1188 + * only 1 char?? */
1189 + *pstrTemp = '\0';
1190 + pstrTemp++;
1194 + /* Location in string for next call */
1195 + *ppstrLast = pstrTemp;
1198 + return pstrToken;
1200 diff --git a/drivers/dsp/bridge/services/dbg.c b/drivers/dsp/bridge/services/dbg.c
1201 new file mode 100644
1202 index 0000000..b93f1de
1203 --- /dev/null
1204 +++ b/drivers/dsp/bridge/services/dbg.c
1205 @@ -0,0 +1,119 @@
1207 + * linux/drivers/dsp/bridge/services/dbg.c
1209 + * DSP-BIOS Bridge driver support functions for TI OMAP processors.
1211 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
1213 + * This package is free software; you can redistribute it and/or modify
1214 + * it under the terms of the GNU General Public License version 2 as
1215 + * published by the Free Software Foundation.
1217 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1218 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1219 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1220 + */
1224 + * ======== dbgce.c ========
1225 + * Purpose:
1226 + * Provide debugging services for DSP/BIOS Bridge Mini Drivers.
1228 + * Public Functions:
1229 + * DBG_Exit
1230 + * DBG_Init
1231 + * DBG_Trace
1233 + * Notes:
1234 + * Requires gt.h.
1236 + * This implementation does not create GT masks on a per WMD basis.
1237 + * There is currently no facility for a WMD to alter the GT mask.
1239 + *! Revision History:
1240 + *! ================
1241 + *! 15-Feb-2000 rr: DBG_Trace prints based on the DebugZones.
1242 + *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
1243 + *! GT Changes.
1244 + *! 29-Oct-1999 kc: Cleaned up for code review.
1245 + *! 10-Oct-1997 cr: Added DBG_Printf service.
1246 + *! 28-May-1997 cr: Added reference counting.
1247 + *! 23-May-1997 cr: Updated DBG_Trace to new gt interface.
1248 + *! 29-May-1996 gp: Removed WCD_ prefix.
1249 + *! 20-May-1996 gp: Remove DEBUG conditional compilation.
1250 + *! 15-May-1996 gp: Created.
1251 + */
1253 +/* ----------------------------------- DSP/BIOS Bridge */
1254 +#include <std.h>
1255 +#include <dbdefs.h>
1256 +#include <errbase.h>
1258 +/* ----------------------------------- Trace & Debug */
1259 +#include <dbc.h>
1260 +#include <gt.h>
1262 +/* ----------------------------------- This */
1263 +#include <dbg.h>
1265 +/* ----------------------------------- Globals */
1266 +#if GT_TRACE
1267 +static struct GT_Mask DBG_debugMask = { NULL, NULL }; /* GT trace var. */
1268 +#endif
1270 +#if ((defined DEBUG) || (defined DDSP_DEBUG_PRODUCT)) && GT_TRACE
1273 + * ======== DBG_Init ========
1274 + * Purpose:
1275 + * Ensures trace capability is set up for link drivers.
1276 + */
1277 +bool DBG_Init(void)
1279 + GT_create(&DBG_debugMask, "WD"); /* for WmD (link driver) debug */
1281 + GT_0trace(DBG_debugMask, GT_5CLASS, "DBG_Init\n");
1283 + return true;
1287 + * ======== DBG_Trace ========
1288 + * Purpose:
1289 + * Output a trace message to the debugger, if the given trace level
1290 + * is unmasked.
1291 + */
1292 +DSP_STATUS DBG_Trace(u8 bLevel, char *pstrFormat, ...)
1294 + s32 arg1, arg2, arg3, arg4, arg5, arg6;
1295 + va_list va;
1297 + va_start(va, pstrFormat);
1299 + arg1 = va_arg(va, s32);
1300 + arg2 = va_arg(va, s32);
1301 + arg3 = va_arg(va, s32);
1302 + arg4 = va_arg(va, s32);
1303 + arg5 = va_arg(va, s32);
1304 + arg6 = va_arg(va, s32);
1306 + va_end(va);
1308 + if (bLevel & *(DBG_debugMask).flags)
1309 + (*GT->PRINTFXN)(pstrFormat, arg1, arg2, arg3, arg4, arg5, arg6);
1311 + return DSP_SOK;
1315 + * ======== DBG_Exit ========
1316 + * Purpose:
1317 + * Discontinue usage of the DBG module.
1318 + */
1319 +void DBG_Exit(void)
1321 + GT_0trace(DBG_debugMask, GT_5CLASS, "DBG_Exit\n");
1324 +#endif /* ((defined DEBUG) || (defined DDSP_DEBUG_PRODUCT)) && GT_TRACE */
1325 diff --git a/drivers/dsp/bridge/services/dpc.c b/drivers/dsp/bridge/services/dpc.c
1326 new file mode 100644
1327 index 0000000..a053ee7
1328 --- /dev/null
1329 +++ b/drivers/dsp/bridge/services/dpc.c
1330 @@ -0,0 +1,275 @@
1332 + * linux/drivers/dsp/bridge/services/dpc.c
1334 + * DSP-BIOS Bridge driver support functions for TI OMAP processors.
1336 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
1338 + * This package is free software; you can redistribute it and/or modify
1339 + * it under the terms of the GNU General Public License version 2 as
1340 + * published by the Free Software Foundation.
1342 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1343 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1344 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1345 + */
1349 + * ======== dpcce.c ========
1350 + * Purpose:
1351 + * Deferred Procedure Call(DPC) Services.
1354 + * Public Functions:
1355 + * DPC_Create
1356 + * DPC_Destroy
1357 + * DPC_Exit
1358 + * DPC_Init
1359 + * DPC_Schedule
1361 + *! Revision History:
1362 + *! ================
1363 + *! 28-Mar-2001 ag: Added #ifdef CHNL_NOIPCINTR to set DPC thread priority
1364 + *! to THREAD_PRIORITY_IDLE for polling IPC.
1365 + *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
1366 + *! GT Changes.
1367 + *! 31-Jan-2000 rr: Changes after code review.Terminate thread,handle
1368 + *! modified.DPC_Destroy frees the DPC_Object only on
1369 + *! Successful termination of the thread and the handle.
1370 + *! 06-Jan-1999 ag: Format cleanup for code review.
1371 + *! Removed DPC_[Lower|Raise]IRQL[From|To]DispatchLevel.
1372 + *! 10-Dec-1999 ag: Added SetProcPermissions in DPC_DeferredProcedure().
1373 + *! (Needed to access client(s) CHNL buffers).
1374 + *! 19-Sep-1999 a0216266: Stubbed from dpcnt.c.
1375 + */
1377 +/* ----------------------------------- Host OS */
1378 +#include <host_os.h>
1380 +/* ----------------------------------- DSP/BIOS Bridge */
1381 +#include <std.h>
1382 +#include <dbdefs.h>
1383 +#include <errbase.h>
1385 +/* ----------------------------------- Trace & Debug */
1386 +#include <dbc.h>
1387 +#include <gt.h>
1389 +/* ----------------------------------- OS Adaptation Layer */
1390 +#include <mem.h>
1392 +/* ----------------------------------- This */
1393 +#include <dpc.h>
1395 +/* ----------------------------------- Defines, Data Structures, Typedefs */
1396 +#define SIGNATURE 0x5f435044 /* "DPC_" (in reverse). */
1398 +/* The DPC object, passed to our priority event callback routine: */
1399 +struct DPC_OBJECT {
1400 + u32 dwSignature; /* Used for object validation. */
1401 + void *pRefData; /* Argument for client's DPC. */
1402 + DPC_PROC pfnDPC; /* Client's DPC. */
1403 + u32 numRequested; /* Number of requested DPC's. */
1404 + u32 numScheduled; /* Number of executed DPC's. */
1405 + struct tasklet_struct dpc_tasklet;
1407 +#ifdef DEBUG
1408 + u32 cEntryCount; /* Number of times DPC reentered. */
1409 + u32 numRequestedMax; /* Keep track of max pending DPC's. */
1410 +#endif
1412 + spinlock_t dpc_lock;
1415 +/* ----------------------------------- Globals */
1416 +#if GT_TRACE
1417 +static struct GT_Mask DPC_DebugMask = { NULL, NULL }; /* DPC Debug Mask */
1418 +#endif
1420 +/* ----------------------------------- Function Prototypes */
1421 +static void DPC_DeferredProcedure(IN unsigned long pDeferredContext);
1424 + * ======== DPC_Create ========
1425 + * Purpose:
1426 + * Create a DPC object, allowing a client's own DPC procedure to be
1427 + * scheduled for a call with client reference data.
1428 + */
1429 +DSP_STATUS DPC_Create(OUT struct DPC_OBJECT **phDPC, DPC_PROC pfnDPC,
1430 + void *pRefData)
1432 + DSP_STATUS status = DSP_SOK;
1433 + struct DPC_OBJECT *pDPCObject = NULL;
1435 + if ((phDPC != NULL) && (pfnDPC != NULL)) {
1436 + /*
1437 + * Allocate a DPC object to store information allowing our DPC
1438 + * callback to dispatch to the client's DPC.
1439 + */
1440 + MEM_AllocObject(pDPCObject, struct DPC_OBJECT, SIGNATURE);
1441 + if (pDPCObject != NULL) {
1442 + tasklet_init(&pDPCObject->dpc_tasklet,
1443 + DPC_DeferredProcedure,
1444 + (u32) pDPCObject);
1445 + /* Fill out our DPC Object: */
1446 + pDPCObject->pRefData = pRefData;
1447 + pDPCObject->pfnDPC = pfnDPC;
1448 + pDPCObject->numRequested = 0;
1449 + pDPCObject->numScheduled = 0;
1450 +#ifdef DEBUG
1451 + pDPCObject->numRequestedMax = 0;
1452 + pDPCObject->cEntryCount = 0;
1453 +#endif
1454 + pDPCObject->dpc_lock =
1455 + __SPIN_LOCK_UNLOCKED(pDPCObject.dpc_lock);
1456 + *phDPC = pDPCObject;
1457 + } else {
1458 + GT_0trace(DPC_DebugMask, GT_6CLASS,
1459 + "DPC_Create: DSP_EMEMORY\n");
1460 + status = DSP_EMEMORY;
1462 + } else {
1463 + GT_0trace(DPC_DebugMask, GT_6CLASS,
1464 + "DPC_Create: DSP_EPOINTER\n");
1465 + status = DSP_EPOINTER;
1467 + DBC_Ensure((DSP_FAILED(status) && (!phDPC || (phDPC && *phDPC == NULL)))
1468 + || DSP_SUCCEEDED(status));
1469 + return status;
1473 + * ======== DPC_Destroy ========
1474 + * Purpose:
1475 + * Cancel the last scheduled DPC, and deallocate a DPC object previously
1476 + * allocated with DPC_Create(). Frees the Object only if the thread
1477 + * and the event terminated successfuly.
1478 + */
1479 +DSP_STATUS DPC_Destroy(struct DPC_OBJECT *hDPC)
1481 + DSP_STATUS status = DSP_SOK;
1482 + struct DPC_OBJECT *pDPCObject = (struct DPC_OBJECT *)hDPC;
1484 + if (MEM_IsValidHandle(hDPC, SIGNATURE)) {
1486 + /* Free our DPC object: */
1487 + if (DSP_SUCCEEDED(status)) {
1488 + tasklet_kill(&pDPCObject->dpc_tasklet);
1489 + MEM_FreeObject(pDPCObject);
1490 + pDPCObject = NULL;
1491 + GT_0trace(DPC_DebugMask, GT_2CLASS,
1492 + "DPC_Destroy: SUCCESS\n");
1494 + } else {
1495 + GT_0trace(DPC_DebugMask, GT_6CLASS,
1496 + "DPC_Destroy: DSP_EHANDLE\n");
1497 + status = DSP_EHANDLE;
1499 + DBC_Ensure((DSP_SUCCEEDED(status) && pDPCObject == NULL)
1500 + || DSP_FAILED(status));
1501 + return status;
1505 + * ======== DPC_Exit ========
1506 + * Purpose:
1507 + * Discontinue usage of the DPC module.
1508 + */
1509 +void DPC_Exit(void)
1511 + GT_0trace(DPC_DebugMask, GT_5CLASS, "Entered DPC_Exit\n");
1515 + * ======== DPC_Init ========
1516 + * Purpose:
1517 + * Initialize the DPC module's private state.
1518 + */
1519 +bool DPC_Init(void)
1521 + GT_create(&DPC_DebugMask, "DP");
1523 + GT_0trace(DPC_DebugMask, GT_5CLASS, "Entered DPC_Init\n");
1525 + return true;
1529 + * ======== DPC_Schedule ========
1530 + * Purpose:
1531 + * Schedule a deferred procedure call to be executed at a later time.
1532 + * Latency and order of DPC execution is platform specific.
1533 + */
1534 +DSP_STATUS DPC_Schedule(struct DPC_OBJECT *hDPC)
1536 + DSP_STATUS status = DSP_SOK;
1537 + struct DPC_OBJECT *pDPCObject = (struct DPC_OBJECT *)hDPC;
1538 + unsigned long flags;
1540 + GT_1trace(DPC_DebugMask, GT_ENTER, "DPC_Schedule hDPC %x\n", hDPC);
1541 + if (MEM_IsValidHandle(hDPC, SIGNATURE)) {
1542 + /* Increment count of DPC's pending. Needs to be protected
1543 + * from ISRs since this function is called from process
1544 + * context also. */
1545 + spin_lock_irqsave(&hDPC->dpc_lock, flags);
1546 + pDPCObject->numRequested++;
1547 + spin_unlock_irqrestore(&hDPC->dpc_lock, flags);
1548 + tasklet_schedule(&(hDPC->dpc_tasklet));
1549 +#ifdef DEBUG
1550 + if (pDPCObject->numRequested > pDPCObject->numScheduled +
1551 + pDPCObject->numRequestedMax) {
1552 + pDPCObject->numRequestedMax = pDPCObject->numRequested -
1553 + pDPCObject->numScheduled;
1555 +#endif
1556 + /* If an interrupt occurs between incrementing numRequested and the
1557 + * assertion below, then DPC will get executed while returning from
1558 + * ISR, which will complete all requests and make numRequested equal
1559 + * to numScheduled, firing this assertion. This happens only when
1560 + * DPC is being scheduled in process context */
1561 + } else {
1562 + GT_0trace(DPC_DebugMask, GT_6CLASS,
1563 + "DPC_Schedule: DSP_EHANDLE\n");
1564 + status = DSP_EHANDLE;
1566 + GT_1trace(DPC_DebugMask, GT_ENTER, "DPC_Schedule status %x\n", status);
1567 + return status;
1571 + * ======== DeferredProcedure ========
1572 + * Purpose:
1573 + * Main DPC routine. This is called by host OS DPC callback
1574 + * mechanism with interrupts enabled.
1575 + */
1576 +static void DPC_DeferredProcedure(IN unsigned long pDeferredContext)
1578 + struct DPC_OBJECT *pDPCObject = (struct DPC_OBJECT *)pDeferredContext;
1579 + /* read numRequested in local variable */
1580 + u32 requested;
1581 + u32 serviced;
1583 + DBC_Require(pDPCObject != NULL);
1584 + requested = pDPCObject->numRequested;
1585 + serviced = pDPCObject->numScheduled;
1587 + GT_1trace(DPC_DebugMask, GT_ENTER, "> DPC_DeferredProcedure "
1588 + "pDeferredContext=%x\n", pDeferredContext);
1589 + /* Rollover taken care of using != instead of < */
1590 + if (serviced != requested) {
1591 + if (pDPCObject->pfnDPC != NULL) {
1592 + /* Process pending DPC's: */
1593 + do {
1594 + /* Call client's DPC: */
1595 + (*(pDPCObject->pfnDPC))(pDPCObject->pRefData);
1596 + serviced++;
1597 + } while (serviced != requested);
1599 + pDPCObject->numScheduled = requested;
1601 + GT_2trace(DPC_DebugMask, GT_ENTER,
1602 + "< DPC_DeferredProcedure requested %d"
1603 + " serviced %d\n", requested, serviced);
1606 diff --git a/drivers/dsp/bridge/services/isr.c b/drivers/dsp/bridge/services/isr.c
1607 new file mode 100644
1608 index 0000000..781a19c
1609 --- /dev/null
1610 +++ b/drivers/dsp/bridge/services/isr.c
1611 @@ -0,0 +1,261 @@
1613 + * linux/drivers/dsp/bridge/services/isr.c
1615 + * DSP-BIOS Bridge driver support functions for TI OMAP processors.
1617 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
1619 + * This package is free software; you can redistribute it and/or modify
1620 + * it under the terms of the GNU General Public License version 2 as
1621 + * published by the Free Software Foundation.
1623 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1624 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1625 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1626 + */
1630 + * ======== isrce.c ========
1631 + * Purpose:
1632 + * Interrupt services.
1634 + * Public Functions:
1635 + * ISR_Exit
1636 + * ISR_Init
1637 + * ISR_Install
1638 + * ISR_Uninstall
1641 + *! Revision History:
1642 + *! ================
1643 + *! 06-Feb-2003 kc: Renamed DSP_MAILBOX1 to ISR_MAILBOX1.
1644 + *! 14-Mar-2002 rr: Added HELEN1_V1 flag while installing the interrupt.
1645 + *! 05-Nov-2001 kc: Updated ISR_Install to support multiple HW interrupts.
1646 + *! 27-Jul-2001 rr: Interrupt Id is based on x86 or ARM define.
1647 + *! 24-Apr-2001 ag: Replaced nkintr.h with hw.h.
1648 + *! 10-Oct-2000 rr: CeSetThreadPriority used instead of SetThreadPriority.
1649 + *! 11-Aug-2000 ag: Removed #include <stdwin.h>
1650 + *! 10-Aug-2000 rr: InterruptInitialize happens before the IST creation.
1651 + *! 15-Feb-2000 rr: InterruptInitialize return value checked.
1652 + *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
1653 + *! GT Changes.
1654 + *! 31-Jan-2000 rr: Changes after code review.Terminate thread,handle
1655 + *! modified.ISR_UnInstall frees the ISR_Object only on
1656 + *! Successful termination of the thread and the handle.
1657 + *! 19-Jan-2000 rr: Code Cleaned up after code review.
1658 + *! 06-Jan-2000 rr: Bus type included in the IRQ object. It is checked
1659 + *! during the install and uninstall.
1660 + *! 29-Dec-1999 rr: WaitForSingleObject removed during ISR_UnInstall
1661 + *! 22-Nov-1999 rr: Event gets created before CardRequestIRQ
1662 + *! 05-Nov-1999 rr: ISR_Install does not intialize the interrupt for PCMCIA
1663 + *! For other bus type this will happen. IST function return
1664 + *! value not checked as anyway we have to say InterruptDone
1665 + *! 29-Oct-1999 rr: Hardware IST is created here.
1666 + *! 25-Oct-1999 rr: New Isr design.
1667 + *! 13-Sep-1999 a0216266: Stubbed from isrnt.c.
1668 + */
1670 +/* ----------------------------------- Host OS */
1671 +#include <host_os.h>
1673 +/* ----------------------------------- DSP/BIOS Bridge */
1674 +#include <std.h>
1675 +#include <dbdefs.h>
1676 +#include <errbase.h>
1678 +/* ----------------------------------- Trace & Debug */
1679 +#include <dbc.h>
1680 +#include <gt.h>
1682 +/* ----------------------------------- OS Adaptation Layer */
1683 +#include <list.h>
1684 +#include <mem.h>
1686 +/* ----------------------------------- This */
1687 +#include <isr.h>
1689 +/* ----------------------------------- Defines, Data Structures, Typedefs */
1690 +#define SIGNATURE 0x5f525349 /* "ISR_" (in reverse). */
1692 +/* The IRQ object, passed to our hardware and virtual interrupt routines: */
1693 +struct ISR_IRQ {
1694 + u32 dwSignature; /* Used for object validation. */
1695 + void *pRefData; /* Argument for client's ISR. */
1696 + ISR_PROC pfnISR; /* Client's ISR. */
1698 + u32 dwIntrID; /* hardware intertupt identifier */
1701 +/* ----------------------------------- Globals & Defines */
1702 +#if GT_TRACE
1703 +static struct GT_Mask ISR_DebugMask = { NULL, NULL }; /* ISR Debug Mask */
1704 +#endif
1706 +/* ----------------------------------- Function Prototypes */
1707 +static irqreturn_t HardwareIST(int irq, void *hIRQ);
1710 + * ======== ISR_Exit ========
1711 + * Purpose:
1712 + * Discontinue usage of the ISR module.
1713 + */
1714 +void ISR_Exit(void)
1716 + GT_0trace(ISR_DebugMask, GT_ENTER, "Entered ISR_Exit\n");
1720 + * ======== ISR_Init ========
1721 + * Purpose:
1722 + * Initialize the ISR module's private state.
1723 + */
1724 +bool ISR_Init(void)
1726 + GT_create(&ISR_DebugMask, "IS");
1728 + GT_0trace(ISR_DebugMask, GT_5CLASS, "Entered ISR_Init\n");
1730 + return true;
1734 + * ======== ISR_Install ========
1735 + * Purpose:
1736 + * Register an ISR for a given IRQ with the system's interrupt manager.
1737 + */
1738 +DSP_STATUS ISR_Install(OUT struct ISR_IRQ **phIRQ,
1739 + IN CONST struct CFG_HOSTRES *pHostConfig,
1740 + ISR_PROC pfnISR, u32 dwIntrType, void *pRefData)
1742 + DSP_STATUS status = DSP_SOK;
1743 + struct ISR_IRQ *pIRQObject = NULL;
1745 + DBC_Require(pHostConfig);
1746 + DBC_Require(pRefData != NULL);
1748 + GT_5trace(ISR_DebugMask, GT_ENTER,
1749 + "Entered ISR_Install, args:" "\n\thIRQ:"
1750 + "0x%x\n\tpHostConfig: 0x%x\n\tpfnISR: 0x%x\n" "\tpRefData:"
1751 + "0x%x\n \tdwIntrType 0x%x\n", phIRQ, pHostConfig, pfnISR,
1752 + pRefData, dwIntrType);
1754 + if (phIRQ != NULL) {
1755 + *phIRQ = NULL;
1756 + /*
1757 + * Allocate an IRQ object to store information allowing our
1758 + * interrupt handler to dispatch to the client's interrupt
1759 + * routines.
1760 + */
1761 + MEM_AllocObject(pIRQObject, struct ISR_IRQ, SIGNATURE);
1762 + if (pIRQObject != NULL) {
1763 + /* Fill out the Object: */
1764 + pIRQObject->pRefData = pRefData;
1765 + pIRQObject->pfnISR = pfnISR;
1767 + /* Install different HW interrupts based on interrupt
1768 + * type. */
1769 + switch (dwIntrType) {
1770 + case ISR_MAILBOX1:
1771 + pIRQObject->dwIntrID = INT_MAIL_MPU_IRQ;
1773 + GT_0trace(ISR_DebugMask, GT_1CLASS,
1774 + "Setting intr id for "
1775 + "ISR_MAILBOX1\n");
1776 + break;
1778 + case ISR_MAILBOX2:
1779 + pIRQObject->dwIntrID = MAIL_U3_MPU_IRQ;
1780 + GT_0trace(ISR_DebugMask, GT_1CLASS,
1781 + "Setting intr id for "
1782 + "ISR_MAILBOX2\n");
1784 + break;
1786 + case DSP_MMUFAULT:
1787 + pIRQObject->dwIntrID = INT_DSP_MMU_IRQ;
1788 + GT_0trace(ISR_DebugMask, GT_1CLASS,
1789 + "Setting intr id for "
1790 + "DSP_MMUFAULT\n");
1791 + break;
1793 + default:
1794 + pIRQObject->dwIntrID = (u32) 0x00;
1795 + GT_0trace(ISR_DebugMask, GT_1CLASS,
1796 + "Setting intr id to NULL\n");
1797 + break;
1800 + if (pIRQObject->dwIntrID != 0) {
1801 + status = request_irq(pIRQObject->dwIntrID,
1802 + HardwareIST, 0,
1803 + "DspBridge", pIRQObject);
1804 + } else {
1805 + status = DSP_EINVALIDARG;
1808 + if (DSP_SUCCEEDED(status)) {
1809 + *phIRQ = pIRQObject;
1810 + GT_1trace(ISR_DebugMask, GT_1CLASS,
1811 + "ISR:IRQ Object 0x%x \n",
1812 + pIRQObject);
1813 + } else {
1814 + MEM_FreeObject(pIRQObject);
1817 + DBC_Ensure(DSP_SUCCEEDED(status) || (!phIRQ || *phIRQ == NULL));
1818 + return status;
1822 + * ======== ISR_Uninstall ========
1823 + * Purpose:
1824 + * Deregister the ISR previously installed by ISR_Install().
1825 + * if it fails we do not delete the IRQ object.
1826 + */
1827 +DSP_STATUS ISR_Uninstall(struct ISR_IRQ *hIRQ)
1829 + DSP_STATUS status = DSP_SOK;
1830 + struct ISR_IRQ *pIRQObject = (struct ISR_IRQ *)hIRQ;
1832 + DBC_Require(hIRQ > 0);
1834 + GT_1trace(ISR_DebugMask, GT_ENTER,
1835 + "Entered ISR_Uninstall, hIRQ: 0x%x\n", hIRQ);
1837 + if (MEM_IsValidHandle(hIRQ, SIGNATURE)) {
1838 + /* Linux function to uninstall ISR */
1839 + free_irq(pIRQObject->dwIntrID, pIRQObject);
1840 + pIRQObject->dwIntrID = (u32) -1;
1841 + } else {
1842 + status = DSP_EHANDLE;
1845 + /* Free our IRQ object: */
1846 + if (DSP_SUCCEEDED(status)) {
1847 + MEM_FreeObject(pIRQObject);
1848 + pIRQObject = NULL;
1851 + DBC_Ensure((DSP_SUCCEEDED(status) && pIRQObject == NULL) ||
1852 + DSP_FAILED(status));
1854 + return status;
1858 + * ======== HardwareIST ========
1859 + * Purpose:
1860 + * Linux calls this IRQ handler on interrupt.
1861 + */
1862 +static irqreturn_t HardwareIST(int irq, void *hIRQ)
1864 + struct ISR_IRQ *pIRQObject = (struct ISR_IRQ *)hIRQ;
1866 + DBC_Require(irq == pIRQObject->dwIntrID);
1868 + /* Call the function registered in ISR_Install */
1869 + (*(pIRQObject->pfnISR)) (pIRQObject->pRefData);
1871 + return IRQ_HANDLED;
1873 diff --git a/drivers/dsp/bridge/services/kfile.c b/drivers/dsp/bridge/services/kfile.c
1874 new file mode 100644
1875 index 0000000..d5c02e3
1876 --- /dev/null
1877 +++ b/drivers/dsp/bridge/services/kfile.c
1878 @@ -0,0 +1,336 @@
1880 + * linux/drivers/dsp/bridge/services/kfile.c
1882 + * DSP-BIOS Bridge driver support functions for TI OMAP processors.
1884 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
1886 + * This package is free software; you can redistribute it and/or modify
1887 + * it under the terms of the GNU General Public License version 2 as
1888 + * published by the Free Software Foundation.
1890 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1891 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1892 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1893 + */
1897 + * ======== kfilece.c ========
1898 + * Purpose:
1899 + * This module provides file i/o services.
1901 + * Public Functions:
1902 + * KFILE_Close
1903 + * KFILE_Exit
1904 + * KFILE_Init
1905 + * KFILE_Open
1906 + * KFILE_Read
1907 + * KFILE_Seek
1908 + * KFILE_Tell
1910 + *! Revision History
1911 + *! ================
1912 + *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
1913 + *! GT Changes.
1914 + *! 22-Nov-1999 kc: Added changes from code review.
1915 + *! 12-Nov-1999 kc: Enabled CSL for UNICODE/ANSI string conversions.
1916 + *! 30-Sep-1999 ag: Changed KFILE_Read() GT level from _ENTER to _4CLASS.
1917 + *! Removed GT_set().
1918 + *! 25-Aug-1999 ag: Changed MEM_Calloc allocation type to MEM_PAGED.
1919 + *! 13-Jul-1999 a0216266(ww - TID): Stubbed from kfilent.c.
1920 + */
1922 +/* ----------------------------------- Host OS */
1923 +#include <host_os.h>
1925 +/* ----------------------------------- DSP/BIOS Bridge */
1926 +#include <std.h>
1927 +#include <dbdefs.h>
1928 +#include <errbase.h>
1930 +/* ----------------------------------- Trace & Debug */
1931 +#include <dbc.h>
1932 +#include <gt.h>
1934 +/* ----------------------------------- OS Adaptation Layer */
1935 +#include <csl.h>
1936 +#include <mem.h>
1937 +#include <prcs.h>
1939 +/* ----------------------------------- This */
1940 +#include <kfile.h>
1942 +/* ----------------------------------- Defines, Data Structures, Typedefs */
1943 +#define SIGNATURE 0x4c49464b /* hex code of KFIL (reversed) */
1944 +#define MAXFILENAMELENGTH 256
1945 +#define GENERAL_FAILURE 0xffffffff /* SetFilePointer error */
1947 +/* The KFILE_FileObj abstracts the true file handle from a KFILE handle. */
1948 +struct KFILE_FileObj {
1949 + u32 dwSignature;
1950 + __kernel_pid_t owner_pid; /* PID of process that opened this file */
1951 + char *fileName ;
1952 + bool isOpen ;
1953 + u32 size ;
1954 + u32 curPos ;
1955 + long hInternal; /* internal handle of file */
1956 + struct file *fileDesc;
1960 +/* ----------------------------------- Globals */
1961 +#if GT_TRACE
1962 +static struct GT_Mask KFILE_debugMask = { NULL, NULL }; /* Debug mask */
1963 +#endif
1966 + * ======== KFILE_Close ========
1967 + * Purpose:
1968 + * This function closes a file's stream.
1969 + */
1970 +s32 KFILE_Close(struct KFILE_FileObj *hFile)
1972 + s32 cRetVal = 0; /* 0 indicates success */
1973 + s32 fRetVal = 0;
1974 + __kernel_pid_t curr_pid;
1976 + GT_1trace(KFILE_debugMask, GT_ENTER, "KFILE_Close: hFile 0x%x\n",
1977 + hFile);
1979 + /* Check for valid handle */
1980 + if (MEM_IsValidHandle(hFile, SIGNATURE)) {
1981 + /* Close file only if opened by the same process (id). Otherwise
1982 + * Linux closes all open file handles when process exits.*/
1983 + PRCS_GetCurrentHandle((void **)&curr_pid);
1985 + fRetVal = filp_close(hFile->fileDesc, NULL) ;
1986 + if (fRetVal) {
1987 + cRetVal = E_KFILE_ERROR;
1988 + GT_1trace(KFILE_debugMask, GT_6CLASS,
1989 + "KFILE_Close: sys_close "
1990 + "returned %d\n", fRetVal);
1992 + MEM_FreeObject(hFile);
1993 + } else {
1994 + cRetVal = E_KFILE_INVALIDHANDLE;
1995 + GT_0trace(KFILE_debugMask, GT_6CLASS, "KFILE_Close: "
1996 + "invalid file handle\n");
1998 + return cRetVal;
2002 + * ======== KFILE_Exit ========
2003 + * Purpose:
2004 + * Decrement reference count, and free resources when reference count
2005 + * is 0.
2006 + */
2007 +void KFILE_Exit(void)
2009 + GT_0trace(KFILE_debugMask, GT_5CLASS, "KFILE_Exit\n");
2013 + * ======== KFILE_Init ========
2014 + */
2015 +bool KFILE_Init(void)
2017 + GT_create(&KFILE_debugMask, "KF"); /* "KF" for KFile */
2019 + GT_0trace(KFILE_debugMask, GT_5CLASS, "KFILE_Init\n");
2021 + return true;
2025 + * ======== KFILE_Open ========
2026 + * Purpose:
2027 + * Open a file for reading ONLY
2028 + */
2029 +struct KFILE_FileObj *KFILE_Open(CONST char *pszFileName, CONST char *pszMode)
2031 + struct KFILE_FileObj *hFile; /* file handle */
2032 + DSP_STATUS status;
2033 + mm_segment_t fs;
2035 + struct file*fileDesc = NULL;
2036 + DBC_Require(pszMode != NULL);
2037 + DBC_Require(pszFileName != NULL);
2039 + GT_2trace(KFILE_debugMask, GT_ENTER,
2040 + "KFILE_Open: pszFileName %s, pszMode "
2041 + "%s\n", pszFileName, pszMode);
2043 + /* create a KFILE object */
2044 + MEM_AllocObject(hFile, struct KFILE_FileObj, SIGNATURE);
2046 + if (hFile) {
2047 + fs = get_fs();
2048 + set_fs(get_ds());
2049 + /* Third argument is mode (permissions). Ignored unless creating file */
2050 + fileDesc = filp_open(pszFileName, O_RDONLY, 0);
2051 + if ((IS_ERR(fileDesc)) || (fileDesc == NULL) ||
2052 + (fileDesc->f_op == NULL) || (fileDesc->f_op->read == NULL)
2053 + || (fileDesc->f_op->llseek == NULL)) {
2054 + status = DSP_EFILE;
2055 + } else {
2056 + hFile->fileDesc = fileDesc;
2057 + hFile->fileName = (char *)pszFileName;
2058 + hFile->isOpen = true;
2059 + hFile->curPos = 0;
2060 + hFile->size = fileDesc->f_op->llseek(fileDesc, 0,
2061 + SEEK_END);
2062 + fileDesc->f_op->llseek(fileDesc, 0, SEEK_SET);
2063 + PRCS_GetCurrentHandle((void **) &hFile->owner_pid);
2064 + status = DSP_SOK;
2066 + set_fs(fs);
2067 + if (DSP_FAILED(status)) {
2068 + /* free memory, and clear handle */
2069 + MEM_FreeObject(hFile);
2070 + hFile = NULL;
2072 + } else {
2073 + GT_0trace(KFILE_debugMask, GT_6CLASS,
2074 + "KFILE_Open: MEM_AllocObject failed\n");
2075 + status = DSP_EMEMORY;
2077 + return hFile;
2081 + * ======== KFILE_Read ========
2082 + * Purpose:
2083 + * Reads a specified number of bytes into a buffer.
2084 + */
2085 +s32
2086 +KFILE_Read(void *pBuffer, s32 cSize, s32 cCount, struct KFILE_FileObj *hFile)
2088 + u32 dwBytesRead = 0;
2089 + s32 cRetVal = 0;
2090 + mm_segment_t fs;
2092 + DBC_Require(pBuffer != NULL);
2094 + GT_4trace(KFILE_debugMask, GT_4CLASS,
2095 + "KFILE_Read: buffer 0x%x, cSize 0x%x,"
2096 + "cCount 0x%x, hFile 0x%x\n", pBuffer, cSize, cCount, hFile);
2098 + /* check for valid file handle */
2099 + if (MEM_IsValidHandle(hFile, SIGNATURE)) {
2100 + if ((cSize > 0) && (cCount > 0) && pBuffer) {
2101 + /* read from file */
2102 + fs = get_fs();
2103 + set_fs(get_ds());
2104 + dwBytesRead = hFile->fileDesc->f_op->read(hFile->
2105 + fileDesc, pBuffer, cSize *cCount,
2106 + &(hFile->fileDesc->f_pos));
2107 + set_fs(fs);
2108 + if (dwBytesRead) {
2109 + cRetVal = dwBytesRead / cSize;
2110 + hFile->curPos += dwBytesRead;
2111 + DBC_Assert((dwBytesRead / cSize) <= \
2112 + (u32)cCount);
2113 + } else {
2114 + cRetVal = E_KFILE_ERROR;
2115 + GT_0trace(KFILE_debugMask, GT_6CLASS,
2116 + "KFILE_Read: sys_read() failed\n");
2118 + } else {
2119 + cRetVal = DSP_EINVALIDARG;
2120 + GT_0trace(KFILE_debugMask, GT_6CLASS,
2121 + "KFILE_Read: Invalid argument(s)\n");
2123 + } else {
2124 + cRetVal = E_KFILE_INVALIDHANDLE;
2125 + GT_0trace(KFILE_debugMask, GT_6CLASS,
2126 + "KFILE_Read: invalid file handle\n");
2129 + return cRetVal;
2133 + * ======== KFILE_Seek ========
2134 + * Purpose:
2135 + * Sets the file position indicator. NOTE: we don't support seeking
2136 + * beyond the boundaries of a file.
2137 + */
2138 +s32 KFILE_Seek(struct KFILE_FileObj *hFile, s32 lOffset, s32 cOrigin)
2140 + s32 cRetVal = 0; /* 0 for success */
2141 + u32 dwCurPos = 0;
2143 + struct file *fileDesc = NULL;
2145 + GT_3trace(KFILE_debugMask, GT_ENTER, "KFILE_Seek: hFile 0x%x, "
2146 + "lOffset 0x%x, cOrigin 0x%x\n",
2147 + hFile, lOffset, cOrigin);
2149 + /* check for valid file handle */
2150 + if (MEM_IsValidHandle(hFile, SIGNATURE)) {
2151 + /* based on the origin flag, move the internal pointer */
2153 + fileDesc = hFile->fileDesc;
2154 + switch (cOrigin) {
2155 + case KFILE_SEEK_SET:
2156 + dwCurPos = hFile->fileDesc->f_op->llseek(hFile->
2157 + fileDesc, lOffset, SEEK_SET);
2158 + cRetVal = ((dwCurPos >= 0) ? 0 : E_KFILE_ERROR);
2159 + break;
2161 + case KFILE_SEEK_CUR:
2162 + dwCurPos = hFile->fileDesc->f_op->llseek(hFile->
2163 + fileDesc, lOffset, SEEK_CUR);
2164 + cRetVal = ((dwCurPos >= 0) ? 0 : E_KFILE_ERROR);
2165 + break;
2166 + case KFILE_SEEK_END:
2167 + dwCurPos = hFile->fileDesc->f_op->llseek(hFile->
2168 + fileDesc, lOffset, SEEK_END);
2169 + cRetVal = ((dwCurPos >= 0) ? 0 : E_KFILE_ERROR);
2170 + break;
2171 + default:
2172 + cRetVal = E_KFILE_BADORIGINFLAG;
2173 + GT_0trace(KFILE_debugMask, GT_6CLASS,
2174 + "KFILE_Seek:bad origin flag\n");
2175 + break;
2177 + } else {
2178 + cRetVal = E_KFILE_INVALIDHANDLE;
2179 + GT_0trace(KFILE_debugMask, GT_6CLASS,
2180 + "KFILE_Seek:invalid file handle\n");
2182 + return cRetVal;
2186 + * ======== KFILE_Tell ========
2187 + * Purpose:
2188 + * Reports the current value of the position indicator. We did not
2189 + * consider 64 bit long file size, which implies a 4GB file limit
2190 + * (2 to 32 power).
2191 + */
2192 +s32 KFILE_Tell(struct KFILE_FileObj *hFile)
2194 + u32 dwCurPos = 0;
2195 + s32 lRetVal = E_KFILE_ERROR;
2197 + GT_1trace(KFILE_debugMask, GT_ENTER, "KFILE_Tell: hFile 0x%x\n", hFile);
2199 + if (MEM_IsValidHandle(hFile, SIGNATURE)) {
2201 + /* Get current position. */
2202 + dwCurPos = hFile->fileDesc->f_op->llseek(hFile->fileDesc, 0,
2203 + SEEK_CUR);
2204 + if (dwCurPos >= 0)
2205 + lRetVal = dwCurPos;
2207 + } else {
2208 + lRetVal = E_KFILE_INVALIDHANDLE;
2209 + GT_0trace(KFILE_debugMask, GT_6CLASS,
2210 + "KFILE_Seek:invalid file handle\n");
2212 + return lRetVal;
2215 diff --git a/drivers/dsp/bridge/services/list.c b/drivers/dsp/bridge/services/list.c
2216 new file mode 100644
2217 index 0000000..3d4c752
2218 --- /dev/null
2219 +++ b/drivers/dsp/bridge/services/list.c
2220 @@ -0,0 +1,285 @@
2222 + * linux/drivers/dsp/bridge/services/list.c
2224 + * DSP-BIOS Bridge driver support functions for TI OMAP processors.
2226 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
2228 + * This package is free software; you can redistribute it and/or modify
2229 + * it under the terms of the GNU General Public License version 2 as
2230 + * published by the Free Software Foundation.
2232 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
2233 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
2234 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2235 + */
2239 + * ======== listce.c ========
2240 + * Purpose
2241 + * Provides standard circular list handling functions.
2243 + * Public Functions:
2244 + * LST_Create
2245 + * LST_Delete
2246 + * LST_Exit
2247 + * LST_First
2248 + * LST_GetHead
2249 + * LST_Init
2250 + * LST_InitElem
2251 + * LST_InsertBefore
2252 + * LST_Next
2253 + * LST_PutTail
2254 + * LST_RemoveElem
2256 + *! Revision History
2257 + *! ================
2258 + *! 06-Mar-2002 jeh Don't set element self to NULL in LST_RemoveElem().
2259 + *! 10-Aug-2000 ag: Added LST_InsertBefore().
2260 + *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
2261 + *! GT Changes.
2262 + *! 22-Nov-1999 kc: Added changes from code review.
2263 + *! 10-Aug-1999 kc: Based on wsx-c18.
2264 + *! 16-Jun-1997 gp: Removed unnecessary enabling/disabling of interrupts around
2265 + *! list manipulation code.
2266 + *! 22-Oct-1996 gp: Added LST_RemoveElem, and LST_First/LST_Next iterators.
2267 + *! 10-Aug-1996 gp: Acquired from SMM for WinSPOX v. 1.1; renamed identifiers.
2268 + */
2270 +/* ----------------------------------- DSP/BIOS Bridge */
2271 +#include <std.h>
2272 +#include <dbdefs.h>
2274 +/* ----------------------------------- Trace & Debug */
2275 +#include <dbc.h>
2276 +#include <gt.h>
2278 +/* ----------------------------------- OS Adaptation Layer */
2279 +#include <mem.h>
2281 +/* ----------------------------------- This */
2282 +#include <list.h>
2284 +/* ----------------------------------- Globals */
2285 +#if GT_TRACE
2286 +static struct GT_Mask LST_debugMask = { NULL, NULL }; /* GT trace var. */
2287 +#endif
2290 + * ======== LST_Create ========
2291 + * Purpose:
2292 + * Allocates and initializes a circular list.
2293 + */
2294 +struct LST_LIST *LST_Create(void)
2296 + struct LST_LIST *pList;
2298 + GT_0trace(LST_debugMask, GT_ENTER, "LST_Create: entered\n");
2300 + pList = (struct LST_LIST *) MEM_Calloc(sizeof(struct LST_LIST),
2301 + MEM_NONPAGED);
2302 + if (pList != NULL) {
2303 + pList->head.next = &pList->head;
2304 + pList->head.prev = &pList->head;
2305 + pList->head.self = NULL;
2308 + return pList;
2312 + * ======== LST_Delete ========
2313 + * Purpose:
2314 + * Removes a list by freeing its control structure's memory space.
2315 + */
2316 +void LST_Delete(struct LST_LIST *pList)
2318 + DBC_Require(pList != NULL);
2320 + GT_1trace(LST_debugMask, GT_ENTER, "LST_Delete: pList 0x%x\n", pList);
2322 + MEM_Free(pList);
2326 + * ======== LST_Exit ========
2327 + * Purpose:
2328 + * Discontinue usage of the LST module.
2329 + */
2330 +void LST_Exit(void)
2332 + GT_0trace(LST_debugMask, GT_5CLASS, "LST_Exit\n");
2336 + * ======== LST_First ========
2337 + * Purpose:
2338 + * Returns a pointer to the first element of the list, or NULL if the
2339 + * list is empty.
2340 + */
2341 +struct LST_ELEM *LST_First(struct LST_LIST *pList)
2343 + struct LST_ELEM *pElem = NULL;
2345 + DBC_Require(pList != NULL);
2347 + GT_1trace(LST_debugMask, GT_ENTER, "LST_First: pList 0x%x\n", pList);
2349 + if (!LST_IsEmpty(pList))
2350 + pElem = pList->head.next;
2352 + return pElem;
2356 + * ======== LST_GetHead ========
2357 + * Purpose:
2358 + * "Pops" the head off the list and returns a pointer to it.
2359 + */
2360 +struct LST_ELEM *LST_GetHead(struct LST_LIST *pList)
2362 + struct LST_ELEM *pElem;
2364 + DBC_Require(pList != NULL);
2366 + GT_1trace(LST_debugMask, GT_ENTER, "LST_GetHead: pList 0x%x\n", pList);
2368 + if (LST_IsEmpty(pList))
2369 + return NULL;
2371 + /* pElem is always valid because the list cannot be empty
2372 + * at this point */
2373 + pElem = pList->head.next;
2374 + pList->head.next = pElem->next;
2375 + pElem->next->prev = &pList->head;
2377 + return pElem->self;
2381 + * ======== LST_Init ========
2382 + * Purpose:
2383 + * Initialize LST module private state.
2384 + */
2385 +bool LST_Init(void)
2387 + GT_create(&LST_debugMask, "LS"); /* LS for LSt module */
2389 + GT_0trace(LST_debugMask, GT_5CLASS, "LST_Init\n");
2391 + return true;
2395 + * ======== LST_InitElem ========
2396 + * Purpose:
2397 + * Initializes a list element to default (cleared) values
2398 + */
2399 +void LST_InitElem(struct LST_ELEM *pElem)
2401 + DBC_Require(pElem != NULL);
2403 + GT_1trace(LST_debugMask, GT_ENTER, "LST_InitElem: pElem 0x%x\n", pElem);
2405 + if (pElem) {
2406 + pElem->next = NULL;
2407 + pElem->prev = NULL;
2408 + pElem->self = pElem;
2413 + * ======== LST_InsertBefore ========
2414 + * Purpose:
2415 + * Insert the element before the existing element.
2416 + */
2417 +void LST_InsertBefore(struct LST_LIST *pList, struct LST_ELEM *pElem,
2418 + struct LST_ELEM *pElemExisting)
2420 + DBC_Require(pList != NULL);
2421 + DBC_Require(pElem != NULL);
2422 + DBC_Require(pElemExisting != NULL);
2424 + GT_3trace(LST_debugMask, GT_ENTER, "LST_InsertBefore: pList 0x%x, "
2425 + "pElem 0x%x pElemExisting 0x%x\n", pList, pElem,
2426 + pElemExisting);
2428 + pElemExisting->prev->next = pElem;
2429 + pElem->prev = pElemExisting->prev;
2430 + pElem->next = pElemExisting;
2431 + pElemExisting->prev = pElem;
2435 + * ======== LST_Next ========
2436 + * Purpose:
2437 + * Returns a pointer to the next element of the list, or NULL if the
2438 + * next element is the head of the list or the list is empty.
2439 + */
2440 +struct LST_ELEM *LST_Next(struct LST_LIST *pList, struct LST_ELEM *pCurElem)
2442 + struct LST_ELEM *pNextElem = NULL;
2444 + DBC_Require(pList != NULL);
2445 + DBC_Require(pCurElem != NULL);
2447 + GT_2trace(LST_debugMask, GT_ENTER,
2448 + "LST_Next: pList 0x%x, pCurElem 0x%x\n",
2449 + pList, pCurElem);
2451 + if (!LST_IsEmpty(pList)) {
2452 + if (pCurElem->next != &pList->head)
2453 + pNextElem = pCurElem->next;
2456 + return pNextElem;
2460 + * ======== LST_PutTail ========
2461 + * Purpose:
2462 + * Adds the specified element to the tail of the list
2463 + */
2464 +void LST_PutTail(struct LST_LIST *pList, struct LST_ELEM *pElem)
2466 + DBC_Require(pList != NULL);
2467 + DBC_Require(pElem != NULL);
2469 + GT_2trace(LST_debugMask, GT_ENTER,
2470 + "LST_PutTail: pList 0x%x, pElem 0x%x\n",
2471 + pList, pElem);
2473 + pElem->prev = pList->head.prev;
2474 + pElem->next = &pList->head;
2475 + pList->head.prev = pElem;
2476 + pElem->prev->next = pElem;
2478 + DBC_Ensure(!LST_IsEmpty(pList));
2482 + * ======== LST_RemoveElem ========
2483 + * Purpose:
2484 + * Removes (unlinks) the given element from the list, if the list is not
2485 + * empty. Does not free the list element.
2486 + */
2487 +void LST_RemoveElem(struct LST_LIST *pList, struct LST_ELEM *pCurElem)
2489 + DBC_Require(pList != NULL);
2490 + DBC_Require(pCurElem != NULL);
2492 + GT_2trace(LST_debugMask, GT_ENTER,
2493 + "LST_RemoveElem: pList 0x%x, pCurElem "
2494 + "0x%x\n", pList, pCurElem);
2496 + if (!LST_IsEmpty(pList)) {
2497 + pCurElem->prev->next = pCurElem->next;
2498 + pCurElem->next->prev = pCurElem->prev;
2500 + /* set elem fields to NULL to prevent illegal references */
2501 + pCurElem->next = NULL;
2502 + pCurElem->prev = NULL;
2506 diff --git a/drivers/dsp/bridge/services/mem.c b/drivers/dsp/bridge/services/mem.c
2507 new file mode 100644
2508 index 0000000..186684e
2509 --- /dev/null
2510 +++ b/drivers/dsp/bridge/services/mem.c
2511 @@ -0,0 +1,594 @@
2513 + * linux/drivers/dsp/bridge/services/mem.c
2515 + * DSP-BIOS Bridge driver support functions for TI OMAP processors.
2517 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
2519 + * This package is free software; you can redistribute it and/or modify
2520 + * it under the terms of the GNU General Public License version 2 as
2521 + * published by the Free Software Foundation.
2523 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
2524 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
2525 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2526 + */
2530 + * ======== mem.c ========
2531 + * Purpose:
2532 + * Implementation of platform specific memory services.
2534 + * Public Functions:
2535 + * MEM_Alloc
2536 + * MEM_AllocPhysMem
2537 + * MEM_Calloc
2538 + * MEM_Exit
2539 + * MEM_FlushCache
2540 + * MEM_Free
2541 + * MEM_FreePhysMem
2542 + * MEM_Init
2543 + * MEM_ExtPhysPoolInit
2545 + *! Revision History:
2546 + *! =================
2547 + *! 18-Jan-2004 hp: Added support for External physical memory pool
2548 + *! 19-Apr-2004 sb: Added Alloc/Free PhysMem, FlushCache, VirtualToPhysical
2549 + *! 01-Sep-2001 ag: Code cleanup.
2550 + *! 02-May-2001 ag: MEM_[UnMap]LinearAddress revamped to align Phys to Virt.
2551 + *! Set PAGE_PHYSICAL if phy addr <= 512MB. Opposite uSoft doc!
2552 + *! 29-Aug-2000 rr: MEM_LinearAddress does not check for 512MB for non-x86.
2553 + *! 28-Mar-2000 rr: MEM_LinearAddress changed.Handles address larger than 512MB
2554 + *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
2555 + *! GT Changes.
2556 + *! 22-Nov-1999 kc: Added changes from code review.
2557 + *! 16-Aug-1999 kc: modified for WinCE.
2558 + *! 20-Mar-1999 ag: SP 4 fix in MEM_UMBCalloc().
2559 + *! Mdl offset now ORed not added to userBuf.
2560 + *! 23-Dec-1997 cr: Code review changes.
2561 + *! 08-Dec-1997 cr: Prepared for code review.
2562 + *! 24-Jun-1997 cr: Created.
2563 + */
2565 +/* ----------------------------------- Host OS */
2566 +#include <host_os.h>
2568 +/* ----------------------------------- DSP/BIOS Bridge */
2569 +#include <std.h>
2570 +#include <dbdefs.h>
2571 +#include <errbase.h>
2573 +/* ----------------------------------- Trace & Debug */
2574 +#include <dbc.h>
2575 +#include <gt.h>
2577 +/* ----------------------------------- This */
2578 +#include <mem.h>
2579 +#include <list.h>
2581 +/* ----------------------------------- Defines */
2582 +#define MEM_512MB 0x1fffffff
2583 +#define memInfoSign 0x464E494D /* "MINF" (in reverse). */
2585 +#ifdef DEBUG
2586 +#define MEM_CHECK /* Use to detect source of memory leaks */
2587 +#endif
2589 +/* ----------------------------------- Globals */
2590 +#if GT_TRACE
2591 +static struct GT_Mask MEM_debugMask = { NULL, NULL }; /* GT trace variable */
2592 +#endif
2594 +static u32 cRefs; /* module reference count */
2596 +static bool extPhysMemPoolEnabled = false;
2598 +struct extPhysMemPool {
2599 + u32 physMemBase;
2600 + u32 physMemSize;
2601 + u32 virtMemBase;
2602 + u32 nextPhysAllocPtr;
2605 +static struct extPhysMemPool extMemPool;
2607 +/* Information about each element allocated on heap */
2608 +struct memInfo {
2609 + struct LST_ELEM link; /* Must be first */
2610 + size_t size;
2611 + void *caller;
2612 + u32 dwSignature; /* Should be last */
2615 +#ifdef MEM_CHECK
2618 + * This structure holds a linked list to all memory elements allocated on
2619 + * heap by DSP/BIOS Bridge. This is used to report memory leaks and free
2620 + * such elements while removing the DSP/BIOS Bridge driver
2621 + */
2622 +struct memMan {
2623 + struct LST_LIST lst;
2624 + spinlock_t lock;
2627 +static struct memMan mMan;
2630 + * These functions are similar to LST_PutTail and LST_RemoveElem and are
2631 + * duplicated here to make MEM independent of LST
2632 + */
2633 +static inline void MLST_PutTail(struct LST_LIST *pList, struct LST_ELEM *pElem)
2635 + pElem->prev = pList->head.prev;
2636 + pElem->next = &pList->head;
2637 + pList->head.prev = pElem;
2638 + pElem->prev->next = pElem;
2639 + pElem->self = pElem;
2642 +static inline void MLST_RemoveElem(struct LST_LIST *pList,
2643 + struct LST_ELEM *pCurElem)
2645 + pCurElem->prev->next = pCurElem->next;
2646 + pCurElem->next->prev = pCurElem->prev;
2647 + pCurElem->next = NULL;
2648 + pCurElem->prev = NULL;
2651 +void MEM_Check(void)
2653 + struct memInfo *pMem;
2654 + struct LST_ELEM *last = &mMan.lst.head;
2655 + struct LST_ELEM *curr = mMan.lst.head.next;
2657 + if (!LST_IsEmpty(&mMan.lst)) {
2658 + GT_0trace(MEM_debugMask, GT_7CLASS, "*** MEMORY LEAK ***\n");
2659 + GT_0trace(MEM_debugMask, GT_7CLASS,
2660 + "Addr Size Caller\n");
2661 + while (curr != last) {
2662 + pMem = (struct memInfo *)curr;
2663 + curr = curr->next;
2664 + if ((u32)pMem > PAGE_OFFSET &&
2665 + MEM_IsValidHandle(pMem, memInfoSign)) {
2666 + GT_3trace(MEM_debugMask, GT_7CLASS,
2667 + "%lx %d\t [<%p>]\n",
2668 + (u32) pMem + sizeof(struct memInfo),
2669 + pMem->size, pMem->caller);
2670 + MLST_RemoveElem(&mMan.lst,
2671 + (struct LST_ELEM *) pMem);
2672 + kfree(pMem);
2673 + } else {
2674 + GT_1trace(MEM_debugMask, GT_7CLASS,
2675 + "Invalid allocation or "
2676 + "Buffer underflow at %x\n",
2677 + (u32)pMem + sizeof(struct memInfo));
2678 + break;
2682 + DBC_Ensure(LST_IsEmpty(&mMan.lst));
2685 +#endif
2687 +void MEM_ExtPhysPoolInit(u32 poolPhysBase, u32 poolSize)
2689 + u32 poolVirtBase;
2691 + /* get the virtual address for the physical memory pool passed */
2692 + poolVirtBase = (u32)ioremap(poolPhysBase, poolSize);
2694 + if ((void **)poolVirtBase == NULL) {
2695 + GT_0trace(MEM_debugMask, GT_7CLASS,
2696 + "[PHYS_POOL]Mapping External "
2697 + "physical memory to virt failed \n");
2698 + extPhysMemPoolEnabled = false;
2699 + } else {
2700 + extMemPool.physMemBase = poolPhysBase;
2701 + extMemPool.physMemSize = poolSize;
2702 + extMemPool.virtMemBase = poolVirtBase;
2703 + extMemPool.nextPhysAllocPtr = poolPhysBase;
2704 + extPhysMemPoolEnabled = true;
2705 + GT_3trace(MEM_debugMask, GT_1CLASS,
2706 + "ExtMemory Pool details " "Pool"
2707 + "Physical mem base = %0x " "Pool Physical mem size "
2708 + "= %0x" "Pool Virtual mem base = %0x \n",
2709 + poolPhysBase, poolSize, poolVirtBase);
2713 +void MEM_ExtPhysPoolRelease(void)
2715 + GT_0trace(MEM_debugMask, GT_1CLASS,
2716 + "Releasing External memory pool \n");
2717 + if (extPhysMemPoolEnabled) {
2718 + iounmap((void *)(extMemPool.virtMemBase));
2719 + extPhysMemPoolEnabled = false;
2724 + * ======== MEM_ExtPhysMemAlloc ========
2725 + * Purpose:
2726 + * Allocate physically contiguous, uncached memory from external memory pool
2727 + */
2729 +void *MEM_ExtPhysMemAlloc(u32 bytes, u32 align, OUT u32 *pPhysAddr)
2731 + u32 newAllocPtr;
2732 + u32 offset;
2733 + u32 virtAddr;
2735 + GT_2trace(MEM_debugMask, GT_1CLASS,
2736 + "Ext Memory Allocation" "bytes=0x%x , "
2737 + "align=0x%x \n", bytes, align);
2738 + if (align == 0) {
2739 + GT_0trace(MEM_debugMask, GT_7CLASS,
2740 + "ExtPhysical Memory Allocation "
2741 + "No alignment request in allocation call !! \n");
2742 + align = 1;
2744 + if (bytes > ((extMemPool.physMemBase + extMemPool.physMemSize)
2745 + - extMemPool.nextPhysAllocPtr)) {
2746 + GT_1trace(MEM_debugMask, GT_7CLASS,
2747 + "ExtPhysical Memory Allocation "
2748 + "unable to allocate memory for bytes = 0x%x \n",
2749 + bytes);
2750 + pPhysAddr = 0;
2751 + return NULL;
2752 + } else {
2753 + offset = (extMemPool.nextPhysAllocPtr & (align - 1));
2754 + if (offset == 0)
2755 + newAllocPtr = extMemPool.nextPhysAllocPtr;
2756 + else
2757 + newAllocPtr = (extMemPool.nextPhysAllocPtr) +
2758 + (align - offset);
2759 + if ((newAllocPtr + bytes) <=
2760 + (extMemPool.physMemBase + extMemPool.physMemSize)) {
2761 + /* we can allocate */
2762 + *pPhysAddr = newAllocPtr;
2763 + extMemPool.nextPhysAllocPtr = newAllocPtr + bytes;
2764 + virtAddr = extMemPool.virtMemBase + (newAllocPtr -
2765 + extMemPool.physMemBase);
2766 + GT_2trace(MEM_debugMask, GT_1CLASS,
2767 + "Ext Memory Allocation succedded "
2768 + "phys address=0x%x , virtaddress=0x%x \n",
2769 + newAllocPtr, virtAddr);
2770 + return (void *)virtAddr;
2771 + } else {
2772 + *pPhysAddr = 0;
2773 + return NULL;
2779 + * ======== MEM_Alloc ========
2780 + * Purpose:
2781 + * Allocate memory from the paged or non-paged pools.
2782 + */
2783 +void *MEM_Alloc(u32 cBytes, enum MEM_POOLATTRS type)
2785 + struct memInfo *pMem = NULL;
2787 + GT_2trace(MEM_debugMask, GT_ENTER,
2788 + "MEM_Alloc: cBytes 0x%x\ttype 0x%x\n", cBytes, type);
2789 + if (cBytes > 0) {
2790 + switch (type) {
2791 + case MEM_NONPAGED:
2792 + /* If non-paged memory required, see note at top of file. */
2793 + case MEM_PAGED:
2794 +#ifndef MEM_CHECK
2795 + pMem = kmalloc(cBytes, GFP_ATOMIC);
2796 +#else
2797 + pMem = kmalloc(cBytes + sizeof(struct memInfo),
2798 + GFP_ATOMIC);
2799 + if (pMem) {
2800 + pMem->size = cBytes;
2801 + pMem->caller = __builtin_return_address(0);
2802 + pMem->dwSignature = memInfoSign;
2804 + spin_lock(&mMan.lock);
2805 + MLST_PutTail(&mMan.lst,
2806 + (struct LST_ELEM *)pMem);
2807 + spin_unlock(&mMan.lock);
2809 + pMem = (void *)((u32)pMem +
2810 + sizeof(struct memInfo));
2812 +#endif
2813 + break;
2814 + case MEM_LARGEVIRTMEM:
2815 +#ifndef MEM_CHECK
2816 + /* FIXME - Replace with 'vmalloc' after BP fix */
2817 + pMem = __vmalloc(cBytes, GFP_ATOMIC, PAGE_KERNEL);
2818 +#else
2819 + /* FIXME - Replace with 'vmalloc' after BP fix */
2820 + pMem = __vmalloc((cBytes + sizeof(struct memInfo)),
2821 + GFP_ATOMIC, PAGE_KERNEL);
2822 + if (pMem) {
2823 + pMem->size = cBytes;
2824 + pMem->caller = __builtin_return_address(0);
2825 + pMem->dwSignature = memInfoSign;
2827 + spin_lock(&mMan.lock);
2828 + MLST_PutTail(&mMan.lst,
2829 + (struct LST_ELEM *) pMem);
2830 + spin_unlock(&mMan.lock);
2832 + pMem = (void *)((u32)pMem +
2833 + sizeof(struct memInfo));
2835 +#endif
2836 + break;
2838 + default:
2839 + GT_0trace(MEM_debugMask, GT_6CLASS,
2840 + "MEM_Alloc: unexpected "
2841 + "MEM_POOLATTRS value\n");
2842 + break;
2846 + return pMem;
2850 + * ======== MEM_AllocPhysMem ========
2851 + * Purpose:
2852 + * Allocate physically contiguous, uncached memory
2853 + */
2854 +void *MEM_AllocPhysMem(u32 cBytes, u32 ulAlign, OUT u32 *pPhysicalAddress)
2856 + void *pVaMem = NULL;
2857 + dma_addr_t paMem;
2859 + DBC_Require(cRefs > 0);
2861 + GT_2trace(MEM_debugMask, GT_ENTER,
2862 + "MEM_AllocPhysMem: cBytes 0x%x\tulAlign"
2863 + "0x%x\n", cBytes, ulAlign);
2865 + if (cBytes > 0) {
2866 + if (extPhysMemPoolEnabled) {
2867 + pVaMem = MEM_ExtPhysMemAlloc(cBytes, ulAlign,
2868 + (u32 *)&paMem);
2869 + } else
2870 + pVaMem = dma_alloc_coherent(NULL, cBytes, &paMem,
2871 + GFP_ATOMIC);
2872 + if (pVaMem == NULL) {
2873 + *pPhysicalAddress = 0;
2874 + GT_1trace(MEM_debugMask, GT_6CLASS,
2875 + "MEM_AllocPhysMem failed: "
2876 + "0x%x\n", pVaMem);
2877 + } else {
2878 + *pPhysicalAddress = paMem;
2881 + return pVaMem;
2885 + * ======== MEM_Calloc ========
2886 + * Purpose:
2887 + * Allocate zero-initialized memory from the paged or non-paged pools.
2888 + */
2889 +void *MEM_Calloc(u32 cBytes, enum MEM_POOLATTRS type)
2891 + struct memInfo *pMem = NULL;
2893 + GT_2trace(MEM_debugMask, GT_ENTER,
2894 + "MEM_Calloc: cBytes 0x%x\ttype 0x%x\n",
2895 + cBytes, type);
2897 + if (cBytes > 0) {
2898 + switch (type) {
2899 + case MEM_NONPAGED:
2900 + /* If non-paged memory required, see note at top of file. */
2901 + case MEM_PAGED:
2902 +#ifndef MEM_CHECK
2903 + pMem = kmalloc(cBytes, GFP_ATOMIC);
2904 + if (pMem)
2905 + memset(pMem, 0, cBytes);
2907 +#else
2908 + pMem = kmalloc(cBytes + sizeof(struct memInfo),
2909 + GFP_ATOMIC);
2910 + if (pMem) {
2911 + memset((void *)((u32)pMem +
2912 + sizeof(struct memInfo)), 0, cBytes);
2913 + pMem->size = cBytes;
2914 + pMem->caller = __builtin_return_address(0);
2915 + pMem->dwSignature = memInfoSign;
2916 + spin_lock(&mMan.lock);
2917 + MLST_PutTail(&mMan.lst,
2918 + (struct LST_ELEM *) pMem);
2919 + spin_unlock(&mMan.lock);
2920 + pMem = (void *)((u32)pMem +
2921 + sizeof(struct memInfo));
2923 +#endif
2924 + break;
2925 + case MEM_LARGEVIRTMEM:
2926 +#ifndef MEM_CHECK
2927 + /* FIXME - Replace with 'vmalloc' after BP fix */
2928 + pMem = __vmalloc(cBytes, GFP_ATOMIC, PAGE_KERNEL);
2929 + if (pMem)
2930 + memset(pMem, 0, cBytes);
2932 +#else
2933 + /* FIXME - Replace with 'vmalloc' after BP fix */
2934 + pMem = __vmalloc(cBytes + sizeof(struct memInfo),
2935 + GFP_ATOMIC, PAGE_KERNEL);
2936 + if (pMem) {
2937 + memset((void *)((u32)pMem +
2938 + sizeof(struct memInfo)), 0, cBytes);
2939 + pMem->size = cBytes;
2940 + pMem->caller = __builtin_return_address(0);
2941 + pMem->dwSignature = memInfoSign;
2942 + spin_lock(&mMan.lock);
2943 + MLST_PutTail(&mMan.lst, (struct LST_ELEM *)
2944 + pMem);
2945 + spin_unlock(&mMan.lock);
2946 + pMem = (void *)((u32)pMem +
2947 + sizeof(struct memInfo));
2949 +#endif
2950 + break;
2951 + default:
2952 + GT_1trace(MEM_debugMask, GT_6CLASS,
2953 + "MEM_Calloc: unexpected "
2954 + "MEM_POOLATTRS value 0x%x\n", type);
2955 + break;
2959 + return pMem;
2963 + * ======== MEM_Exit ========
2964 + * Purpose:
2965 + * Discontinue usage of the MEM module.
2966 + */
2967 +void MEM_Exit(void)
2969 + DBC_Require(cRefs > 0);
2971 + GT_1trace(MEM_debugMask, GT_5CLASS, "MEM_Exit: cRefs 0x%x\n", cRefs);
2973 + cRefs--;
2974 +#ifdef MEM_CHECK
2975 + if (cRefs == 0)
2976 + MEM_Check();
2978 +#endif
2979 + MEM_ExtPhysPoolRelease();
2980 + DBC_Ensure(cRefs >= 0);
2984 + * ======== MEM_FlushCache ========
2985 + * Purpose:
2986 + * Flush cache
2987 + */
2988 +void MEM_FlushCache(void *pMemBuf, u32 cBytes, s32 FlushType)
2990 + DBC_Require(cRefs > 0);
2992 + switch (FlushType) {
2993 + /* invalidate only */
2994 + case PROC_INVALIDATE_MEM:
2995 + dmac_inv_range(pMemBuf, pMemBuf + cBytes - 1);
2996 + outer_inv_range(__pa((u32)pMemBuf), __pa((u32)pMemBuf +
2997 + cBytes - 1));
2998 + break;
2999 + /* writeback only */
3000 + case PROC_WRITEBACK_MEM:
3001 + dmac_clean_range(pMemBuf, pMemBuf + cBytes - 1);
3002 + outer_clean_range(__pa((u32)pMemBuf), __pa((u32)pMemBuf +
3003 + cBytes - 1));
3004 + break;
3005 + /* writeback and invalidate */
3006 + case PROC_WRITEBACK_INVALIDATE_MEM:
3007 + dmac_flush_range(pMemBuf, pMemBuf + cBytes - 1);
3008 + outer_flush_range(__pa((u32)pMemBuf), __pa((u32)pMemBuf +
3009 + cBytes - 1));
3010 + break;
3011 + default:
3012 + GT_1trace(MEM_debugMask, GT_6CLASS, "MEM_FlushCache: invalid "
3013 + "FlushMemType 0x%x\n", FlushType);
3014 + break;
3021 + * ======== MEM_Free ========
3022 + * Purpose:
3023 + * Free the given block of system memory.
3024 + */
3025 +void MEM_Free(IN void *pMemBuf)
3027 +#ifdef MEM_CHECK
3028 + struct memInfo *pMem = (void *)((u32)pMemBuf - sizeof(struct memInfo));
3029 +#endif
3031 + DBC_Require(pMemBuf != NULL);
3033 + GT_1trace(MEM_debugMask, GT_ENTER, "MEM_Free: pMemBufs 0x%x\n",
3034 + pMemBuf);
3036 + if (pMemBuf) {
3037 +#ifndef MEM_CHECK
3038 + kfree(pMemBuf);
3039 +#else
3040 + if (pMem) {
3041 + if (pMem->dwSignature == memInfoSign) {
3042 + spin_lock(&mMan.lock);
3043 + MLST_RemoveElem(&mMan.lst,
3044 + (struct LST_ELEM *) pMem);
3045 + spin_unlock(&mMan.lock);
3046 + pMem->dwSignature = 0;
3047 + kfree(pMem);
3048 + } else {
3049 + GT_1trace(MEM_debugMask, GT_7CLASS,
3050 + "Invalid allocation or "
3051 + "Buffer underflow at %x\n",
3052 + (u32) pMem + sizeof(struct memInfo));
3055 +#endif
3060 + * ======== MEM_FreePhysMem ========
3061 + * Purpose:
3062 + * Free the given block of physically contiguous memory.
3063 + */
3064 +void MEM_FreePhysMem(void *pVirtualAddress, u32 pPhysicalAddress,
3065 + u32 cBytes)
3067 + DBC_Require(cRefs > 0);
3068 + DBC_Require(pVirtualAddress != NULL);
3070 + GT_1trace(MEM_debugMask, GT_ENTER, "MEM_FreePhysMem: pVirtualAddress "
3071 + "0x%x\n", pVirtualAddress);
3073 + if (!extPhysMemPoolEnabled)
3074 + dma_free_coherent(NULL, cBytes, pVirtualAddress,
3075 + pPhysicalAddress);
3079 + * ======== MEM_Init ========
3080 + * Purpose:
3081 + * Initialize MEM module private state.
3082 + */
3083 +bool MEM_Init(void)
3085 + DBC_Require(cRefs >= 0);
3087 + if (cRefs == 0) {
3088 + GT_create(&MEM_debugMask, "MM"); /* MM for MeM module */
3090 +#ifdef MEM_CHECK
3091 + mMan.lst.head.next = &mMan.lst.head;
3092 + mMan.lst.head.prev = &mMan.lst.head;
3093 + mMan.lst.head.self = NULL;
3094 +#endif
3098 + cRefs++;
3100 + GT_1trace(MEM_debugMask, GT_5CLASS, "MEM_Init: cRefs 0x%x\n", cRefs);
3102 + DBC_Ensure(cRefs > 0);
3104 + return true;
3106 diff --git a/drivers/dsp/bridge/services/ntfy.c b/drivers/dsp/bridge/services/ntfy.c
3107 new file mode 100644
3108 index 0000000..72bb1e4
3109 --- /dev/null
3110 +++ b/drivers/dsp/bridge/services/ntfy.c
3111 @@ -0,0 +1,329 @@
3113 + * linux/drivers/dsp/bridge/services/ntfy.c
3115 + * DSP-BIOS Bridge driver support functions for TI OMAP processors.
3117 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
3119 + * This package is free software; you can redistribute it and/or modify
3120 + * it under the terms of the GNU General Public License version 2 as
3121 + * published by the Free Software Foundation.
3123 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
3124 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
3125 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
3126 + */
3130 + * ======== ntfyce.c ========
3131 + * Purpose:
3132 + * Manage lists of notification events.
3134 + * Public Functions:
3135 + * NTFY_Create
3136 + * NTFY_Delete
3137 + * NTFY_Exit
3138 + * NTFY_Init
3139 + * NTFY_Notify
3140 + * NTFY_Register
3142 + *! Revision History:
3143 + *! =================
3144 + *! 06-Feb-2003 kc Removed DSP_POSTMESSAGE related code.
3145 + *! 05-Nov-2001 kc Updated DSP_HNOTIFICATION structure.
3146 + *! 10-May-2001 jeh Removed SERVICES module init/exit from NTFY_Init/Exit.
3147 + *! NTFY_Register() returns DSP_ENOTIMPL for all but
3148 + *! DSP_SIGNALEVENT.
3149 + *! 12-Oct-2000 jeh Use MEM_IsValidHandle().
3150 + *! 07-Sep-2000 jeh Created.
3151 + */
3153 +/* ----------------------------------- Host OS */
3154 +#include <host_os.h>
3156 +/* ----------------------------------- DSP/BIOS Bridge */
3157 +#include <std.h>
3158 +#include <dbdefs.h>
3159 +#include <errbase.h>
3161 +/* ----------------------------------- Trace & Debug */
3162 +#include <dbc.h>
3163 +#include <gt.h>
3165 +/* ----------------------------------- OS Adaptation Layer */
3166 +#include <csl.h>
3167 +#include <list.h>
3168 +#include <mem.h>
3169 +#include <sync.h>
3171 +/* ----------------------------------- This */
3172 +#include <ntfy.h>
3174 +/* ----------------------------------- Defines, Data Structures, Typedefs */
3175 +#define NTFY_SIGNATURE 0x5946544e /* "YFTN" */
3178 + * ======== NTFY_OBJECT ========
3179 + */
3180 +struct NTFY_OBJECT {
3181 + u32 dwSignature; /* For object validation */
3182 + struct LST_LIST *notifyList; /* List of NOTIFICATION objects */
3183 + struct SYNC_CSOBJECT *hSync; /* For critical sections */
3187 + * ======== NOTIFICATION ========
3188 + * This object will be created when a client registers for events.
3189 + */
3190 +struct NOTIFICATION {
3191 + struct LST_ELEM listElem;
3192 + u32 uEventMask; /* Events to be notified about */
3193 + u32 uNotifyType; /* Type of notification to be sent */
3195 + /*
3196 + * We keep a copy of the event name to check if the event has
3197 + * already been registered. (SYNC also keeps a copy of the name).
3198 + */
3199 + char *pstrName; /* Name of event */
3200 + HANDLE hEvent; /* Handle for notification */
3201 + struct SYNC_OBJECT *hSync;
3204 +/* ----------------------------------- Globals */
3205 +#if GT_TRACE
3206 +static struct GT_Mask NTFY_debugMask = { NULL, NULL }; /* GT trace variable */
3207 +#endif
3209 +/* ----------------------------------- Function Prototypes */
3210 +static void DeleteNotify(struct NOTIFICATION *pNotify);
3213 + * ======== NTFY_Create ========
3214 + * Purpose:
3215 + * Create an empty list of notifications.
3216 + */
3217 +DSP_STATUS NTFY_Create(struct NTFY_OBJECT **phNtfy)
3219 + struct NTFY_OBJECT *pNtfy;
3220 + DSP_STATUS status = DSP_SOK;
3222 + DBC_Require(phNtfy != NULL);
3224 + *phNtfy = NULL;
3225 + MEM_AllocObject(pNtfy, struct NTFY_OBJECT, NTFY_SIGNATURE);
3227 + if (pNtfy) {
3229 + status = SYNC_InitializeDPCCS(&pNtfy->hSync);
3230 + if (DSP_SUCCEEDED(status)) {
3231 + pNtfy->notifyList = LST_Create();
3232 + if (pNtfy->notifyList == NULL) {
3233 + (void) SYNC_DeleteCS(pNtfy->hSync);
3234 + MEM_FreeObject(pNtfy);
3235 + status = DSP_EMEMORY;
3236 + } else {
3237 + *phNtfy = pNtfy;
3240 + } else {
3241 + status = DSP_EMEMORY;
3244 + DBC_Ensure((DSP_FAILED(status) && *phNtfy == NULL) ||
3245 + (DSP_SUCCEEDED(status) && MEM_IsValidHandle((*phNtfy),
3246 + NTFY_SIGNATURE)));
3248 + return status;
3252 + * ======== NTFY_Delete ========
3253 + * Purpose:
3254 + * Free resources allocated in NTFY_Create.
3255 + */
3256 +void NTFY_Delete(struct NTFY_OBJECT *hNtfy)
3258 + struct NOTIFICATION *pNotify;
3260 + DBC_Require(MEM_IsValidHandle(hNtfy, NTFY_SIGNATURE));
3262 + /* Remove any elements remaining in list */
3263 + if (hNtfy->notifyList) {
3264 + while ((pNotify = (struct NOTIFICATION *)LST_GetHead(hNtfy->
3265 + notifyList))) {
3266 + DeleteNotify(pNotify);
3268 + DBC_Assert(LST_IsEmpty(hNtfy->notifyList));
3269 + LST_Delete(hNtfy->notifyList);
3271 + if (hNtfy->hSync)
3272 + (void)SYNC_DeleteCS(hNtfy->hSync);
3274 + MEM_FreeObject(hNtfy);
3278 + * ======== NTFY_Exit ========
3279 + * Purpose:
3280 + * Discontinue usage of NTFY module.
3281 + */
3282 +void NTFY_Exit(void)
3284 + GT_0trace(NTFY_debugMask, GT_5CLASS, "Entered NTFY_Exit\n");
3288 + * ======== NTFY_Init ========
3289 + * Purpose:
3290 + * Initialize the NTFY module.
3291 + */
3292 +bool NTFY_Init(void)
3294 + GT_create(&NTFY_debugMask, "NY"); /* "NY" for NtfY */
3296 + GT_0trace(NTFY_debugMask, GT_5CLASS, "NTFY_Init()\n");
3298 + return true;
3302 + * ======== NTFY_Notify ========
3303 + * Purpose:
3304 + * Execute notify function (signal event) for every
3305 + * element in the notification list that is to be notified about the
3306 + * event specified in uEventMask.
3307 + */
3308 +void NTFY_Notify(struct NTFY_OBJECT *hNtfy, u32 uEventMask)
3310 + struct NOTIFICATION *pNotify;
3312 + DBC_Require(MEM_IsValidHandle(hNtfy, NTFY_SIGNATURE));
3314 + /*
3315 + * Go through notifyList and notify all clients registered for
3316 + * uEventMask events.
3317 + */
3319 + (void) SYNC_EnterCS(hNtfy->hSync);
3321 + pNotify = (struct NOTIFICATION *)LST_First(hNtfy->notifyList);
3322 + while (pNotify != NULL) {
3323 + if (pNotify->uEventMask & uEventMask) {
3324 + /* Notify */
3325 + if (pNotify->uNotifyType == DSP_SIGNALEVENT)
3326 + (void)SYNC_SetEvent(pNotify->hSync);
3329 + pNotify = (struct NOTIFICATION *)LST_Next(hNtfy->notifyList,
3330 + (struct LST_ELEM *)pNotify);
3333 + (void) SYNC_LeaveCS(hNtfy->hSync);
3337 + * ======== NTFY_Register ========
3338 + * Purpose:
3339 + * Add a notification element to the list. If the notification is already
3340 + * registered, and uEventMask != 0, the notification will get posted for
3341 + * events specified in the new event mask. If the notification is already
3342 + * registered and uEventMask == 0, the notification will be unregistered.
3343 + */
3344 +DSP_STATUS NTFY_Register(struct NTFY_OBJECT *hNtfy,
3345 + struct DSP_NOTIFICATION *hNotification,
3346 + u32 uEventMask, u32 uNotifyType)
3348 + struct NOTIFICATION *pNotify;
3349 + struct SYNC_ATTRS syncAttrs;
3350 + DSP_STATUS status = DSP_SOK;
3352 + DBC_Require(MEM_IsValidHandle(hNtfy, NTFY_SIGNATURE));
3354 + if (hNotification == NULL)
3355 + status = DSP_EHANDLE;
3357 + /* Return DSP_ENOTIMPL if uNotifyType is not supported */
3358 + if (DSP_SUCCEEDED(status)) {
3359 + if (!IsValidNotifyMask(uNotifyType))
3360 + status = DSP_ENOTIMPL;
3364 + if (DSP_FAILED(status))
3365 + return status;
3367 + (void)SYNC_EnterCS(hNtfy->hSync);
3369 + pNotify = (struct NOTIFICATION *)LST_First(hNtfy->notifyList);
3370 + while (pNotify != NULL) {
3371 + /* If there is more than one notification type, each
3372 + * type may require its own handler code. */
3374 + if (hNotification->handle == pNotify->hSync) {
3375 + /* found */
3376 + break;
3378 + pNotify = (struct NOTIFICATION *)LST_Next(hNtfy->notifyList,
3379 + (struct LST_ELEM *)pNotify);
3381 + if (pNotify == NULL) {
3382 + /* Not registered */
3383 + if (uEventMask == 0) {
3384 + status = DSP_EVALUE;
3385 + } else {
3386 + /* Allocate NOTIFICATION object, add to list */
3387 + pNotify = MEM_Calloc(sizeof(struct NOTIFICATION),
3388 + MEM_PAGED);
3389 + if (pNotify == NULL)
3390 + status = DSP_EMEMORY;
3393 + if (DSP_SUCCEEDED(status)) {
3394 + LST_InitElem((struct LST_ELEM *) pNotify);
3395 + /* If there is more than one notification type, each
3396 + * type may require its own handler code. */
3397 + status = SYNC_OpenEvent(&pNotify->hSync, &syncAttrs);
3398 + hNotification->handle = pNotify->hSync;
3400 + if (DSP_SUCCEEDED(status)) {
3401 + pNotify->uEventMask = uEventMask;
3402 + pNotify->uNotifyType = uNotifyType;
3403 + LST_PutTail(hNtfy->notifyList,
3404 + (struct LST_ELEM *)pNotify);
3405 + } else {
3406 + DeleteNotify(pNotify);
3409 + } else {
3410 + /* Found in list */
3411 + if (uEventMask == 0) {
3412 + /* Remove from list and free */
3413 + LST_RemoveElem(hNtfy->notifyList,
3414 + (struct LST_ELEM *)pNotify);
3415 + DeleteNotify(pNotify);
3416 + } else {
3417 + /* Update notification mask (type shouldn't change) */
3418 + pNotify->uEventMask = uEventMask;
3421 + (void)SYNC_LeaveCS(hNtfy->hSync);
3422 + return status;
3426 + * ======== DeleteNotify ========
3427 + * Purpose:
3428 + * Free the notification object.
3429 + */
3430 +static void DeleteNotify(struct NOTIFICATION *pNotify)
3432 + if (pNotify->hSync)
3433 + (void) SYNC_CloseEvent(pNotify->hSync);
3435 + if (pNotify->pstrName)
3436 + MEM_Free(pNotify->pstrName);
3438 + MEM_Free(pNotify);
3441 diff --git a/drivers/dsp/bridge/services/prcs.c b/drivers/dsp/bridge/services/prcs.c
3442 new file mode 100644
3443 index 0000000..cb45541
3444 --- /dev/null
3445 +++ b/drivers/dsp/bridge/services/prcs.c
3446 @@ -0,0 +1,119 @@
3448 + * linux/drivers/dsp/bridge/services/prcs.c
3450 + * DSP-BIOS Bridge driver support functions for TI OMAP processors.
3452 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
3454 + * This package is free software; you can redistribute it and/or modify
3455 + * it under the terms of the GNU General Public License version 2 as
3456 + * published by the Free Software Foundation.
3458 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
3459 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
3460 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
3461 + */
3465 + * ======== procce.c ========
3466 + * Purpose:
3467 + * Provide information about processes and threads.
3469 + * Public Functions:
3470 + * PRCS_Exit
3471 + * PRCS_GetCurrentHandle
3472 + * PRCS_Init
3474 + *! Revision History:
3475 + *! ================
3476 + *! 18-Dec-2000 rr: PRCS_GetCurrentProcesshandle's DBC_Ensure class
3477 + *! removed. See the foot node.
3478 + *! 06-Jul-2000 rr: Prefix changed to PRCS to accomodate RM PROC.
3479 + *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
3480 + *! GT Changes.
3481 + *! 22-Nov-1999 kc: Added changes from code review.
3482 + *! 22-Sep-1999 kc: Modified from procnt.c.
3483 + *! 26-Aug-1997 cr: Implemented.
3484 + *! 16-Aug-1997 cr: Stubbed from proc95.c
3485 + */
3487 +/* ----------------------------------- Host OS */
3488 +#include <host_os.h>
3490 +/* ----------------------------------- DSP/BIOS Bridge */
3491 +#include <std.h>
3492 +#include <dbdefs.h>
3493 +#include <errbase.h>
3495 +/* ----------------------------------- Trace & Debug */
3496 +#include <dbc.h>
3497 +#include <gt.h>
3499 +/* ----------------------------------- This */
3500 +#include <prcs.h>
3502 +/* ----------------------------------- Globals & Defines */
3503 +#if GT_TRACE
3504 +static struct GT_Mask PRCS_debugMask = { NULL, NULL }; /* GT trace var. */
3505 +#endif
3508 + * ======== PRCS_Exit ========
3509 + * Purpose:
3510 + * Discontinue usage of the PRCS module.
3511 + */
3512 +void PRCS_Exit(void)
3514 + GT_0trace(PRCS_debugMask, GT_5CLASS, "PRCS_Exit\n");
3518 + * ======== PRCS_GetCurrentHandle ========
3519 + * Purpose:
3520 + * This functions returns the process handle of the
3521 + * caller process.
3522 + */
3523 +DSP_STATUS PRCS_GetCurrentHandle(OUT HANDLE *phProcess)
3525 + DSP_STATUS status;
3527 + DBC_Require(phProcess != NULL);
3529 + GT_1trace(PRCS_debugMask, GT_ENTER,
3530 + "PRCS_GetCurrentHandle: phProcess 0x%x\n",
3531 + phProcess);
3532 + if (phProcess) {
3533 + if (!in_interrupt()) {
3534 + /* Return PID instead of process handle */
3535 + *phProcess = (HANDLE)current->pid;
3536 + status = DSP_SOK;
3537 + } else {
3538 + *phProcess = NULL;
3539 + status = DSP_EFAIL;
3541 + } else {
3542 + *phProcess = NULL;
3543 + status = DSP_EPOINTER;
3544 + GT_0trace(PRCS_debugMask, GT_6CLASS,
3545 + "PRCS_GetCurrentHandle: invalid "
3546 + "handle\n");
3548 + return status;
3552 + * ======== PRCS_Init ========
3553 + * Purpose:
3554 + * Initialize the PRCS module's private state.
3555 + */
3556 +bool PRCS_Init(void)
3559 + GT_create(&PRCS_debugMask, "PS"); /* PS for ProcesS */
3561 + GT_0trace(PRCS_debugMask, GT_5CLASS, "PRCS_Init\n");
3563 + return true;
3566 diff --git a/drivers/dsp/bridge/services/reg.c b/drivers/dsp/bridge/services/reg.c
3567 new file mode 100644
3568 index 0000000..f540944
3569 --- /dev/null
3570 +++ b/drivers/dsp/bridge/services/reg.c
3571 @@ -0,0 +1,196 @@
3573 + * linux/drivers/dsp/bridge/services/reg.c
3575 + * DSP-BIOS Bridge driver support functions for TI OMAP processors.
3577 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
3579 + * This package is free software; you can redistribute it and/or modify
3580 + * it under the terms of the GNU General Public License version 2 as
3581 + * published by the Free Software Foundation.
3583 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
3584 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
3585 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
3586 + */
3590 + * ======== regce.c ========
3591 + * Purpose:
3592 + * Provide registry functions.
3594 + * Public Functions:
3595 + * REG_DeleteValue
3596 + * REG_EnumValue
3597 + * REG_Exit
3598 + * REG_GetValue
3599 + * REG_Init
3600 + * REG_SetValue
3602 + *! Revision History:
3603 + *! ================
3605 + */
3607 +/* ----------------------------------- Host OS */
3608 +#include <host_os.h>
3610 +/* ----------------------------------- DSP/BIOS Bridge */
3611 +#include <std.h>
3612 +#include <dbdefs.h>
3613 +#include <errbase.h>
3615 +/* ----------------------------------- Trace & Debug */
3616 +#include <dbc.h>
3617 +#include <gt.h>
3619 +/* ----------------------------------- OS Adaptation Layer */
3620 +#include <csl.h>
3621 +#include <mem.h>
3623 +/* ----------------------------------- Others */
3624 +#include <dbreg.h>
3626 +/* ----------------------------------- This */
3627 +#include <reg.h>
3628 +#include <regsup.h>
3630 +#if GT_TRACE
3631 +struct GT_Mask REG_debugMask = { NULL, NULL }; /* GT trace var. */
3632 +#endif
3635 + * ======== REG_DeleteValue ========
3636 + * Deletes a registry entry value. NOTE: A registry entry value is not the
3637 + * same as * a registry key.
3638 + */
3639 +DSP_STATUS REG_DeleteValue(OPTIONAL IN HANDLE *phKey, IN CONST char *pstrSubkey,
3640 + IN CONST char *pstrValue)
3642 + DSP_STATUS status;
3643 + DBC_Require(pstrSubkey && pstrValue);
3644 + DBC_Require(phKey == NULL);
3645 + DBC_Require(CSL_Strlen(pstrSubkey) < REG_MAXREGPATHLENGTH);
3646 + DBC_Require(CSL_Strlen(pstrValue) < REG_MAXREGPATHLENGTH);
3648 + GT_0trace(REG_debugMask, GT_ENTER, "REG_DeleteValue: entered\n");
3650 + /* Note that we don't use phKey */
3651 + if (regsupDeleteValue(pstrSubkey, pstrValue) == DSP_SOK)
3652 + status = DSP_SOK;
3653 + else
3654 + status = DSP_EFAIL;
3656 + return status;
3660 + * ======== REG_EnumValue ========
3661 + * Enumerates a registry key and retrieve values stored under the key.
3662 + * We will assume the input pdwValueSize is smaller than
3663 + * REG_MAXREGPATHLENGTH for implementation purposes.
3664 + */
3665 +DSP_STATUS REG_EnumValue(IN HANDLE *phKey, IN u32 dwIndex,
3666 + IN CONST char *pstrKey, IN OUT char *pstrValue,
3667 + IN OUT u32 *pdwValueSize, IN OUT char *pstrData,
3668 + IN OUT u32 *pdwDataSize)
3670 + DSP_STATUS status;
3672 + DBC_Require(pstrKey && pstrValue && pdwValueSize && pstrData &&
3673 + pdwDataSize);
3674 + DBC_Require(*pdwValueSize <= REG_MAXREGPATHLENGTH);
3675 + DBC_Require(phKey == NULL);
3676 + DBC_Require(CSL_Strlen(pstrKey) < REG_MAXREGPATHLENGTH);
3678 + GT_0trace(REG_debugMask, GT_ENTER, "REG_EnumValue: entered\n");
3680 + status = regsupEnumValue(dwIndex, pstrKey, pstrValue, pdwValueSize,
3681 + pstrData, pdwDataSize);
3683 + return status;
3687 + * ======== REG_Exit ========
3688 + * Discontinue usage of the REG module.
3689 + */
3690 +void REG_Exit(void)
3692 + GT_0trace(REG_debugMask, GT_5CLASS, "REG_Exit\n");
3694 + regsupExit();
3698 + * ======== REG_GetValue ========
3699 + * Retrieve a value from the registry.
3700 + */
3701 +DSP_STATUS REG_GetValue(OPTIONAL IN HANDLE *phKey, IN CONST char *pstrSubkey,
3702 + IN CONST char *pstrValue, OUT u8 *pbData,
3703 + IN OUT u32 *pdwDataSize)
3705 + DSP_STATUS status;
3707 + DBC_Require(pstrSubkey && pstrValue && pbData);
3708 + DBC_Require(phKey == NULL);
3709 + DBC_Require(CSL_Strlen(pstrSubkey) < REG_MAXREGPATHLENGTH);
3710 + DBC_Require(CSL_Strlen(pstrValue) < REG_MAXREGPATHLENGTH);
3712 + GT_0trace(REG_debugMask, GT_ENTER, "REG_GetValue: entered\n");
3714 + /* We need to use regsup calls... */
3715 + /* ...for now we don't need the key handle or */
3716 + /* the subkey, all we need is the value to lookup. */
3717 + if (regsupGetValue((char *)pstrValue, pbData, pdwDataSize) == DSP_SOK)
3718 + status = DSP_SOK;
3719 + else
3720 + status = DSP_EFAIL;
3722 + return status;
3726 + * ======== REG_Init ========
3727 + * Initialize the REG module's private state.
3728 + */
3729 +bool REG_Init(void)
3731 + bool fInit;
3733 + GT_create(&REG_debugMask, "RG"); /* RG for ReG */
3735 + fInit = regsupInit();
3737 + GT_0trace(REG_debugMask, GT_5CLASS, "REG_Init\n");
3739 + return fInit;
3743 + * ======== REG_SetValue ========
3744 + * Set a value in the registry.
3745 + */
3746 +DSP_STATUS REG_SetValue(OPTIONAL IN HANDLE *phKey, IN CONST char *pstrSubkey,
3747 + IN CONST char *pstrValue, IN CONST u32 dwType,
3748 + IN u8 *pbData, IN u32 dwDataSize)
3750 + DSP_STATUS status;
3752 + DBC_Require(pstrValue && pbData);
3753 + DBC_Require(phKey == NULL);
3754 + DBC_Require(dwDataSize > 0);
3755 + DBC_Require(CSL_Strlen(pstrValue) < REG_MAXREGPATHLENGTH);
3757 + /* We need to use regsup calls... */
3758 + /* ...for now we don't need the key handle or */
3759 + /* the subkey, all we need is the value to lookup. */
3760 + if (regsupSetValue((char *)pstrValue, pbData, dwDataSize) == DSP_SOK)
3761 + status = DSP_SOK;
3762 + else
3763 + status = DSP_EFAIL;
3765 + return status;
3768 diff --git a/drivers/dsp/bridge/services/regsup.c b/drivers/dsp/bridge/services/regsup.c
3769 new file mode 100644
3770 index 0000000..f1d2c51
3771 --- /dev/null
3772 +++ b/drivers/dsp/bridge/services/regsup.c
3773 @@ -0,0 +1,367 @@
3775 + * linux/drivers/dsp/bridge/services/regsup.c
3777 + * DSP-BIOS Bridge driver support functions for TI OMAP processors.
3779 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
3781 + * This package is free software; you can redistribute it and/or modify
3782 + * it under the terms of the GNU General Public License version 2 as
3783 + * published by the Free Software Foundation.
3785 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
3786 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
3787 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
3788 + */
3792 + * ======== regsup.c ========
3793 + * Purpose:
3794 + * Provide registry support functions.
3796 + *! Revision History:
3797 + *! ================
3798 + *! 28-May-2002 map: Integrated PSI's dspimage update mechanism
3799 + *! 11-May-2002 gp: Turned PERF "on".
3800 + *! 21-May-2002 map: Fixed bug in SetValue - if resizing datasize, set
3801 + *! new size too
3802 + */
3804 +/* ----------------------------------- Host OS */
3805 +#include <host_os.h>
3807 +/* ----------------------------------- DSP/BIOS Bridge */
3808 +#include <std.h>
3809 +#include <dbdefs.h>
3810 +#include <errbase.h>
3811 +#include <dbreg.h>
3813 +/* ----------------------------------- Trace & Debug */
3814 +#include <dbc.h>
3815 +#include <gt.h>
3817 +/* ----------------------------------- OS Adaptation Layer */
3818 +#include <mem.h>
3819 +#include <csl.h>
3821 +/* ----------------------------------- This */
3822 +#include <regsup.h>
3824 +struct RegValueStruct {
3825 + char name[BRIDGE_MAX_NAME_SIZE]; /* Name of a given value entry */
3826 + u32 dataSize; /* Size of the data */
3827 + void *pData; /* Pointer to the actual data */
3830 +struct RegKeyStruct {
3831 + /*The current number of value entries this key has*/
3832 + u32 numValueEntries;
3833 + /* Array of value entries */
3834 + struct RegValueStruct values[BRIDGE_MAX_NUM_REG_ENTRIES];
3838 +/* Pointer to the registry support key */
3839 +static struct RegKeyStruct *pRegKey;
3841 +#if GT_TRACE
3842 +extern struct GT_Mask REG_debugMask; /* GT trace var. */
3844 + * ======== printS ========
3845 + * Purpose:
3846 + * Displays printable characters in pBuf, if any.
3847 + */
3848 +static inline void printS(void *pBuf)
3850 + int pos = 0;
3851 + if (*(REG_debugMask).flags & (GT_2CLASS)) {
3852 + while (*(u8 *)((pBuf)+pos) >= ' ' &&
3853 + *(u8 *)((pBuf)+pos) <= '~') {
3854 + GT_1trace(REG_debugMask, GT_2CLASS, "%c",
3855 + *(u8 *)((pBuf) + pos++));
3858 + GT_0trace(REG_debugMask, GT_2CLASS, "\n");
3861 +#else
3862 +#define printS(pBuf)
3863 +#endif
3866 + * ======== regsupInit ========
3867 + * Purpose:
3868 + * Initialize the Registry Support module's private state.
3869 + */
3870 +bool regsupInit(void)
3872 + if (pRegKey != NULL)
3873 + return true;
3875 + /* Need to allocate and setup our registry. */
3876 + pRegKey = MEM_Calloc(sizeof(struct RegKeyStruct), MEM_NONPAGED);
3877 + if (pRegKey == NULL)
3878 + return false;
3880 + return true;
3884 + * ======== regsupExit ========
3885 + * Purpose:
3886 + * Release all registry support allocations.
3887 + */
3888 +void regsupExit(void)
3890 + u32 i;
3892 + /* Make sure data has actually been allocated. */
3893 + if (pRegKey == NULL) {
3894 + /* Nothing initialized.return! */
3895 + return;
3898 + GT_1trace(REG_debugMask, GT_2CLASS, "pRegKey->numValueEntries %d\n",
3899 + pRegKey->numValueEntries);
3901 + /* Now go through each entry and free all resources. */
3902 + for (i = 0; ((i < BRIDGE_MAX_NUM_REG_ENTRIES) &&
3903 + (i < pRegKey->numValueEntries)); i++) {
3904 + if (pRegKey->values[i].name[0] != '\0') {
3905 + /* We have a valid entry.free it up! */
3906 + if (pRegKey->values[i].pData != NULL) {
3907 + GT_3trace(REG_debugMask, GT_2CLASS,
3908 + "E %d\t %s DATA %x ", i,
3909 + pRegKey->values[i].name,
3910 + *(u32 *)pRegKey->values[i].pData);
3911 + printS((u8 *)(pRegKey->values[i].pData));
3912 + MEM_Free(pRegKey->values[i].pData);
3914 + pRegKey->values[i].pData = NULL;
3915 + pRegKey->values[i].dataSize = 0;
3916 + pRegKey->values[i].name[0] = '\0';
3920 + /* Now that all of the resources are freed up, free the main one! */
3921 + MEM_Free(pRegKey);
3923 + /* Don't forget to NULL out the global entry! */
3924 + pRegKey = NULL;
3928 + * ======== regsupGetValue ========
3929 + * Purpose:
3930 + * Get the value of the entry having the given name.
3931 + */
3932 +DSP_STATUS regsupGetValue(char *valName, void *pBuf, u32 *dataSize)
3934 + DSP_STATUS retVal = DSP_EFAIL;
3935 + u32 i;
3937 + /* Need to search through the entries looking for the right one. */
3938 + for (i = 0; i < pRegKey->numValueEntries; i++) {
3939 + /* See if the name matches. */
3940 + if (CSL_Strncmp(pRegKey->values[i].name, valName,
3941 + BRIDGE_MAX_NAME_SIZE) == 0) {
3943 + /* We have a match! Copy out the data. */
3944 + memcpy(pBuf, pRegKey->values[i].pData,
3945 + pRegKey->values[i].dataSize);
3947 + /* Get the size for the caller. */
3948 + *dataSize = pRegKey->values[i].dataSize;
3950 + /* Set our status to good and exit. */
3951 + retVal = DSP_SOK;
3952 + break;
3956 + if (DSP_SUCCEEDED(retVal)) {
3957 + GT_2trace(REG_debugMask, GT_2CLASS, "G %s DATA %x ", valName,
3958 + *(u32 *)pBuf);
3959 + printS((u8 *)pBuf);
3960 + } else {
3961 + GT_1trace(REG_debugMask, GT_3CLASS, "G %s FAILED\n", valName);
3964 + return retVal;
3968 + * ======== regsupSetValue ========
3969 + * Purpose:
3970 + * Sets the value of the entry having the given name.
3971 + */
3972 +DSP_STATUS regsupSetValue(char *valName, void *pBuf, u32 dataSize)
3974 + DSP_STATUS retVal = DSP_EFAIL;
3975 + u32 i;
3977 + GT_2trace(REG_debugMask, GT_2CLASS, "S %s DATA %x ", valName,
3978 + *(u32 *)pBuf);
3979 + printS((u8 *)pBuf);
3981 + /* Need to search through the entries looking for the right one. */
3982 + for (i = 0; i < pRegKey->numValueEntries; i++) {
3983 + /* See if the name matches. */
3984 + if (CSL_Strncmp(pRegKey->values[i].name, valName,
3985 + BRIDGE_MAX_NAME_SIZE) == 0) {
3986 + /* Make sure the new data size is the same. */
3987 + if (dataSize != pRegKey->values[i].dataSize) {
3988 + /* The caller needs a different data size! */
3989 + MEM_Free(pRegKey->values[i].pData);
3990 + pRegKey->values[i].pData = MEM_Alloc(dataSize,
3991 + MEM_NONPAGED);
3992 + if (pRegKey->values[i].pData == NULL)
3993 + break;
3997 + /* We have a match! Copy out the data. */
3998 + memcpy(pRegKey->values[i].pData, pBuf, dataSize);
4000 + /* Reset datasize - overwrite if new or same */
4001 + pRegKey->values[i].dataSize = dataSize;
4003 + /* Set our status to good and exit. */
4004 + retVal = DSP_SOK;
4005 + break;
4009 + /* See if we found a match or if this is a new entry */
4010 + if (i == pRegKey->numValueEntries) {
4011 + /* No match, need to make a new entry */
4012 + /* First check to see if we can make any more entries. */
4013 + if (pRegKey->numValueEntries < BRIDGE_MAX_NUM_REG_ENTRIES) {
4014 + CSL_Strcpyn(pRegKey->
4015 + values[pRegKey->numValueEntries].name, valName,
4016 + BRIDGE_MAX_NAME_SIZE);
4017 + pRegKey->values[pRegKey->numValueEntries].pData =
4018 + MEM_Alloc(dataSize, MEM_NONPAGED);
4019 + if (pRegKey->values[pRegKey->numValueEntries].pData !=
4020 + NULL) {
4021 + memcpy(pRegKey->
4022 + values[pRegKey->numValueEntries].pData,
4023 + pBuf, dataSize);
4024 + pRegKey->
4025 + values[pRegKey->numValueEntries].dataSize =
4026 + dataSize;
4027 + pRegKey->numValueEntries++;
4028 + retVal = DSP_SOK;
4030 + } else {
4031 + GT_0trace(REG_debugMask, GT_7CLASS,
4032 + "MAX NUM REG ENTRIES REACHED\n");
4036 + return retVal;
4040 + * ======== regsupEnumValue ========
4041 + * Purpose:
4042 + * Returns registry "values" and their "data" under a (sub)key.
4043 + */
4044 +DSP_STATUS regsupEnumValue(IN u32 dwIndex, IN CONST char *pstrKey,
4045 + IN OUT char *pstrValue, IN OUT u32 *pdwValueSize,
4046 + IN OUT char *pstrData, IN OUT u32 *pdwDataSize)
4048 + DSP_STATUS retVal = REG_E_INVALIDSUBKEY;
4049 + u32 i;
4050 + u32 dwKeyLen = CSL_Strlen(pstrKey);
4051 + u32 count = 0;
4053 + /* Need to search through the entries looking for the right one. */
4054 + for (i = 0; i < pRegKey->numValueEntries; i++) {
4055 + /* See if the name matches. */
4056 + if ((CSL_Strncmp(pRegKey->values[i].name, pstrKey,
4057 + dwKeyLen) == 0) && count++ == dwIndex) {
4058 + /* We have a match! Copy out the data. */
4059 + memcpy(pstrData, pRegKey->values[i].pData,
4060 + pRegKey->values[i].dataSize);
4061 + /* Get the size for the caller. */
4062 + *pdwDataSize = pRegKey->values[i].dataSize;
4063 + *pdwValueSize = CSL_Strlen(&(pRegKey->
4064 + values[i].name[dwKeyLen]));
4065 + CSL_Strcpyn(pstrValue,
4066 + &(pRegKey->values[i].name[dwKeyLen]),
4067 + *pdwValueSize + 1);
4068 + GT_3trace(REG_debugMask, GT_2CLASS,
4069 + "E Key %s, Value %s, Data %x ",
4070 + pstrKey, pstrValue, *(u32 *)pstrData);
4071 + printS((u8 *)pstrData);
4072 + /* Set our status to good and exit. */
4073 + retVal = DSP_SOK;
4074 + break;
4078 + if (count && DSP_FAILED(retVal))
4079 + retVal = REG_E_NOMOREITEMS;
4081 + return retVal;
4085 + * ======== regsupDeleteValue ========
4086 + */
4087 +DSP_STATUS regsupDeleteValue(IN CONST char *pstrSubkey,
4088 + IN CONST char *pstrValue)
4090 + DSP_STATUS retVal = DSP_EFAIL;
4091 + u32 i;
4093 + for (i = 0; ((i < BRIDGE_MAX_NUM_REG_ENTRIES) &&
4094 + (i < pRegKey->numValueEntries)); i++) {
4095 + /* See if the name matches... */
4096 + if (CSL_Strncmp(pRegKey->values[i].name, pstrValue,
4097 + BRIDGE_MAX_NAME_SIZE) == 0) {
4098 + /* We have a match! Delete this key. To delete a
4099 + * key, we free all resources associated with this
4100 + * key and, if we're not already the last entry in
4101 + * the array, we copy that entry into this deleted
4102 + * key.
4103 + */
4104 + MEM_Free(pRegKey->values[i].pData);
4105 + if ((pRegKey->numValueEntries - 1) == i) {
4106 + /* we're deleting the last one */
4107 + pRegKey->values[i].name[0] = '\0';
4108 + pRegKey->values[i].dataSize = 0;
4109 + pRegKey->values[i].pData = NULL;
4110 + } else {
4111 + /* move the last one here */
4112 + CSL_Strcpyn(pRegKey->values[i].name,
4113 + pRegKey->
4114 + values[pRegKey->numValueEntries - 1].name,
4115 + BRIDGE_MAX_NAME_SIZE);
4116 + pRegKey->values[i].dataSize =
4117 + pRegKey->
4118 + values[pRegKey->numValueEntries-1].dataSize;
4119 + pRegKey->values[i].pData =
4120 + pRegKey->
4121 + values[pRegKey->numValueEntries-1].pData;
4122 + /* don't have to do this, but for
4123 + * the paranoid... */
4124 + pRegKey->
4125 + values[pRegKey->numValueEntries-1].name[0] =
4126 + '\0';
4129 + /* another one bites the dust. */
4130 + pRegKey->numValueEntries--;
4132 + /* Set our status to good and exit... */
4133 + retVal = DSP_SOK;
4134 + break;
4137 + return retVal;
4141 diff --git a/drivers/dsp/bridge/services/regsup.h b/drivers/dsp/bridge/services/regsup.h
4142 new file mode 100644
4143 index 0000000..8893854
4144 --- /dev/null
4145 +++ b/drivers/dsp/bridge/services/regsup.h
4146 @@ -0,0 +1,58 @@
4148 + * linux/drivers/dsp/bridge/services/regsup.h
4150 + * DSP-BIOS Bridge driver support functions for TI OMAP processors.
4152 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
4154 + * This package is free software; you can redistribute it and/or modify
4155 + * it under the terms of the GNU General Public License version 2 as
4156 + * published by the Free Software Foundation.
4158 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
4159 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
4160 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
4161 + */
4165 + * ======== regsup.h ========
4167 + *! Revision History
4168 + *! ================
4169 + */
4171 +#ifndef _REGSUP_H_
4172 +#define _REGSUP_H_
4174 +#define BRIDGE_MAX_NAME_SIZE MAXREGPATHLENGTH
4175 +#define BRIDGE_MAX_NUM_REG_ENTRIES 52
4177 +/* Init function. MUST be called BEFORE any calls are */
4178 +/* made into this psuedo-registry!!! Returns TRUE/FALSE for SUCCESS/ERROR */
4179 +extern bool regsupInit(void);
4181 +/* Release all registry support allocations. */
4182 +extern void regsupExit(void);
4185 + * ======== regsupDeleteValue ========
4186 + */
4187 +extern DSP_STATUS regsupDeleteValue(IN CONST char *pstrSubkey,
4188 + IN CONST char *pstrValue);
4189 +/* Get the value of the entry having the given name. Returns DSP_SOK */
4190 +/* if an entry was found and the value retrieved. Returns DSP_EFAIL
4191 + * otherwise.*/
4192 +extern DSP_STATUS regsupGetValue(char *valName, void *pBuf, u32 *dataSize);
4194 +/* Sets the value of the entry having the given name. Returns DSP_SOK */
4195 +/* if an entry was found and the value set. Returns DSP_EFAIL otherwise. */
4196 +extern DSP_STATUS regsupSetValue(char *valName, void *pBuf, u32 dataSize);
4198 +/* Returns registry "values" and their "data" under a (sub)key. */
4199 +extern DSP_STATUS regsupEnumValue(IN u32 dwIndex, IN CONST char *pstrKey,
4200 + IN OUT char *pstrValue, IN OUT u32 *pdwValueSize,
4201 + IN OUT char *pstrData, IN OUT u32 *pdwDataSize);
4203 +#endif
4205 diff --git a/drivers/dsp/bridge/services/services.c b/drivers/dsp/bridge/services/services.c
4206 new file mode 100644
4207 index 0000000..5e92d3e
4208 --- /dev/null
4209 +++ b/drivers/dsp/bridge/services/services.c
4210 @@ -0,0 +1,205 @@
4212 + * linux/drivers/dsp/bridge/services/services.c
4214 + * DSP-BIOS Bridge driver support functions for TI OMAP processors.
4216 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
4218 + * This package is free software; you can redistribute it and/or modify
4219 + * it under the terms of the GNU General Public License version 2 as
4220 + * published by the Free Software Foundation.
4222 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
4223 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
4224 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
4225 + */
4229 + * ======== services.c ========
4230 + * Purpose:
4231 + * Provide SERVICES loading.
4233 + * Public Functions:
4234 + * SERVICES_Exit
4235 + * SERVICES_Init
4238 + *! Revision History
4239 + *! ================
4240 + *! 20-Nov-2000 rr: NTFY_Init/Exit added.
4241 + *! 06-Jul-2000 rr: PROC prefix changed to PRCS to accomodate RM.
4242 + *! 01-Feb-2000 kc: Created.
4243 + */
4245 +#include <host_os.h>
4247 +/* ----------------------------------- DSP/BIOS Bridge */
4248 +#include <std.h>
4249 +#include <dbdefs.h>
4251 +/* ----------------------------------- Trace & Debug */
4252 +#include <dbc.h>
4253 +#include <gt.h>
4255 +/* ----------------------------------- OS Adaptation Layer */
4256 +#include <cfg.h>
4257 +#include <csl.h>
4258 +#include <dbg.h>
4259 +#include <dpc.h>
4260 +#include <isr.h>
4261 +#include <kfile.h>
4262 +#include <list.h>
4263 +#include <mem.h>
4264 +#include <ntfy.h>
4265 +#include <prcs.h>
4266 +#include <reg.h>
4267 +#include <sync.h>
4268 +#include <clk.h>
4269 +#include <util.h>
4271 +/* ----------------------------------- This */
4272 +#include <services.h>
4274 +/* ----------------------------------- Globals */
4275 +#if GT_TRACE
4276 +static struct GT_Mask SERVICES_debugMask = { NULL, NULL }; /* GT trace var. */
4277 +#endif
4279 +static u32 cRefs; /* SERVICES module reference count */
4282 + * ======== SERVICES_Exit ========
4283 + * Purpose:
4284 + * Discontinue usage of module; free resources when reference count
4285 + * reaches 0.
4286 + */
4287 +void SERVICES_Exit(void)
4289 + DBC_Require(cRefs > 0);
4291 + GT_1trace(SERVICES_debugMask, GT_5CLASS, "SERVICES_Exit: cRefs 0x%x\n",
4292 + cRefs);
4294 + cRefs--;
4295 + if (cRefs == 0) {
4296 + /* Uninitialize all SERVICES modules here */
4297 + NTFY_Exit();
4298 + UTIL_Exit();
4299 + SYNC_Exit();
4300 + CLK_Exit();
4301 + REG_Exit();
4302 + PRCS_Exit();
4303 + LST_Exit();
4304 + KFILE_Exit();
4305 + ISR_Exit();
4306 + DPC_Exit();
4307 + DBG_Exit();
4308 + CSL_Exit();
4309 + CFG_Exit();
4310 + MEM_Exit();
4312 + GT_exit();
4315 + DBC_Ensure(cRefs >= 0);
4319 + * ======== SERVICES_Init ========
4320 + * Purpose:
4321 + * Initializes SERVICES modules.
4322 + */
4323 +bool SERVICES_Init(void)
4325 + bool fInit = true;
4326 + bool fCFG, fCSL, fDBG, fDPC, fISR, fKFILE, fLST, fMEM;
4327 + bool fPRCS, fREG, fSYNC, fCLK, fUTIL, fNTFY;
4329 + DBC_Require(cRefs >= 0);
4331 + if (cRefs == 0) {
4333 + GT_init();
4334 + GT_create(&SERVICES_debugMask, "OS"); /* OS for OSal */
4336 + GT_0trace(SERVICES_debugMask, GT_ENTER,
4337 + "SERVICES_Init: entered\n");
4339 + /* Perform required initialization of SERVICES modules. */
4340 + fMEM = MEM_Init();
4341 + fREG = REG_Init();
4342 + fCFG = CFG_Init();
4343 + fCSL = CSL_Init();
4344 + fDBG = DBG_Init();
4345 + fDPC = DPC_Init();
4346 + fISR = ISR_Init();
4347 + fKFILE = KFILE_Init();
4348 + fLST = LST_Init();
4349 + fPRCS = PRCS_Init();
4350 + /* fREG = REG_Init(); */
4351 + fSYNC = SYNC_Init();
4352 + fCLK = CLK_Init();
4353 + fUTIL = UTIL_Init();
4354 + fNTFY = NTFY_Init();
4356 + fInit = fCFG && fCSL && fDBG && fDPC && fISR && fKFILE &&
4357 + fLST && fMEM && fPRCS && fREG && fSYNC && fCLK && fUTIL;
4359 + if (!fInit) {
4360 + if (fNTFY)
4361 + NTFY_Exit();
4363 + if (fUTIL)
4364 + UTIL_Exit();
4366 + if (fSYNC)
4367 + SYNC_Exit();
4369 + if (fCLK)
4370 + CLK_Exit();
4372 + if (fREG)
4373 + REG_Exit();
4375 + if (fPRCS)
4376 + PRCS_Exit();
4378 + if (fLST)
4379 + LST_Exit();
4381 + if (fKFILE)
4382 + KFILE_Exit();
4384 + if (fISR)
4385 + ISR_Exit();
4387 + if (fDPC)
4388 + DPC_Exit();
4390 + if (fDBG)
4391 + DBG_Exit();
4393 + if (fCSL)
4394 + CSL_Exit();
4396 + if (fCFG)
4397 + CFG_Exit();
4399 + if (fMEM)
4400 + MEM_Exit();
4405 + if (fInit)
4406 + cRefs++;
4408 + GT_1trace(SERVICES_debugMask, GT_5CLASS, "SERVICES_Init: cRefs 0x%x\n",
4409 + cRefs);
4411 + DBC_Ensure((fInit && (cRefs > 0)) || (!fInit && (cRefs >= 0)));
4413 + return fInit;
4416 diff --git a/drivers/dsp/bridge/services/sync.c b/drivers/dsp/bridge/services/sync.c
4417 new file mode 100644
4418 index 0000000..f472b2d
4419 --- /dev/null
4420 +++ b/drivers/dsp/bridge/services/sync.c
4421 @@ -0,0 +1,610 @@
4423 + * linux/drivers/dsp/bridge/services/sync.c
4425 + * DSP-BIOS Bridge driver support functions for TI OMAP processors.
4427 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
4429 + * This package is free software; you can redistribute it and/or modify
4430 + * it under the terms of the GNU General Public License version 2 as
4431 + * published by the Free Software Foundation.
4433 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
4434 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
4435 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
4436 + */
4439 + * ======== syncce.c ========
4440 + * Purpose:
4441 + * Synchronization services.
4443 + * Public Functions:
4444 + * SYNC_CloseEvent
4445 + * SYNC_DeleteCS
4446 + * SYNC_EnterCS
4447 + * SYNC_Exit
4448 + * SYNC_Init
4449 + * SYNC_InitializeCS
4450 + * SYNC_LeaveCS
4451 + * SYNC_OpenEvent
4452 + * SYNC_ResetEvent
4453 + * SYNC_SetEvent
4454 + * SYNC_WaitOnEvent
4455 + * SYNC_WaitOnMultipleEvents
4457 + *! Revision History:
4458 + *! ================
4459 + *! 05-Nov-2001 kc: Minor cosmetic changes.
4460 + *! 05-Oct-2000 jeh Added SYNC_WaitOnMultipleEvents().
4461 + *! 10-Aug-2000 rr: SYNC_PostMessage added.
4462 + *! 10-Jul-2000 jeh Modified SYNC_OpenEvent() to handle NULL attrs.
4463 + *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
4464 + *! GT Changes.
4465 + *! 01-Dec-1999 ag: Added optional named event creation in SYNC_OpenEvent().
4466 + *! 22-Nov-1999 kc: Added changes from code review.
4467 + *! 22-Sep-1999 kc: Modified from sync95.c.
4468 + *! 05-Aug-1996 gp: Created.
4469 + */
4471 +/* ----------------------------------- Host OS */
4472 +#include <host_os.h>
4474 +/* ----------------------------------- DSP/BIOS Bridge */
4475 +#include <std.h>
4476 +#include <dbdefs.h>
4477 +#include <errbase.h>
4479 +/* ----------------------------------- Trace & Debug */
4480 +#include <dbc.h>
4481 +#include <gt.h>
4483 +/* ----------------------------------- OS Adaptation Layer */
4484 +#include <csl.h>
4485 +#include <mem.h>
4487 +/* ----------------------------------- This */
4488 +#include <sync.h>
4490 +/* ----------------------------------- Defines, Data Structures, Typedefs */
4491 +#define SIGNATURE 0x434e5953 /* "SYNC" (in reverse) */
4492 +#define SIGNATURECS 0x53435953 /* "SYCS" (in reverse) */
4493 +#define SIGNATUREDPCCS 0x53445953 /* "SYDS" (in reverse) */
4495 +enum wait_state {
4496 + wo_waiting,
4497 + wo_signalled
4498 +} ;
4500 +enum sync_state {
4501 + so_reset,
4502 + so_signalled
4503 +} ;
4505 +struct WAIT_OBJECT {
4506 + enum wait_state state;
4507 + struct SYNC_OBJECT *signalling_event;
4508 + struct semaphore sem;
4511 +/* Generic SYNC object: */
4512 +struct SYNC_OBJECT {
4513 + u32 dwSignature; /* Used for object validation. */
4514 + enum sync_state state;
4515 + spinlock_t sync_lock;
4516 + struct WAIT_OBJECT *pWaitObj;
4519 +struct SYNC_CSOBJECT {
4520 + u32 dwSignature; /* used for object validation */
4521 + struct semaphore sem;
4522 +} ;
4524 +struct SYNC_DPCCSOBJECT {
4525 + u32 dwSignature; /* used for object validation */
4526 + spinlock_t sync_dpccs_lock;
4527 + s32 count;
4528 +} ;
4530 +/* ----------------------------------- Globals */
4531 +#if GT_TRACE
4532 +static struct GT_Mask SYNC_debugMask = { NULL, NULL }; /* GT trace variable */
4533 +#endif
4535 +static int test_and_set(volatile void *ptr, int val)
4537 + int ret = val;
4538 + asm volatile (" swp %0, %0, [%1]" : "+r" (ret) : "r"(ptr) : "memory");
4539 + return ret;
4542 +static void timeout_callback(unsigned long hWaitObj);
4545 + * ======== SYNC_CloseEvent ========
4546 + * Purpose:
4547 + * Close an existing SYNC event object.
4548 + */
4549 +DSP_STATUS SYNC_CloseEvent(struct SYNC_OBJECT *hEvent)
4551 + DSP_STATUS status = DSP_SOK;
4552 + struct SYNC_OBJECT *pEvent = (struct SYNC_OBJECT *)hEvent;
4554 + DBC_Require(pEvent != NULL && pEvent->pWaitObj == NULL);
4556 + GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_CloseEvent: hEvent 0x%x\n",
4557 + hEvent);
4559 + if (MEM_IsValidHandle(hEvent, SIGNATURE)) {
4560 + if (pEvent->pWaitObj) {
4561 + status = DSP_EFAIL;
4562 + GT_0trace(SYNC_debugMask, GT_6CLASS,
4563 + "SYNC_CloseEvent: Wait object not NULL\n");
4565 + MEM_FreeObject(pEvent);
4567 + } else {
4568 + status = DSP_EHANDLE;
4569 + GT_1trace(SYNC_debugMask, GT_6CLASS,
4570 + "SYNC_CloseEvent: invalid "
4571 + "hEvent handle 0x%x\n", hEvent);
4574 + return status;
4578 + * ======== SYNC_Exit ========
4579 + * Purpose:
4580 + * Cleanup SYNC module.
4581 + */
4582 +void SYNC_Exit(void)
4584 + GT_0trace(SYNC_debugMask, GT_5CLASS, "SYNC_Exit\n");
4588 + * ======== SYNC_Init ========
4589 + * Purpose:
4590 + * Initialize SYNC module.
4591 + */
4592 +bool SYNC_Init(void)
4594 + GT_create(&SYNC_debugMask, "SY"); /* SY for SYnc */
4596 + GT_0trace(SYNC_debugMask, GT_5CLASS, "SYNC_Init\n");
4598 + return true;
4602 + * ======== SYNC_OpenEvent ========
4603 + * Purpose:
4604 + * Open a new synchronization event object.
4605 + */
4606 +DSP_STATUS SYNC_OpenEvent(OUT struct SYNC_OBJECT **phEvent,
4607 + IN OPTIONAL struct SYNC_ATTRS *pAttrs)
4609 + struct SYNC_OBJECT *pEvent = NULL;
4610 + DSP_STATUS status = DSP_SOK;
4612 + DBC_Require(phEvent != NULL);
4614 + GT_2trace(SYNC_debugMask, GT_ENTER,
4615 + "SYNC_OpenEvent: phEvent 0x%x, pAttrs "
4616 + "0x%x\n", phEvent, pAttrs);
4618 + /* Allocate memory for sync object */
4619 + MEM_AllocObject(pEvent, struct SYNC_OBJECT, SIGNATURE);
4620 + if (pEvent != NULL) {
4621 + pEvent->state = so_reset;
4622 + pEvent->pWaitObj = NULL;
4623 + pEvent->sync_lock = __SPIN_LOCK_UNLOCKED(pEvent.sync_lock);
4624 + } else {
4625 + status = DSP_EMEMORY;
4626 + GT_0trace(SYNC_debugMask, GT_6CLASS,
4627 + "SYNC_OpenEvent: MEM_AllocObject failed\n");
4630 + *phEvent = pEvent;
4632 + return status;
4636 + * ======== SYNC_ResetEvent ========
4637 + * Purpose:
4638 + * Reset an event to non-signalled.
4639 + */
4640 +DSP_STATUS SYNC_ResetEvent(struct SYNC_OBJECT *hEvent)
4642 + DSP_STATUS status = DSP_SOK;
4643 + struct SYNC_OBJECT *pEvent = (struct SYNC_OBJECT *)hEvent;
4645 + GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_ResetEvent: hEvent 0x%x\n",
4646 + hEvent);
4648 + if (MEM_IsValidHandle(hEvent, SIGNATURE)) {
4649 + pEvent->state = so_reset;
4650 + status = DSP_SOK;
4651 + } else {
4652 + status = DSP_EHANDLE;
4653 + GT_1trace(SYNC_debugMask, GT_6CLASS,
4654 + "SYNC_ResetEvent: invalid hEvent "
4655 + "handle 0x%x\n", hEvent);
4658 + return status;
4662 + * ======== SYNC_SetEvent ========
4663 + * Purpose:
4664 + * Set an event to signaled and unblock one waiting thread.
4666 + * This function is called from ISR, DPC and user context. Hence interrupts
4667 + * are disabled to ensure atomicity.
4668 + */
4670 +DSP_STATUS SYNC_SetEvent(struct SYNC_OBJECT *hEvent)
4672 + DSP_STATUS status = DSP_SOK;
4673 + struct SYNC_OBJECT *pEvent = (struct SYNC_OBJECT *)hEvent;
4674 + unsigned long flags;
4676 + GT_1trace(SYNC_debugMask, GT_6CLASS, "SYNC_SetEvent: hEvent 0x%x\n",
4677 + hEvent);
4679 + if (MEM_IsValidHandle(hEvent, SIGNATURE)) {
4680 + spin_lock_irqsave(&hEvent->sync_lock, flags);
4681 + GT_1trace(SYNC_debugMask, GT_6CLASS,
4682 + "SYNC_SetEvent: pEvent->pWaitObj "
4683 + "= 0x%x \n", pEvent->pWaitObj);
4684 + if (pEvent->pWaitObj)
4685 + GT_1trace(SYNC_debugMask, GT_6CLASS, "SYNC_SetEvent: "
4686 + "pEvent->pWaitObj->state = 0x%x \n",
4687 + pEvent->pWaitObj->state);
4688 + if (pEvent->pWaitObj != NULL &&
4689 + test_and_set(&pEvent->pWaitObj->state,
4690 + wo_signalled) == wo_waiting) {
4692 + pEvent->state = so_reset;
4693 + pEvent->pWaitObj->signalling_event = pEvent;
4694 + up(&pEvent->pWaitObj->sem);
4695 + GT_1trace(SYNC_debugMask, GT_6CLASS,
4696 + "SYNC_SetEvent: Unlock "
4697 + "Semaphore for hEvent 0x%x\n", hEvent);
4698 + } else {
4699 + pEvent->state = so_signalled;
4701 + spin_unlock_irqrestore(&hEvent->sync_lock, flags);
4702 + } else {
4703 + status = DSP_EHANDLE;
4704 + GT_1trace(SYNC_debugMask, GT_6CLASS,
4705 + "SYNC_SetEvent: invalid hEvent "
4706 + "handle 0x%x\n", hEvent);
4708 + return status;
4712 + * ======== SYNC_WaitOnEvent ========
4713 + * Purpose:
4714 + * Wait for an event to be signalled, up to the specified timeout.
4715 + * Note: dwTimeOut must be 0xffffffff to signal infinite wait.
4716 + */
4717 +DSP_STATUS SYNC_WaitOnEvent(struct SYNC_OBJECT *hEvent, u32 dwTimeout)
4719 + DSP_STATUS status = DSP_SOK;
4720 + struct SYNC_OBJECT *pEvent = (struct SYNC_OBJECT *)hEvent;
4721 + u32 temp;
4723 + GT_2trace(SYNC_debugMask, GT_6CLASS, "SYNC_WaitOnEvent: hEvent 0x%x\n, "
4724 + "dwTimeOut 0x%x", hEvent, dwTimeout);
4725 + if (MEM_IsValidHandle(hEvent, SIGNATURE)) {
4726 + status = SYNC_WaitOnMultipleEvents(&pEvent, 1, dwTimeout,
4727 + &temp);
4728 + } else {
4729 + status = DSP_EHANDLE;
4730 + GT_1trace(SYNC_debugMask, GT_6CLASS,
4731 + "SYNC_WaitOnEvent: invalid hEvent"
4732 + "handle 0x%x\n", hEvent);
4734 + return status;
4738 + * ======== SYNC_WaitOnMultipleEvents ========
4739 + * Purpose:
4740 + * Wait for any of an array of events to be signalled, up to the
4741 + * specified timeout.
4742 + */
4743 +DSP_STATUS SYNC_WaitOnMultipleEvents(struct SYNC_OBJECT **hSyncEvents,
4744 + u32 uCount, u32 dwTimeout,
4745 + OUT u32 *puIndex)
4747 + u32 i;
4748 + DSP_STATUS status = DSP_SOK;
4749 + u32 curr;
4750 + struct WAIT_OBJECT *Wp;
4752 + DBC_Require(uCount > 0);
4753 + DBC_Require(hSyncEvents != NULL);
4754 + DBC_Require(puIndex != NULL);
4756 + for (i = 0; i < uCount; i++)
4757 + DBC_Require(MEM_IsValidHandle(hSyncEvents[i], SIGNATURE));
4759 + GT_4trace(SYNC_debugMask, GT_6CLASS,
4760 + "SYNC_WaitOnMultipleEvents: hSyncEvents:"
4761 + "0x%x\tuCount: 0x%x" "\tdwTimeout: 0x%x\tpuIndex: 0x%x\n",
4762 + hSyncEvents, uCount, dwTimeout, puIndex);
4764 + Wp = MEM_Calloc(sizeof(struct WAIT_OBJECT), MEM_NONPAGED);
4765 + if (Wp == NULL)
4766 + return DSP_EMEMORY;
4768 + Wp->state = wo_waiting;
4769 + Wp->signalling_event = NULL;
4770 + init_MUTEX_LOCKED(&(Wp->sem));
4772 + for (curr = 0; curr < uCount; curr++) {
4773 + hSyncEvents[curr]->pWaitObj = Wp;
4774 + if (hSyncEvents[curr]->state == so_signalled) {
4775 + GT_0trace(SYNC_debugMask, GT_6CLASS,
4776 + "Detected signaled Event !!!\n");
4777 + if (test_and_set(&(Wp->state), wo_signalled) ==
4778 + wo_waiting) {
4779 + GT_0trace(SYNC_debugMask, GT_6CLASS,
4780 + "Setting Signal Event!!!\n");
4781 + hSyncEvents[curr]->state = so_reset;
4782 + Wp->signalling_event = hSyncEvents[curr];
4784 + curr++; /* Will try optimizing later */
4785 + break;
4789 + curr--; /* Will try optimizing later */
4790 + if (Wp->state != wo_signalled && dwTimeout > 0) {
4791 + struct timer_list timeout;
4792 + if (dwTimeout != SYNC_INFINITE) {
4793 + init_timer(&timeout);
4794 + timeout.function = timeout_callback;
4795 + timeout.data = (unsigned long)Wp;
4796 + timeout.expires = jiffies + dwTimeout * HZ / 1000;
4797 + add_timer(&timeout);
4799 + if (down_interruptible(&(Wp->sem))) {
4800 + GT_0trace(SYNC_debugMask, GT_7CLASS, "SYNC: "
4801 + "WaitOnMultipleEvents Interrupted by signal\n");
4802 + status = DSP_EFAIL;
4804 + if (dwTimeout != SYNC_INFINITE) {
4805 + if (in_interrupt()) {
4806 + if (!del_timer(&timeout)) {
4807 + GT_0trace(SYNC_debugMask, GT_7CLASS,
4808 + "SYNC: Timer expired\n");
4810 + } else {
4811 + if (!del_timer_sync(&timeout)) {
4812 + GT_0trace(SYNC_debugMask, GT_7CLASS,
4813 + "SYNC: Timer expired\n");
4818 + for (i = 0; i <= curr; i++) {
4819 + if (MEM_IsValidHandle(hSyncEvents[i], SIGNATURE)) {
4820 + /* Memory corruption here if hSyncEvents[i] is
4821 + * freed before following statememt. */
4822 + hSyncEvents[i]->pWaitObj = NULL;
4824 + if (hSyncEvents[i] == Wp->signalling_event)
4825 + *puIndex = i;
4828 + if (Wp->signalling_event == NULL && DSP_SUCCEEDED(status)) {
4829 + GT_0trace(SYNC_debugMask, GT_7CLASS,
4830 + "SYNC:Signaling Event NULL!!!(:-\n");
4831 + status = DSP_ETIMEOUT;
4833 + if (Wp)
4834 + MEM_Free(Wp);
4835 + return status;
4838 +static void timeout_callback(unsigned long hWaitObj)
4840 + struct WAIT_OBJECT *pWaitObj = (struct WAIT_OBJECT *)hWaitObj;
4841 + if (test_and_set(&pWaitObj->state, wo_signalled) == wo_waiting)
4842 + up(&pWaitObj->sem);
4847 + * ======== SYNC_DeleteCS ========
4848 + */
4849 +DSP_STATUS SYNC_DeleteCS(struct SYNC_CSOBJECT *hCSObj)
4851 + DSP_STATUS status = DSP_SOK;
4852 + struct SYNC_CSOBJECT *pCSObj = (struct SYNC_CSOBJECT *)hCSObj;
4854 + GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_DeleteCS\n");
4856 + if (MEM_IsValidHandle(hCSObj, SIGNATURECS)) {
4857 + if (down_trylock(&pCSObj->sem) != 0) {
4858 + GT_1trace(SYNC_debugMask, GT_7CLASS,
4859 + "CS in use (locked) while "
4860 + "deleting! pCSObj=0x%X", pCSObj);
4861 + DBC_Assert(0);
4863 + MEM_FreeObject(hCSObj);
4864 + } else if (MEM_IsValidHandle(hCSObj, SIGNATUREDPCCS)) {
4865 + struct SYNC_DPCCSOBJECT *pDPCCSObj =
4866 + (struct SYNC_DPCCSOBJECT *)hCSObj;
4867 + if (pDPCCSObj->count != 1) {
4868 + GT_1trace(SYNC_debugMask, GT_7CLASS,
4869 + "DPC CS in use (locked) while "
4870 + "deleting! pCSObj=0x%X", pCSObj);
4871 + DBC_Assert(0);
4873 + MEM_FreeObject(pDPCCSObj);
4874 + } else {
4875 + status = DSP_EHANDLE;
4876 + GT_1trace(SYNC_debugMask, GT_6CLASS,
4877 + "SYNC_DeleteCS: invalid hCSObj "
4878 + "handle 0x%x\n", hCSObj);
4881 + return status;
4885 + * ======== SYNC_EnterCS ========
4886 + */
4887 +DSP_STATUS SYNC_EnterCS(struct SYNC_CSOBJECT *hCSObj)
4889 + DSP_STATUS status = DSP_SOK;
4890 + struct SYNC_CSOBJECT *pCSObj = (struct SYNC_CSOBJECT *)hCSObj;
4892 + GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_EnterCS: hCSObj %p\n",
4893 + hCSObj);
4894 + if (MEM_IsValidHandle(hCSObj, SIGNATURECS)) {
4895 + if (in_interrupt()) {
4896 + status = DSP_EFAIL;
4897 + GT_0trace(SYNC_debugMask, GT_7CLASS,
4898 + "SYNC_EnterCS called from "
4899 + "ISR/DPC or with ISR/DPC disabled!");
4900 + DBC_Assert(0);
4901 + } else if (down_interruptible(&pCSObj->sem)) {
4902 + GT_1trace(SYNC_debugMask, GT_7CLASS,
4903 + "CS interrupted by signal! "
4904 + "pCSObj=0x%X", pCSObj);
4905 + status = DSP_EFAIL;
4907 + } else if (MEM_IsValidHandle(hCSObj, SIGNATUREDPCCS)) {
4908 + struct SYNC_DPCCSOBJECT *pDPCCSObj =
4909 + (struct SYNC_DPCCSOBJECT *)hCSObj;
4910 + GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_EnterCS DPC\n");
4911 + spin_lock_bh(&pDPCCSObj->sync_dpccs_lock);
4912 + pDPCCSObj->count--;
4913 + if (pDPCCSObj->count != 0) {
4914 + /* FATAL ERROR : Failed to acquire DPC CS */
4915 + GT_2trace(SYNC_debugMask, GT_7CLASS,
4916 + "SYNC_EnterCS DPCCS %x locked,"
4917 + "count %d", pDPCCSObj, pDPCCSObj->count);
4918 + spin_unlock_bh(&pDPCCSObj->sync_dpccs_lock);
4919 + DBC_Assert(0);
4921 + } else {
4922 + status = DSP_EHANDLE;
4923 + GT_1trace(SYNC_debugMask, GT_6CLASS,
4924 + "SYNC_EnterCS: invalid hCSObj "
4925 + "handle 0x%x\n", hCSObj);
4928 + return status;
4932 + * ======== SYNC_InitializeCS ========
4933 + */
4934 +DSP_STATUS SYNC_InitializeCS(OUT struct SYNC_CSOBJECT **phCSObj)
4936 + DSP_STATUS status = DSP_SOK;
4937 + struct SYNC_CSOBJECT *pCSObj = NULL;
4939 + GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_InitializeCS\n");
4941 + /* Allocate memory for sync CS object */
4942 + MEM_AllocObject(pCSObj, struct SYNC_CSOBJECT, SIGNATURECS);
4943 + if (pCSObj != NULL) {
4944 + init_MUTEX(&pCSObj->sem);
4945 + } else {
4946 + status = DSP_EMEMORY;
4947 + GT_0trace(SYNC_debugMask, GT_6CLASS,
4948 + "SYNC_InitializeCS: MEM_AllocObject"
4949 + "failed\n");
4951 + /* return CS object */
4952 + *phCSObj = pCSObj;
4953 + DBC_Assert(DSP_FAILED(status) || (pCSObj));
4954 + return status;
4957 +DSP_STATUS SYNC_InitializeDPCCS(OUT struct SYNC_CSOBJECT **phCSObj)
4959 + DSP_STATUS status = DSP_SOK;
4960 + struct SYNC_DPCCSOBJECT *pCSObj = NULL;
4962 + DBC_Require(phCSObj);
4964 + GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_InitializeDPCCS\n");
4966 + if (phCSObj) {
4967 + /* Allocate memory for sync CS object */
4968 + MEM_AllocObject(pCSObj, struct SYNC_DPCCSOBJECT,
4969 + SIGNATUREDPCCS);
4970 + if (pCSObj != NULL) {
4971 + pCSObj->count = 1;
4972 + pCSObj->sync_dpccs_lock =
4973 + __SPIN_LOCK_UNLOCKED(pCSObj.sync_dpccs_lock);
4974 + } else {
4975 + status = DSP_EMEMORY;
4976 + GT_0trace(SYNC_debugMask, GT_6CLASS,
4977 + "SYNC_InitializeDPCCS: "
4978 + "MEM_AllocObject failed\n");
4981 + /* return CS object */
4982 + *phCSObj = (struct SYNC_CSOBJECT *)pCSObj;
4983 + } else {
4984 + status = DSP_EPOINTER;
4987 + GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_InitializeDPCCS "
4988 + "pCSObj %p\n", pCSObj);
4989 + DBC_Assert(DSP_FAILED(status) || (pCSObj));
4991 + return status;
4995 + * ======== SYNC_LeaveCS ========
4996 + */
4997 +DSP_STATUS SYNC_LeaveCS(struct SYNC_CSOBJECT *hCSObj)
4999 + DSP_STATUS status = DSP_SOK;
5000 + struct SYNC_CSOBJECT *pCSObj = (struct SYNC_CSOBJECT *)hCSObj;
5002 + GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_LeaveCS: hCSObj %p\n",
5003 + hCSObj);
5005 + if (MEM_IsValidHandle(hCSObj, SIGNATURECS)) {
5006 + up(&pCSObj->sem);
5007 + } else if (MEM_IsValidHandle(hCSObj, SIGNATUREDPCCS)) {
5008 + struct SYNC_DPCCSOBJECT *pDPCCSObj =
5009 + (struct SYNC_DPCCSOBJECT *)hCSObj;
5010 + pDPCCSObj->count++;
5011 + if (pDPCCSObj->count != 1) {
5012 + /* FATAL ERROR : Invalid DPC CS count */
5013 + GT_2trace(SYNC_debugMask, GT_7CLASS,
5014 + "SYNC_LeaveCS DPCCS %x, "
5015 + "Invalid count %d", pDPCCSObj,
5016 + pDPCCSObj->count);
5017 + spin_unlock_bh(&pDPCCSObj->sync_dpccs_lock);
5018 + DBC_Assert(0);
5019 + spin_lock_bh(&pDPCCSObj->sync_dpccs_lock);
5021 + spin_unlock_bh(&pDPCCSObj->sync_dpccs_lock);
5022 + GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_LeaveCS DPC\n");
5023 + } else {
5024 + status = DSP_EHANDLE;
5025 + GT_1trace(SYNC_debugMask, GT_6CLASS,
5026 + "SYNC_LeaveCS: invalid hCSObj "
5027 + "handle 0x%x\n", hCSObj);
5030 + return status;
5033 1.5.5.1.357.g1af8b