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