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