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