summaryrefslogtreecommitdiff
path: root/wcte12xp
diff options
context:
space:
mode:
authorsruffell <sruffell@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2008-01-02 20:30:58 +0000
committersruffell <sruffell@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2008-01-02 20:30:58 +0000
commit9099095634b7c959954a1d420c277b743e6ee7f6 (patch)
tree50cc73d7844e503e879812a5afc60e8423ddb481 /wcte12xp
parentdf19a0df6dab13f2be16680f039f0fe68a778198 (diff)
VPMADT032 stability changes for wctdm24xxp and wcte12xp:
- Remove double reads. - Wait for writes to complete before starting reads. - Optimize reads of multi-word register. git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.2@3592 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'wcte12xp')
-rw-r--r--wcte12xp/vpmadt032.c155
1 files changed, 105 insertions, 50 deletions
diff --git a/wcte12xp/vpmadt032.c b/wcte12xp/vpmadt032.c
index 9050c6e..68455b8 100644
--- a/wcte12xp/vpmadt032.c
+++ b/wcte12xp/vpmadt032.c
@@ -289,7 +289,7 @@ static struct vpm150m_cmd * vpm150m_empty_slot(struct t1 *wc)
{
unsigned int x;
- for (x = 0; x < sizeof(wc->vpm150m->cmdq) / sizeof(wc->vpm150m->cmdq[0]); x++) {
+ for (x = 0; x < VPM150M_MAX_COMMANDS; x++) {
if (!wc->vpm150m->cmdq[x].flags) {
return &wc->vpm150m->cmdq[x];
}
@@ -297,50 +297,92 @@ static struct vpm150m_cmd * vpm150m_empty_slot(struct t1 *wc)
return NULL;
}
-unsigned short t1_vpm150m_getreg_full(struct t1 *wc, int pagechange, unsigned int len, unsigned short addr, unsigned short *outbuf)
+/* Wait for any outstanding commands to be completed. */
+static inline int vpm150m_io_wait(struct t1 *wc)
+{
+ int x;
+ int ret=0;
+ for (x=0; x < VPM150M_MAX_COMMANDS;) {
+ if (wc->vpm150m->cmdq[x].flags) {
+ if ((ret=schluffen(&wc->regq))) {
+ return ret;
+ }
+ x=0;
+ }
+ else {
+ ++x;
+ }
+ }
+ return ret;
+}
+
+int t1_vpm150m_getreg_full_async(struct t1 *wc, int pagechange, unsigned int len,
+ unsigned short addr, unsigned short *outbuf, struct vpm150m_cmd **hit_p)
{
+ int ret=0;
unsigned long flags;
- volatile struct vpm150m_cmd *hit;
- unsigned short ret = 0;
- int i;
+ BUG_ON(!hit_p);
+ spin_lock_irqsave(&wc->reglock, flags);
+ (*hit_p) = vpm150m_empty_slot(wc);
+ if (*hit_p) {
+ (*hit_p)->flags = __VPM150M_RD;
+ if (pagechange) {
+ (*hit_p)->flags |= __VPM150M_RWPAGE;
+ }
+ (*hit_p)->datalen = len;
+ (*hit_p)->address = addr;
+ memset((*hit_p)->data, 0, len*sizeof(outbuf[0]));
+ }
+ else {
+ ret = -EBUSY;
+ }
+ spin_unlock_irqrestore(&wc->reglock, flags);
+ return ret;
+}
+int t1_vpm150m_getreg_full_return(struct t1 *wc, int pagechange, unsigned int len,
+ unsigned short addr, unsigned short *outbuf, struct vpm150m_cmd **hit_p)
+{
+ int ret = 0;
+ unsigned long flags;
+ BUG_ON(!hit_p);
+ spin_lock_irqsave(&wc->reglock, flags);
do {
- spin_lock_irqsave(&wc->reglock, flags);
- hit = vpm150m_empty_slot(wc);
- if (hit) {
- hit->flags = __VPM150M_RD;
- if(pagechange)
- hit->flags |= __VPM150M_RWPAGE;
- hit->datalen = len;
- hit->address = addr;
- for (i=0; i < hit->datalen; i++)
- hit->data[i] = 0x0000;
+ if ((*hit_p)->flags & __VPM150M_FIN) {
+ memcpy(outbuf, (*hit_p)->data, len*(sizeof(outbuf[0])));
+ (*hit_p)->flags = 0;
+ (*hit_p) = NULL;
+ ret = 0;
}
- spin_unlock_irqrestore(&wc->reglock, flags);
- if (!hit) {
- if ((ret = schluffen(&wc->regq)))
+ else {
+ spin_unlock_irqrestore(&wc->reglock, flags);
+ if ((ret=schluffen(&wc->regq))) {
return ret;
+ }
+ spin_lock_irqsave(&wc->reglock, flags);
+ ret = -EBUSY;
}
- } while (!hit);
+ } while (-EBUSY == ret);
+ spin_unlock_irqrestore(&wc->reglock, flags);
+ return ret;
+}
-#if 1
+int t1_vpm150m_getreg_full(struct t1 *wc, int pagechange, unsigned int len, unsigned short addr, unsigned short *outbuf)
+{
+ struct vpm150m_cmd *hit = 0;
+ int ret = 0;
do {
- spin_lock_irqsave(&wc->reglock, flags);
- if (hit->flags & __VPM150M_FIN) {
- for (i = 0; i < hit->datalen; i++)
- outbuf[i] = hit->data[i];
- hit->flags = 0;
- hit=NULL;
- }
- spin_unlock_irqrestore(&wc->reglock, flags);
- if (hit) {
- if ((ret = schluffen(&wc->regq)))
- return ret;
+ ret = t1_vpm150m_getreg_full_async(wc, pagechange, len, addr, outbuf, &hit);
+ if (!hit) {
+ if ( -EBUSY == ret ) {
+ if ((ret = schluffen(&wc->regq)))
+ return ret;
+ }
+ BUG_ON( 0 != ret);
}
- } while (hit);
-
-#endif
+ } while (!hit);
+ ret = t1_vpm150m_getreg_full_return(wc, pagechange, len, addr, outbuf, &hit);
return ret;
}
@@ -403,20 +445,10 @@ int t1_vpm150m_setreg(struct t1 *wc, unsigned int len, unsigned int addr, unsign
unsigned short t1_vpm150m_getreg(struct t1 *wc, unsigned int len, unsigned int addr, unsigned short *data)
{
unsigned short res;
- unsigned short count=0;
- unsigned short first_data=0;
- do {
- t1_vpm150m_setpage(wc, addr >> 16);
- if ((addr >> 16) != ((addr + len) >> 16))
- module_printk("getreg: You found it!\n");
- if (count > 0) {
- first_data = *data;
- }
- res = t1_vpm150m_getreg_full(wc, 0, len, addr & 0xffff, data);
- } while (((0==count++) || (first_data != *data)) && (count < 100));
- if (count >= 100) {
- module_printk(" %s:%d\n", __FILE__, __LINE__);
- }
+ t1_vpm150m_setpage(wc, addr >> 16);
+ if ((addr >> 16) != ((addr + len) >> 16))
+ module_printk("getreg: You found it!\n");
+ res = t1_vpm150m_getreg_full(wc, 0, len, addr & 0xffff, data);
return res;
}
@@ -985,8 +1017,31 @@ void gpakReadDspMemory(
struct t1 *wc = wc_find_iface(DspId);
int i;
int transcount;
-
- if (wc && wc->vpm150m) {
+ int ret;
+
+ vpm150m_io_wait(wc);
+ if ( NumWords < VPM150M_MAX_COMMANDS ) {
+ struct vpm150m_cmd* cmds[VPM150M_MAX_COMMANDS] = {0};
+ t1_vpm150m_setpage(wc, DspAddress >> 16);
+ DspAddress &= 0xffff;
+ for (i=0; i < NumWords; ++i) {
+ ret = t1_vpm150m_getreg_full_async(wc,0,1,DspAddress+i,&pWordValues[i],
+ &cmds[i]);
+ if (0 != ret) {
+ dump_stack();
+ return;
+ }
+ }
+ for (i=NumWords-1; i >=0; --i) {
+ ret = t1_vpm150m_getreg_full_return(wc,0,1,DspAddress+i,&pWordValues[i],
+ &cmds[i]);
+ if (0 != ret) {
+ dump_stack();
+ return;
+ }
+ }
+ }
+ else {
for (i = 0; i < NumWords;) {
if ((NumWords - i) > VPM150M_MAX_DATA)
transcount = VPM150M_MAX_DATA;