OpenCores
URL https://opencores.org/ocsvn/mips_enhanced/mips_enhanced/trunk

Subversion Repositories mips_enhanced

[/] [mips_enhanced/] [trunk/] [grlib-gpl-1.0.19-b3188/] [software/] [spw/] [spwapi.c] - Rev 2

Compare with Previous | Blame | View Log

/*****************************************************************************/
/*   This file is a part of the GRLIB VHDL IP LIBRARY */
/*   Copyright (C) 2004 GAISLER RESEARCH */
 
/*   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. */
 
/*   See the file COPYING for the full details of the license. */
/*****************************************************************************/
 
#include "spwapi.h"
#include <stdlib.h>
 
static char *almalloc(int sz)
{
  char *tmp;
  tmp = calloc(1,2*sz);
  tmp = (char *) (((int)tmp+sz) & ~(sz -1));
  return(tmp);
}
 
static inline int loadmem(int addr)
{
  int tmp;        
  asm(" lda [%1]1, %0 "
      : "=r"(tmp)
      : "r"(addr)
    );
  return tmp;
}
 
/* static void storemem(int addr, int data)  */
/* { */
/*         asm("sta %0, [%1]1 " */
/*             :  */
/*             : "r"(data), "r"(addr)  */
/*            ); */
/* } */
 
int spw_setparam(int nodeaddr, int clkdiv, int destkey,
                 int timetxen, int timerxen, int spwadr, 
                 int khz, struct spwvars *spw) 
{
  if ((nodeaddr < 0) || (nodeaddr > 255)) {
    return 1;
  }
  if ((clkdiv < 0) || (clkdiv > 255)) {
    return 1;
  }
  if ((destkey < 0) || (destkey > 255)) {
    return 1;
  }
  if ((timetxen < 0) || (timetxen > 1)) {
    return 1;
  }
  if ((timerxen < 0) || (timerxen > 1)) {
    return 1;
  }
  spw->timetxen = timetxen;
  spw->timerxen = timerxen;
  spw->destkey = destkey;
  spw->nodeaddr = nodeaddr;
  spw->clkdiv = clkdiv;
  spw->khz = khz;
  spw->regs = (struct spwregs *) spwadr;
  return 0;
}
 
int spw_setparam_dma(int dmachan, int addr, int mask, int nospill, int rxmaxlen, struct spwvars *spw) 
{
  if ((addr < 0) || (addr > 255)) {
    return 1;
  }
  if ((mask < 0) || (mask > 255)) {
    return 1;
  }
  if ((rxmaxlen < 0) || (rxmaxlen > 33554432)) {
    return 1;
  }
  if ((nospill < 0) || (nospill > 1)) {
    return 1;
  }
  spw->dma[dmachan].nospill = nospill;
  spw->dma[dmachan].addr = addr;
  spw->dma[dmachan].mask = mask;
  spw->dma[dmachan].rxmaxlen = rxmaxlen;
  return 0;
}
 
 
int spw_init(struct spwvars *spw)
{
  int i;
  int j;
  int tmp;
  /*determine grspw version by checking if timer and disconnect register exists */
  spw->regs->timer = 0xFFFFFF;
  tmp = loadmem((int)&(spw->regs->timer));
  spw->ver = 0;
  if (!tmp) 
          spw->ver = 1;
  tmp = loadmem((int)&(spw->regs->ctrl));
  spw->rmap = (tmp >> 31) & 1;
  spw->rxunaligned = (tmp >> 30) & 1;
  spw->rmapcrc = (tmp >> 29) & 1;
  spw->dmachan = ((tmp >> 27) & 3) + 1;
  spw->regs->nodeaddr = spw->nodeaddr; /*set node address*/
  spw->regs->clkdiv = spw->clkdiv | (spw->clkdivs << 8); /* set clock divisor */
 
  for(i = 0; i < spw->dmachan; i++) {
          spw->regs->dma[i].rxmaxlen = spw->dma[i].rxmaxlen; /*set rx maxlength*/
          if (loadmem((int)&(spw->regs->dma[i].rxmaxlen)) != spw->dma[i].rxmaxlen) {
                  return 1;
          }
  }
  if (spw->khz) 
          spw->regs->timer = ((spw->khz*64)/10000) | ((((spw->khz*850)/1000000)-3) << 12);
  if (spw->rmap == 1) {
    spw->regs->destkey = spw->destkey;
  }
  for(i = 0; i < spw->dmachan; i++) {
          spw->regs->dma[i].ctrl = 0xFFFE01E0; /*clear status, set ctrl for dma chan*/
          if (loadmem((int)&(spw->regs->dma[i].ctrl)) != 0) {
                  return 2;
          }
          /*set tx descriptor pointer*/
          if ((spw->dma[i].txd = (struct txdescriptor *)almalloc(1024)) == NULL) {
                  return 3;
          }
          spw->dma[i].txpnt = 0;
          spw->dma[i].txchkpnt = 0;
          spw->regs->dma[i].txdesc = (int) spw->dma[i].txd;
          /*set rx descriptor pointer*/
          if (( spw->dma[i].rxd = (struct rxdescriptor *)almalloc(1024)) == NULL) {
                  return 4;
          }
          spw->dma[i].rxpnt = 0;
          spw->dma[i].rxchkpnt = 0;
          spw->regs->dma[i].rxdesc = (int) spw->dma[i].rxd;
  }
  spw->regs->status = 0xFFF; /*clear status*/
  spw->regs->ctrl = 0x2 | (spw->timetxen << 10) | (spw->timerxen << 11); /*set ctrl*/
  for(i = 0; i < spw->dmachan; i++) {
          spw->regs->dma[i].ctrl = loadmem((int)&(spw->regs->dma[i].ctrl)) | (spw->dma[i].nospill << 12);
  }
  return 0;
}
 
int wait_running(struct spwvars *spw) 
{
        int i;
        int j;
 
        j = 0;
        while (((loadmem((int)&(spw->regs->status)) >> 21) & 7) != 5) {
                if (j > 1000) {
                        return 1;
                }
                for(i = 0; i < 1000; i++) {}
		j++;
        }
        return 0;
}
 
int set_txdesc(int dmachan, int pnt, struct spwvars *spw) 
{
        spw->regs->dma[dmachan].txdesc = pnt;
        spw->dma[dmachan].txpnt = 0;
        spw->dma[dmachan].txchkpnt = 0;
        if (loadmem((int)&(spw->regs->dma[dmachan].txdesc)) != pnt) {
                return 1;
        }
        return 0;
}
 
int set_rxdesc(int dmachan, int pnt, struct spwvars *spw) 
{
        spw->regs->dma[dmachan].rxdesc = pnt;
        spw->dma[dmachan].rxpnt = 0;
        spw->dma[dmachan].rxchkpnt = 0;
        if (loadmem((int)&(spw->regs->dma[dmachan].rxdesc)) != pnt) {
                return 1;
        }
        return 0;
}
 
void spw_disable(struct spwvars *spw) 
{
        spw->regs->ctrl = loadmem((int)&(spw->regs->ctrl)) | 1;
}
 
void spw_enable(struct spwvars *spw) 
{
        spw->regs->ctrl = loadmem((int)&(spw->regs->ctrl)) & 0x20F7E;
}
 
void spw_start(struct spwvars *spw) 
{
        spw->regs->ctrl = loadmem((int)&(spw->regs->ctrl)) | (1 << 1);
}
 
void spw_stop(struct spwvars *spw) 
{
        spw->regs->ctrl = loadmem((int)&(spw->regs->ctrl)) & 0x20F7D;
}
 
int spw_setclockdiv(struct spwvars *spw) 
{
        if ( (spw->clkdiv < 0) || (spw->clkdiv > 255) ) {
                return 1;
        } else {
                spw->regs->clkdiv = spw->clkdiv;
                return 0;
        }
}
 
int spw_set_nodeadr(struct spwvars *spw) 
{
        if ( (spw->nodeaddr < 0) || (spw->nodeaddr > 255) || 
             (spw->mask < 0) || (spw->mask > 255) ) {
                return 1;
        } else {
                spw->regs->nodeaddr = (spw->nodeaddr & 0xFF) | ((spw->mask & 0xFF) << 8);
                return 0;
        }
}
 
int spw_set_chanadr(int dmachan, struct spwvars *spw) 
{
        if ( (spw->dma[dmachan].addr < 0) || (spw->dma[dmachan].addr > 255) || 
             (spw->dma[dmachan].mask < 0) || (spw->dma[dmachan].mask > 255) ) {
                return 1;
        } else {
                spw->regs->dma[dmachan].addr = (spw->dma[dmachan].addr & 0xFF) | ((spw->dma[dmachan].mask & 0xFF) << 8);
                return 0;
        }
}
 
int spw_set_rxmaxlength(int dmachan, struct spwvars *spw) 
{
        if ((spw->dma[dmachan].rxmaxlen < 4) || (spw->dma[dmachan].rxmaxlen > 33554431)) {
                return 1;
        } else {
                spw->regs->dma[dmachan].rxmaxlen = spw->dma[dmachan].rxmaxlen;
                return 0;
        }
}
 
int spw_tx(int dmachan, int hcrc, int dcrc, int skipcrcsize, int hsize, char *hbuf, int dsize, char *dbuf, struct spwvars *spw) 
{
  if ((dsize < 0) || (dsize > 16777215)) {
    return 6;
  }
  if ((hsize < 0) || (hsize > 255)) {
    return 5;
  }
  if ((dbuf == NULL) || (hbuf == NULL)) {
    return 4;
  }
  if ( (((hcrc == 1) || (dcrc == 1)) && ((spw->rmapcrc | spw->rmap) == 0)) || (hcrc < 0) || (hcrc > 1) || (dcrc < 0) || (dcrc > 1)) {
    return 3;
  } 
  if ((skipcrcsize < 0) || (skipcrcsize > 15) ) {
    return 2;
  }
  if ((loadmem((int)&(spw->dma[dmachan].txd[spw->dma[dmachan].txpnt].ctrl)) >> 12) & 1) {
    return 1;
  }
  spw->dma[dmachan].txd[spw->dma[dmachan].txpnt].haddr = (int)hbuf;
  spw->dma[dmachan].txd[spw->dma[dmachan].txpnt].dlen = dsize;
  spw->dma[dmachan].txd[spw->dma[dmachan].txpnt].daddr = (int)dbuf;
  if (spw->dma[dmachan].txpnt == 63) {
    spw->dma[dmachan].txd[spw->dma[dmachan].txpnt].ctrl = 0x3000 | hsize | (hcrc << 16) | (dcrc << 17) | (skipcrcsize << 8);
    spw->dma[dmachan].txpnt = 0;
  } else {
    spw->dma[dmachan].txd[spw->dma[dmachan].txpnt].ctrl = 0x1000 | hsize | (hcrc << 16) | (dcrc << 17) | (skipcrcsize << 8);
    spw->dma[dmachan].txpnt++;
  }
  spw->regs->dma[dmachan].ctrl = loadmem((int)&(spw->regs->dma[dmachan].ctrl)) & 0xFAAA | 1;
 
  return 0;
}
 
int spw_rx(int dmachan, char *buf, struct spwvars *spw) 
{
  if (((loadmem((int)&(spw->dma[dmachan].rxd[spw->dma[dmachan].rxpnt].ctrl)) >> 25) & 1)) {
    return 1;
  }
  spw->dma[dmachan].rxd[spw->dma[dmachan].rxpnt].daddr = (int)buf;
  if (spw->dma[dmachan].rxpnt == 127) {
    spw->dma[dmachan].rxd[spw->dma[dmachan].rxpnt].ctrl = 0x6000000;
    spw->dma[dmachan].rxpnt = 0;
  } else {
    spw->dma[dmachan].rxd[spw->dma[dmachan].rxpnt].ctrl = 0x2000000;
    spw->dma[dmachan].rxpnt++;
  }
  spw->regs->dma[dmachan].ctrl = loadmem((int)&(spw->regs->dma[dmachan].ctrl)) & 0xF955 | 2 | (1 << 11);
  return 0;
}
 
int spw_checkrx(int dmachan, int *size, struct rxstatus *rxs, struct spwvars *spw) 
{
  int tmp;
  tmp = loadmem((int)&(spw->dma[dmachan].rxd[spw->dma[dmachan].rxchkpnt].ctrl));
  if (!((tmp >> 25) & 1)) {
    *size = tmp & 0x1FFFFFF;
    rxs->truncated = (tmp >> 31) & 1;
    rxs->dcrcerr = (tmp >> 30) & 1;
    rxs->hcrcerr = (tmp >> 29) & 1;
    rxs->eep = (tmp >> 28) & 1;
    if (spw->dma[dmachan].rxchkpnt == 127) {
      spw->dma[dmachan].rxchkpnt = 0;
    } else {
      spw->dma[dmachan].rxchkpnt++;
    }
    return 1;
  } else {
    return 0;
  }
}
 
int spw_checktx(int dmachan, struct spwvars *spw)
{
  int tmp;
  tmp = loadmem((int)&(spw->dma[dmachan].txd[spw->dma[dmachan].txchkpnt].ctrl));
  if (!((tmp >> 12) & 1)) {
    if (spw->dma[dmachan].txchkpnt == 63) {
      spw->dma[dmachan].txchkpnt = 0;
    } else {
      spw->dma[dmachan].txchkpnt++;
    }
    if ((tmp >> 15) & 1) {
      return 2;
    } else {
      return 1;
    }
  } else {
    return 0;
  }
}
 
void send_time(struct spwvars *spw)
{
  int i;
  while( ((loadmem((int)&(spw->regs->ctrl)) >> 4) & 1)) {
    for(i = 0; i < 16; i++) {}
  }
  spw->regs->ctrl = loadmem((int)&(spw->regs->ctrl)) | (1 << 4);
}
 
int check_time(struct spwvars *spw) 
{
  int tmp = loadmem((int)&(spw->regs->status)) & 1;
  if (tmp) {
    spw->regs->status = loadmem((int)&(spw->regs->status)) | 1;
  }
  return tmp;
}
 
int get_time(struct spwvars *spw) 
{
  return (loadmem((int)&(spw->regs->timereg)) & 0x3F );
}
 
void spw_reset(struct spwvars *spw) 
{
  spw->regs->ctrl = loadmem((int)&(spw->regs->ctrl)) | (1 << 6);
}
 
void spw_rmapen(struct spwvars *spw) 
{
  spw->regs->ctrl = loadmem((int)&(spw->regs->ctrl)) | (1 << 16);
}
 
void spw_rmapdis(struct spwvars *spw) 
{
  spw->regs->ctrl = loadmem((int)&(spw->regs->ctrl)) & 0xEFFFF;
}
 
int spw_setdestkey(struct spwvars *spw) 
{
  if ((spw->destkey < 0) || (spw->destkey > 255)) {
    return 1;
  }
  spw->regs->destkey = spw->destkey;
  return 0;
}
 
void spw_setsepaddr(int dmachan, struct spwvars *spw) 
{
        spw->regs->dma[dmachan].ctrl = loadmem((int)&(spw->regs->dma[dmachan].ctrl)) | (1 << 13);
}
 
void spw_disablesepaddr(int dmachan, struct spwvars *spw) 
{
        spw->regs->dma[dmachan].ctrl = loadmem((int)&(spw->regs->dma[dmachan].ctrl)) & 0xFFFFDFFF;
}
 
 
void spw_enablerx(int dmachan, struct spwvars *spw) 
{
        spw->regs->dma[dmachan].ctrl = loadmem((int)&(spw->regs->dma[dmachan].ctrl)) | 0x2;
}
 
 
void spw_disablerx(int dmachan, struct spwvars *spw) 
{
        spw->regs->dma[dmachan].ctrl = loadmem((int)&(spw->regs->dma[dmachan].ctrl)) & 0xFFFFFFFD;
}
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.