⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 toklibios.c

📁 TI OMAP 1510上mcbsp的驱动程序
💻 C
字号:
/* * dspapps/dsp/tokliBIOS/tokliBIOS.c * * OMAP DSP bridge DSP-side core library * * Copyright (C) 2002,2003 Nokia Corporation * * Written by Toshihiro Kobayashi <toshihiro.kobayashi@nokia.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * $Id: tokliBIOS.c * $Revision: 2.0 * $Date: 2003/11/11 * */#include <std.h>#include <mem.h>#include "omap1510.h"#include "mailbox.h"#include "tokliBIOS.h"#include "tokliBIOSlib.h"#include "toklibioscfg.h"struct dsptask		*dsptask[N_TASK_MAX];struct task_prop	*task_prop[N_TASK_MAX];struct dsptask		task_anon;struct ipbuf	**ipbuf;Uns		**ipbuf_d;//LgUns		**ipbuf_longd;static struct ipblink	ipb_free;static Uns	ipbuf_bsycnt;#pragma DATA_ALIGN(ipbuf_sys, 2)struct ipbuf_p	ipbuf_sys;Void mbsend(Uns cmd, Uns data);Void busywait(Uns cnt);Uns release_ipbuf(Uns bid);Void balance_ipbuf(Void);Uns sync_ipbuf(Uns tid, Uns bid);Uns sync_ipbuf_anon(Uns bid);static Void init_icache(Void);static Uns init_mailbox(Void);Void init_ipbuf(Void);Void mailbox_interrupt(Void);#ifdef BKYLD_IN_INTHANDLERstatic Uns do_bkyld(Uns bid);#endif /* BKYLD_IN_INTHANDLER *//* * system functions */Void mbsend(Uns cmd, Uns data){	Uns	intm_saved;	while(inw(_DSP2ARM1_Flag));	// need atomic operation	intm_saved = HWI_disable();	outw(data, _DSP2ARM1);	outw(cmd,  _DSP2ARM1b);	HWI_restore(intm_saved);}Uns release_ipbuf(Uns bid){	Uns	intm_saved;	if(ipbuf[bid]->ld == MBCMD_TID_FREE) { // not locked?		return MBCMD_EID_NOTLOCKED;	}	ipbuf[bid]->ld = MBCMD_TID_FREE; // release	ipbuf[bid]->sd = MBCMD_TID_FREE;	intm_saved = HWI_disable();	ipblink_add_tail(&ipb_free, bid, ipbuf);	HWI_restore(intm_saved);	ipbuf_bsycnt--;	return 0;}Void balance_ipbuf(Void){	/*	 * balancing ipbuf lines with ARM	 */	while(_ipbuf_lines - ipbuf_bsycnt >= _ipbuf_keep) {		Uns	bid;		bid = get_free_ipbuf(&task_anon);		if(bid == MBCMD_BID_NULL)			return;		mbsend(mbcmd(MBCMD_BKYLD, 0), bid);	}}Uns sync_ipbuf(Uns tid, Uns bid){	if(bid >= _ipbuf_lines) {		return MBCMD_EID_BADBID;	}	if((tid >= N_TASK_MAX) || (dsptask[tid] == NULL)) {		//unuse_ipbuf(&task_anon, bid);		return MBCMD_EID_BADTID;	}	while(*(volatile Uns*)&ipbuf[bid]->la != tid) {		busywait(10);	}	return 0;}Uns sync_ipbuf_anon(Uns bid){	if(bid >= _ipbuf_lines) {		return MBCMD_EID_BADBID;	}	while(*(volatile Uns*)&ipbuf[bid]->la != MBCMD_TID_ANON) {		busywait(10);	}	return 0;}static Void init_icache(Void){	/*	 * configuring 2-way set-associative cache (8KB each)	 */	outw(_ICACHE_GCR_BIT_CUT_CLOCK |	     _ICACHE_GCR_BIT_AUTO_GATING |	     _ICACHE_GCR_BIT_GLOBAL_FLUSH |	     _ICACHE_GCR_BIT_WAY_PRESENCE |	     _ICACHE_GCR_BIT_WAY_NUMBER_2 |	     _ICACHE_GCR_BIT_STREAMING |	     _ICACHE_GCR_BIT_GLOBAL_ENABLE,	     _ICACHE_GCR);	outw(_ICACHE_NWCR_BIT_WAY_SIZE_8K |	     _ICACHE_NWCR_BIT_ENABLE,	     _ICACHE_NWCR);	/*	 * cache clear and wait for the process done	 */	asm(" BSET CACLR");	while(*_ST3_55 & _ST3_55_BIT_CACLR) {}	/*	 * cache enable	 */	asm(" BSET CAEN");}static Uns init_mailbox(Void){	Uns	dummy;	dummy = inw(_ARM2DSP1b); // clear interrupt source	*_IER0 |= _IER0_BIT_MAILBOX1; // enable mailbox interrupt	return dummy; // this value will not be used at all.	              // just to make compiler silent.}Void init_ipbuf(Void){	Uns	i;	Void	**ptrs;//	ipbuf       = MEM_alloc(MEM->MALLOCSEG, sizeof(Void*) * _ipbuf_lines, 1);//	ipbuf_d     = MEM_alloc(MEM->MALLOCSEG, sizeof(Void*) * _ipbuf_lines, 1);//	ipbuf_longd = MEM_alloc(MEM->MALLOCSEG, sizeof(Void*) * _ipbuf_lines, 1);//	if((ipbuf       == MEM_ILLEGAL) ||//	   (ipbuf_d     == MEM_ILLEGAL) ||//	   (ipbuf_longd == MEM_ILLEGAL)) {//		sys_cmderr(MBCMD_EID_NOMEM, MBCMD_TID_ANON);//		return;//	}	// reducing MEM_alloc//	ptrs = MEM_alloc(MEM->MALLOCSEG,//			 sizeof(Void*) * _ipbuf_lines * 3, 1);	ptrs = MEM_alloc(MEM->MALLOCSEG,			 sizeof(Void*) * _ipbuf_lines * 2, 1);	if(ptrs == MEM_ILLEGAL) {		sys_cmderr(MBCMD_EID_NOMEM, MBCMD_TID_ANON);		return;	}	ipbuf       = (Void*)&ptrs[0];	ipbuf_d     = (Void*)&ptrs[_ipbuf_lines];//	ipbuf_longd = (Void*)&ptrs[_ipbuf_lines*2];	for(i=0; i<_ipbuf_lines; i++) {		ipbuf[i]   = (struct ipbuf *)			     ((LgUns)_ipbuf_body +			      (IPBUF_HEADER_SZ+(LgUns)_ipbuf_sz) * i);		ipbuf_d[i] = ipbuf[i]->d;//		ipbuf_longd[i] = is_external(&_ipbuf_body) ?//					(LgUns *)&ipbuf_d[i][0] ://					(LgUns *)&ipbuf_d[i][1];	}	INIT_IPBLINK(&ipb_free);	/*	 * DSP holds all ipbufs initially.	 */	ipbuf_bsycnt = 0;	for(i=0; i<_ipbuf_keep; i++) {		/* hold for us */		ipbuf[i]->la = MBCMD_TID_ANON;		ipbuf[i]->sa = MBCMD_TID_ANON;		ipbuf[i]->ld = MBCMD_TID_FREE;		ipbuf[i]->sd = MBCMD_TID_FREE;		ipblink_add_tail(&ipb_free, i, ipbuf);	}	for(; i<_ipbuf_lines; i++) {		/* yield to MPU */		ipbuf[i]->la = MBCMD_TID_ANON;		ipbuf[i]->sa = MBCMD_TID_ANON;		ipbuf[i]->ld = MBCMD_TID_ANON;		ipbuf[i]->sd = MBCMD_TID_ANON;		ipbuf[i]->next = MBCMD_BID_NULL;		ipbuf_bsycnt++;		mbsend(mbcmd(MBCMD_BKYLD, 0), i);	}}Void main(){	init_icache();	init_wdt();	init_timer();	init_mailbox();	init_tq();	init_tasks();	init_super();	init_icr();}/* * task I/F functions */Uns get_free_ipbuf(struct dsptask *task){	Uns	bid;	Uns	intm_saved;	if(ipblink_empty(&ipb_free)) {		sys_cmderr(MBCMD_EID_IPBFULL, MBCMD_TID_ANON);		/*		 * FIXME: wait on queue		 */		do {			busywait(10);		} while(ipblink_empty(&ipb_free));	}	intm_saved = HWI_disable();	bid = ipb_free.top;	ipbuf[bid]->ld = task->tid; // lock	ipblink_del_top(&ipb_free, ipbuf);	HWI_restore(intm_saved);	ipbuf_bsycnt++;	return bid;}Void unuse_ipbuf(struct dsptask *task, Uns bid){	Uns	eid;	if(_ipbuf_lines - ipbuf_bsycnt < _ipbuf_keep) {		eid = release_ipbuf(bid);		if(eid) {			sys_cmderr(eid, task->tid);		}		return;	}	// return this line	ipbuf[bid]->ld = MBCMD_TID_ANON;	ipbuf[bid]->sd = MBCMD_TID_ANON;	mbsend(mbcmd(MBCMD_BKYLD, 0), bid);}Void wdsnd(struct dsptask *task, Uns data){	mbsend(mbcmd(MBCMD_WDSND, task->tid), data);}Void bksnd(struct dsptask *task, Uns bid, Uns cnt){	Uns	tid = task->tid;	ipbuf[bid]->c  = cnt;	ipbuf[bid]->sd = tid;	mbsend(mbcmd(MBCMD_BKSND, tid), bid);}Void bksndp(struct dsptask *task, Void *data, Uns cnt){	Uns	tid = task->tid;	LgUns	adr = (LgUns)data;	struct ipbuf_p	*ipbuf_p = &task_prop[tid]->ipbuf_p_snd;	// sync with ARM	while(*(volatile Uns*)&ipbuf_p->s != MBCMD_TID_FREE) {		busywait(10);	}	ipbuf_p->c  = cnt;	ipbuf_p->s  = tid;	ipbuf_p->ah = adr >> 16;	ipbuf_p->al = adr & 0xffff;	mbsend(mbcmd(MBCMD_BKSNDP, tid), 0);}Void wdreq(struct dsptask *task){	mbsend(mbcmd(MBCMD_WDREQ, task->tid), 0);}Void bkreq(struct dsptask *task, Uns cnt){	mbsend(mbcmd(MBCMD_BKREQ, task->tid), cnt);}Void bkreqp(struct dsptask *task, Void *data, Uns cnt){	Uns	tid = task->tid;	LgUns	adr = (LgUns)data;	struct ipbuf_p	*ipbuf_p = &task_prop[tid]->ipbuf_p_req;	ipbuf_p->c  = cnt;	ipbuf_p->s  = MBCMD_TID_FREE;	ipbuf_p->ah = adr >> 16;	ipbuf_p->al = adr & 0xffff;	mbsend(mbcmd(MBCMD_BKREQP, tid), 0);}Void cmderr(struct dsptask *task, Uns eid){	sys_cmderr(eid, task->tid);}#pragma DATA_SECTION(dbgbuf, "dbgbuf")#define DBGBUFSZ	256static Char	dbgbuf[DBGBUFSZ];Void dbg(struct dsptask *task, Char *s){	Uns	tid = task->tid;	// sync with ARM	while(*(volatile Uns*)&ipbuf_sys.s != MBCMD_TID_FREE) {		busywait(10);	}	/*	 * The fact the ipbuf_sys is free means that	 * the last debug message has been read in ARM side.	 * So, now we can overwrite it.	 */	strncpy(dbgbuf, s, DBGBUFSZ-1);	dbgbuf[DBGBUFSZ-1] = '\0';	ipbuf_sys.c  = strlen(dbgbuf);	ipbuf_sys.s  = tid;	ipbuf_sys.ah = ((LgUns)dbgbuf) >> 16;	ipbuf_sys.al = ((LgUns)dbgbuf) & 0xffff;	mbsend(mbcmd(MBCMD_DBG, tid), 0);}/* * interrupt handler routine * * INTM is set automatically when an interrupt occurs, * and will be restored at iret. * * Do not use 'interrupt' modifier in conjunction with DSP/BIOS. */Void mailbox_interrupt(Void){	Uns	cmd, data, cmd_h, tid;	Uns	eid;	data  = inw(_ARM2DSP1);	cmd   = inw(_ARM2DSP1b);	cmd_h = cmd >> 8;	tid   = cmd & 0x00ff;	switch(cmd_h) {		// commands handled immediately#ifdef BKYLD_IN_INTHANDLER		case MBCMD_BKYLD:			if(eid = do_bkyld(data))				break;			return;#endif /* BKYLD_IN_INTHANDLER */		// commands handled by supertask		case MBCMD_TADD:			if(eid = sync_ipbuf_anon(data))				break;			balance_ipbuf();			// Do not break!!!#ifndef BKYLD_IN_INTHANDLER		case MBCMD_BKYLD:#endif /* BKYLD_IN_INTHANDLER */		case MBCMD_DSPCFG:		case MBCMD_REGRW:		case MBCMD_GETVAR:		case MBCMD_SETVAR:		case MBCMD_TDEL:			register_super_mbq(cmd_h, tid, data);			return;		// commands handled by each task		case MBCMD_BKSND:			if(eid = sync_ipbuf(tid, data))				break;			balance_ipbuf();			// Do not break!!!		case MBCMD_WDSND:		case MBCMD_WDREQ:		case MBCMD_BKREQ:		case MBCMD_BKSNDP:		case MBCMD_BKREQP:		case MBCMD_TCTL:		case MBCMD_TCFG:			if(eid = register_mbq(tid, cmd_h, data))				break;			return;		// illegal commands		case MBCMD_ERR:		default:			eid = MBCMD_EID_BADCMD;	}	// error!	sys_cmderr(eid, cmd);}#ifdef BKYLD_IN_INTHANDLERstatic Uns do_bkyld(Uns bid){	Uns	eid;	if(eid = sync_ipbuf_anon(bid))		return eid;	if(eid = release_ipbuf(bid))		return eid;	return 0;}#endif /* BKYLD_IN_INTHANDLER */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -