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 */
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 
79 struct drv_ext {
80 	struct list_head link;
81 	char sz_string[MAXREGPATHLENGTH];
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  */
dev_brd_write_fxn(void * arb,u32 dsp_add,void * host_buf,u32 ul_num_bytes,u32 mem_space)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  */
dev_create_device(struct dev_object ** device_obj,const char * driver_file_name,struct cfg_devnode * dev_node_obj)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  */
dev_create2(struct dev_object * hdev_obj)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  */
dev_destroy2(struct dev_object * hdev_obj)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  */
dev_destroy_device(struct dev_object * hdev_obj)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  */
dev_get_chnl_mgr(struct dev_object * hdev_obj,struct chnl_mgr ** mgr)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  */
dev_get_cmm_mgr(struct dev_object * hdev_obj,struct cmm_object ** mgr)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  */
dev_get_dmm_mgr(struct dev_object * hdev_obj,struct dmm_object ** mgr)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  */
dev_get_cod_mgr(struct dev_object * hdev_obj,struct cod_manager ** cod_mgr)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  */
dev_get_deh_mgr(struct dev_object * hdev_obj,struct deh_mgr ** deh_manager)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  */
dev_get_dev_node(struct dev_object * hdev_obj,struct cfg_devnode ** dev_nde)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  */
dev_get_first(void)508 struct 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  */
dev_get_intf_fxns(struct dev_object * hdev_obj,struct bridge_drv_interface ** if_fxns)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  */
dev_get_io_mgr(struct dev_object * hdev_obj,struct io_mgr ** io_man)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  */
dev_get_next(struct dev_object * hdev_obj)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  */
dev_get_msg_mgr(struct dev_object * hdev_obj,struct msg_mgr ** msg_man)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  */
dev_get_node_manager(struct dev_object * hdev_obj,struct node_mgr ** node_man)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  */
dev_get_symbol(struct dev_object * hdev_obj,const char * str_sym,u32 * pul_value)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  */
dev_get_bridge_context(struct dev_object * hdev_obj,struct bridge_dev_context ** phbridge_context)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  */
dev_notify_clients(struct dev_object * dev_obj,u32 ret)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  */
dev_remove_device(struct cfg_devnode * dev_node_obj)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  */
dev_set_chnl_mgr(struct dev_object * hdev_obj,struct chnl_mgr * hmgr)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  */
dev_set_msg_mgr(struct dev_object * hdev_obj,struct msg_mgr * hmgr)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  */
dev_start_device(struct cfg_devnode * dev_node_obj)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  */
fxn_not_implemented(int arg,...)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  */
init_cod_mgr(struct dev_object * dev_obj)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  */
dev_insert_proc_object(struct dev_object * hdev_obj,u32 proc_obj,bool * already_attached)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  */
dev_remove_proc_object(struct dev_object * hdev_obj,u32 proc_obj)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 
dev_get_dev_type(struct dev_object * dev_obj,u8 * dev_type)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  */
store_interface_fxns(struct bridge_drv_interface * drv_fxns,struct bridge_drv_interface * intf_fxns)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);
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 }
970