Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dev.c
Go to the documentation of this file.
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: */
56 struct 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 */
62  /* Function interface to Bridge driver. */
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 */
76  struct node_mgr *node_mgr;
77 };
78 
79 struct drv_ext {
80  struct list_head link;
82 };
83 
84 /* ----------------------------------- Function Prototypes */
85 static int fxn_not_implemented(int arg, ...);
86 static int init_cod_mgr(struct dev_object *dev_obj);
87 static 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  */
96 u32 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  */
124 int 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);
241 leave:
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  */
268 int 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  */
286 int 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  */
308 int 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  */
383 int 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  */
405 int 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  */
427 int 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  */
448 int 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  */
467 int 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  */
486 int 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  */
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  */
523 int 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  */
542 int 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  */
564 struct 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  */
579 void 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  */
589 int 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  */
608 int 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  */
632 int 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  */
653 int 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  */
670 int 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  */
707 int 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  */
726 void 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  */
736 int 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  */
784 static 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  */
803 static 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  */
832 int 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  */
868 int 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 
886 int 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  */
912 static 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);
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);
956  STORE_FXN(fxn_io_onloaded, io_on_loaded);
957  STORE_FXN(fxn_io_getprocload, io_get_proc_load);
959  STORE_FXN(fxn_msg_createqueue, msg_create_queue);
961  STORE_FXN(fxn_msg_deletequeue, msg_delete_queue);
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 }