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