• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/drivers/staging/tidspbridge/pmgr/
1/*
2 * dev.c
3 *
4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5 *
6 * Implementation of Bridge Bridge driver device operations.
7 *
8 * Copyright (C) 2005-2006 Texas Instruments, Inc.
9 *
10 * This package is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 *
14 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17 */
18#include <linux/types.h>
19
20/*  ----------------------------------- Host OS */
21#include <dspbridge/host_os.h>
22
23/*  ----------------------------------- DSP/BIOS Bridge */
24#include <dspbridge/dbdefs.h>
25
26/*  ----------------------------------- Trace & Debug */
27#include <dspbridge/dbc.h>
28
29/*  ----------------------------------- OS Adaptation Layer */
30#include <dspbridge/cfg.h>
31#include <dspbridge/ldr.h>
32#include <dspbridge/list.h>
33
34/*  ----------------------------------- Platform Manager */
35#include <dspbridge/cod.h>
36#include <dspbridge/drv.h>
37#include <dspbridge/proc.h>
38#include <dspbridge/dmm.h>
39
40/*  ----------------------------------- Resource Manager */
41#include <dspbridge/mgr.h>
42#include <dspbridge/node.h>
43
44/*  ----------------------------------- Others */
45#include <dspbridge/dspapi.h>	/* DSP API version info. */
46
47#include <dspbridge/chnl.h>
48#include <dspbridge/io.h>
49#include <dspbridge/msg.h>
50#include <dspbridge/cmm.h>
51#include <dspbridge/dspdeh.h>
52
53/*  ----------------------------------- This */
54#include <dspbridge/dev.h>
55
56/*  ----------------------------------- Defines, Data Structures, Typedefs */
57
58#define MAKEVERSION(major, minor)   (major * 10 + minor)
59#define BRD_API_VERSION		MAKEVERSION(BRD_API_MAJOR_VERSION,	\
60				BRD_API_MINOR_VERSION)
61
62/* The Bridge device object: */
63struct dev_object {
64	/* LST requires "link" to be first field! */
65	struct list_head link;	/* Link to next dev_object. */
66	u8 dev_type;		/* Device Type */
67	struct cfg_devnode *dev_node_obj;	/* Platform specific dev id */
68	/* Bridge Context Handle */
69	struct bridge_dev_context *hbridge_context;
70	/* Function interface to Bridge driver. */
71	struct bridge_drv_interface bridge_interface;
72	struct brd_object *lock_owner;	/* Client with exclusive access. */
73	struct cod_manager *cod_mgr;	/* Code manager handle. */
74	struct chnl_mgr *hchnl_mgr;	/* Channel manager. */
75	struct deh_mgr *hdeh_mgr;	/* DEH manager. */
76	struct msg_mgr *hmsg_mgr;	/* Message manager. */
77	struct io_mgr *hio_mgr;	/* IO manager (CHNL, msg_ctrl) */
78	struct cmm_object *hcmm_mgr;	/* SM memory manager. */
79	struct dmm_object *dmm_mgr;	/* Dynamic memory manager. */
80	struct ldr_module *module_obj;	/* Bridge Module handle. */
81	u32 word_size;		/* DSP word size: quick access. */
82	struct drv_object *hdrv_obj;	/* Driver Object */
83	struct lst_list *proc_list;	/* List of Proceeosr attached to
84					 * this device */
85	struct node_mgr *hnode_mgr;
86};
87
88/*  ----------------------------------- Globals */
89static u32 refs;		/* Module reference count */
90
91/*  ----------------------------------- Function Prototypes */
92static int fxn_not_implemented(int arg, ...);
93static int init_cod_mgr(struct dev_object *dev_obj);
94static void store_interface_fxns(struct bridge_drv_interface *drv_fxns,
95				 struct bridge_drv_interface *intf_fxns);
96/*
97 *  ======== dev_brd_write_fxn ========
98 *  Purpose:
99 *      Exported function to be used as the COD write function.  This function
100 *      is passed a handle to a DEV_hObject, then calls the
101 *      device's bridge_brd_write() function.
102 */
103u32 dev_brd_write_fxn(void *arb, u32 dsp_add, void *host_buf,
104		      u32 ul_num_bytes, u32 mem_space)
105{
106	struct dev_object *dev_obj = (struct dev_object *)arb;
107	u32 ul_written = 0;
108	int status;
109
110	DBC_REQUIRE(refs > 0);
111	DBC_REQUIRE(host_buf != NULL);	/* Required of BrdWrite(). */
112	if (dev_obj) {
113		/* Require of BrdWrite() */
114		DBC_ASSERT(dev_obj->hbridge_context != NULL);
115		status = (*dev_obj->bridge_interface.pfn_brd_write) (
116					dev_obj->hbridge_context, host_buf,
117					dsp_add, ul_num_bytes, mem_space);
118		/* Special case of getting the address only */
119		if (ul_num_bytes == 0)
120			ul_num_bytes = 1;
121		if (!status)
122			ul_written = ul_num_bytes;
123
124	}
125	return ul_written;
126}
127
128/*
129 *  ======== dev_create_device ========
130 *  Purpose:
131 *      Called by the operating system to load the PM Bridge Driver for a
132 *      PM board (device).
133 */
134int dev_create_device(struct dev_object **device_obj,
135			     const char *driver_file_name,
136			     struct cfg_devnode *dev_node_obj)
137{
138	struct cfg_hostres *host_res;
139	struct ldr_module *module_obj = NULL;
140	struct bridge_drv_interface *drv_fxns = NULL;
141	struct dev_object *dev_obj = NULL;
142	struct chnl_mgrattrs mgr_attrs;
143	struct io_attrs io_mgr_attrs;
144	u32 num_windows;
145	struct drv_object *hdrv_obj = NULL;
146	int status = 0;
147	DBC_REQUIRE(refs > 0);
148	DBC_REQUIRE(device_obj != NULL);
149	DBC_REQUIRE(driver_file_name != NULL);
150
151	status = drv_request_bridge_res_dsp((void *)&host_res);
152
153	if (status) {
154		dev_dbg(bridge, "%s: Failed to reserve bridge resources\n",
155			__func__);
156		goto leave;
157	}
158
159	/*  Get the Bridge driver interface functions */
160	bridge_drv_entry(&drv_fxns, driver_file_name);
161	if (cfg_get_object((u32 *) &hdrv_obj, REG_DRV_OBJECT)) {
162		/* don't propogate CFG errors from this PROC function */
163		status = -EPERM;
164	}
165	/* Create the device object, and pass a handle to the Bridge driver for
166	 * storage. */
167	if (!status) {
168		DBC_ASSERT(drv_fxns);
169		dev_obj = kzalloc(sizeof(struct dev_object), GFP_KERNEL);
170		if (dev_obj) {
171			/* Fill out the rest of the Dev Object structure: */
172			dev_obj->dev_node_obj = dev_node_obj;
173			dev_obj->module_obj = module_obj;
174			dev_obj->cod_mgr = NULL;
175			dev_obj->hchnl_mgr = NULL;
176			dev_obj->hdeh_mgr = NULL;
177			dev_obj->lock_owner = NULL;
178			dev_obj->word_size = DSPWORDSIZE;
179			dev_obj->hdrv_obj = hdrv_obj;
180			dev_obj->dev_type = DSP_UNIT;
181			/* Store this Bridge's interface functions, based on its
182			 * version. */
183			store_interface_fxns(drv_fxns,
184						&dev_obj->bridge_interface);
185
186			/* Call fxn_dev_create() to get the Bridge's device
187			 * context handle. */
188			status = (dev_obj->bridge_interface.pfn_dev_create)
189			    (&dev_obj->hbridge_context, dev_obj,
190			     host_res);
191			/* Assert bridge_dev_create()'s ensure clause: */
192			DBC_ASSERT(status
193				   || (dev_obj->hbridge_context != NULL));
194		} else {
195			status = -ENOMEM;
196		}
197	}
198	/* Attempt to create the COD manager for this device: */
199	if (!status)
200		status = init_cod_mgr(dev_obj);
201
202	/* Attempt to create the channel manager for this device: */
203	if (!status) {
204		mgr_attrs.max_channels = CHNL_MAXCHANNELS;
205		io_mgr_attrs.birq = host_res->birq_registers;
206		io_mgr_attrs.irq_shared =
207		    (host_res->birq_attrib & CFG_IRQSHARED);
208		io_mgr_attrs.word_size = DSPWORDSIZE;
209		mgr_attrs.word_size = DSPWORDSIZE;
210		num_windows = host_res->num_mem_windows;
211		if (num_windows) {
212			/* Assume last memory window is for CHNL */
213			io_mgr_attrs.shm_base = host_res->dw_mem_base[1] +
214			    host_res->dw_offset_for_monitor;
215			io_mgr_attrs.usm_length =
216			    host_res->dw_mem_length[1] -
217			    host_res->dw_offset_for_monitor;
218		} else {
219			io_mgr_attrs.shm_base = 0;
220			io_mgr_attrs.usm_length = 0;
221			pr_err("%s: No memory reserved for shared structures\n",
222			       __func__);
223		}
224		status = chnl_create(&dev_obj->hchnl_mgr, dev_obj, &mgr_attrs);
225		if (status == -ENOSYS) {
226			/* It's OK for a device not to have a channel
227			 * manager: */
228			status = 0;
229		}
230		/* Create CMM mgr even if Msg Mgr not impl. */
231		status = cmm_create(&dev_obj->hcmm_mgr,
232				    (struct dev_object *)dev_obj, NULL);
233		/* Only create IO manager if we have a channel manager */
234		if (!status && dev_obj->hchnl_mgr) {
235			status = io_create(&dev_obj->hio_mgr, dev_obj,
236					   &io_mgr_attrs);
237		}
238		/* Only create DEH manager if we have an IO manager */
239		if (!status) {
240			/* Instantiate the DEH module */
241			status = bridge_deh_create(&dev_obj->hdeh_mgr, dev_obj);
242		}
243		/* Create DMM mgr . */
244		status = dmm_create(&dev_obj->dmm_mgr,
245				    (struct dev_object *)dev_obj, NULL);
246	}
247	/* Add the new DEV_Object to the global list: */
248	if (!status) {
249		lst_init_elem(&dev_obj->link);
250		status = drv_insert_dev_object(hdrv_obj, dev_obj);
251	}
252	/* Create the Processor List */
253	if (!status) {
254		dev_obj->proc_list = kzalloc(sizeof(struct lst_list),
255							GFP_KERNEL);
256		if (!(dev_obj->proc_list))
257			status = -EPERM;
258		else
259			INIT_LIST_HEAD(&dev_obj->proc_list->head);
260	}
261leave:
262	/*  If all went well, return a handle to the dev object;
263	 *  else, cleanup and return NULL in the OUT parameter. */
264	if (!status) {
265		*device_obj = dev_obj;
266	} else {
267		if (dev_obj) {
268			kfree(dev_obj->proc_list);
269			if (dev_obj->cod_mgr)
270				cod_delete(dev_obj->cod_mgr);
271			if (dev_obj->dmm_mgr)
272				dmm_destroy(dev_obj->dmm_mgr);
273			kfree(dev_obj);
274		}
275
276		*device_obj = NULL;
277	}
278
279	DBC_ENSURE((!status && *device_obj) || (status && !*device_obj));
280	return status;
281}
282
283/*
284 *  ======== dev_create2 ========
285 *  Purpose:
286 *      After successful loading of the image from api_init_complete2
287 *      (PROC Auto_Start) or proc_load this fxn is called. This creates
288 *      the Node Manager and updates the DEV Object.
289 */
290int dev_create2(struct dev_object *hdev_obj)
291{
292	int status = 0;
293	struct dev_object *dev_obj = hdev_obj;
294
295	DBC_REQUIRE(refs > 0);
296	DBC_REQUIRE(hdev_obj);
297
298	/* There can be only one Node Manager per DEV object */
299	DBC_ASSERT(!dev_obj->hnode_mgr);
300	status = node_create_mgr(&dev_obj->hnode_mgr, hdev_obj);
301	if (status)
302		dev_obj->hnode_mgr = NULL;
303
304	DBC_ENSURE((!status && dev_obj->hnode_mgr != NULL)
305		   || (status && dev_obj->hnode_mgr == NULL));
306	return status;
307}
308
309/*
310 *  ======== dev_destroy2 ========
311 *  Purpose:
312 *      Destroys the Node manager for this device.
313 */
314int dev_destroy2(struct dev_object *hdev_obj)
315{
316	int status = 0;
317	struct dev_object *dev_obj = hdev_obj;
318
319	DBC_REQUIRE(refs > 0);
320	DBC_REQUIRE(hdev_obj);
321
322	if (dev_obj->hnode_mgr) {
323		if (node_delete_mgr(dev_obj->hnode_mgr))
324			status = -EPERM;
325		else
326			dev_obj->hnode_mgr = NULL;
327
328	}
329
330	DBC_ENSURE((!status && dev_obj->hnode_mgr == NULL) || status);
331	return status;
332}
333
334/*
335 *  ======== dev_destroy_device ========
336 *  Purpose:
337 *      Destroys the channel manager for this device, if any, calls
338 *      bridge_dev_destroy(), and then attempts to unload the Bridge module.
339 */
340int dev_destroy_device(struct dev_object *hdev_obj)
341{
342	int status = 0;
343	struct dev_object *dev_obj = hdev_obj;
344
345	DBC_REQUIRE(refs > 0);
346
347	if (hdev_obj) {
348		if (dev_obj->cod_mgr) {
349			cod_delete(dev_obj->cod_mgr);
350			dev_obj->cod_mgr = NULL;
351		}
352
353		if (dev_obj->hnode_mgr) {
354			node_delete_mgr(dev_obj->hnode_mgr);
355			dev_obj->hnode_mgr = NULL;
356		}
357
358		/* Free the io, channel, and message managers for this board: */
359		if (dev_obj->hio_mgr) {
360			io_destroy(dev_obj->hio_mgr);
361			dev_obj->hio_mgr = NULL;
362		}
363		if (dev_obj->hchnl_mgr) {
364			chnl_destroy(dev_obj->hchnl_mgr);
365			dev_obj->hchnl_mgr = NULL;
366		}
367		if (dev_obj->hmsg_mgr) {
368			msg_delete(dev_obj->hmsg_mgr);
369			dev_obj->hmsg_mgr = NULL;
370		}
371
372		if (dev_obj->hdeh_mgr) {
373			/* Uninitialize DEH module. */
374			bridge_deh_destroy(dev_obj->hdeh_mgr);
375			dev_obj->hdeh_mgr = NULL;
376		}
377		if (dev_obj->hcmm_mgr) {
378			cmm_destroy(dev_obj->hcmm_mgr, true);
379			dev_obj->hcmm_mgr = NULL;
380		}
381
382		if (dev_obj->dmm_mgr) {
383			dmm_destroy(dev_obj->dmm_mgr);
384			dev_obj->dmm_mgr = NULL;
385		}
386
387		/* Call the driver's bridge_dev_destroy() function: */
388		/* Require of DevDestroy */
389		if (dev_obj->hbridge_context) {
390			status = (*dev_obj->bridge_interface.pfn_dev_destroy)
391			    (dev_obj->hbridge_context);
392			dev_obj->hbridge_context = NULL;
393		} else
394			status = -EPERM;
395		if (!status) {
396			kfree(dev_obj->proc_list);
397			dev_obj->proc_list = NULL;
398
399			/* Remove this DEV_Object from the global list: */
400			drv_remove_dev_object(dev_obj->hdrv_obj, dev_obj);
401			/* Free The library * LDR_FreeModule
402			 * (dev_obj->module_obj); */
403			/* Free this dev object: */
404			kfree(dev_obj);
405			dev_obj = NULL;
406		}
407	} else {
408		status = -EFAULT;
409	}
410
411	return status;
412}
413
414/*
415 *  ======== dev_get_chnl_mgr ========
416 *  Purpose:
417 *      Retrieve the handle to the channel manager handle created for this
418 *      device.
419 */
420int dev_get_chnl_mgr(struct dev_object *hdev_obj,
421			    struct chnl_mgr **mgr)
422{
423	int status = 0;
424	struct dev_object *dev_obj = hdev_obj;
425
426	DBC_REQUIRE(refs > 0);
427	DBC_REQUIRE(mgr != NULL);
428
429	if (hdev_obj) {
430		*mgr = dev_obj->hchnl_mgr;
431	} else {
432		*mgr = NULL;
433		status = -EFAULT;
434	}
435
436	DBC_ENSURE(!status || (mgr != NULL && *mgr == NULL));
437	return status;
438}
439
440/*
441 *  ======== dev_get_cmm_mgr ========
442 *  Purpose:
443 *      Retrieve the handle to the shared memory manager created for this
444 *      device.
445 */
446int dev_get_cmm_mgr(struct dev_object *hdev_obj,
447			   struct cmm_object **mgr)
448{
449	int status = 0;
450	struct dev_object *dev_obj = hdev_obj;
451
452	DBC_REQUIRE(refs > 0);
453	DBC_REQUIRE(mgr != NULL);
454
455	if (hdev_obj) {
456		*mgr = dev_obj->hcmm_mgr;
457	} else {
458		*mgr = NULL;
459		status = -EFAULT;
460	}
461
462	DBC_ENSURE(!status || (mgr != NULL && *mgr == NULL));
463	return status;
464}
465
466/*
467 *  ======== dev_get_dmm_mgr ========
468 *  Purpose:
469 *      Retrieve the handle to the dynamic memory manager created for this
470 *      device.
471 */
472int dev_get_dmm_mgr(struct dev_object *hdev_obj,
473			   struct dmm_object **mgr)
474{
475	int status = 0;
476	struct dev_object *dev_obj = hdev_obj;
477
478	DBC_REQUIRE(refs > 0);
479	DBC_REQUIRE(mgr != NULL);
480
481	if (hdev_obj) {
482		*mgr = dev_obj->dmm_mgr;
483	} else {
484		*mgr = NULL;
485		status = -EFAULT;
486	}
487
488	DBC_ENSURE(!status || (mgr != NULL && *mgr == NULL));
489	return status;
490}
491
492/*
493 *  ======== dev_get_cod_mgr ========
494 *  Purpose:
495 *      Retrieve the COD manager create for this device.
496 */
497int dev_get_cod_mgr(struct dev_object *hdev_obj,
498			   struct cod_manager **cod_mgr)
499{
500	int status = 0;
501	struct dev_object *dev_obj = hdev_obj;
502
503	DBC_REQUIRE(refs > 0);
504	DBC_REQUIRE(cod_mgr != NULL);
505
506	if (hdev_obj) {
507		*cod_mgr = dev_obj->cod_mgr;
508	} else {
509		*cod_mgr = NULL;
510		status = -EFAULT;
511	}
512
513	DBC_ENSURE(!status || (cod_mgr != NULL && *cod_mgr == NULL));
514	return status;
515}
516
517/*
518 *  ========= dev_get_deh_mgr ========
519 */
520int dev_get_deh_mgr(struct dev_object *hdev_obj,
521			   struct deh_mgr **deh_manager)
522{
523	int status = 0;
524
525	DBC_REQUIRE(refs > 0);
526	DBC_REQUIRE(deh_manager != NULL);
527	DBC_REQUIRE(hdev_obj);
528	if (hdev_obj) {
529		*deh_manager = hdev_obj->hdeh_mgr;
530	} else {
531		*deh_manager = NULL;
532		status = -EFAULT;
533	}
534	return status;
535}
536
537/*
538 *  ======== dev_get_dev_node ========
539 *  Purpose:
540 *      Retrieve the platform specific device ID for this device.
541 */
542int dev_get_dev_node(struct dev_object *hdev_obj,
543			    struct cfg_devnode **dev_nde)
544{
545	int status = 0;
546	struct dev_object *dev_obj = hdev_obj;
547
548	DBC_REQUIRE(refs > 0);
549	DBC_REQUIRE(dev_nde != NULL);
550
551	if (hdev_obj) {
552		*dev_nde = dev_obj->dev_node_obj;
553	} else {
554		*dev_nde = NULL;
555		status = -EFAULT;
556	}
557
558	DBC_ENSURE(!status || (dev_nde != NULL && *dev_nde == NULL));
559	return status;
560}
561
562/*
563 *  ======== dev_get_first ========
564 *  Purpose:
565 *      Retrieve the first Device Object handle from an internal linked list
566 *      DEV_OBJECTs maintained by DEV.
567 */
568struct dev_object *dev_get_first(void)
569{
570	struct dev_object *dev_obj = NULL;
571
572	dev_obj = (struct dev_object *)drv_get_first_dev_object();
573
574	return dev_obj;
575}
576
577/*
578 *  ======== dev_get_intf_fxns ========
579 *  Purpose:
580 *      Retrieve the Bridge interface function structure for the loaded driver.
581 *      if_fxns != NULL.
582 */
583int dev_get_intf_fxns(struct dev_object *hdev_obj,
584			     struct bridge_drv_interface **if_fxns)
585{
586	int status = 0;
587	struct dev_object *dev_obj = hdev_obj;
588
589	DBC_REQUIRE(refs > 0);
590	DBC_REQUIRE(if_fxns != NULL);
591
592	if (hdev_obj) {
593		*if_fxns = &dev_obj->bridge_interface;
594	} else {
595		*if_fxns = NULL;
596		status = -EFAULT;
597	}
598
599	DBC_ENSURE(!status || ((if_fxns != NULL) && (*if_fxns == NULL)));
600	return status;
601}
602
603/*
604 *  ========= dev_get_io_mgr ========
605 */
606int dev_get_io_mgr(struct dev_object *hdev_obj,
607			  struct io_mgr **io_man)
608{
609	int status = 0;
610
611	DBC_REQUIRE(refs > 0);
612	DBC_REQUIRE(io_man != NULL);
613	DBC_REQUIRE(hdev_obj);
614
615	if (hdev_obj) {
616		*io_man = hdev_obj->hio_mgr;
617	} else {
618		*io_man = NULL;
619		status = -EFAULT;
620	}
621
622	return status;
623}
624
625/*
626 *  ======== dev_get_next ========
627 *  Purpose:
628 *      Retrieve the next Device Object handle from an internal linked list
629 *      of DEV_OBJECTs maintained by DEV, after having previously called
630 *      dev_get_first() and zero or more dev_get_next
631 */
632struct dev_object *dev_get_next(struct dev_object *hdev_obj)
633{
634	struct dev_object *next_dev_object = NULL;
635
636	if (hdev_obj) {
637		next_dev_object = (struct dev_object *)
638		    drv_get_next_dev_object((u32) hdev_obj);
639	}
640
641	return next_dev_object;
642}
643
644/*
645 *  ========= dev_get_msg_mgr ========
646 */
647void dev_get_msg_mgr(struct dev_object *hdev_obj, struct msg_mgr **msg_man)
648{
649	DBC_REQUIRE(refs > 0);
650	DBC_REQUIRE(msg_man != NULL);
651	DBC_REQUIRE(hdev_obj);
652
653	*msg_man = hdev_obj->hmsg_mgr;
654}
655
656/*
657 *  ======== dev_get_node_manager ========
658 *  Purpose:
659 *      Retrieve the Node Manager Handle
660 */
661int dev_get_node_manager(struct dev_object *hdev_obj,
662				struct node_mgr **node_man)
663{
664	int status = 0;
665	struct dev_object *dev_obj = hdev_obj;
666
667	DBC_REQUIRE(refs > 0);
668	DBC_REQUIRE(node_man != NULL);
669
670	if (hdev_obj) {
671		*node_man = dev_obj->hnode_mgr;
672	} else {
673		*node_man = NULL;
674		status = -EFAULT;
675	}
676
677	DBC_ENSURE(!status || (node_man != NULL && *node_man == NULL));
678	return status;
679}
680
681/*
682 *  ======== dev_get_symbol ========
683 */
684int dev_get_symbol(struct dev_object *hdev_obj,
685			  const char *str_sym, u32 * pul_value)
686{
687	int status = 0;
688	struct cod_manager *cod_mgr;
689
690	DBC_REQUIRE(refs > 0);
691	DBC_REQUIRE(str_sym != NULL && pul_value != NULL);
692
693	if (hdev_obj) {
694		status = dev_get_cod_mgr(hdev_obj, &cod_mgr);
695		if (cod_mgr)
696			status = cod_get_sym_value(cod_mgr, (char *)str_sym,
697						   pul_value);
698		else
699			status = -EFAULT;
700	}
701
702	return status;
703}
704
705/*
706 *  ======== dev_get_bridge_context ========
707 *  Purpose:
708 *      Retrieve the Bridge Context handle, as returned by the
709 *      bridge_dev_create fxn.
710 */
711int dev_get_bridge_context(struct dev_object *hdev_obj,
712			       struct bridge_dev_context **phbridge_context)
713{
714	int status = 0;
715	struct dev_object *dev_obj = hdev_obj;
716
717	DBC_REQUIRE(refs > 0);
718	DBC_REQUIRE(phbridge_context != NULL);
719
720	if (hdev_obj) {
721		*phbridge_context = dev_obj->hbridge_context;
722	} else {
723		*phbridge_context = NULL;
724		status = -EFAULT;
725	}
726
727	DBC_ENSURE(!status || ((phbridge_context != NULL) &&
728					     (*phbridge_context == NULL)));
729	return status;
730}
731
732/*
733 *  ======== dev_exit ========
734 *  Purpose:
735 *      Decrement reference count, and free resources when reference count is
736 *      0.
737 */
738void dev_exit(void)
739{
740	DBC_REQUIRE(refs > 0);
741
742	refs--;
743
744	if (refs == 0) {
745		cmm_exit();
746		dmm_exit();
747	}
748
749	DBC_ENSURE(refs >= 0);
750}
751
752/*
753 *  ======== dev_init ========
754 *  Purpose:
755 *      Initialize DEV's private state, keeping a reference count on each call.
756 */
757bool dev_init(void)
758{
759	bool cmm_ret, dmm_ret, ret = true;
760
761	DBC_REQUIRE(refs >= 0);
762
763	if (refs == 0) {
764		cmm_ret = cmm_init();
765		dmm_ret = dmm_init();
766
767		ret = cmm_ret && dmm_ret;
768
769		if (!ret) {
770			if (cmm_ret)
771				cmm_exit();
772
773			if (dmm_ret)
774				dmm_exit();
775
776		}
777	}
778
779	if (ret)
780		refs++;
781
782	DBC_ENSURE((ret && (refs > 0)) || (!ret && (refs >= 0)));
783
784	return ret;
785}
786
787/*
788 *  ======== dev_notify_clients ========
789 *  Purpose:
790 *      Notify all clients of this device of a change in device status.
791 */
792int dev_notify_clients(struct dev_object *hdev_obj, u32 ret)
793{
794	int status = 0;
795
796	struct dev_object *dev_obj = hdev_obj;
797	void *proc_obj;
798
799	for (proc_obj = (void *)lst_first(dev_obj->proc_list);
800	     proc_obj != NULL;
801	     proc_obj = (void *)lst_next(dev_obj->proc_list,
802					 (struct list_head *)proc_obj))
803		proc_notify_clients(proc_obj, (u32) ret);
804
805	return status;
806}
807
808/*
809 *  ======== dev_remove_device ========
810 */
811int dev_remove_device(struct cfg_devnode *dev_node_obj)
812{
813	struct dev_object *hdev_obj;	/* handle to device object */
814	int status = 0;
815	struct dev_object *dev_obj;
816
817	/* Retrieve the device object handle originaly stored with
818	 * the dev_node: */
819	status = cfg_get_dev_object(dev_node_obj, (u32 *) &hdev_obj);
820	if (!status) {
821		/* Remove the Processor List */
822		dev_obj = (struct dev_object *)hdev_obj;
823		/* Destroy the device object. */
824		status = dev_destroy_device(hdev_obj);
825	}
826
827	return status;
828}
829
830/*
831 *  ======== dev_set_chnl_mgr ========
832 *  Purpose:
833 *      Set the channel manager for this device.
834 */
835int dev_set_chnl_mgr(struct dev_object *hdev_obj,
836			    struct chnl_mgr *hmgr)
837{
838	int status = 0;
839	struct dev_object *dev_obj = hdev_obj;
840
841	DBC_REQUIRE(refs > 0);
842
843	if (hdev_obj)
844		dev_obj->hchnl_mgr = hmgr;
845	else
846		status = -EFAULT;
847
848	DBC_ENSURE(status || (dev_obj->hchnl_mgr == hmgr));
849	return status;
850}
851
852/*
853 *  ======== dev_set_msg_mgr ========
854 *  Purpose:
855 *      Set the message manager for this device.
856 */
857void dev_set_msg_mgr(struct dev_object *hdev_obj, struct msg_mgr *hmgr)
858{
859	DBC_REQUIRE(refs > 0);
860	DBC_REQUIRE(hdev_obj);
861
862	hdev_obj->hmsg_mgr = hmgr;
863}
864
865/*
866 *  ======== dev_start_device ========
867 *  Purpose:
868 *      Initializes the new device with the BRIDGE environment.
869 */
870int dev_start_device(struct cfg_devnode *dev_node_obj)
871{
872	struct dev_object *hdev_obj = NULL;	/* handle to 'Bridge Device */
873	/* Bridge driver filename */
874	char bridge_file_name[CFG_MAXSEARCHPATHLEN] = "UMA";
875	int status;
876	struct mgr_object *hmgr_obj = NULL;
877
878	DBC_REQUIRE(refs > 0);
879
880	/* Given all resources, create a device object. */
881	status = dev_create_device(&hdev_obj, bridge_file_name,
882				   dev_node_obj);
883	if (!status) {
884		/* Store away the hdev_obj with the DEVNODE */
885		status = cfg_set_dev_object(dev_node_obj, (u32) hdev_obj);
886		if (status) {
887			/* Clean up */
888			dev_destroy_device(hdev_obj);
889			hdev_obj = NULL;
890		}
891	}
892	if (!status) {
893		/* Create the Manager Object */
894		status = mgr_create(&hmgr_obj, dev_node_obj);
895	}
896	if (status) {
897		if (hdev_obj)
898			dev_destroy_device(hdev_obj);
899
900		/* Ensure the device extension is NULL */
901		cfg_set_dev_object(dev_node_obj, 0L);
902	}
903
904	return status;
905}
906
907/*
908 *  ======== fxn_not_implemented ========
909 *  Purpose:
910 *      Takes the place of a Bridge Null Function.
911 *  Parameters:
912 *      Multiple, optional.
913 *  Returns:
914 *      -ENOSYS:   Always.
915 */
916static int fxn_not_implemented(int arg, ...)
917{
918	return -ENOSYS;
919}
920
921/*
922 *  ======== init_cod_mgr ========
923 *  Purpose:
924 *      Create a COD manager for this device.
925 *  Parameters:
926 *      dev_obj:             Pointer to device object created with
927 *                              dev_create_device()
928 *  Returns:
929 *      0:                Success.
930 *      -EFAULT:            Invalid hdev_obj.
931 *  Requires:
932 *      Should only be called once by dev_create_device() for a given DevObject.
933 *  Ensures:
934 */
935static int init_cod_mgr(struct dev_object *dev_obj)
936{
937	int status = 0;
938	char *sz_dummy_file = "dummy";
939
940	DBC_REQUIRE(refs > 0);
941	DBC_REQUIRE(!dev_obj || (dev_obj->cod_mgr == NULL));
942
943	status = cod_create(&dev_obj->cod_mgr, sz_dummy_file, NULL);
944
945	return status;
946}
947
948/*
949 *  ======== dev_insert_proc_object ========
950 *  Purpose:
951 *      Insert a ProcObject into the list maintained by DEV.
952 *  Parameters:
953 *      p_proc_object:        Ptr to ProcObject to insert.
954 *      dev_obj:         Ptr to Dev Object where the list is.
955  *     already_attached:  Ptr to return the bool
956 *  Returns:
957 *      0:           If successful.
958 *  Requires:
959 *      List Exists
960 *      hdev_obj is Valid handle
961 *      DEV Initialized
962 *      already_attached != NULL
963 *      proc_obj != 0
964 *  Ensures:
965 *      0 and List is not Empty.
966 */
967int dev_insert_proc_object(struct dev_object *hdev_obj,
968				  u32 proc_obj, bool *already_attached)
969{
970	int status = 0;
971	struct dev_object *dev_obj = (struct dev_object *)hdev_obj;
972
973	DBC_REQUIRE(refs > 0);
974	DBC_REQUIRE(dev_obj);
975	DBC_REQUIRE(proc_obj != 0);
976	DBC_REQUIRE(dev_obj->proc_list != NULL);
977	DBC_REQUIRE(already_attached != NULL);
978	if (!LST_IS_EMPTY(dev_obj->proc_list))
979		*already_attached = true;
980
981	/* Add DevObject to tail. */
982	lst_put_tail(dev_obj->proc_list, (struct list_head *)proc_obj);
983
984	DBC_ENSURE(!status && !LST_IS_EMPTY(dev_obj->proc_list));
985
986	return status;
987}
988
989/*
990 *  ======== dev_remove_proc_object ========
991 *  Purpose:
992 *      Search for and remove a Proc object from the given list maintained
993 *      by the DEV
994 *  Parameters:
995 *      p_proc_object:        Ptr to ProcObject to insert.
996 *      dev_obj          Ptr to Dev Object where the list is.
997 *  Returns:
998 *      0:            If successful.
999 *  Requires:
1000 *      List exists and is not empty
1001 *      proc_obj != 0
1002 *      hdev_obj is a valid Dev handle.
1003 *  Ensures:
1004 *  Details:
1005 *      List will be deleted when the DEV is destroyed.
1006 */
1007int dev_remove_proc_object(struct dev_object *hdev_obj, u32 proc_obj)
1008{
1009	int status = -EPERM;
1010	struct list_head *cur_elem;
1011	struct dev_object *dev_obj = (struct dev_object *)hdev_obj;
1012
1013	DBC_REQUIRE(dev_obj);
1014	DBC_REQUIRE(proc_obj != 0);
1015	DBC_REQUIRE(dev_obj->proc_list != NULL);
1016	DBC_REQUIRE(!LST_IS_EMPTY(dev_obj->proc_list));
1017
1018	/* Search list for dev_obj: */
1019	for (cur_elem = lst_first(dev_obj->proc_list); cur_elem != NULL;
1020	     cur_elem = lst_next(dev_obj->proc_list, cur_elem)) {
1021		/* If found, remove it. */
1022		if ((u32) cur_elem == proc_obj) {
1023			lst_remove_elem(dev_obj->proc_list, cur_elem);
1024			status = 0;
1025			break;
1026		}
1027	}
1028
1029	return status;
1030}
1031
1032int dev_get_dev_type(struct dev_object *device_obj, u8 *dev_type)
1033{
1034	int status = 0;
1035	struct dev_object *dev_obj = (struct dev_object *)device_obj;
1036
1037	*dev_type = dev_obj->dev_type;
1038
1039	return status;
1040}
1041
1042/*
1043 *  ======== store_interface_fxns ========
1044 *  Purpose:
1045 *      Copy the Bridge's interface functions into the device object,
1046 *      ensuring that fxn_not_implemented() is set for:
1047 *
1048 *      1. All Bridge function pointers which are NULL; and
1049 *      2. All function slots in the struct dev_object structure which have no
1050 *         corresponding slots in the the Bridge's interface, because the Bridge
1051 *         is of an *older* version.
1052 *  Parameters:
1053 *      intf_fxns:      Interface fxn Structure of the Bridge's Dev Object.
1054 *      drv_fxns:      Interface Fxns offered by the Bridge during DEV_Create().
1055 *  Returns:
1056 *  Requires:
1057 *      Input pointers are valid.
1058 *      Bridge driver is *not* written for a newer DSP API.
1059 *  Ensures:
1060 *      All function pointers in the dev object's fxn interface are not NULL.
1061 */
1062static void store_interface_fxns(struct bridge_drv_interface *drv_fxns,
1063				 struct bridge_drv_interface *intf_fxns)
1064{
1065	u32 bridge_version;
1066
1067	/* Local helper macro: */
1068#define  STORE_FXN(cast, pfn) \
1069    (intf_fxns->pfn = ((drv_fxns->pfn != NULL) ? drv_fxns->pfn : \
1070    (cast)fxn_not_implemented))
1071
1072	DBC_REQUIRE(intf_fxns != NULL);
1073	DBC_REQUIRE(drv_fxns != NULL);
1074	DBC_REQUIRE(MAKEVERSION(drv_fxns->brd_api_major_version,
1075			drv_fxns->brd_api_minor_version) <= BRD_API_VERSION);
1076	bridge_version = MAKEVERSION(drv_fxns->brd_api_major_version,
1077				     drv_fxns->brd_api_minor_version);
1078	intf_fxns->brd_api_major_version = drv_fxns->brd_api_major_version;
1079	intf_fxns->brd_api_minor_version = drv_fxns->brd_api_minor_version;
1080	/* Install functions up to DSP API version .80 (first alpha): */
1081	if (bridge_version > 0) {
1082		STORE_FXN(fxn_dev_create, pfn_dev_create);
1083		STORE_FXN(fxn_dev_destroy, pfn_dev_destroy);
1084		STORE_FXN(fxn_dev_ctrl, pfn_dev_cntrl);
1085		STORE_FXN(fxn_brd_monitor, pfn_brd_monitor);
1086		STORE_FXN(fxn_brd_start, pfn_brd_start);
1087		STORE_FXN(fxn_brd_stop, pfn_brd_stop);
1088		STORE_FXN(fxn_brd_status, pfn_brd_status);
1089		STORE_FXN(fxn_brd_read, pfn_brd_read);
1090		STORE_FXN(fxn_brd_write, pfn_brd_write);
1091		STORE_FXN(fxn_brd_setstate, pfn_brd_set_state);
1092		STORE_FXN(fxn_brd_memcopy, pfn_brd_mem_copy);
1093		STORE_FXN(fxn_brd_memwrite, pfn_brd_mem_write);
1094		STORE_FXN(fxn_brd_memmap, pfn_brd_mem_map);
1095		STORE_FXN(fxn_brd_memunmap, pfn_brd_mem_un_map);
1096		STORE_FXN(fxn_chnl_create, pfn_chnl_create);
1097		STORE_FXN(fxn_chnl_destroy, pfn_chnl_destroy);
1098		STORE_FXN(fxn_chnl_open, pfn_chnl_open);
1099		STORE_FXN(fxn_chnl_close, pfn_chnl_close);
1100		STORE_FXN(fxn_chnl_addioreq, pfn_chnl_add_io_req);
1101		STORE_FXN(fxn_chnl_getioc, pfn_chnl_get_ioc);
1102		STORE_FXN(fxn_chnl_cancelio, pfn_chnl_cancel_io);
1103		STORE_FXN(fxn_chnl_flushio, pfn_chnl_flush_io);
1104		STORE_FXN(fxn_chnl_getinfo, pfn_chnl_get_info);
1105		STORE_FXN(fxn_chnl_getmgrinfo, pfn_chnl_get_mgr_info);
1106		STORE_FXN(fxn_chnl_idle, pfn_chnl_idle);
1107		STORE_FXN(fxn_chnl_registernotify, pfn_chnl_register_notify);
1108		STORE_FXN(fxn_io_create, pfn_io_create);
1109		STORE_FXN(fxn_io_destroy, pfn_io_destroy);
1110		STORE_FXN(fxn_io_onloaded, pfn_io_on_loaded);
1111		STORE_FXN(fxn_io_getprocload, pfn_io_get_proc_load);
1112		STORE_FXN(fxn_msg_create, pfn_msg_create);
1113		STORE_FXN(fxn_msg_createqueue, pfn_msg_create_queue);
1114		STORE_FXN(fxn_msg_delete, pfn_msg_delete);
1115		STORE_FXN(fxn_msg_deletequeue, pfn_msg_delete_queue);
1116		STORE_FXN(fxn_msg_get, pfn_msg_get);
1117		STORE_FXN(fxn_msg_put, pfn_msg_put);
1118		STORE_FXN(fxn_msg_registernotify, pfn_msg_register_notify);
1119		STORE_FXN(fxn_msg_setqueueid, pfn_msg_set_queue_id);
1120	}
1121	/* Add code for any additional functions in newerBridge versions here */
1122	/* Ensure postcondition: */
1123	DBC_ENSURE(intf_fxns->pfn_dev_create != NULL);
1124	DBC_ENSURE(intf_fxns->pfn_dev_destroy != NULL);
1125	DBC_ENSURE(intf_fxns->pfn_dev_cntrl != NULL);
1126	DBC_ENSURE(intf_fxns->pfn_brd_monitor != NULL);
1127	DBC_ENSURE(intf_fxns->pfn_brd_start != NULL);
1128	DBC_ENSURE(intf_fxns->pfn_brd_stop != NULL);
1129	DBC_ENSURE(intf_fxns->pfn_brd_status != NULL);
1130	DBC_ENSURE(intf_fxns->pfn_brd_read != NULL);
1131	DBC_ENSURE(intf_fxns->pfn_brd_write != NULL);
1132	DBC_ENSURE(intf_fxns->pfn_chnl_create != NULL);
1133	DBC_ENSURE(intf_fxns->pfn_chnl_destroy != NULL);
1134	DBC_ENSURE(intf_fxns->pfn_chnl_open != NULL);
1135	DBC_ENSURE(intf_fxns->pfn_chnl_close != NULL);
1136	DBC_ENSURE(intf_fxns->pfn_chnl_add_io_req != NULL);
1137	DBC_ENSURE(intf_fxns->pfn_chnl_get_ioc != NULL);
1138	DBC_ENSURE(intf_fxns->pfn_chnl_cancel_io != NULL);
1139	DBC_ENSURE(intf_fxns->pfn_chnl_flush_io != NULL);
1140	DBC_ENSURE(intf_fxns->pfn_chnl_get_info != NULL);
1141	DBC_ENSURE(intf_fxns->pfn_chnl_get_mgr_info != NULL);
1142	DBC_ENSURE(intf_fxns->pfn_chnl_idle != NULL);
1143	DBC_ENSURE(intf_fxns->pfn_chnl_register_notify != NULL);
1144	DBC_ENSURE(intf_fxns->pfn_io_create != NULL);
1145	DBC_ENSURE(intf_fxns->pfn_io_destroy != NULL);
1146	DBC_ENSURE(intf_fxns->pfn_io_on_loaded != NULL);
1147	DBC_ENSURE(intf_fxns->pfn_io_get_proc_load != NULL);
1148	DBC_ENSURE(intf_fxns->pfn_msg_set_queue_id != NULL);
1149
1150#undef  STORE_FXN
1151}
1152