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