Linux Audio

Check our new training course

Loading...
  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#include <linux/list.h>
 20
 21/*  ----------------------------------- Host OS */
 22#include <dspbridge/host_os.h>
 23
 24/*  ----------------------------------- DSP/BIOS Bridge */
 25#include <dspbridge/dbdefs.h>
 26
 27/*  ----------------------------------- Platform Manager */
 28#include <dspbridge/cod.h>
 29#include <dspbridge/drv.h>
 30#include <dspbridge/proc.h>
 31#include <dspbridge/dmm.h>
 32
 33/*  ----------------------------------- Resource Manager */
 34#include <dspbridge/mgr.h>
 35#include <dspbridge/node.h>
 36
 37/*  ----------------------------------- Others */
 38#include <dspbridge/dspapi.h>	/* DSP API version info. */
 39
 40#include <dspbridge/chnl.h>
 41#include <dspbridge/io.h>
 42#include <dspbridge/msg.h>
 43#include <dspbridge/cmm.h>
 44#include <dspbridge/dspdeh.h>
 45
 46/*  ----------------------------------- This */
 47#include <dspbridge/dev.h>
 48
 49/*  ----------------------------------- Defines, Data Structures, Typedefs */
 50
 51#define MAKEVERSION(major, minor)   (major * 10 + minor)
 52#define BRD_API_VERSION		MAKEVERSION(BRD_API_MAJOR_VERSION,	\
 53				BRD_API_MINOR_VERSION)
 54
 55/* The Bridge device object: */
 56struct dev_object {
 57	struct list_head link;	/* Link to next dev_object. */
 58	u8 dev_type;		/* Device Type */
 59	struct cfg_devnode *dev_node_obj;	/* Platform specific dev id */
 60	/* Bridge Context Handle */
 61	struct bridge_dev_context *bridge_context;
 62	/* Function interface to Bridge driver. */
 63	struct bridge_drv_interface bridge_interface;
 64	struct brd_object *lock_owner;	/* Client with exclusive access. */
 65	struct cod_manager *cod_mgr;	/* Code manager handle. */
 66	struct chnl_mgr *chnl_mgr;	/* Channel manager. */
 67	struct deh_mgr *deh_mgr;	/* DEH manager. */
 68	struct msg_mgr *msg_mgr;	/* Message manager. */
 69	struct io_mgr *iomgr;	/* IO manager (CHNL, msg_ctrl) */
 70	struct cmm_object *cmm_mgr;	/* SM memory manager. */
 71	struct dmm_object *dmm_mgr;	/* Dynamic memory manager. */
 72	u32 word_size;		/* DSP word size: quick access. */
 73	struct drv_object *drv_obj;	/* Driver Object */
 74	/* List of Processors attached to this device */
 75	struct list_head proc_list;
 76	struct node_mgr *node_mgr;
 77};
 78
 79struct drv_ext {
 80	struct list_head link;
 81	char sz_string[MAXREGPATHLENGTH];
 82};
 83
 84/*  ----------------------------------- Function Prototypes */
 85static int fxn_not_implemented(int arg, ...);
 86static int init_cod_mgr(struct dev_object *dev_obj);
 87static void store_interface_fxns(struct bridge_drv_interface *drv_fxns,
 88				 struct bridge_drv_interface *intf_fxns);
 89/*
 90 *  ======== dev_brd_write_fxn ========
 91 *  Purpose:
 92 *      Exported function to be used as the COD write function.  This function
 93 *      is passed a handle to a DEV_hObject, then calls the
 94 *      device's bridge_brd_write() function.
 95 */
 96u32 dev_brd_write_fxn(void *arb, u32 dsp_add, void *host_buf,
 97		      u32 ul_num_bytes, u32 mem_space)
 98{
 99	struct dev_object *dev_obj = (struct dev_object *)arb;
100	u32 ul_written = 0;
101	int status;
102
103	if (dev_obj) {
104		/* Require of BrdWrite() */
105		status = (*dev_obj->bridge_interface.brd_write) (
106					dev_obj->bridge_context, host_buf,
107					dsp_add, ul_num_bytes, mem_space);
108		/* Special case of getting the address only */
109		if (ul_num_bytes == 0)
110			ul_num_bytes = 1;
111		if (!status)
112			ul_written = ul_num_bytes;
113
114	}
115	return ul_written;
116}
117
118/*
119 *  ======== dev_create_device ========
120 *  Purpose:
121 *      Called by the operating system to load the PM Bridge Driver for a
122 *      PM board (device).
123 */
124int dev_create_device(struct dev_object **device_obj,
125			     const char *driver_file_name,
126			     struct cfg_devnode *dev_node_obj)
127{
128	struct cfg_hostres *host_res;
129	struct bridge_drv_interface *drv_fxns = NULL;
130	struct dev_object *dev_obj = NULL;
131	struct chnl_mgrattrs mgr_attrs;
132	struct io_attrs io_mgr_attrs;
133	u32 num_windows;
134	struct drv_object *hdrv_obj = NULL;
135	struct drv_data *drv_datap = dev_get_drvdata(bridge);
136	int status = 0;
137
138	status = drv_request_bridge_res_dsp((void *)&host_res);
139
140	if (status) {
141		dev_dbg(bridge, "%s: Failed to reserve bridge resources\n",
142			__func__);
143		goto leave;
144	}
145
146	/*  Get the Bridge driver interface functions */
147	bridge_drv_entry(&drv_fxns, driver_file_name);
148
149	/* Retrieve the Object handle from the driver data */
150	if (drv_datap && drv_datap->drv_object) {
151		hdrv_obj = drv_datap->drv_object;
152	} else {
153		status = -EPERM;
154		pr_err("%s: Failed to retrieve the object handle\n", __func__);
155	}
156
157	/* Create the device object, and pass a handle to the Bridge driver for
158	 * storage. */
159	if (!status) {
160		dev_obj = kzalloc(sizeof(struct dev_object), GFP_KERNEL);
161		if (dev_obj) {
162			/* Fill out the rest of the Dev Object structure: */
163			dev_obj->dev_node_obj = dev_node_obj;
164			dev_obj->cod_mgr = NULL;
165			dev_obj->chnl_mgr = NULL;
166			dev_obj->deh_mgr = NULL;
167			dev_obj->lock_owner = NULL;
168			dev_obj->word_size = DSPWORDSIZE;
169			dev_obj->drv_obj = hdrv_obj;
170			dev_obj->dev_type = DSP_UNIT;
171			/* Store this Bridge's interface functions, based on its
172			 * version. */
173			store_interface_fxns(drv_fxns,
174						&dev_obj->bridge_interface);
175
176			/* Call fxn_dev_create() to get the Bridge's device
177			 * context handle. */
178			status = (dev_obj->bridge_interface.dev_create)
179			    (&dev_obj->bridge_context, dev_obj,
180			     host_res);
181		} else {
182			status = -ENOMEM;
183		}
184	}
185	/* Attempt to create the COD manager for this device: */
186	if (!status)
187		status = init_cod_mgr(dev_obj);
188
189	/* Attempt to create the channel manager for this device: */
190	if (!status) {
191		mgr_attrs.max_channels = CHNL_MAXCHANNELS;
192		io_mgr_attrs.birq = host_res->birq_registers;
193		io_mgr_attrs.irq_shared =
194		    (host_res->birq_attrib & CFG_IRQSHARED);
195		io_mgr_attrs.word_size = DSPWORDSIZE;
196		mgr_attrs.word_size = DSPWORDSIZE;
197		num_windows = host_res->num_mem_windows;
198		if (num_windows) {
199			/* Assume last memory window is for CHNL */
200			io_mgr_attrs.shm_base = host_res->mem_base[1] +
201			    host_res->offset_for_monitor;
202			io_mgr_attrs.sm_length =
203			    host_res->mem_length[1] -
204			    host_res->offset_for_monitor;
205		} else {
206			io_mgr_attrs.shm_base = 0;
207			io_mgr_attrs.sm_length = 0;
208			pr_err("%s: No memory reserved for shared structures\n",
209			       __func__);
210		}
211		status = chnl_create(&dev_obj->chnl_mgr, dev_obj, &mgr_attrs);
212		if (status == -ENOSYS) {
213			/* It's OK for a device not to have a channel
214			 * manager: */
215			status = 0;
216		}
217		/* Create CMM mgr even if Msg Mgr not impl. */
218		status = cmm_create(&dev_obj->cmm_mgr,
219				    (struct dev_object *)dev_obj, NULL);
220		/* Only create IO manager if we have a channel manager */
221		if (!status && dev_obj->chnl_mgr) {
222			status = io_create(&dev_obj->iomgr, dev_obj,
223					   &io_mgr_attrs);
224		}
225		/* Only create DEH manager if we have an IO manager */
226		if (!status) {
227			/* Instantiate the DEH module */
228			status = bridge_deh_create(&dev_obj->deh_mgr, dev_obj);
229		}
230		/* Create DMM mgr . */
231		status = dmm_create(&dev_obj->dmm_mgr,
232				    (struct dev_object *)dev_obj, NULL);
233	}
234	/* Add the new DEV_Object to the global list: */
235	if (!status)
236		status = drv_insert_dev_object(hdrv_obj, dev_obj);
237
238	/* Create the Processor List */
239	if (!status)
240		INIT_LIST_HEAD(&dev_obj->proc_list);
241leave:
242	/*  If all went well, return a handle to the dev object;
243	 *  else, cleanup and return NULL in the OUT parameter. */
244	if (!status) {
245		*device_obj = dev_obj;
246	} else {
247		if (dev_obj) {
248			if (dev_obj->cod_mgr)
249				cod_delete(dev_obj->cod_mgr);
250			if (dev_obj->dmm_mgr)
251				dmm_destroy(dev_obj->dmm_mgr);
252			kfree(dev_obj);
253		}
254
255		*device_obj = NULL;
256	}
257
258	return status;
259}
260
261/*
262 *  ======== dev_create2 ========
263 *  Purpose:
264 *      After successful loading of the image from api_init_complete2
265 *      (PROC Auto_Start) or proc_load this fxn is called. This creates
266 *      the Node Manager and updates the DEV Object.
267 */
268int dev_create2(struct dev_object *hdev_obj)
269{
270	int status = 0;
271	struct dev_object *dev_obj = hdev_obj;
272
273	/* There can be only one Node Manager per DEV object */
274	status = node_create_mgr(&dev_obj->node_mgr, hdev_obj);
275	if (status)
276		dev_obj->node_mgr = NULL;
277
278	return status;
279}
280
281/*
282 *  ======== dev_destroy2 ========
283 *  Purpose:
284 *      Destroys the Node manager for this device.
285 */
286int dev_destroy2(struct dev_object *hdev_obj)
287{
288	int status = 0;
289	struct dev_object *dev_obj = hdev_obj;
290
291	if (dev_obj->node_mgr) {
292		if (node_delete_mgr(dev_obj->node_mgr))
293			status = -EPERM;
294		else
295			dev_obj->node_mgr = NULL;
296
297	}
298
299	return status;
300}
301
302/*
303 *  ======== dev_destroy_device ========
304 *  Purpose:
305 *      Destroys the channel manager for this device, if any, calls
306 *      bridge_dev_destroy(), and then attempts to unload the Bridge module.
307 */
308int dev_destroy_device(struct dev_object *hdev_obj)
309{
310	int status = 0;
311	struct dev_object *dev_obj = hdev_obj;
312
313	if (hdev_obj) {
314		if (dev_obj->cod_mgr) {
315			cod_delete(dev_obj->cod_mgr);
316			dev_obj->cod_mgr = NULL;
317		}
318
319		if (dev_obj->node_mgr) {
320			node_delete_mgr(dev_obj->node_mgr);
321			dev_obj->node_mgr = NULL;
322		}
323
324		/* Free the io, channel, and message managers for this board: */
325		if (dev_obj->iomgr) {
326			io_destroy(dev_obj->iomgr);
327			dev_obj->iomgr = NULL;
328		}
329		if (dev_obj->chnl_mgr) {
330			chnl_destroy(dev_obj->chnl_mgr);
331			dev_obj->chnl_mgr = NULL;
332		}
333		if (dev_obj->msg_mgr) {
334			msg_delete(dev_obj->msg_mgr);
335			dev_obj->msg_mgr = NULL;
336		}
337
338		if (dev_obj->deh_mgr) {
339			/* Uninitialize DEH module. */
340			bridge_deh_destroy(dev_obj->deh_mgr);
341			dev_obj->deh_mgr = NULL;
342		}
343		if (dev_obj->cmm_mgr) {
344			cmm_destroy(dev_obj->cmm_mgr, true);
345			dev_obj->cmm_mgr = NULL;
346		}
347
348		if (dev_obj->dmm_mgr) {
349			dmm_destroy(dev_obj->dmm_mgr);
350			dev_obj->dmm_mgr = NULL;
351		}
352
353		/* Call the driver's bridge_dev_destroy() function: */
354		/* Require of DevDestroy */
355		if (dev_obj->bridge_context) {
356			status = (*dev_obj->bridge_interface.dev_destroy)
357			    (dev_obj->bridge_context);
358			dev_obj->bridge_context = NULL;
359		} else
360			status = -EPERM;
361		if (!status) {
362			/* Remove this DEV_Object from the global list: */
363			drv_remove_dev_object(dev_obj->drv_obj, dev_obj);
364			/* Free The library * LDR_FreeModule
365			 * (dev_obj->module_obj); */
366			/* Free this dev object: */
367			kfree(dev_obj);
368			dev_obj = NULL;
369		}
370	} else {
371		status = -EFAULT;
372	}
373
374	return status;
375}
376
377/*
378 *  ======== dev_get_chnl_mgr ========
379 *  Purpose:
380 *      Retrieve the handle to the channel manager handle created for this
381 *      device.
382 */
383int dev_get_chnl_mgr(struct dev_object *hdev_obj,
384			    struct chnl_mgr **mgr)
385{
386	int status = 0;
387	struct dev_object *dev_obj = hdev_obj;
388
389	if (hdev_obj) {
390		*mgr = dev_obj->chnl_mgr;
391	} else {
392		*mgr = NULL;
393		status = -EFAULT;
394	}
395
396	return status;
397}
398
399/*
400 *  ======== dev_get_cmm_mgr ========
401 *  Purpose:
402 *      Retrieve the handle to the shared memory manager created for this
403 *      device.
404 */
405int dev_get_cmm_mgr(struct dev_object *hdev_obj,
406			   struct cmm_object **mgr)
407{
408	int status = 0;
409	struct dev_object *dev_obj = hdev_obj;
410
411	if (hdev_obj) {
412		*mgr = dev_obj->cmm_mgr;
413	} else {
414		*mgr = NULL;
415		status = -EFAULT;
416	}
417
418	return status;
419}
420
421/*
422 *  ======== dev_get_dmm_mgr ========
423 *  Purpose:
424 *      Retrieve the handle to the dynamic memory manager created for this
425 *      device.
426 */
427int dev_get_dmm_mgr(struct dev_object *hdev_obj,
428			   struct dmm_object **mgr)
429{
430	int status = 0;
431	struct dev_object *dev_obj = hdev_obj;
432
433	if (hdev_obj) {
434		*mgr = dev_obj->dmm_mgr;
435	} else {
436		*mgr = NULL;
437		status = -EFAULT;
438	}
439
440	return status;
441}
442
443/*
444 *  ======== dev_get_cod_mgr ========
445 *  Purpose:
446 *      Retrieve the COD manager create for this device.
447 */
448int dev_get_cod_mgr(struct dev_object *hdev_obj,
449			   struct cod_manager **cod_mgr)
450{
451	int status = 0;
452	struct dev_object *dev_obj = hdev_obj;
453
454	if (hdev_obj) {
455		*cod_mgr = dev_obj->cod_mgr;
456	} else {
457		*cod_mgr = NULL;
458		status = -EFAULT;
459	}
460
461	return status;
462}
463
464/*
465 *  ========= dev_get_deh_mgr ========
466 */
467int dev_get_deh_mgr(struct dev_object *hdev_obj,
468			   struct deh_mgr **deh_manager)
469{
470	int status = 0;
471
472	if (hdev_obj) {
473		*deh_manager = hdev_obj->deh_mgr;
474	} else {
475		*deh_manager = NULL;
476		status = -EFAULT;
477	}
478	return status;
479}
480
481/*
482 *  ======== dev_get_dev_node ========
483 *  Purpose:
484 *      Retrieve the platform specific device ID for this device.
485 */
486int dev_get_dev_node(struct dev_object *hdev_obj,
487			    struct cfg_devnode **dev_nde)
488{
489	int status = 0;
490	struct dev_object *dev_obj = hdev_obj;
491
492	if (hdev_obj) {
493		*dev_nde = dev_obj->dev_node_obj;
494	} else {
495		*dev_nde = NULL;
496		status = -EFAULT;
497	}
498
499	return status;
500}
501
502/*
503 *  ======== dev_get_first ========
504 *  Purpose:
505 *      Retrieve the first Device Object handle from an internal linked list
506 *      DEV_OBJECTs maintained by DEV.
507 */
508struct dev_object *dev_get_first(void)
509{
510	struct dev_object *dev_obj = NULL;
511
512	dev_obj = (struct dev_object *)drv_get_first_dev_object();
513
514	return dev_obj;
515}
516
517/*
518 *  ======== dev_get_intf_fxns ========
519 *  Purpose:
520 *      Retrieve the Bridge interface function structure for the loaded driver.
521 *      if_fxns != NULL.
522 */
523int dev_get_intf_fxns(struct dev_object *hdev_obj,
524			     struct bridge_drv_interface **if_fxns)
525{
526	int status = 0;
527	struct dev_object *dev_obj = hdev_obj;
528
529	if (hdev_obj) {
530		*if_fxns = &dev_obj->bridge_interface;
531	} else {
532		*if_fxns = NULL;
533		status = -EFAULT;
534	}
535
536	return status;
537}
538
539/*
540 *  ========= dev_get_io_mgr ========
541 */
542int dev_get_io_mgr(struct dev_object *hdev_obj,
543			  struct io_mgr **io_man)
544{
545	int status = 0;
546
547	if (hdev_obj) {
548		*io_man = hdev_obj->iomgr;
549	} else {
550		*io_man = NULL;
551		status = -EFAULT;
552	}
553
554	return status;
555}
556
557/*
558 *  ======== dev_get_next ========
559 *  Purpose:
560 *      Retrieve the next Device Object handle from an internal linked list
561 *      of DEV_OBJECTs maintained by DEV, after having previously called
562 *      dev_get_first() and zero or more dev_get_next
563 */
564struct dev_object *dev_get_next(struct dev_object *hdev_obj)
565{
566	struct dev_object *next_dev_object = NULL;
567
568	if (hdev_obj) {
569		next_dev_object = (struct dev_object *)
570		    drv_get_next_dev_object((u32) hdev_obj);
571	}
572
573	return next_dev_object;
574}
575
576/*
577 *  ========= dev_get_msg_mgr ========
578 */
579void dev_get_msg_mgr(struct dev_object *hdev_obj, struct msg_mgr **msg_man)
580{
581	*msg_man = hdev_obj->msg_mgr;
582}
583
584/*
585 *  ======== dev_get_node_manager ========
586 *  Purpose:
587 *      Retrieve the Node Manager Handle
588 */
589int dev_get_node_manager(struct dev_object *hdev_obj,
590				struct node_mgr **node_man)
591{
592	int status = 0;
593	struct dev_object *dev_obj = hdev_obj;
594
595	if (hdev_obj) {
596		*node_man = dev_obj->node_mgr;
597	} else {
598		*node_man = NULL;
599		status = -EFAULT;
600	}
601
602	return status;
603}
604
605/*
606 *  ======== dev_get_symbol ========
607 */
608int dev_get_symbol(struct dev_object *hdev_obj,
609			  const char *str_sym, u32 * pul_value)
610{
611	int status = 0;
612	struct cod_manager *cod_mgr;
613
614	if (hdev_obj) {
615		status = dev_get_cod_mgr(hdev_obj, &cod_mgr);
616		if (cod_mgr)
617			status = cod_get_sym_value(cod_mgr, (char *)str_sym,
618						   pul_value);
619		else
620			status = -EFAULT;
621	}
622
623	return status;
624}
625
626/*
627 *  ======== dev_get_bridge_context ========
628 *  Purpose:
629 *      Retrieve the Bridge Context handle, as returned by the
630 *      bridge_dev_create fxn.
631 */
632int dev_get_bridge_context(struct dev_object *hdev_obj,
633			       struct bridge_dev_context **phbridge_context)
634{
635	int status = 0;
636	struct dev_object *dev_obj = hdev_obj;
637
638	if (hdev_obj) {
639		*phbridge_context = dev_obj->bridge_context;
640	} else {
641		*phbridge_context = NULL;
642		status = -EFAULT;
643	}
644
645	return status;
646}
647
648/*
649 *  ======== dev_notify_clients ========
650 *  Purpose:
651 *      Notify all clients of this device of a change in device status.
652 */
653int dev_notify_clients(struct dev_object *dev_obj, u32 ret)
654{
655	struct list_head *curr;
656
657	/*
658	 * FIXME: this code needs struct proc_object to have a list_head
659	 * at the beginning. If not, this can go horribly wrong.
660	 */
661	list_for_each(curr, &dev_obj->proc_list)
662		proc_notify_clients((void *)curr, ret);
663
664	return 0;
665}
666
667/*
668 *  ======== dev_remove_device ========
669 */
670int dev_remove_device(struct cfg_devnode *dev_node_obj)
671{
672	struct dev_object *hdev_obj;	/* handle to device object */
673	int status = 0;
674	struct drv_data *drv_datap = dev_get_drvdata(bridge);
675
676	if (!drv_datap)
677		status = -ENODATA;
678
679	if (!dev_node_obj)
680		status = -EFAULT;
681
682	/* Retrieve the device object handle originally stored with
683	 * the dev_node: */
684	if (!status) {
685		/* check the device string and then store dev object */
686		if (!strcmp((char *)((struct drv_ext *)dev_node_obj)->sz_string,
687								"TIOMAP1510")) {
688			hdev_obj = drv_datap->dev_object;
689			/* Destroy the device object. */
690			status = dev_destroy_device(hdev_obj);
691		} else {
692			status = -EPERM;
693		}
694	}
695
696	if (status)
697		pr_err("%s: Failed, status 0x%x\n", __func__, status);
698
699	return status;
700}
701
702/*
703 *  ======== dev_set_chnl_mgr ========
704 *  Purpose:
705 *      Set the channel manager for this device.
706 */
707int dev_set_chnl_mgr(struct dev_object *hdev_obj,
708			    struct chnl_mgr *hmgr)
709{
710	int status = 0;
711	struct dev_object *dev_obj = hdev_obj;
712
713	if (hdev_obj)
714		dev_obj->chnl_mgr = hmgr;
715	else
716		status = -EFAULT;
717
718	return status;
719}
720
721/*
722 *  ======== dev_set_msg_mgr ========
723 *  Purpose:
724 *      Set the message manager for this device.
725 */
726void dev_set_msg_mgr(struct dev_object *hdev_obj, struct msg_mgr *hmgr)
727{
728	hdev_obj->msg_mgr = hmgr;
729}
730
731/*
732 *  ======== dev_start_device ========
733 *  Purpose:
734 *      Initializes the new device with the BRIDGE environment.
735 */
736int dev_start_device(struct cfg_devnode *dev_node_obj)
737{
738	struct dev_object *hdev_obj = NULL;	/* handle to 'Bridge Device */
739	/* Bridge driver filename */
740	char *bridge_file_name = "UMA";
741	int status;
742	struct mgr_object *hmgr_obj = NULL;
743	struct drv_data *drv_datap = dev_get_drvdata(bridge);
744
745	/* Given all resources, create a device object. */
746	status = dev_create_device(&hdev_obj, bridge_file_name,
747				   dev_node_obj);
748	if (!status) {
749		/* Store away the hdev_obj with the DEVNODE */
750		if (!drv_datap || !dev_node_obj) {
751			status = -EFAULT;
752			pr_err("%s: Failed, status 0x%x\n", __func__, status);
753		} else if (!(strcmp((char *)dev_node_obj, "TIOMAP1510"))) {
754			drv_datap->dev_object = (void *) hdev_obj;
755		}
756		if (!status) {
757			/* Create the Manager Object */
758			status = mgr_create(&hmgr_obj, dev_node_obj);
759			if (status && !(strcmp((char *)dev_node_obj,
760							"TIOMAP1510"))) {
761				/* Ensure the device extension is NULL */
762				drv_datap->dev_object = NULL;
763			}
764		}
765		if (status) {
766			/* Clean up */
767			dev_destroy_device(hdev_obj);
768			hdev_obj = NULL;
769		}
770	}
771
772	return status;
773}
774
775/*
776 *  ======== fxn_not_implemented ========
777 *  Purpose:
778 *      Takes the place of a Bridge Null Function.
779 *  Parameters:
780 *      Multiple, optional.
781 *  Returns:
782 *      -ENOSYS:   Always.
783 */
784static int fxn_not_implemented(int arg, ...)
785{
786	return -ENOSYS;
787}
788
789/*
790 *  ======== init_cod_mgr ========
791 *  Purpose:
792 *      Create a COD manager for this device.
793 *  Parameters:
794 *      dev_obj:             Pointer to device object created with
795 *                              dev_create_device()
796 *  Returns:
797 *      0:                Success.
798 *      -EFAULT:            Invalid hdev_obj.
799 *  Requires:
800 *      Should only be called once by dev_create_device() for a given DevObject.
801 *  Ensures:
802 */
803static int init_cod_mgr(struct dev_object *dev_obj)
804{
805	int status = 0;
806	char *sz_dummy_file = "dummy";
807
808	status = cod_create(&dev_obj->cod_mgr, sz_dummy_file);
809
810	return status;
811}
812
813/*
814 *  ======== dev_insert_proc_object ========
815 *  Purpose:
816 *      Insert a ProcObject into the list maintained by DEV.
817 *  Parameters:
818 *      p_proc_object:        Ptr to ProcObject to insert.
819 *      dev_obj:         Ptr to Dev Object where the list is.
820  *     already_attached:  Ptr to return the bool
821 *  Returns:
822 *      0:           If successful.
823 *  Requires:
824 *      List Exists
825 *      hdev_obj is Valid handle
826 *      DEV Initialized
827 *      already_attached != NULL
828 *      proc_obj != 0
829 *  Ensures:
830 *      0 and List is not Empty.
831 */
832int dev_insert_proc_object(struct dev_object *hdev_obj,
833				  u32 proc_obj, bool *already_attached)
834{
835	struct dev_object *dev_obj = (struct dev_object *)hdev_obj;
836
837	if (!list_empty(&dev_obj->proc_list))
838		*already_attached = true;
839
840	/* Add DevObject to tail. */
841	/*
842	 * FIXME: this code needs struct proc_object to have a list_head
843	 * at the beginning. If not, this can go horribly wrong.
844	 */
845	list_add_tail((struct list_head *)proc_obj, &dev_obj->proc_list);
846
847	return 0;
848}
849
850/*
851 *  ======== dev_remove_proc_object ========
852 *  Purpose:
853 *      Search for and remove a Proc object from the given list maintained
854 *      by the DEV
855 *  Parameters:
856 *      p_proc_object:        Ptr to ProcObject to insert.
857 *      dev_obj          Ptr to Dev Object where the list is.
858 *  Returns:
859 *      0:            If successful.
860 *  Requires:
861 *      List exists and is not empty
862 *      proc_obj != 0
863 *      hdev_obj is a valid Dev handle.
864 *  Ensures:
865 *  Details:
866 *      List will be deleted when the DEV is destroyed.
867 */
868int dev_remove_proc_object(struct dev_object *hdev_obj, u32 proc_obj)
869{
870	int status = -EPERM;
871	struct list_head *cur_elem;
872	struct dev_object *dev_obj = (struct dev_object *)hdev_obj;
873
874	/* Search list for dev_obj: */
875	list_for_each(cur_elem, &dev_obj->proc_list) {
876		if ((u32) cur_elem == proc_obj) {
877			list_del(cur_elem);
878			status = 0;
879			break;
880		}
881	}
882
883	return status;
884}
885
886int dev_get_dev_type(struct dev_object *dev_obj, u8 *dev_type)
887{
888	*dev_type = dev_obj->dev_type;
889	return 0;
890}
891
892/*
893 *  ======== store_interface_fxns ========
894 *  Purpose:
895 *      Copy the Bridge's interface functions into the device object,
896 *      ensuring that fxn_not_implemented() is set for:
897 *
898 *      1. All Bridge function pointers which are NULL; and
899 *      2. All function slots in the struct dev_object structure which have no
900 *         corresponding slots in the the Bridge's interface, because the Bridge
901 *         is of an *older* version.
902 *  Parameters:
903 *      intf_fxns:      Interface fxn Structure of the Bridge's Dev Object.
904 *      drv_fxns:      Interface Fxns offered by the Bridge during DEV_Create().
905 *  Returns:
906 *  Requires:
907 *      Input pointers are valid.
908 *      Bridge driver is *not* written for a newer DSP API.
909 *  Ensures:
910 *      All function pointers in the dev object's fxn interface are not NULL.
911 */
912static void store_interface_fxns(struct bridge_drv_interface *drv_fxns,
913				 struct bridge_drv_interface *intf_fxns)
914{
915	u32 bridge_version;
916
917	/* Local helper macro: */
918#define  STORE_FXN(cast, pfn) \
919    (intf_fxns->pfn = ((drv_fxns->pfn != NULL) ? drv_fxns->pfn : \
920    (cast)fxn_not_implemented))
921
922	bridge_version = MAKEVERSION(drv_fxns->brd_api_major_version,
923				     drv_fxns->brd_api_minor_version);
924	intf_fxns->brd_api_major_version = drv_fxns->brd_api_major_version;
925	intf_fxns->brd_api_minor_version = drv_fxns->brd_api_minor_version;
926	/* Install functions up to DSP API version .80 (first alpha): */
927	if (bridge_version > 0) {
928		STORE_FXN(fxn_dev_create, dev_create);
929		STORE_FXN(fxn_dev_destroy, dev_destroy);
930		STORE_FXN(fxn_dev_ctrl, dev_cntrl);
931		STORE_FXN(fxn_brd_monitor, brd_monitor);
932		STORE_FXN(fxn_brd_start, brd_start);
933		STORE_FXN(fxn_brd_stop, brd_stop);
934		STORE_FXN(fxn_brd_status, brd_status);
935		STORE_FXN(fxn_brd_read, brd_read);
936		STORE_FXN(fxn_brd_write, brd_write);
937		STORE_FXN(fxn_brd_setstate, brd_set_state);
938		STORE_FXN(fxn_brd_memcopy, brd_mem_copy);
939		STORE_FXN(fxn_brd_memwrite, brd_mem_write);
940		STORE_FXN(fxn_brd_memmap, brd_mem_map);
941		STORE_FXN(fxn_brd_memunmap, brd_mem_un_map);
942		STORE_FXN(fxn_chnl_create, chnl_create);
943		STORE_FXN(fxn_chnl_destroy, chnl_destroy);
944		STORE_FXN(fxn_chnl_open, chnl_open);
945		STORE_FXN(fxn_chnl_close, chnl_close);
946		STORE_FXN(fxn_chnl_addioreq, chnl_add_io_req);
947		STORE_FXN(fxn_chnl_getioc, chnl_get_ioc);
948		STORE_FXN(fxn_chnl_cancelio, chnl_cancel_io);
949		STORE_FXN(fxn_chnl_flushio, chnl_flush_io);
950		STORE_FXN(fxn_chnl_getinfo, chnl_get_info);
951		STORE_FXN(fxn_chnl_getmgrinfo, chnl_get_mgr_info);
952		STORE_FXN(fxn_chnl_idle, chnl_idle);
953		STORE_FXN(fxn_chnl_registernotify, chnl_register_notify);
954		STORE_FXN(fxn_io_create, io_create);
955		STORE_FXN(fxn_io_destroy, io_destroy);
956		STORE_FXN(fxn_io_onloaded, io_on_loaded);
957		STORE_FXN(fxn_io_getprocload, io_get_proc_load);
958		STORE_FXN(fxn_msg_create, msg_create);
959		STORE_FXN(fxn_msg_createqueue, msg_create_queue);
960		STORE_FXN(fxn_msg_delete, msg_delete);
961		STORE_FXN(fxn_msg_deletequeue, msg_delete_queue);
962		STORE_FXN(fxn_msg_get, msg_get);
963		STORE_FXN(fxn_msg_put, msg_put);
964		STORE_FXN(fxn_msg_registernotify, msg_register_notify);
965		STORE_FXN(fxn_msg_setqueueid, msg_set_queue_id);
966	}
967	/* Add code for any additional functions in newerBridge versions here */
968#undef  STORE_FXN
969}