Fix common misspellings
[deliverable/linux.git] / drivers / staging / tidspbridge / pmgr / dev.c
CommitLineData
c4ca3d5a
ORL
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 */
2094f12d 18#include <linux/types.h>
5fb45dac 19#include <linux/list.h>
c4ca3d5a
ORL
20
21/* ----------------------------------- Host OS */
22#include <dspbridge/host_os.h>
23
24/* ----------------------------------- DSP/BIOS Bridge */
c4ca3d5a
ORL
25#include <dspbridge/dbdefs.h>
26
27/* ----------------------------------- Trace & Debug */
28#include <dspbridge/dbc.h>
29
c4ca3d5a
ORL
30/* ----------------------------------- Platform Manager */
31#include <dspbridge/cod.h>
32#include <dspbridge/drv.h>
33#include <dspbridge/proc.h>
677f2ded 34#include <dspbridge/dmm.h>
c4ca3d5a
ORL
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>
61a5b769 47#include <dspbridge/dspdeh.h>
c4ca3d5a
ORL
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: */
59struct dev_object {
c4ca3d5a
ORL
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 */
085467b8 64 struct bridge_dev_context *bridge_context;
c4ca3d5a
ORL
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. */
085467b8
RS
69 struct chnl_mgr *chnl_mgr; /* Channel manager. */
70 struct deh_mgr *deh_mgr; /* DEH manager. */
71 struct msg_mgr *msg_mgr; /* Message manager. */
121e8f9b 72 struct io_mgr *iomgr; /* IO manager (CHNL, msg_ctrl) */
085467b8 73 struct cmm_object *cmm_mgr; /* SM memory manager. */
677f2ded 74 struct dmm_object *dmm_mgr; /* Dynamic memory manager. */
c4ca3d5a 75 u32 word_size; /* DSP word size: quick access. */
085467b8 76 struct drv_object *drv_obj; /* Driver Object */
ba44df6f
IN
77 /* List of Processors attached to this device */
78 struct list_head proc_list;
085467b8 79 struct node_mgr *node_mgr;
c4ca3d5a
ORL
80};
81
e8184e6c
IGC
82struct drv_ext {
83 struct list_head link;
84 char sz_string[MAXREGPATHLENGTH];
85};
86
c4ca3d5a
ORL
87/* ----------------------------------- Globals */
88static u32 refs; /* Module reference count */
89
90/* ----------------------------------- Function Prototypes */
91static int fxn_not_implemented(int arg, ...);
92static int init_cod_mgr(struct dev_object *dev_obj);
93static void store_interface_fxns(struct bridge_drv_interface *drv_fxns,
e6bf74f0 94 struct bridge_drv_interface *intf_fxns);
c4ca3d5a
ORL
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 */
5e2eae57 102u32 dev_brd_write_fxn(void *arb, u32 dsp_add, void *host_buf,
95870a88 103 u32 ul_num_bytes, u32 mem_space)
c4ca3d5a 104{
aa09b091 105 struct dev_object *dev_obj = (struct dev_object *)arb;
c4ca3d5a
ORL
106 u32 ul_written = 0;
107 int status;
108
109 DBC_REQUIRE(refs > 0);
daa89e6c 110 DBC_REQUIRE(host_buf != NULL); /* Required of BrdWrite(). */
c4ca3d5a
ORL
111 if (dev_obj) {
112 /* Require of BrdWrite() */
085467b8 113 DBC_ASSERT(dev_obj->bridge_context != NULL);
e17ba7f2 114 status = (*dev_obj->bridge_interface.brd_write) (
085467b8 115 dev_obj->bridge_context, host_buf,
5e2eae57 116 dsp_add, ul_num_bytes, mem_space);
c4ca3d5a
ORL
117 /* Special case of getting the address only */
118 if (ul_num_bytes == 0)
119 ul_num_bytes = 1;
157990f0 120 if (!status)
c4ca3d5a
ORL
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 */
e6bf74f0 133int dev_create_device(struct dev_object **device_obj,
9d7d0a52 134 const char *driver_file_name,
c4ca3d5a
ORL
135 struct cfg_devnode *dev_node_obj)
136{
137 struct cfg_hostres *host_res;
c4ca3d5a
ORL
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;
73b87a91 144 struct drv_data *drv_datap = dev_get_drvdata(bridge);
c4ca3d5a
ORL
145 int status = 0;
146 DBC_REQUIRE(refs > 0);
e436d07d 147 DBC_REQUIRE(device_obj != NULL);
c4ca3d5a
ORL
148 DBC_REQUIRE(driver_file_name != NULL);
149
150 status = drv_request_bridge_res_dsp((void *)&host_res);
151
51d5e099 152 if (status) {
c4ca3d5a
ORL
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);
73b87a91
IGC
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 {
c4ca3d5a 165 status = -EPERM;
73b87a91 166 pr_err("%s: Failed to retrieve the object handle\n", __func__);
c4ca3d5a 167 }
73b87a91 168
c4ca3d5a
ORL
169 /* Create the device object, and pass a handle to the Bridge driver for
170 * storage. */
157990f0 171 if (!status) {
c4ca3d5a
ORL
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;
c4ca3d5a 177 dev_obj->cod_mgr = NULL;
085467b8
RS
178 dev_obj->chnl_mgr = NULL;
179 dev_obj->deh_mgr = NULL;
c4ca3d5a
ORL
180 dev_obj->lock_owner = NULL;
181 dev_obj->word_size = DSPWORDSIZE;
085467b8 182 dev_obj->drv_obj = hdrv_obj;
c4ca3d5a
ORL
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. */
09f13304 191 status = (dev_obj->bridge_interface.dev_create)
085467b8 192 (&dev_obj->bridge_context, dev_obj,
c4ca3d5a
ORL
193 host_res);
194 /* Assert bridge_dev_create()'s ensure clause: */
51d5e099 195 DBC_ASSERT(status
085467b8 196 || (dev_obj->bridge_context != NULL));
c4ca3d5a
ORL
197 } else {
198 status = -ENOMEM;
199 }
200 }
201 /* Attempt to create the COD manager for this device: */
157990f0 202 if (!status)
c4ca3d5a
ORL
203 status = init_cod_mgr(dev_obj);
204
205 /* Attempt to create the channel manager for this device: */
157990f0 206 if (!status) {
c4ca3d5a
ORL
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 */
5108de0a
RS
216 io_mgr_attrs.shm_base = host_res->mem_base[1] +
217 host_res->offset_for_monitor;
a534f17b 218 io_mgr_attrs.sm_length =
5108de0a
RS
219 host_res->mem_length[1] -
220 host_res->offset_for_monitor;
c4ca3d5a
ORL
221 } else {
222 io_mgr_attrs.shm_base = 0;
a534f17b 223 io_mgr_attrs.sm_length = 0;
c4ca3d5a
ORL
224 pr_err("%s: No memory reserved for shared structures\n",
225 __func__);
226 }
085467b8 227 status = chnl_create(&dev_obj->chnl_mgr, dev_obj, &mgr_attrs);
c4ca3d5a
ORL
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. */
085467b8 234 status = cmm_create(&dev_obj->cmm_mgr,
c4ca3d5a
ORL
235 (struct dev_object *)dev_obj, NULL);
236 /* Only create IO manager if we have a channel manager */
085467b8 237 if (!status && dev_obj->chnl_mgr) {
121e8f9b 238 status = io_create(&dev_obj->iomgr, dev_obj,
c4ca3d5a
ORL
239 &io_mgr_attrs);
240 }
241 /* Only create DEH manager if we have an IO manager */
157990f0 242 if (!status) {
c4ca3d5a 243 /* Instantiate the DEH module */
085467b8 244 status = bridge_deh_create(&dev_obj->deh_mgr, dev_obj);
c4ca3d5a 245 }
677f2ded
FC
246 /* Create DMM mgr . */
247 status = dmm_create(&dev_obj->dmm_mgr,
248 (struct dev_object *)dev_obj, NULL);
c4ca3d5a
ORL
249 }
250 /* Add the new DEV_Object to the global list: */
5fb45dac 251 if (!status)
c4ca3d5a 252 status = drv_insert_dev_object(hdrv_obj, dev_obj);
5fb45dac 253
c4ca3d5a 254 /* Create the Processor List */
5fb45dac
IN
255 if (!status)
256 INIT_LIST_HEAD(&dev_obj->proc_list);
c4ca3d5a
ORL
257leave:
258 /* If all went well, return a handle to the dev object;
157990f0
ER
259 * else, cleanup and return NULL in the OUT parameter. */
260 if (!status) {
e436d07d 261 *device_obj = dev_obj;
c4ca3d5a
ORL
262 } else {
263 if (dev_obj) {
c4ca3d5a
ORL
264 if (dev_obj->cod_mgr)
265 cod_delete(dev_obj->cod_mgr);
677f2ded
FC
266 if (dev_obj->dmm_mgr)
267 dmm_destroy(dev_obj->dmm_mgr);
c4ca3d5a
ORL
268 kfree(dev_obj);
269 }
270
e436d07d 271 *device_obj = NULL;
c4ca3d5a
ORL
272 }
273
51d5e099 274 DBC_ENSURE((!status && *device_obj) || (status && !*device_obj));
c4ca3d5a
ORL
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 */
285int 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 */
085467b8
RS
294 DBC_ASSERT(!dev_obj->node_mgr);
295 status = node_create_mgr(&dev_obj->node_mgr, hdev_obj);
51d5e099 296 if (status)
085467b8 297 dev_obj->node_mgr = NULL;
c4ca3d5a 298
085467b8
RS
299 DBC_ENSURE((!status && dev_obj->node_mgr != NULL)
300 || (status && dev_obj->node_mgr == NULL));
c4ca3d5a
ORL
301 return status;
302}
303
304/*
305 * ======== dev_destroy2 ========
306 * Purpose:
307 * Destroys the Node manager for this device.
308 */
309int 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
085467b8
RS
317 if (dev_obj->node_mgr) {
318 if (node_delete_mgr(dev_obj->node_mgr))
c4ca3d5a
ORL
319 status = -EPERM;
320 else
085467b8 321 dev_obj->node_mgr = NULL;
c4ca3d5a
ORL
322
323 }
324
085467b8 325 DBC_ENSURE((!status && dev_obj->node_mgr == NULL) || status);
c4ca3d5a
ORL
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 */
335int 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
085467b8
RS
348 if (dev_obj->node_mgr) {
349 node_delete_mgr(dev_obj->node_mgr);
350 dev_obj->node_mgr = NULL;
c4ca3d5a
ORL
351 }
352
353 /* Free the io, channel, and message managers for this board: */
121e8f9b
RS
354 if (dev_obj->iomgr) {
355 io_destroy(dev_obj->iomgr);
356 dev_obj->iomgr = NULL;
c4ca3d5a 357 }
085467b8
RS
358 if (dev_obj->chnl_mgr) {
359 chnl_destroy(dev_obj->chnl_mgr);
360 dev_obj->chnl_mgr = NULL;
c4ca3d5a 361 }
085467b8
RS
362 if (dev_obj->msg_mgr) {
363 msg_delete(dev_obj->msg_mgr);
364 dev_obj->msg_mgr = NULL;
c4ca3d5a
ORL
365 }
366
085467b8 367 if (dev_obj->deh_mgr) {
c4ca3d5a 368 /* Uninitialize DEH module. */
085467b8
RS
369 bridge_deh_destroy(dev_obj->deh_mgr);
370 dev_obj->deh_mgr = NULL;
c4ca3d5a 371 }
085467b8
RS
372 if (dev_obj->cmm_mgr) {
373 cmm_destroy(dev_obj->cmm_mgr, true);
374 dev_obj->cmm_mgr = NULL;
c4ca3d5a
ORL
375 }
376
677f2ded
FC
377 if (dev_obj->dmm_mgr) {
378 dmm_destroy(dev_obj->dmm_mgr);
379 dev_obj->dmm_mgr = NULL;
380 }
381
c4ca3d5a
ORL
382 /* Call the driver's bridge_dev_destroy() function: */
383 /* Require of DevDestroy */
085467b8 384 if (dev_obj->bridge_context) {
09f13304 385 status = (*dev_obj->bridge_interface.dev_destroy)
085467b8
RS
386 (dev_obj->bridge_context);
387 dev_obj->bridge_context = NULL;
c4ca3d5a
ORL
388 } else
389 status = -EPERM;
157990f0 390 if (!status) {
c4ca3d5a 391 /* Remove this DEV_Object from the global list: */
085467b8 392 drv_remove_dev_object(dev_obj->drv_obj, dev_obj);
c4ca3d5a
ORL
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 */
412int dev_get_chnl_mgr(struct dev_object *hdev_obj,
e6bf74f0 413 struct chnl_mgr **mgr)
c4ca3d5a
ORL
414{
415 int status = 0;
416 struct dev_object *dev_obj = hdev_obj;
417
418 DBC_REQUIRE(refs > 0);
e436d07d 419 DBC_REQUIRE(mgr != NULL);
c4ca3d5a
ORL
420
421 if (hdev_obj) {
085467b8 422 *mgr = dev_obj->chnl_mgr;
c4ca3d5a 423 } else {
e436d07d 424 *mgr = NULL;
c4ca3d5a
ORL
425 status = -EFAULT;
426 }
427
157990f0 428 DBC_ENSURE(!status || (mgr != NULL && *mgr == NULL));
c4ca3d5a
ORL
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 */
438int dev_get_cmm_mgr(struct dev_object *hdev_obj,
e6bf74f0 439 struct cmm_object **mgr)
c4ca3d5a
ORL
440{
441 int status = 0;
442 struct dev_object *dev_obj = hdev_obj;
443
444 DBC_REQUIRE(refs > 0);
e436d07d 445 DBC_REQUIRE(mgr != NULL);
c4ca3d5a
ORL
446
447 if (hdev_obj) {
085467b8 448 *mgr = dev_obj->cmm_mgr;
c4ca3d5a 449 } else {
e436d07d 450 *mgr = NULL;
c4ca3d5a
ORL
451 status = -EFAULT;
452 }
453
157990f0 454 DBC_ENSURE(!status || (mgr != NULL && *mgr == NULL));
c4ca3d5a
ORL
455 return status;
456}
457
677f2ded
FC
458/*
459 * ======== dev_get_dmm_mgr ========
460 * Purpose:
461 * Retrieve the handle to the dynamic memory manager created for this
462 * device.
463 */
464int 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
c4ca3d5a
ORL
484/*
485 * ======== dev_get_cod_mgr ========
486 * Purpose:
487 * Retrieve the COD manager create for this device.
488 */
489int dev_get_cod_mgr(struct dev_object *hdev_obj,
e6bf74f0 490 struct cod_manager **cod_mgr)
c4ca3d5a
ORL
491{
492 int status = 0;
493 struct dev_object *dev_obj = hdev_obj;
494
495 DBC_REQUIRE(refs > 0);
a5120278 496 DBC_REQUIRE(cod_mgr != NULL);
c4ca3d5a
ORL
497
498 if (hdev_obj) {
a5120278 499 *cod_mgr = dev_obj->cod_mgr;
c4ca3d5a 500 } else {
a5120278 501 *cod_mgr = NULL;
c4ca3d5a
ORL
502 status = -EFAULT;
503 }
504
157990f0 505 DBC_ENSURE(!status || (cod_mgr != NULL && *cod_mgr == NULL));
c4ca3d5a
ORL
506 return status;
507}
508
509/*
510 * ========= dev_get_deh_mgr ========
511 */
512int dev_get_deh_mgr(struct dev_object *hdev_obj,
e6bf74f0 513 struct deh_mgr **deh_manager)
c4ca3d5a
ORL
514{
515 int status = 0;
516
517 DBC_REQUIRE(refs > 0);
a5120278 518 DBC_REQUIRE(deh_manager != NULL);
c4ca3d5a
ORL
519 DBC_REQUIRE(hdev_obj);
520 if (hdev_obj) {
085467b8 521 *deh_manager = hdev_obj->deh_mgr;
c4ca3d5a 522 } else {
a5120278 523 *deh_manager = NULL;
c4ca3d5a
ORL
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 */
534int dev_get_dev_node(struct dev_object *hdev_obj,
e6bf74f0 535 struct cfg_devnode **dev_nde)
c4ca3d5a
ORL
536{
537 int status = 0;
538 struct dev_object *dev_obj = hdev_obj;
539
540 DBC_REQUIRE(refs > 0);
e436d07d 541 DBC_REQUIRE(dev_nde != NULL);
c4ca3d5a
ORL
542
543 if (hdev_obj) {
e436d07d 544 *dev_nde = dev_obj->dev_node_obj;
c4ca3d5a 545 } else {
e436d07d 546 *dev_nde = NULL;
c4ca3d5a
ORL
547 status = -EFAULT;
548 }
549
157990f0 550 DBC_ENSURE(!status || (dev_nde != NULL && *dev_nde == NULL));
c4ca3d5a
ORL
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 */
560struct 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.
13b18c29 573 * if_fxns != NULL.
c4ca3d5a
ORL
574 */
575int dev_get_intf_fxns(struct dev_object *hdev_obj,
e6bf74f0 576 struct bridge_drv_interface **if_fxns)
c4ca3d5a
ORL
577{
578 int status = 0;
579 struct dev_object *dev_obj = hdev_obj;
580
581 DBC_REQUIRE(refs > 0);
13b18c29 582 DBC_REQUIRE(if_fxns != NULL);
c4ca3d5a
ORL
583
584 if (hdev_obj) {
13b18c29 585 *if_fxns = &dev_obj->bridge_interface;
c4ca3d5a 586 } else {
13b18c29 587 *if_fxns = NULL;
c4ca3d5a
ORL
588 status = -EFAULT;
589 }
590
157990f0 591 DBC_ENSURE(!status || ((if_fxns != NULL) && (*if_fxns == NULL)));
c4ca3d5a
ORL
592 return status;
593}
594
595/*
596 * ========= dev_get_io_mgr ========
597 */
598int dev_get_io_mgr(struct dev_object *hdev_obj,
e6bf74f0 599 struct io_mgr **io_man)
c4ca3d5a
ORL
600{
601 int status = 0;
602
603 DBC_REQUIRE(refs > 0);
e436d07d 604 DBC_REQUIRE(io_man != NULL);
c4ca3d5a
ORL
605 DBC_REQUIRE(hdev_obj);
606
607 if (hdev_obj) {
121e8f9b 608 *io_man = hdev_obj->iomgr;
c4ca3d5a 609 } else {
e436d07d 610 *io_man = NULL;
c4ca3d5a
ORL
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 */
624struct 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 */
e6bf74f0 639void dev_get_msg_mgr(struct dev_object *hdev_obj, struct msg_mgr **msg_man)
c4ca3d5a
ORL
640{
641 DBC_REQUIRE(refs > 0);
e436d07d 642 DBC_REQUIRE(msg_man != NULL);
c4ca3d5a
ORL
643 DBC_REQUIRE(hdev_obj);
644
085467b8 645 *msg_man = hdev_obj->msg_mgr;
c4ca3d5a
ORL
646}
647
648/*
649 * ======== dev_get_node_manager ========
650 * Purpose:
651 * Retrieve the Node Manager Handle
652 */
653int dev_get_node_manager(struct dev_object *hdev_obj,
e6bf74f0 654 struct node_mgr **node_man)
c4ca3d5a
ORL
655{
656 int status = 0;
657 struct dev_object *dev_obj = hdev_obj;
658
659 DBC_REQUIRE(refs > 0);
daa89e6c 660 DBC_REQUIRE(node_man != NULL);
c4ca3d5a
ORL
661
662 if (hdev_obj) {
085467b8 663 *node_man = dev_obj->node_mgr;
c4ca3d5a 664 } else {
daa89e6c 665 *node_man = NULL;
c4ca3d5a
ORL
666 status = -EFAULT;
667 }
668
157990f0 669 DBC_ENSURE(!status || (node_man != NULL && *node_man == NULL));
c4ca3d5a
ORL
670 return status;
671}
672
673/*
674 * ======== dev_get_symbol ========
675 */
676int dev_get_symbol(struct dev_object *hdev_obj,
e6bf74f0 677 const char *str_sym, u32 * pul_value)
c4ca3d5a
ORL
678{
679 int status = 0;
680 struct cod_manager *cod_mgr;
681
682 DBC_REQUIRE(refs > 0);
383b8345 683 DBC_REQUIRE(str_sym != NULL && pul_value != NULL);
c4ca3d5a
ORL
684
685 if (hdev_obj) {
686 status = dev_get_cod_mgr(hdev_obj, &cod_mgr);
687 if (cod_mgr)
383b8345 688 status = cod_get_sym_value(cod_mgr, (char *)str_sym,
c4ca3d5a
ORL
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 */
703int dev_get_bridge_context(struct dev_object *hdev_obj,
e6bf74f0 704 struct bridge_dev_context **phbridge_context)
c4ca3d5a
ORL
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) {
085467b8 713 *phbridge_context = dev_obj->bridge_context;
c4ca3d5a
ORL
714 } else {
715 *phbridge_context = NULL;
716 status = -EFAULT;
717 }
718
157990f0 719 DBC_ENSURE(!status || ((phbridge_context != NULL) &&
c4ca3d5a
ORL
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 */
730void dev_exit(void)
731{
732 DBC_REQUIRE(refs > 0);
733
734 refs--;
735
677f2ded 736 if (refs == 0) {
c4ca3d5a 737 cmm_exit();
677f2ded
FC
738 dmm_exit();
739 }
c4ca3d5a
ORL
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 */
749bool dev_init(void)
750{
677f2ded 751 bool cmm_ret, dmm_ret, ret = true;
c4ca3d5a
ORL
752
753 DBC_REQUIRE(refs >= 0);
754
677f2ded
FC
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 }
c4ca3d5a
ORL
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 */
ba44df6f 784int dev_notify_clients(struct dev_object *dev_obj, u32 ret)
c4ca3d5a 785{
5fb45dac 786 struct list_head *curr;
c4ca3d5a 787
5fb45dac
IN
788 /*
789 * FIXME: this code needs struct proc_object to have a list_head
25985edc 790 * at the beginning. If not, this can go horribly wrong.
5fb45dac
IN
791 */
792 list_for_each(curr, &dev_obj->proc_list)
ba44df6f 793 proc_notify_clients((void *)curr, ret);
c4ca3d5a 794
5fb45dac 795 return 0;
c4ca3d5a
ORL
796}
797
798/*
799 * ======== dev_remove_device ========
800 */
801int dev_remove_device(struct cfg_devnode *dev_node_obj)
802{
803 struct dev_object *hdev_obj; /* handle to device object */
804 int status = 0;
e8184e6c
IGC
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;
c4ca3d5a 812
25985edc 813 /* Retrieve the device object handle originally stored with
c4ca3d5a 814 * the dev_node: */
157990f0 815 if (!status) {
e8184e6c
IGC
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 }
c4ca3d5a
ORL
825 }
826
e8184e6c
IGC
827 if (status)
828 pr_err("%s: Failed, status 0x%x\n", __func__, status);
829
c4ca3d5a
ORL
830 return status;
831}
832
833/*
834 * ======== dev_set_chnl_mgr ========
835 * Purpose:
836 * Set the channel manager for this device.
837 */
838int 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)
085467b8 847 dev_obj->chnl_mgr = hmgr;
c4ca3d5a
ORL
848 else
849 status = -EFAULT;
850
085467b8 851 DBC_ENSURE(status || (dev_obj->chnl_mgr == hmgr));
c4ca3d5a
ORL
852 return status;
853}
854
855/*
856 * ======== dev_set_msg_mgr ========
857 * Purpose:
858 * Set the message manager for this device.
859 */
860void 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
085467b8 865 hdev_obj->msg_mgr = hmgr;
c4ca3d5a
ORL
866}
867
868/*
869 * ======== dev_start_device ========
870 * Purpose:
871 * Initializes the new device with the BRIDGE environment.
872 */
873int 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 */
2c36fac4 877 char *bridge_file_name = "UMA";
c4ca3d5a
ORL
878 int status;
879 struct mgr_object *hmgr_obj = NULL;
a47d4dee 880 struct drv_data *drv_datap = dev_get_drvdata(bridge);
c4ca3d5a
ORL
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);
157990f0 887 if (!status) {
c4ca3d5a 888 /* Store away the hdev_obj with the DEVNODE */
a47d4dee
IGC
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 }
51d5e099 904 if (status) {
c4ca3d5a
ORL
905 /* Clean up */
906 dev_destroy_device(hdev_obj);
907 hdev_obj = NULL;
908 }
909 }
c4ca3d5a
ORL
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 */
923static 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 */
942static 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
5db9e2bf 950 status = cod_create(&dev_obj->cod_mgr, sz_dummy_file);
c4ca3d5a
ORL
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.
aa09b091 962 * already_attached: Ptr to return the bool
c4ca3d5a
ORL
963 * Returns:
964 * 0: If successful.
965 * Requires:
966 * List Exists
967 * hdev_obj is Valid handle
968 * DEV Initialized
aa09b091 969 * already_attached != NULL
c4ca3d5a
ORL
970 * proc_obj != 0
971 * Ensures:
972 * 0 and List is not Empty.
973 */
974int dev_insert_proc_object(struct dev_object *hdev_obj,
e6bf74f0 975 u32 proc_obj, bool *already_attached)
c4ca3d5a 976{
c4ca3d5a
ORL
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);
aa09b091 982 DBC_REQUIRE(already_attached != NULL);
5fb45dac 983 if (!list_empty(&dev_obj->proc_list))
aa09b091 984 *already_attached = true;
c4ca3d5a
ORL
985
986 /* Add DevObject to tail. */
5fb45dac
IN
987 /*
988 * FIXME: this code needs struct proc_object to have a list_head
25985edc 989 * at the beginning. If not, this can go horribly wrong.
5fb45dac
IN
990 */
991 list_add_tail((struct list_head *)proc_obj, &dev_obj->proc_list);
c4ca3d5a 992
ba44df6f 993 return 0;
c4ca3d5a
ORL
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 */
1014int 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);
5fb45dac 1022 DBC_REQUIRE(!list_empty(&dev_obj->proc_list));
c4ca3d5a
ORL
1023
1024 /* Search list for dev_obj: */
5fb45dac 1025 list_for_each(cur_elem, &dev_obj->proc_list) {
c4ca3d5a 1026 if ((u32) cur_elem == proc_obj) {
5fb45dac 1027 list_del(cur_elem);
c4ca3d5a
ORL
1028 status = 0;
1029 break;
1030 }
1031 }
1032
1033 return status;
1034}
1035
ba44df6f 1036int dev_get_dev_type(struct dev_object *dev_obj, u8 *dev_type)
c4ca3d5a 1037{
c4ca3d5a 1038 *dev_type = dev_obj->dev_type;
ba44df6f 1039 return 0;
c4ca3d5a
ORL
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 */
1062static void store_interface_fxns(struct bridge_drv_interface *drv_fxns,
e6bf74f0 1063 struct bridge_drv_interface *intf_fxns)
c4ca3d5a
ORL
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) {
09f13304
RS
1082 STORE_FXN(fxn_dev_create, dev_create);
1083 STORE_FXN(fxn_dev_destroy, dev_destroy);
e17ba7f2 1084 STORE_FXN(fxn_dev_ctrl, dev_cntrl);
3c882de5 1085 STORE_FXN(fxn_brd_monitor, brd_monitor);
e17ba7f2
RS
1086 STORE_FXN(fxn_brd_start, brd_start);
1087 STORE_FXN(fxn_brd_stop, brd_stop);
1088 STORE_FXN(fxn_brd_status, brd_status);
3c882de5 1089 STORE_FXN(fxn_brd_read, brd_read);
e17ba7f2
RS
1090 STORE_FXN(fxn_brd_write, brd_write);
1091 STORE_FXN(fxn_brd_setstate, brd_set_state);
3c882de5
RS
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);
e17ba7f2
RS
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);
09f13304
RS
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);
c4ca3d5a
ORL
1120 }
1121 /* Add code for any additional functions in newerBridge versions here */
1122 /* Ensure postcondition: */
09f13304
RS
1123 DBC_ENSURE(intf_fxns->dev_create != NULL);
1124 DBC_ENSURE(intf_fxns->dev_destroy != NULL);
e17ba7f2 1125 DBC_ENSURE(intf_fxns->dev_cntrl != NULL);
3c882de5 1126 DBC_ENSURE(intf_fxns->brd_monitor != NULL);
e17ba7f2
RS
1127 DBC_ENSURE(intf_fxns->brd_start != NULL);
1128 DBC_ENSURE(intf_fxns->brd_stop != NULL);
1129 DBC_ENSURE(intf_fxns->brd_status != NULL);
3c882de5 1130 DBC_ENSURE(intf_fxns->brd_read != NULL);
e17ba7f2
RS
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);
09f13304
RS
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);
c4ca3d5a
ORL
1149
1150#undef STORE_FXN
1151}
This page took 0.153711 seconds and 5 git commands to generate.