staging: ti dspbridge: add platform manager code

Add TI's DSP Bridge platform manager driver sources

Signed-off-by: Omar Ramirez Luna <omar.ramirez@ti.com>
Signed-off-by: Kanigeri, Hari <h-kanigeri2@ti.com>
Signed-off-by: Ameya Palande <ameya.palande@nokia.com>
Signed-off-by: Guzman Lugo, Fernando <fernando.lugo@ti.com>
Signed-off-by: Hebbar, Shivananda <x0hebbar@ti.com>
Signed-off-by: Ramos Falcon, Ernesto <ernesto@ti.com>
Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
Signed-off-by: Anna, Suman <s-anna@ti.com>
Signed-off-by: Gupta, Ramesh <grgupta@ti.com>
Signed-off-by: Gomez Castellanos, Ivan <ivan.gomez@ti.com>
Signed-off-by: Andy Shevchenko <ext-andriy.shevchenko@nokia.com>
Signed-off-by: Armando Uribe De Leon <x0095078@ti.com>
Signed-off-by: Deepak Chitriki <deepak.chitriki@ti.com>
Signed-off-by: Menon, Nishanth <nm@ti.com>
Signed-off-by: Phil Carmody <ext-phil.2.carmody@nokia.com>
Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Omar Ramirez Luna 2010-06-23 16:01:57 +03:00 committed by Greg Kroah-Hartman
parent 999e07d632
commit c4ca3d5a4b
12 changed files with 7360 additions and 0 deletions

View file

@ -0,0 +1,163 @@
/*
* chnl.c
*
* DSP-BIOS Bridge driver support functions for TI OMAP processors.
*
* DSP API channel interface: multiplexes data streams through the single
* physical link managed by a Bridge Bridge driver.
*
* Copyright (C) 2005-2006 Texas Instruments, Inc.
*
* This package is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/* ----------------------------------- Host OS */
#include <dspbridge/host_os.h>
/* ----------------------------------- DSP/BIOS Bridge */
#include <dspbridge/std.h>
#include <dspbridge/dbdefs.h>
/* ----------------------------------- Trace & Debug */
#include <dspbridge/dbc.h>
/* ----------------------------------- OS Adaptation Layer */
#include <dspbridge/cfg.h>
#include <dspbridge/sync.h>
/* ----------------------------------- Platform Manager */
#include <dspbridge/proc.h>
#include <dspbridge/dev.h>
/* ----------------------------------- Others */
#include <dspbridge/chnlpriv.h>
#include <chnlobj.h>
/* ----------------------------------- This */
#include <dspbridge/chnl.h>
/* ----------------------------------- Globals */
static u32 refs;
/*
* ======== chnl_create ========
* Purpose:
* Create a channel manager object, responsible for opening new channels
* and closing old ones for a given 'Bridge board.
*/
int chnl_create(OUT struct chnl_mgr **phChnlMgr,
struct dev_object *hdev_obj,
IN CONST struct chnl_mgrattrs *pMgrAttrs)
{
int status;
struct chnl_mgr *hchnl_mgr;
struct chnl_mgr_ *chnl_mgr_obj = NULL;
DBC_REQUIRE(refs > 0);
DBC_REQUIRE(phChnlMgr != NULL);
DBC_REQUIRE(pMgrAttrs != NULL);
*phChnlMgr = NULL;
/* Validate args: */
if ((0 < pMgrAttrs->max_channels) &&
(pMgrAttrs->max_channels <= CHNL_MAXCHANNELS))
status = 0;
else if (pMgrAttrs->max_channels == 0)
status = -EINVAL;
else
status = -ECHRNG;
if (pMgrAttrs->word_size == 0)
status = -EINVAL;
if (DSP_SUCCEEDED(status)) {
status = dev_get_chnl_mgr(hdev_obj, &hchnl_mgr);
if (DSP_SUCCEEDED(status) && hchnl_mgr != NULL)
status = -EEXIST;
}
if (DSP_SUCCEEDED(status)) {
struct bridge_drv_interface *intf_fxns;
dev_get_intf_fxns(hdev_obj, &intf_fxns);
/* Let Bridge channel module finish the create: */
status = (*intf_fxns->pfn_chnl_create) (&hchnl_mgr, hdev_obj,
pMgrAttrs);
if (DSP_SUCCEEDED(status)) {
/* Fill in DSP API channel module's fields of the
* chnl_mgr structure */
chnl_mgr_obj = (struct chnl_mgr_ *)hchnl_mgr;
chnl_mgr_obj->intf_fxns = intf_fxns;
/* Finally, return the new channel manager handle: */
*phChnlMgr = hchnl_mgr;
}
}
DBC_ENSURE(DSP_FAILED(status) || chnl_mgr_obj);
return status;
}
/*
* ======== chnl_destroy ========
* Purpose:
* Close all open channels, and destroy the channel manager.
*/
int chnl_destroy(struct chnl_mgr *hchnl_mgr)
{
struct chnl_mgr_ *chnl_mgr_obj = (struct chnl_mgr_ *)hchnl_mgr;
struct bridge_drv_interface *intf_fxns;
int status;
DBC_REQUIRE(refs > 0);
if (chnl_mgr_obj) {
intf_fxns = chnl_mgr_obj->intf_fxns;
/* Let Bridge channel module destroy the chnl_mgr: */
status = (*intf_fxns->pfn_chnl_destroy) (hchnl_mgr);
} else {
status = -EFAULT;
}
return status;
}
/*
* ======== chnl_exit ========
* Purpose:
* Discontinue usage of the CHNL module.
*/
void chnl_exit(void)
{
DBC_REQUIRE(refs > 0);
refs--;
DBC_ENSURE(refs >= 0);
}
/*
* ======== chnl_init ========
* Purpose:
* Initialize the CHNL module's private state.
*/
bool chnl_init(void)
{
bool ret = true;
DBC_REQUIRE(refs >= 0);
if (ret)
refs++;
DBC_ENSURE((ret && (refs > 0)) || (!ret && (refs >= 0)));
return ret;
}

View file

@ -0,0 +1,46 @@
/*
* chnlobj.h
*
* DSP-BIOS Bridge driver support functions for TI OMAP processors.
*
* Structure subcomponents of channel class library channel objects which
* are exposed to DSP API from Bridge driver.
*
* Copyright (C) 2005-2006 Texas Instruments, Inc.
*
* This package is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef CHNLOBJ_
#define CHNLOBJ_
#include <dspbridge/chnldefs.h>
#include <dspbridge/dspdefs.h>
/*
* This struct is the first field in a chnl_mgr struct. Other. implementation
* specific fields follow this structure in memory.
*/
struct chnl_mgr_ {
/* These must be the first fields in a chnl_mgr struct: */
/* Function interface to Bridge driver. */
struct bridge_drv_interface *intf_fxns;
};
/*
* This struct is the first field in a chnl_object struct. Other,
* implementation specific fields follow this structure in memory.
*/
struct chnl_object_ {
/* These must be the first fields in a chnl_object struct: */
struct chnl_mgr_ *chnl_mgr_obj; /* Pointer back to channel manager. */
};
#endif /* CHNLOBJ_ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,658 @@
/*
* cod.c
*
* DSP-BIOS Bridge driver support functions for TI OMAP processors.
*
* This module implements DSP code management for the DSP/BIOS Bridge
* environment. It is mostly a thin wrapper.
*
* This module provides an interface for loading both static and
* dynamic code objects onto DSP systems.
*
* Copyright (C) 2005-2006 Texas Instruments, Inc.
*
* This package is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/* ----------------------------------- Host OS */
#include <dspbridge/host_os.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
/* ----------------------------------- DSP/BIOS Bridge */
#include <dspbridge/std.h>
#include <dspbridge/dbdefs.h>
/* ----------------------------------- Trace & Debug */
#include <dspbridge/dbc.h>
/* ----------------------------------- OS Adaptation Layer */
#include <dspbridge/ldr.h>
/* ----------------------------------- Platform Manager */
/* Include appropriate loader header file */
#include <dspbridge/dbll.h>
/* ----------------------------------- This */
#include <dspbridge/cod.h>
/* magic number for handle validation */
#define MAGIC 0xc001beef
/* macro to validate COD manager handles */
#define IS_VALID(h) ((h) != NULL && (h)->ul_magic == MAGIC)
/*
* ======== cod_manager ========
*/
struct cod_manager {
struct dbll_tar_obj *target;
struct dbll_library_obj *base_lib;
bool loaded; /* Base library loaded? */
u32 ul_entry;
struct ldr_module *dll_obj;
struct dbll_fxns fxns;
struct dbll_attrs attrs;
char sz_zl_file[COD_MAXPATHLENGTH];
u32 ul_magic;
};
/*
* ======== cod_libraryobj ========
*/
struct cod_libraryobj {
struct dbll_library_obj *dbll_lib;
struct cod_manager *cod_mgr;
};
static u32 refs = 0L;
static struct dbll_fxns ldr_fxns = {
(dbll_close_fxn) dbll_close,
(dbll_create_fxn) dbll_create,
(dbll_delete_fxn) dbll_delete,
(dbll_exit_fxn) dbll_exit,
(dbll_get_attrs_fxn) dbll_get_attrs,
(dbll_get_addr_fxn) dbll_get_addr,
(dbll_get_c_addr_fxn) dbll_get_c_addr,
(dbll_get_sect_fxn) dbll_get_sect,
(dbll_init_fxn) dbll_init,
(dbll_load_fxn) dbll_load,
(dbll_load_sect_fxn) dbll_load_sect,
(dbll_open_fxn) dbll_open,
(dbll_read_sect_fxn) dbll_read_sect,
(dbll_set_attrs_fxn) dbll_set_attrs,
(dbll_unload_fxn) dbll_unload,
(dbll_unload_sect_fxn) dbll_unload_sect,
};
static bool no_op(void);
/*
* File operations (originally were under kfile.c)
*/
static s32 cod_f_close(struct file *filp)
{
/* Check for valid handle */
if (!filp)
return -EFAULT;
filp_close(filp, NULL);
/* we can't use 0 here */
return 0;
}
static struct file *cod_f_open(CONST char *psz_file_name, CONST char *pszMode)
{
mm_segment_t fs;
struct file *filp;
fs = get_fs();
set_fs(get_ds());
/* ignore given mode and open file as read-only */
filp = filp_open(psz_file_name, O_RDONLY, 0);
if (IS_ERR(filp))
filp = NULL;
set_fs(fs);
return filp;
}
static s32 cod_f_read(void __user *pbuffer, s32 size, s32 cCount,
struct file *filp)
{
/* check for valid file handle */
if (!filp)
return -EFAULT;
if ((size > 0) && (cCount > 0) && pbuffer) {
u32 dw_bytes_read;
mm_segment_t fs;
/* read from file */
fs = get_fs();
set_fs(get_ds());
dw_bytes_read = filp->f_op->read(filp, pbuffer, size * cCount,
&(filp->f_pos));
set_fs(fs);
if (!dw_bytes_read)
return -EBADF;
return dw_bytes_read / size;
}
return -EINVAL;
}
static s32 cod_f_seek(struct file *filp, s32 lOffset, s32 cOrigin)
{
loff_t dw_cur_pos;
/* check for valid file handle */
if (!filp)
return -EFAULT;
/* based on the origin flag, move the internal pointer */
dw_cur_pos = filp->f_op->llseek(filp, lOffset, cOrigin);
if ((s32) dw_cur_pos < 0)
return -EPERM;
/* we can't use 0 here */
return 0;
}
static s32 cod_f_tell(struct file *filp)
{
loff_t dw_cur_pos;
if (!filp)
return -EFAULT;
/* Get current position */
dw_cur_pos = filp->f_op->llseek(filp, 0, SEEK_CUR);
if ((s32) dw_cur_pos < 0)
return -EPERM;
return dw_cur_pos;
}
/*
* ======== cod_close ========
*/
void cod_close(struct cod_libraryobj *lib)
{
struct cod_manager *hmgr;
DBC_REQUIRE(refs > 0);
DBC_REQUIRE(lib != NULL);
DBC_REQUIRE(IS_VALID(((struct cod_libraryobj *)lib)->cod_mgr));
hmgr = lib->cod_mgr;
hmgr->fxns.close_fxn(lib->dbll_lib);
kfree(lib);
}
/*
* ======== cod_create ========
* Purpose:
* Create an object to manage code on a DSP system.
* This object can be used to load an initial program image with
* arguments that can later be expanded with
* dynamically loaded object files.
*
*/
int cod_create(OUT struct cod_manager **phMgr, char *pstrDummyFile,
IN OPTIONAL CONST struct cod_attrs *attrs)
{
struct cod_manager *mgr_new;
struct dbll_attrs zl_attrs;
int status = 0;
DBC_REQUIRE(refs > 0);
DBC_REQUIRE(phMgr != NULL);
/* assume failure */
*phMgr = NULL;
/* we don't support non-default attrs yet */
if (attrs != NULL)
return -ENOSYS;
mgr_new = kzalloc(sizeof(struct cod_manager), GFP_KERNEL);
if (mgr_new == NULL)
return -ENOMEM;
mgr_new->ul_magic = MAGIC;
/* Set up loader functions */
mgr_new->fxns = ldr_fxns;
/* initialize the ZL module */
mgr_new->fxns.init_fxn();
zl_attrs.alloc = (dbll_alloc_fxn) no_op;
zl_attrs.free = (dbll_free_fxn) no_op;
zl_attrs.fread = (dbll_read_fxn) cod_f_read;
zl_attrs.fseek = (dbll_seek_fxn) cod_f_seek;
zl_attrs.ftell = (dbll_tell_fxn) cod_f_tell;
zl_attrs.fclose = (dbll_f_close_fxn) cod_f_close;
zl_attrs.fopen = (dbll_f_open_fxn) cod_f_open;
zl_attrs.sym_lookup = NULL;
zl_attrs.base_image = true;
zl_attrs.log_write = NULL;
zl_attrs.log_write_handle = NULL;
zl_attrs.write = NULL;
zl_attrs.rmm_handle = NULL;
zl_attrs.input_params = NULL;
zl_attrs.sym_handle = NULL;
zl_attrs.sym_arg = NULL;
mgr_new->attrs = zl_attrs;
status = mgr_new->fxns.create_fxn(&mgr_new->target, &zl_attrs);
if (DSP_FAILED(status)) {
cod_delete(mgr_new);
return -ESPIPE;
}
/* return the new manager */
*phMgr = mgr_new;
return 0;
}
/*
* ======== cod_delete ========
* Purpose:
* Delete a code manager object.
*/
void cod_delete(struct cod_manager *hmgr)
{
DBC_REQUIRE(refs > 0);
DBC_REQUIRE(IS_VALID(hmgr));
if (hmgr->base_lib) {
if (hmgr->loaded)
hmgr->fxns.unload_fxn(hmgr->base_lib, &hmgr->attrs);
hmgr->fxns.close_fxn(hmgr->base_lib);
}
if (hmgr->target) {
hmgr->fxns.delete_fxn(hmgr->target);
hmgr->fxns.exit_fxn();
}
hmgr->ul_magic = ~MAGIC;
kfree(hmgr);
}
/*
* ======== cod_exit ========
* Purpose:
* Discontinue usage of the COD module.
*
*/
void cod_exit(void)
{
DBC_REQUIRE(refs > 0);
refs--;
DBC_ENSURE(refs >= 0);
}
/*
* ======== cod_get_base_lib ========
* Purpose:
* Get handle to the base image DBL library.
*/
int cod_get_base_lib(struct cod_manager *cod_mgr_obj,
struct dbll_library_obj **plib)
{
int status = 0;
DBC_REQUIRE(refs > 0);
DBC_REQUIRE(IS_VALID(cod_mgr_obj));
DBC_REQUIRE(plib != NULL);
*plib = (struct dbll_library_obj *)cod_mgr_obj->base_lib;
return status;
}
/*
* ======== cod_get_base_name ========
*/
int cod_get_base_name(struct cod_manager *cod_mgr_obj, char *pszName,
u32 usize)
{
int status = 0;
DBC_REQUIRE(refs > 0);
DBC_REQUIRE(IS_VALID(cod_mgr_obj));
DBC_REQUIRE(pszName != NULL);
if (usize <= COD_MAXPATHLENGTH)
strncpy(pszName, cod_mgr_obj->sz_zl_file, usize);
else
status = -EPERM;
return status;
}
/*
* ======== cod_get_entry ========
* Purpose:
* Retrieve the entry point of a loaded DSP program image
*
*/
int cod_get_entry(struct cod_manager *cod_mgr_obj, u32 *pulEntry)
{
DBC_REQUIRE(refs > 0);
DBC_REQUIRE(IS_VALID(cod_mgr_obj));
DBC_REQUIRE(pulEntry != NULL);
*pulEntry = cod_mgr_obj->ul_entry;
return 0;
}
/*
* ======== cod_get_loader ========
* Purpose:
* Get handle to the DBLL loader.
*/
int cod_get_loader(struct cod_manager *cod_mgr_obj,
struct dbll_tar_obj **phLoader)
{
int status = 0;
DBC_REQUIRE(refs > 0);
DBC_REQUIRE(IS_VALID(cod_mgr_obj));
DBC_REQUIRE(phLoader != NULL);
*phLoader = (struct dbll_tar_obj *)cod_mgr_obj->target;
return status;
}
/*
* ======== cod_get_section ========
* Purpose:
* Retrieve the starting address and length of a section in the COFF file
* given the section name.
*/
int cod_get_section(struct cod_libraryobj *lib, IN char *pstrSect,
OUT u32 *puAddr, OUT u32 *puLen)
{
struct cod_manager *cod_mgr_obj;
int status = 0;
DBC_REQUIRE(refs > 0);
DBC_REQUIRE(lib != NULL);
DBC_REQUIRE(IS_VALID(lib->cod_mgr));
DBC_REQUIRE(pstrSect != NULL);
DBC_REQUIRE(puAddr != NULL);
DBC_REQUIRE(puLen != NULL);
*puAddr = 0;
*puLen = 0;
if (lib != NULL) {
cod_mgr_obj = lib->cod_mgr;
status = cod_mgr_obj->fxns.get_sect_fxn(lib->dbll_lib, pstrSect,
puAddr, puLen);
} else {
status = -ESPIPE;
}
DBC_ENSURE(DSP_SUCCEEDED(status) || ((*puAddr == 0) && (*puLen == 0)));
return status;
}
/*
* ======== cod_get_sym_value ========
* Purpose:
* Retrieve the value for the specified symbol. The symbol is first
* searched for literally and then, if not found, searched for as a
* C symbol.
*
*/
int cod_get_sym_value(struct cod_manager *hmgr, char *pstrSym,
u32 *pul_value)
{
struct dbll_sym_val *dbll_sym;
DBC_REQUIRE(refs > 0);
DBC_REQUIRE(IS_VALID(hmgr));
DBC_REQUIRE(pstrSym != NULL);
DBC_REQUIRE(pul_value != NULL);
dev_dbg(bridge, "%s: hmgr: %p pstrSym: %s pul_value: %p\n",
__func__, hmgr, pstrSym, pul_value);
if (hmgr->base_lib) {
if (!hmgr->fxns.
get_addr_fxn(hmgr->base_lib, pstrSym, &dbll_sym)) {
if (!hmgr->fxns.
get_c_addr_fxn(hmgr->base_lib, pstrSym, &dbll_sym))
return -ESPIPE;
}
} else {
return -ESPIPE;
}
*pul_value = dbll_sym->value;
return 0;
}
/*
* ======== cod_init ========
* Purpose:
* Initialize the COD module's private state.
*
*/
bool cod_init(void)
{
bool ret = true;
DBC_REQUIRE(refs >= 0);
if (ret)
refs++;
DBC_ENSURE((ret && refs > 0) || (!ret && refs >= 0));
return ret;
}
/*
* ======== cod_load_base ========
* Purpose:
* Load the initial program image, optionally with command-line arguments,
* on the DSP system managed by the supplied handle. The program to be
* loaded must be the first element of the args array and must be a fully
* qualified pathname.
* Details:
* if nArgc doesn't match the number of arguments in the aArgs array, the
* aArgs array is searched for a NULL terminating entry, and argc is
* recalculated to reflect this. In this way, we can support NULL
* terminating aArgs arrays, if nArgc is very large.
*/
int cod_load_base(struct cod_manager *hmgr, u32 nArgc, char *aArgs[],
cod_writefxn pfn_write, void *pArb, char *envp[])
{
dbll_flags flags;
struct dbll_attrs save_attrs;
struct dbll_attrs new_attrs;
int status;
u32 i;
DBC_REQUIRE(refs > 0);
DBC_REQUIRE(IS_VALID(hmgr));
DBC_REQUIRE(nArgc > 0);
DBC_REQUIRE(aArgs != NULL);
DBC_REQUIRE(aArgs[0] != NULL);
DBC_REQUIRE(pfn_write != NULL);
DBC_REQUIRE(hmgr->base_lib != NULL);
/*
* Make sure every argv[] stated in argc has a value, or change argc to
* reflect true number in NULL terminated argv array.
*/
for (i = 0; i < nArgc; i++) {
if (aArgs[i] == NULL) {
nArgc = i;
break;
}
}
/* set the write function for this operation */
hmgr->fxns.get_attrs_fxn(hmgr->target, &save_attrs);
new_attrs = save_attrs;
new_attrs.write = (dbll_write_fxn) pfn_write;
new_attrs.input_params = pArb;
new_attrs.alloc = (dbll_alloc_fxn) no_op;
new_attrs.free = (dbll_free_fxn) no_op;
new_attrs.log_write = NULL;
new_attrs.log_write_handle = NULL;
/* Load the image */
flags = DBLL_CODE | DBLL_DATA | DBLL_SYMB;
status = hmgr->fxns.load_fxn(hmgr->base_lib, flags, &new_attrs,
&hmgr->ul_entry);
if (DSP_FAILED(status))
hmgr->fxns.close_fxn(hmgr->base_lib);
if (DSP_SUCCEEDED(status))
hmgr->loaded = true;
else
hmgr->base_lib = NULL;
return status;
}
/*
* ======== cod_open ========
* Open library for reading sections.
*/
int cod_open(struct cod_manager *hmgr, IN char *pszCoffPath,
u32 flags, struct cod_libraryobj **pLib)
{
int status = 0;
struct cod_libraryobj *lib = NULL;
DBC_REQUIRE(refs > 0);
DBC_REQUIRE(IS_VALID(hmgr));
DBC_REQUIRE(pszCoffPath != NULL);
DBC_REQUIRE(flags == COD_NOLOAD || flags == COD_SYMB);
DBC_REQUIRE(pLib != NULL);
*pLib = NULL;
lib = kzalloc(sizeof(struct cod_libraryobj), GFP_KERNEL);
if (lib == NULL)
status = -ENOMEM;
if (DSP_SUCCEEDED(status)) {
lib->cod_mgr = hmgr;
status = hmgr->fxns.open_fxn(hmgr->target, pszCoffPath, flags,
&lib->dbll_lib);
if (DSP_SUCCEEDED(status))
*pLib = lib;
}
if (DSP_FAILED(status))
pr_err("%s: error status 0x%x, pszCoffPath: %s flags: 0x%x\n",
__func__, status, pszCoffPath, flags);
return status;
}
/*
* ======== cod_open_base ========
* Purpose:
* Open base image for reading sections.
*/
int cod_open_base(struct cod_manager *hmgr, IN char *pszCoffPath,
dbll_flags flags)
{
int status = 0;
struct dbll_library_obj *lib;
DBC_REQUIRE(refs > 0);
DBC_REQUIRE(IS_VALID(hmgr));
DBC_REQUIRE(pszCoffPath != NULL);
/* if we previously opened a base image, close it now */
if (hmgr->base_lib) {
if (hmgr->loaded) {
hmgr->fxns.unload_fxn(hmgr->base_lib, &hmgr->attrs);
hmgr->loaded = false;
}
hmgr->fxns.close_fxn(hmgr->base_lib);
hmgr->base_lib = NULL;
}
status = hmgr->fxns.open_fxn(hmgr->target, pszCoffPath, flags, &lib);
if (DSP_SUCCEEDED(status)) {
/* hang onto the library for subsequent sym table usage */
hmgr->base_lib = lib;
strncpy(hmgr->sz_zl_file, pszCoffPath, COD_MAXPATHLENGTH - 1);
hmgr->sz_zl_file[COD_MAXPATHLENGTH - 1] = '\0';
}
if (DSP_FAILED(status))
pr_err("%s: error status 0x%x pszCoffPath: %s\n", __func__,
status, pszCoffPath);
return status;
}
/*
* ======== cod_read_section ========
* Purpose:
* Retrieve the content of a code section given the section name.
*/
int cod_read_section(struct cod_libraryobj *lib, IN char *pstrSect,
OUT char *pstrContent, IN u32 cContentSize)
{
int status = 0;
DBC_REQUIRE(refs > 0);
DBC_REQUIRE(lib != NULL);
DBC_REQUIRE(IS_VALID(lib->cod_mgr));
DBC_REQUIRE(pstrSect != NULL);
DBC_REQUIRE(pstrContent != NULL);
if (lib != NULL)
status =
lib->cod_mgr->fxns.read_sect_fxn(lib->dbll_lib, pstrSect,
pstrContent, cContentSize);
else
status = -ESPIPE;
return status;
}
/*
* ======== no_op ========
* Purpose:
* No Operation.
*
*/
static bool no_op(void)
{
return true;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,533 @@
/*
* dmm.c
*
* DSP-BIOS Bridge driver support functions for TI OMAP processors.
*
* The Dynamic Memory Manager (DMM) module manages the DSP Virtual address
* space that can be directly mapped to any MPU buffer or memory region
*
* Notes:
* Region: Generic memory entitiy having a start address and a size
* Chunk: Reserved region
*
* Copyright (C) 2005-2006 Texas Instruments, Inc.
*
* This package is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/* ----------------------------------- Host OS */
#include <dspbridge/host_os.h>
/* ----------------------------------- DSP/BIOS Bridge */
#include <dspbridge/std.h>
#include <dspbridge/dbdefs.h>
/* ----------------------------------- Trace & Debug */
#include <dspbridge/dbc.h>
/* ----------------------------------- OS Adaptation Layer */
#include <dspbridge/sync.h>
/* ----------------------------------- Platform Manager */
#include <dspbridge/dev.h>
#include <dspbridge/proc.h>
/* ----------------------------------- This */
#include <dspbridge/dmm.h>
/* ----------------------------------- Defines, Data Structures, Typedefs */
#define DMM_ADDR_VIRTUAL(a) \
(((struct map_page *)(a) - virtual_mapping_table) * PG_SIZE4K +\
dyn_mem_map_beg)
#define DMM_ADDR_TO_INDEX(a) (((a) - dyn_mem_map_beg) / PG_SIZE4K)
/* DMM Mgr */
struct dmm_object {
/* Dmm Lock is used to serialize access mem manager for
* multi-threads. */
spinlock_t dmm_lock; /* Lock to access dmm mgr */
};
/* ----------------------------------- Globals */
static u32 refs; /* module reference count */
struct map_page {
u32 region_size:15;
u32 mapped_size:15;
u32 reserved:1;
u32 mapped:1;
};
/* Create the free list */
static struct map_page *virtual_mapping_table;
static u32 free_region; /* The index of free region */
static u32 free_size;
static u32 dyn_mem_map_beg; /* The Beginning of dynamic memory mapping */
static u32 table_size; /* The size of virt and phys pages tables */
/* ----------------------------------- Function Prototypes */
static struct map_page *get_region(u32 addr);
static struct map_page *get_free_region(u32 aSize);
static struct map_page *get_mapped_region(u32 aAddr);
/* ======== dmm_create_tables ========
* Purpose:
* Create table to hold the information of physical address
* the buffer pages that is passed by the user, and the table
* to hold the information of the virtual memory that is reserved
* for DSP.
*/
int dmm_create_tables(struct dmm_object *dmm_mgr, u32 addr, u32 size)
{
struct dmm_object *dmm_obj = (struct dmm_object *)dmm_mgr;
int status = 0;
status = dmm_delete_tables(dmm_obj);
if (DSP_SUCCEEDED(status)) {
dyn_mem_map_beg = addr;
table_size = PG_ALIGN_HIGH(size, PG_SIZE4K) / PG_SIZE4K;
/* Create the free list */
virtual_mapping_table = __vmalloc(table_size *
sizeof(struct map_page), GFP_KERNEL |
__GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL);
if (virtual_mapping_table == NULL)
status = -ENOMEM;
else {
/* On successful allocation,
* all entries are zero ('free') */
free_region = 0;
free_size = table_size * PG_SIZE4K;
virtual_mapping_table[0].region_size = table_size;
}
}
if (DSP_FAILED(status))
pr_err("%s: failure, status 0x%x\n", __func__, status);
return status;
}
/*
* ======== dmm_create ========
* Purpose:
* Create a dynamic memory manager object.
*/
int dmm_create(OUT struct dmm_object **phDmmMgr,
struct dev_object *hdev_obj,
IN CONST struct dmm_mgrattrs *pMgrAttrs)
{
struct dmm_object *dmm_obj = NULL;
int status = 0;
DBC_REQUIRE(refs > 0);
DBC_REQUIRE(phDmmMgr != NULL);
*phDmmMgr = NULL;
/* create, zero, and tag a cmm mgr object */
dmm_obj = kzalloc(sizeof(struct dmm_object), GFP_KERNEL);
if (dmm_obj != NULL) {
spin_lock_init(&dmm_obj->dmm_lock);
*phDmmMgr = dmm_obj;
} else {
status = -ENOMEM;
}
return status;
}
/*
* ======== dmm_destroy ========
* Purpose:
* Release the communication memory manager resources.
*/
int dmm_destroy(struct dmm_object *dmm_mgr)
{
struct dmm_object *dmm_obj = (struct dmm_object *)dmm_mgr;
int status = 0;
DBC_REQUIRE(refs > 0);
if (dmm_mgr) {
status = dmm_delete_tables(dmm_obj);
if (DSP_SUCCEEDED(status))
kfree(dmm_obj);
} else
status = -EFAULT;
return status;
}
/*
* ======== dmm_delete_tables ========
* Purpose:
* Delete DMM Tables.
*/
int dmm_delete_tables(struct dmm_object *dmm_mgr)
{
int status = 0;
DBC_REQUIRE(refs > 0);
/* Delete all DMM tables */
if (dmm_mgr)
vfree(virtual_mapping_table);
else
status = -EFAULT;
return status;
}
/*
* ======== dmm_exit ========
* Purpose:
* Discontinue usage of module; free resources when reference count
* reaches 0.
*/
void dmm_exit(void)
{
DBC_REQUIRE(refs > 0);
refs--;
}
/*
* ======== dmm_get_handle ========
* Purpose:
* Return the dynamic memory manager object for this device.
* This is typically called from the client process.
*/
int dmm_get_handle(void *hprocessor, OUT struct dmm_object **phDmmMgr)
{
int status = 0;
struct dev_object *hdev_obj;
DBC_REQUIRE(refs > 0);
DBC_REQUIRE(phDmmMgr != NULL);
if (hprocessor != NULL)
status = proc_get_dev_object(hprocessor, &hdev_obj);
else
hdev_obj = dev_get_first(); /* default */
if (DSP_SUCCEEDED(status))
status = dev_get_dmm_mgr(hdev_obj, phDmmMgr);
return status;
}
/*
* ======== dmm_init ========
* Purpose:
* Initializes private state of DMM module.
*/
bool dmm_init(void)
{
bool ret = true;
DBC_REQUIRE(refs >= 0);
if (ret)
refs++;
DBC_ENSURE((ret && (refs > 0)) || (!ret && (refs >= 0)));
virtual_mapping_table = NULL;
table_size = 0;
return ret;
}
/*
* ======== dmm_map_memory ========
* Purpose:
* Add a mapping block to the reserved chunk. DMM assumes that this block
* will be mapped in the DSP/IVA's address space. DMM returns an error if a
* mapping overlaps another one. This function stores the info that will be
* required later while unmapping the block.
*/
int dmm_map_memory(struct dmm_object *dmm_mgr, u32 addr, u32 size)
{
struct dmm_object *dmm_obj = (struct dmm_object *)dmm_mgr;
struct map_page *chunk;
int status = 0;
spin_lock(&dmm_obj->dmm_lock);
/* Find the Reserved memory chunk containing the DSP block to
* be mapped */
chunk = (struct map_page *)get_region(addr);
if (chunk != NULL) {
/* Mark the region 'mapped', leave the 'reserved' info as-is */
chunk->mapped = true;
chunk->mapped_size = (size / PG_SIZE4K);
} else
status = -ENOENT;
spin_unlock(&dmm_obj->dmm_lock);
dev_dbg(bridge, "%s dmm_mgr %p, addr %x, size %x\n\tstatus %x, "
"chunk %p", __func__, dmm_mgr, addr, size, status, chunk);
return status;
}
/*
* ======== dmm_reserve_memory ========
* Purpose:
* Reserve a chunk of virtually contiguous DSP/IVA address space.
*/
int dmm_reserve_memory(struct dmm_object *dmm_mgr, u32 size,
u32 *prsv_addr)
{
int status = 0;
struct dmm_object *dmm_obj = (struct dmm_object *)dmm_mgr;
struct map_page *node;
u32 rsv_addr = 0;
u32 rsv_size = 0;
spin_lock(&dmm_obj->dmm_lock);
/* Try to get a DSP chunk from the free list */
node = get_free_region(size);
if (node != NULL) {
/* DSP chunk of given size is available. */
rsv_addr = DMM_ADDR_VIRTUAL(node);
/* Calculate the number entries to use */
rsv_size = size / PG_SIZE4K;
if (rsv_size < node->region_size) {
/* Mark remainder of free region */
node[rsv_size].mapped = false;
node[rsv_size].reserved = false;
node[rsv_size].region_size =
node->region_size - rsv_size;
node[rsv_size].mapped_size = 0;
}
/* get_region will return first fit chunk. But we only use what
is requested. */
node->mapped = false;
node->reserved = true;
node->region_size = rsv_size;
node->mapped_size = 0;
/* Return the chunk's starting address */
*prsv_addr = rsv_addr;
} else
/*dSP chunk of given size is not available */
status = -ENOMEM;
spin_unlock(&dmm_obj->dmm_lock);
dev_dbg(bridge, "%s dmm_mgr %p, size %x, prsv_addr %p\n\tstatus %x, "
"rsv_addr %x, rsv_size %x\n", __func__, dmm_mgr, size,
prsv_addr, status, rsv_addr, rsv_size);
return status;
}
/*
* ======== dmm_un_map_memory ========
* Purpose:
* Remove the mapped block from the reserved chunk.
*/
int dmm_un_map_memory(struct dmm_object *dmm_mgr, u32 addr, u32 *psize)
{
struct dmm_object *dmm_obj = (struct dmm_object *)dmm_mgr;
struct map_page *chunk;
int status = 0;
spin_lock(&dmm_obj->dmm_lock);
chunk = get_mapped_region(addr);
if (chunk == NULL)
status = -ENOENT;
if (DSP_SUCCEEDED(status)) {
/* Unmap the region */
*psize = chunk->mapped_size * PG_SIZE4K;
chunk->mapped = false;
chunk->mapped_size = 0;
}
spin_unlock(&dmm_obj->dmm_lock);
dev_dbg(bridge, "%s: dmm_mgr %p, addr %x, psize %p\n\tstatus %x, "
"chunk %p\n", __func__, dmm_mgr, addr, psize, status, chunk);
return status;
}
/*
* ======== dmm_un_reserve_memory ========
* Purpose:
* Free a chunk of reserved DSP/IVA address space.
*/
int dmm_un_reserve_memory(struct dmm_object *dmm_mgr, u32 rsv_addr)
{
struct dmm_object *dmm_obj = (struct dmm_object *)dmm_mgr;
struct map_page *chunk;
u32 i;
int status = 0;
u32 chunk_size;
spin_lock(&dmm_obj->dmm_lock);
/* Find the chunk containing the reserved address */
chunk = get_mapped_region(rsv_addr);
if (chunk == NULL)
status = -ENOENT;
if (DSP_SUCCEEDED(status)) {
/* Free all the mapped pages for this reserved region */
i = 0;
while (i < chunk->region_size) {
if (chunk[i].mapped) {
/* Remove mapping from the page tables. */
chunk_size = chunk[i].mapped_size;
/* Clear the mapping flags */
chunk[i].mapped = false;
chunk[i].mapped_size = 0;
i += chunk_size;
} else
i++;
}
/* Clear the flags (mark the region 'free') */
chunk->reserved = false;
/* NOTE: We do NOT coalesce free regions here.
* Free regions are coalesced in get_region(), as it traverses
*the whole mapping table
*/
}
spin_unlock(&dmm_obj->dmm_lock);
dev_dbg(bridge, "%s: dmm_mgr %p, rsv_addr %x\n\tstatus %x chunk %p",
__func__, dmm_mgr, rsv_addr, status, chunk);
return status;
}
/*
* ======== get_region ========
* Purpose:
* Returns a region containing the specified memory region
*/
static struct map_page *get_region(u32 aAddr)
{
struct map_page *curr_region = NULL;
u32 i = 0;
if (virtual_mapping_table != NULL) {
/* find page mapped by this address */
i = DMM_ADDR_TO_INDEX(aAddr);
if (i < table_size)
curr_region = virtual_mapping_table + i;
}
dev_dbg(bridge, "%s: curr_region %p, free_region %d, free_size %d\n",
__func__, curr_region, free_region, free_size);
return curr_region;
}
/*
* ======== get_free_region ========
* Purpose:
* Returns the requested free region
*/
static struct map_page *get_free_region(u32 aSize)
{
struct map_page *curr_region = NULL;
u32 i = 0;
u32 region_size = 0;
u32 next_i = 0;
if (virtual_mapping_table == NULL)
return curr_region;
if (aSize > free_size) {
/* Find the largest free region
* (coalesce during the traversal) */
while (i < table_size) {
region_size = virtual_mapping_table[i].region_size;
next_i = i + region_size;
if (virtual_mapping_table[i].reserved == false) {
/* Coalesce, if possible */
if (next_i < table_size &&
virtual_mapping_table[next_i].reserved
== false) {
virtual_mapping_table[i].region_size +=
virtual_mapping_table
[next_i].region_size;
continue;
}
region_size *= PG_SIZE4K;
if (region_size > free_size) {
free_region = i;
free_size = region_size;
}
}
i = next_i;
}
}
if (aSize <= free_size) {
curr_region = virtual_mapping_table + free_region;
free_region += (aSize / PG_SIZE4K);
free_size -= aSize;
}
return curr_region;
}
/*
* ======== get_mapped_region ========
* Purpose:
* Returns the requestedmapped region
*/
static struct map_page *get_mapped_region(u32 aAddr)
{
u32 i = 0;
struct map_page *curr_region = NULL;
if (virtual_mapping_table == NULL)
return curr_region;
i = DMM_ADDR_TO_INDEX(aAddr);
if (i < table_size && (virtual_mapping_table[i].mapped ||
virtual_mapping_table[i].reserved))
curr_region = virtual_mapping_table + i;
return curr_region;
}
#ifdef DSP_DMM_DEBUG
u32 dmm_mem_map_dump(struct dmm_object *dmm_mgr)
{
struct map_page *curr_node = NULL;
u32 i;
u32 freemem = 0;
u32 bigsize = 0;
spin_lock(&dmm_mgr->dmm_lock);
if (virtual_mapping_table != NULL) {
for (i = 0; i < table_size; i +=
virtual_mapping_table[i].region_size) {
curr_node = virtual_mapping_table + i;
if (curr_node->reserved == TRUE) {
/*printk("RESERVED size = 0x%x, "
"Map size = 0x%x\n",
(curr_node->region_size * PG_SIZE4K),
(curr_node->mapped == false) ? 0 :
(curr_node->mapped_size * PG_SIZE4K));
*/
} else {
/* printk("UNRESERVED size = 0x%x\n",
(curr_node->region_size * PG_SIZE4K));
*/
freemem += (curr_node->region_size * PG_SIZE4K);
if (curr_node->region_size > bigsize)
bigsize = curr_node->region_size;
}
}
}
spin_unlock(&dmm_mgr->dmm_lock);
printk(KERN_INFO "Total DSP VA FREE memory = %d Mbytes\n",
freemem / (1024 * 1024));
printk(KERN_INFO "Total DSP VA USED memory= %d Mbytes \n",
(((table_size * PG_SIZE4K) - freemem)) / (1024 * 1024));
printk(KERN_INFO "DSP VA - Biggest FREE block = %d Mbytes \n\n",
(bigsize * PG_SIZE4K / (1024 * 1024)));
return 0;
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,142 @@
/*
* io.c
*
* DSP-BIOS Bridge driver support functions for TI OMAP processors.
*
* IO manager interface: Manages IO between CHNL and msg_ctrl.
*
* Copyright (C) 2005-2006 Texas Instruments, Inc.
*
* This package is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/* ----------------------------------- Host OS */
#include <dspbridge/host_os.h>
/* ----------------------------------- DSP/BIOS Bridge */
#include <dspbridge/std.h>
#include <dspbridge/dbdefs.h>
/* ----------------------------------- Trace & Debug */
#include <dspbridge/dbc.h>
/* ----------------------------------- OS Adaptation Layer */
#include <dspbridge/cfg.h>
/* ----------------------------------- Platform Manager */
#include <dspbridge/dev.h>
/* ----------------------------------- This */
#include <ioobj.h>
#include <dspbridge/iodefs.h>
#include <dspbridge/io.h>
/* ----------------------------------- Globals */
static u32 refs;
/*
* ======== io_create ========
* Purpose:
* Create an IO manager object, responsible for managing IO between
* CHNL and msg_ctrl
*/
int io_create(OUT struct io_mgr **phIOMgr, struct dev_object *hdev_obj,
IN CONST struct io_attrs *pMgrAttrs)
{
struct bridge_drv_interface *intf_fxns;
struct io_mgr *hio_mgr = NULL;
struct io_mgr_ *pio_mgr = NULL;
int status = 0;
DBC_REQUIRE(refs > 0);
DBC_REQUIRE(phIOMgr != NULL);
DBC_REQUIRE(pMgrAttrs != NULL);
*phIOMgr = NULL;
/* A memory base of 0 implies no memory base: */
if ((pMgrAttrs->shm_base != 0) && (pMgrAttrs->usm_length == 0))
status = -EINVAL;
if (pMgrAttrs->word_size == 0)
status = -EINVAL;
if (DSP_SUCCEEDED(status)) {
dev_get_intf_fxns(hdev_obj, &intf_fxns);
/* Let Bridge channel module finish the create: */
status = (*intf_fxns->pfn_io_create) (&hio_mgr, hdev_obj,
pMgrAttrs);
if (DSP_SUCCEEDED(status)) {
pio_mgr = (struct io_mgr_ *)hio_mgr;
pio_mgr->intf_fxns = intf_fxns;
pio_mgr->hdev_obj = hdev_obj;
/* Return the new channel manager handle: */
*phIOMgr = hio_mgr;
}
}
return status;
}
/*
* ======== io_destroy ========
* Purpose:
* Delete IO manager.
*/
int io_destroy(struct io_mgr *hio_mgr)
{
struct bridge_drv_interface *intf_fxns;
struct io_mgr_ *pio_mgr = (struct io_mgr_ *)hio_mgr;
int status;
DBC_REQUIRE(refs > 0);
intf_fxns = pio_mgr->intf_fxns;
/* Let Bridge channel module destroy the io_mgr: */
status = (*intf_fxns->pfn_io_destroy) (hio_mgr);
return status;
}
/*
* ======== io_exit ========
* Purpose:
* Discontinue usage of the IO module.
*/
void io_exit(void)
{
DBC_REQUIRE(refs > 0);
refs--;
DBC_ENSURE(refs >= 0);
}
/*
* ======== io_init ========
* Purpose:
* Initialize the IO module's private state.
*/
bool io_init(void)
{
bool ret = true;
DBC_REQUIRE(refs >= 0);
if (ret)
refs++;
DBC_ENSURE((ret && (refs > 0)) || (!ret && (refs >= 0)));
return ret;
}

View file

@ -0,0 +1,38 @@
/*
* ioobj.h
*
* DSP-BIOS Bridge driver support functions for TI OMAP processors.
*
* Structure subcomponents of channel class library IO objects which
* are exposed to DSP API from Bridge driver.
*
* Copyright (C) 2005-2006 Texas Instruments, Inc.
*
* This package is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef IOOBJ_
#define IOOBJ_
#include <dspbridge/devdefs.h>
#include <dspbridge/dspdefs.h>
/*
* This struct is the first field in a io_mgr struct. Other, implementation
* specific fields follow this structure in memory.
*/
struct io_mgr_ {
/* These must be the first fields in a io_mgr struct: */
struct bridge_dev_context *hbridge_context; /* Bridge context. */
/* Function interface to Bridge driver. */
struct bridge_drv_interface *intf_fxns;
struct dev_object *hdev_obj; /* Device this board represents. */
};
#endif /* IOOBJ_ */

View file

@ -0,0 +1,129 @@
/*
* msg.c
*
* DSP-BIOS Bridge driver support functions for TI OMAP processors.
*
* DSP/BIOS Bridge msg_ctrl Module.
*
* Copyright (C) 2005-2006 Texas Instruments, Inc.
*
* This package is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/* ----------------------------------- Host OS */
#include <dspbridge/host_os.h>
/* ----------------------------------- DSP/BIOS Bridge */
#include <dspbridge/std.h>
#include <dspbridge/dbdefs.h>
/* ----------------------------------- Trace & Debug */
#include <dspbridge/dbc.h>
/* ----------------------------------- Bridge Driver */
#include <dspbridge/dspdefs.h>
/* ----------------------------------- Platform Manager */
#include <dspbridge/dev.h>
/* ----------------------------------- This */
#include <msgobj.h>
#include <dspbridge/msg.h>
/* ----------------------------------- Globals */
static u32 refs; /* module reference count */
/*
* ======== msg_create ========
* Purpose:
* Create an object to manage message queues. Only one of these objects
* can exist per device object.
*/
int msg_create(OUT struct msg_mgr **phMsgMgr,
struct dev_object *hdev_obj, msg_onexit msgCallback)
{
struct bridge_drv_interface *intf_fxns;
struct msg_mgr_ *msg_mgr_obj;
struct msg_mgr *hmsg_mgr;
int status = 0;
DBC_REQUIRE(refs > 0);
DBC_REQUIRE(phMsgMgr != NULL);
DBC_REQUIRE(msgCallback != NULL);
DBC_REQUIRE(hdev_obj != NULL);
*phMsgMgr = NULL;
dev_get_intf_fxns(hdev_obj, &intf_fxns);
/* Let Bridge message module finish the create: */
status =
(*intf_fxns->pfn_msg_create) (&hmsg_mgr, hdev_obj, msgCallback);
if (DSP_SUCCEEDED(status)) {
/* Fill in DSP API message module's fields of the msg_mgr
* structure */
msg_mgr_obj = (struct msg_mgr_ *)hmsg_mgr;
msg_mgr_obj->intf_fxns = intf_fxns;
/* Finally, return the new message manager handle: */
*phMsgMgr = hmsg_mgr;
} else {
status = -EPERM;
}
return status;
}
/*
* ======== msg_delete ========
* Purpose:
* Delete a msg_ctrl manager allocated in msg_create().
*/
void msg_delete(struct msg_mgr *hmsg_mgr)
{
struct msg_mgr_ *msg_mgr_obj = (struct msg_mgr_ *)hmsg_mgr;
struct bridge_drv_interface *intf_fxns;
DBC_REQUIRE(refs > 0);
if (msg_mgr_obj) {
intf_fxns = msg_mgr_obj->intf_fxns;
/* Let Bridge message module destroy the msg_mgr: */
(*intf_fxns->pfn_msg_delete) (hmsg_mgr);
} else {
dev_dbg(bridge, "%s: Error hmsg_mgr handle: %p\n",
__func__, hmsg_mgr);
}
}
/*
* ======== msg_exit ========
*/
void msg_exit(void)
{
DBC_REQUIRE(refs > 0);
refs--;
DBC_ENSURE(refs >= 0);
}
/*
* ======== msg_mod_init ========
*/
bool msg_mod_init(void)
{
DBC_REQUIRE(refs >= 0);
refs++;
DBC_ENSURE(refs >= 0);
return true;
}

View file

@ -0,0 +1,38 @@
/*
* msgobj.h
*
* DSP-BIOS Bridge driver support functions for TI OMAP processors.
*
* Structure subcomponents of channel class library msg_ctrl objects which
* are exposed to DSP API from Bridge driver.
*
* Copyright (C) 2005-2006 Texas Instruments, Inc.
*
* This package is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef MSGOBJ_
#define MSGOBJ_
#include <dspbridge/dspdefs.h>
#include <dspbridge/msgdefs.h>
/*
* This struct is the first field in a msg_mgr struct. Other, implementation
* specific fields follow this structure in memory.
*/
struct msg_mgr_ {
/* The first field must match that in _msg_sm.h */
/* Function interface to Bridge driver. */
struct bridge_drv_interface *intf_fxns;
};
#endif /* MSGOBJ_ */