📄 toklibios.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 + -