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

📄 sdev.c

📁 这是单板上DPRAM的驱动程序
💻 C
字号:
#include <string.h>
#include <psos.h>
#include <bspfuncs.h>
#include "board.h"
#include "bsp.h"
#include "sdev.h"

SDIndexTableStruct sd_table[SDN_MAX];
char UncachedBuffer[MAX_UNCACHED_BUFFER_LEN];
#pragma use_section UNCACHE UncachedBuffer

char*  UncachedBufferStart=NULL; 
char *AllocUncachedBuffer(int size,int align)
{
    char *temp;
    static int i='a';
    if(i<'a' || i>'z')i='a'; else i++;
    temp=(char *)ALIGN((ULONG)UncachedBufferStart+4,align);
    if(temp+size+4>UncachedBuffer+MAX_UNCACHED_BUFFER_LEN)
        bsp_fatal(BSPF_OUT_OF_UNCACHE);
    UncachedBufferStart=temp+size+4;
    *(temp-4)='['; *(temp-3)=i; *(temp-2)=']'; *(temp-1)='<';
    *(temp+size)='>'; *(temp+size+1)='['; *(temp+size+2)=i; *(temp+size+3)=']';
    return temp;
}

void InstallSD(int DEV,
    int (*read )(void *databuf, void *buf, int BufLen),
    int (*write)(void *databuf, void *buf, int BufLen),
    int (*cntrl)(void *databuf, int cmd,   void *param, int ParamLen),
    void *databuf)
{
    if(DEV < SDN_MAX)
    {
        memset(&sd_table[DEV],0,sizeof(sd_table[DEV]));
        sd_table[DEV].read  = read;
        sd_table[DEV].write = write;
        sd_table[DEV].cntrl = cntrl;
        sd_table[DEV].databuf = databuf;
    }
}

#define GET_REGLL(addr,size) \
    ((size==32)?(*(volatile ULONG *)addr):\
    (size==16)?(*(volatile USHORT*)addr):(*(volatile UCHAR*)addr))
#define PUT_REGLL(addr,size,val) \
    ((size==32)?(*(volatile ULONG *)addr=val):\
    (size==16)?(*(volatile USHORT*)addr=val):(*(volatile UCHAR*)addr=val))

void SetLLDat(LineLevelStruct *p,int val)
{
    ULONG temp = GET_REGLL(p->Addr,p->Size);
    temp &= (~((ULONG)p->Mask)); 
    temp |= (p->Mask&((val!=0)?p->Hi:p->Lo));
    if((USHORT *)(p->Addr) == (USHORT *)(&S_PortADataReg)) SET_PA_VAL(temp, p->Mask)
    else if((ULONG *)(p->Addr) == (ULONG *)(&S_PortBDataReg)) SET_PB_VAL(temp, p->Mask)
    else if((USHORT *)(p->Addr) == (USHORT *)(&S_PortCDataReg)) SET_PC_VAL(temp, p->Mask)
    else if((USHORT *)(p->Addr) == (USHORT *)(&S_PortDDataReg)) SET_PD_VAL(temp, p->Mask)
    else SPLX(PUT_REGLL(p->Addr,p->Size,temp);)
}

ULONG GetLLDat(LineLevelStruct *p)
{
    return ((GET_REGLL(p->Addr,p->Size)&p->Mask)==p->Hi)?1:0;
}

/* we don't check validation of DEV for next three funs is used internally */
static void sd_smCreate(int DEV)
{
    char name[10];
    ULONG sm,ret=(DEV&0xFFFF);
    sprintf(name,"%04x",ret);
    ret=sm_create(name,1,SM_LOCAL|SM_PRIOR,&sm);
    if(ret!=0)bsp_fatal(ret);
    sd_table[DEV].sm=sm;
}

int sd_smp(int DEV,int NoWait)
{
    int ret;
    if(sd_table[DEV].sm == NULL)sd_smCreate(DEV);
    ret=sm_p(sd_table[DEV].sm,(NoWait==0)?SM_WAIT:SM_NOWAIT,0);
    if(NoWait==0 && ret!=0)bsp_fatal(ret);
    return ret;
}

void sd_smv(int DEV) 
{
    ULONG ret;
    if(sd_table[DEV].sm == NULL)sd_smCreate(DEV);
    ret=sm_v(sd_table[DEV].sm);
    if(ret!=0)bsp_fatal(ret);
}

int sd_write(int DEV, void *buf, int BufLen)
{
    int ret;
    ULONG thistaskid=0;
    if(DEV < 0 || DEV >= SDN_MAX)return SDE_DEV_NOT_EXIST;
    if(sd_table[DEV].databuf == NULL) return SDE_DEV_NOT_EXIST;
    if(sd_table[DEV].write == NULL )return SDE_UNKNOW_CMD;
    sd_smp(DEV,0);
    if(sd_table[DEV].devmode==1)
    {
        t_ident(NULL,0,&thistaskid);
        if(thistaskid!=sd_table[DEV].testtaskid)
            ret=SDE_IN_TEST_MODE;
           else
            ret=(sd_table[DEV].write)(sd_table[DEV].databuf,buf,BufLen);            
    }else
    ret=(sd_table[DEV].write)(sd_table[DEV].databuf,buf,BufLen);
    sd_smv(DEV);
    return ret;
}

int sd_read(int DEV, void *buf, int BufLen)
{
    int ret;
    ULONG thistaskid=0;
    if(DEV < 0 || DEV >= SDN_MAX)return SDE_DEV_NOT_EXIST;
    if(sd_table[DEV].databuf == NULL) return SDE_DEV_NOT_EXIST;
    if(sd_table[DEV].read == NULL)return SDE_UNKNOW_CMD;
    sd_smp(DEV,0);
    if(sd_table[DEV].devmode==1)
    {
        t_ident(NULL,0,&thistaskid);
        if(thistaskid!=sd_table[DEV].testtaskid)
            ret=SDE_IN_TEST_MODE;
           else
            ret=(sd_table[DEV].read)(sd_table[DEV].databuf,buf,BufLen);
    }else
    ret=(sd_table[DEV].read)(sd_table[DEV].databuf,buf,BufLen);
    sd_smv(DEV);
    return ret;
}

int sd_cntrl(int DEV,int cmd, void *param, int ParamLen)
{
    int ret;
    ULONG thistaskid=0;
    if(DEV < 0 || DEV >= SDN_MAX)return SDE_DEV_NOT_EXIST;
    if(sd_table[DEV].databuf == NULL) return SDE_DEV_NOT_EXIST;
    if(sd_table[DEV].cntrl == NULL)return SDE_UNKNOW_CMD;
    sd_smp(DEV,0);
    
    if(cmd==SDC_SET_TEST_MODE)
    {
       sd_table[DEV].devmode=1;
       t_ident(NULL,0,&(sd_table[DEV].testtaskid));
       if(param==NULL) ret=SDE_OK;
       else
          ret=(sd_table[DEV].cntrl)(sd_table[DEV].databuf,SDC_GET_EV_QUEUE_ACTION, param, ParamLen);
    }
    else if(cmd==SDC_SET_UNTEST_MODE)
    {
       sd_table[DEV].devmode=0;
       sd_table[DEV].testtaskid=0;
       if(param==NULL) ret=SDE_OK;
       else
         ret=(sd_table[DEV].cntrl)(sd_table[DEV].databuf,SDC_SET_EV_QUEUE_ACTION, param, ParamLen);
    }
    else if(sd_table[DEV].devmode==1)
    {
        t_ident(NULL,0,&thistaskid);
        if(thistaskid!=sd_table[DEV].testtaskid)
            ret=SDE_IN_TEST_MODE;
           else
               ret=(sd_table[DEV].cntrl)(sd_table[DEV].databuf, cmd, param, ParamLen);
    }
    else
       ret=(sd_table[DEV].cntrl)(sd_table[DEV].databuf, cmd, param, ParamLen);
    sd_smv(DEV);
    return ret;
}

/* for common BD process functions */

int BDRead(void *pDataBuf,char *pBuf, int MaxLen)         
{
    int i,pktlen;
    USHORT temp_ulong;
    DataBufStruct*  Ttemp;
    Ttemp=(DataBufStruct*)(pDataBuf);

    while(1)
    {
        temp_ulong=Ttemp->pBaseRecvBD[Ttemp->CurRecvBD].status;
        if((temp_ulong&BD_EMPTY)  == BD_EMPTY) return SDE_BUF_EMPTY;
        temp_ulong&=Ttemp->RecvErrMask;
        if(temp_ulong != 0)
        {
            Ttemp->DrvInfo.RecvError++;
            for(i=0;i<=15;i++)
                if(temp_ulong&( 0x8000L>>i))
                    Ttemp->DrvInfo.RecvBDStat[i]++;
            Ttemp->pBaseRecvBD[Ttemp->CurRecvBD].status &= (~temp_ulong);
            Ttemp->pBaseRecvBD[Ttemp->CurRecvBD].status |= BD_EMPTY;
            Ttemp->CurRecvBD=(Ttemp->CurRecvBD+1)%Ttemp->MaxRecvBD;
        }/* end of frame error */
        else
        {
            int retval;
            Ttemp->DrvInfo.RecvNum++;
            retval=pktlen=Ttemp->pBaseRecvBD[Ttemp->CurRecvBD].length;
            if(pktlen<0||pktlen>MaxLen){pktlen=MaxLen; retval=SDE_SHORTER_BUF; }
            Ttemp->DrvInfo.TotalRecvByte+=pktlen;
            for(i=0;i<pktlen;i++)pBuf[i]
                =((char*)(Ttemp->pBaseRecvBD[Ttemp->CurRecvBD].address))[i];
            Ttemp->pBaseRecvBD[Ttemp->CurRecvBD].status |= BD_EMPTY;
            Ttemp->CurRecvBD=(Ttemp->CurRecvBD+1)%Ttemp->MaxRecvBD;
            return retval;
        }/* end of frame ok */
    }/* end of while 1 */
}

int BDWrite(void *pDataBuf, char *pBuf, int Len) 
{
    int i;
    DataBufStruct*  Ttemp=(DataBufStruct *)pDataBuf;
    char *temp=(char *)(Ttemp->pBaseSendBD[Ttemp->CurSendBD].address);

    Ttemp->DrvInfo.SendTryNum++;
    if(Len <= 0 || Len >Ttemp->MaxBufLen)return SDE_PACKET_LEN;
    if((Ttemp->pBaseSendBD[Ttemp->CurSendBD].status&BD_READY)==BD_READY)
        return SDE_DEV_BUSY;
    Ttemp->DrvInfo.SendPerNum++;     
    Ttemp->DrvInfo.TotalSendByte+=Len;     
    for(i=0;i<Len;i++)temp[i]=pBuf[i]; 
    Ttemp->pBaseSendBD[Ttemp->CurSendBD].length=Len;
    Ttemp->pBaseSendBD[Ttemp->CurSendBD].status &= (~Ttemp->SendErrMask);
    Ttemp->pBaseSendBD[Ttemp->CurSendBD].status |= BD_READY;
    Ttemp->CurSendBD=(Ttemp->CurSendBD+1)%Ttemp->MaxSendBD;
    
    return Len;
}



int BDCntrl(void *pDataBuf, int Cmd, void *pParam, int ParamLen)
{
    int i,j;
    ULONG temp_ulong;
    DataBufStruct*  pData;
    ULONG buf[4];
    pData=(DataBufStruct*)pDataBuf;

    switch(Cmd)
    {
        case SDC_GET_MAX_BUF_LEN: return pData->MaxBufLen;
        case SDC_GET_MAX_SEND_BD_NUM: return pData->MaxSendBD;
        case SDC_GET_MAX_RECV_BD_NUM: return pData->MaxRecvBD;
        case SDC_GET_EMPTY_SEND_BD_NUM:
            for(i=0,j=0;i<pData->MaxSendBD;i++)
                if((pData->pBaseSendBD[i].status&BD_READY) != BD_READY)j++; 
            return j;
        case SDC_GET_EMPTY_RECV_BD_NUM:
            for(i=0,j=0;i<pData->MaxRecvBD;i++)
                if((pData->pBaseRecvBD[i].status&BD_EMPTY) == BD_EMPTY)j++;
            return j;
        case SDC_SET_ACTION:
            if(ParamLen < 4*sizeof(ULONG))return SDE_INVALID_LEN; 
            temp_ulong=((SDCSetActionStruct *)pParam)->SendTid;
            if( (temp_ulong !=0) && (t_getreg(temp_ulong,0,buf)!=0) )
                return SDE_INVALID_TASKID;
            temp_ulong=((SDCSetActionStruct *)pParam)->RecvTid;
            if( (temp_ulong !=0) && (t_getreg(temp_ulong,0,buf)!=0) )
                return SDE_INVALID_TASKID;
            if((((SDCSetActionStruct*)pParam)->SendEv & 0xffff0000)!=0
               || (((SDCSetActionStruct*)pParam)->RecvEv & 0xffff0000)!=0)
               return SDE_INVALID_EV;
            pData->SendTid=((SDCSetActionStruct*)pParam)->SendTid;
            pData->RecvTid=((SDCSetActionStruct*)pParam)->RecvTid;
            pData->SendEv=((SDCSetActionStruct*)pParam)->SendEv;
            pData->RecvEv=((SDCSetActionStruct*)pParam)->RecvEv;
            return SDE_OK;

        case SDC_SET_QUEUE_ACTION:
            #define qs ((SDCSetQueueStruct *)pParam)
            if(ParamLen < sizeof(SDCSetQueueStruct) )return SDE_INVALID_LEN; 
            pData->SendQID=qs->SendQID;
            pData->RecvQID=qs->RecvQID;
            memmove(pData->RecvMessage,qs->RecvMessage,sizeof(qs->RecvMessage));
            memmove(pData->SendMessage,qs->SendMessage,sizeof(qs->SendMessage));
            return SDE_OK;
            #undef qs

        case SDC_GET_DRIVER_INFO:
            if(ParamLen < sizeof(SDCGetDriverInfoStruct))return SDE_INVALID_LEN;
            memcpy(pParam,&(pData->DrvInfo),sizeof(SDCGetDriverInfoStruct));
            return SDE_OK;
        case SDC_CLR_DRIVER_INFO:
            i=splx(MAX_ILEV);
            if(ParamLen >= sizeof(SDCGetDriverInfoStruct)){
                memcpy(pParam,&(pData->DrvInfo),sizeof(SDCGetDriverInfoStruct));
            }
            memset(&(pData->DrvInfo),0,sizeof(SDCGetDriverInfoStruct));
            splx(i);
            return SDE_OK;
        case SDC_SET_EV_QUEUE_ACTION:
            #define qs ((SDCEventQueueStruct*)pParam)
            if(pParam==NULL) return SDE_INVALID_ARG;
            if(ParamLen != sizeof(SDCEventQueueStruct))return SDE_INVALID_LEN;
            
            temp_ulong=qs->SendTid;
            if( (temp_ulong !=0) && (t_getreg(temp_ulong,0,buf)!=0) )
                return SDE_INVALID_TASKID;
            temp_ulong=qs->RecvTid;
            if( (temp_ulong !=0) && (t_getreg(temp_ulong,0,buf)!=0) )
                return SDE_INVALID_TASKID;
            if((qs->SendEv & 0xffff0000)!=0
               || (qs->RecvEv & 0xffff0000)!=0)
               return SDE_INVALID_EV;
            pData->SendTid=qs->SendTid;
            pData->RecvTid=qs->RecvTid;
            pData->SendEv=qs->SendEv;
            pData->RecvEv=qs->RecvEv;
        
            pData->SendQID=qs->SendQID;
            pData->RecvQID=qs->RecvQID;
            for(i=0;i<4;i++)pData->SendMessage[i]=qs->SendMessage[i];
            for(i=0;i<4;i++)pData->RecvMessage[i]=qs->RecvMessage[i];
            return SDE_OK;
            #undef qs
        case SDC_GET_EV_QUEUE_ACTION:
            if(pParam==NULL) return SDE_INVALID_ARG;
            if(ParamLen != sizeof(SDCEventQueueStruct))return SDE_INVALID_LEN;
            #define ps ((SDCEventQueueStruct *)pParam)
            ps->SendTid=pData->SendTid;
            ps->RecvTid=pData->RecvTid;
            ps->SendEv=pData->SendEv;
            ps->RecvEv=pData->RecvEv;
            ps->SendQID=pData->SendQID;
            ps->RecvQID=pData->RecvQID;
            for(i=0;i<4;i++)ps->SendMessage[i]=pData->SendMessage[i];
            for(i=0;i<4;i++)ps->RecvMessage[i]=pData->RecvMessage[i];
            #undef ps
            return SDE_OK;
        default: 
            return SDE_UNKNOW_CMD;
    } /* end of switch */
}

char *sd_err(int err)
{
    switch(err)
    {
        case SDE_DEV_BUSY:
            return "SDE_DEV_BUSY";
        case SDE_PACKET_LEN:
            return "SDE_PACKET_LEN";
        case SDE_SHORTER_BUF:
            return "SDE_SHORTER_BUF";
        case SDE_BUF_EMPTY:
            return "SDE_BUF_EMPTY";
        case SDE_UNKNOW_CMD:
            return "SDE_UNKNOW_CMD";
        case SDE_OUT_OF_MEMORY:
            return "SDE_OUT_OF_MEMORY";
        case SDE_DEV_NOT_EXIST:
            return "SDE_DEV_NOT_EXIST";
        case SDE_INVALID_TASKID:
            return "SDE_INVALID_TASKID";
        case SDE_INVALID_EV:
            return "SDE_INVALID_EV";
        case SDE_INVALID_LEN:
            return "SDE_INVALID_LEN";
        case SDE_PACKET_ERR:
            return "SDE_PACKET_ERR";
	case SDE_INVALID_ARG:  
            return "SDE_INVALID_ARG";
	case SDE_INVALID_SLAVE: 
            return "SDE_INVALID_SLAVE";
	case SDE_INVALID_PACKET:   
            return "SDE_INVALID_PACKET";
	case SDE_GENERAL_FAIL: 
            return "SDE_GENERAL_FAIL";
        default: 
            return "Not a valid error!, Or is a user defined error!";
    }
}

⌨️ 快捷键说明

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