📄 smsc9118.c
字号:
goto DONE;
}
}
if(!Platform_RequestIRQ(platformData,irq,Smsc9118_ISR,privateData)) {
result=-ENODEV;
goto DONE;
}
acquired_isr=TRUE;
//must now test the IRQ connection to the ISR
SMSC_TRACE("Testing ISR using IRQ %ld",Platform_CurrentIRQ(platformData));
{
DWORD dwTimeOut=100000;
Lan_SignalSoftwareInterrupt(privateData);
do {
udelay(10);
dwTimeOut--;
} while((dwTimeOut)&&(!(privateData->SoftwareInterruptSignal)));
if(!(privateData->SoftwareInterruptSignal)) {
SMSC_WARNING("ISR failed signaling test");
result=-ENODEV;
goto DONE;
}
}
SMSC_TRACE("ISR passed test using IRQ %ld",Platform_CurrentIRQ(platformData));
if(!Mac_Initialize(privateData)) {
SMSC_WARNING("Failed Mac_Initialize");
result=-ENODEV;
goto DONE;
}
{//get mac address
DWORD dwHigh16=0;
DWORD dwLow32=0;
DWORD dwIntFlags=0;
VL_KEY keyCode=Vl_WaitForLock(&(privateData->MacPhyLock),&dwIntFlags);
if(mac_addr_hi16==0xFFFFFFFF) {
dwHigh16=Mac_GetRegDW(privateData,ADDRH,keyCode);
dwLow32=Mac_GetRegDW(privateData,ADDRL,keyCode);
if((dwHigh16==0x0000FFFFUL)&&(dwLow32==0xFFFFFFFF))
{
dwHigh16=0x00000070UL;
dwLow32=0x110F8000UL;
Mac_SetRegDW(privateData,ADDRH,dwHigh16,keyCode);
Mac_SetRegDW(privateData,ADDRL,dwLow32,keyCode);
SMSC_TRACE("Mac Address is set by default to 0x%04lX%08lX",
dwHigh16,dwLow32);
} else {
SMSC_TRACE("Mac Address is read from LAN9118 as 0x%04lX%08lX",
dwHigh16,dwLow32);
}
} else {
//SMSC_ASSERT((mac_addr_hi16&0xFFFF8000UL)==0);
dwHigh16=mac_addr_hi16;
dwLow32=mac_addr_lo32;
Mac_SetRegDW(privateData,ADDRH,dwHigh16,keyCode);
Mac_SetRegDW(privateData,ADDRL,dwLow32,keyCode);
SMSC_TRACE("Mac Address is set by parameter to 0x%04lX%08lX",
dwHigh16,dwLow32);
}
Vl_ReleaseLock(&(privateData->MacPhyLock),keyCode,&dwIntFlags);
dev->dev_addr[0]=LOBYTE(LOWORD(dwLow32));
dev->dev_addr[1]=HIBYTE(LOWORD(dwLow32));
dev->dev_addr[2]=LOBYTE(HIWORD(dwLow32));
dev->dev_addr[3]=HIBYTE(HIWORD(dwLow32));
dev->dev_addr[4]=LOBYTE(LOWORD(dwHigh16));
dev->dev_addr[5]=HIBYTE(LOWORD(dwHigh16));
}
privateData->MulticastUpdatePending = FALSE;
#ifdef USE_PHY_WORK_AROUND
netif_carrier_off(dev);
if(!Phy_Initialize(
privateData,
phy_addr,
link_mode))
{
SMSC_WARNING("Failed to initialize Phy");
result=-ENODEV;
goto DONE;
}
#endif
{
DWORD dwRxDmaCh=rx_dma;
DWORD dwTxDmaCh=tx_dma;
privateData->RxDmaChReserved=FALSE;
if(rx_dma==TRANSFER_REQUEST_DMA) {
dwRxDmaCh=Platform_RequestDmaChannel(&(privateData->PlatformData));
SMSC_ASSERT(dwRxDmaCh!=TRANSFER_REQUEST_DMA);
if(dwRxDmaCh<TRANSFER_REQUEST_DMA) {
privateData->RxDmaChReserved=TRUE;
}
}
privateData->TxDmaChReserved=FALSE;
if(tx_dma==TRANSFER_REQUEST_DMA) {
dwTxDmaCh=Platform_RequestDmaChannel(&(privateData->PlatformData));
SMSC_ASSERT(dwTxDmaCh!=TRANSFER_REQUEST_DMA);
if(dwTxDmaCh<TRANSFER_REQUEST_DMA) {
privateData->TxDmaChReserved=TRUE;
}
}
Tx_Initialize(privateData,dwTxDmaCh,dma_threshold);
Rx_Initialize(privateData,dwRxDmaCh,dma_threshold);
}
#ifndef LINUX_2_6_OR_NEWER
MOD_INC_USE_COUNT;
#endif
privateData->Running=TRUE;
netif_start_queue(dev);
Tx_StopQueue(privateData,0x01UL);
spin_lock_init(&(privateData->GpTimerLock));
Lan_EnableInterrupt(privateData,INT_EN_GPT_INT_EN_);
#ifndef USE_PHY_WORK_AROUND
netif_carrier_off(dev);
if(!Phy_Initialize(
privateData,
phy_addr,
link_mode))
{
SMSC_WARNING("Failed to initialize Phy");
result=-ENODEV;
goto DONE;
}
#endif
result=0;
DONE:
if(result!=0) {
#ifndef LINUX_2_6_OR_NEWER
MOD_DEC_USE_COUNT;
#endif
if(privateData!=NULL) {
if(privateData->TxDmaChReserved) {
Platform_ReleaseDmaChannel(platformData,
privateData->dwTxDmaCh);
privateData->TxDmaChReserved=FALSE;
}
if(privateData->RxDmaChReserved) {
Platform_ReleaseDmaChannel(platformData,
privateData->dwRxDmaCh);
privateData->RxDmaChReserved=FALSE;
}
if(acquired_isr) {
Platform_FreeIRQ(platformData);
}
if(acquired_mem_region) {
release_mem_region(
privateData->dwLanBase,
LAN_REGISTER_EXTENT);
}
}
}
SMSC_TRACE("<--Smsc9118_open, result=%d",result);
return result;
}
int Smsc9118_stop(struct net_device *dev)
{
int result=0;
PPRIVATE_DATA privateData=NULL;
SMSC_TRACE("-->Smsc9118_stop(dev=0x%08lX)",(DWORD)dev);
if(dev==NULL) {
SMSC_WARNING("Smsc9118_stop(dev==NULL)");
result=-EFAULT;
goto DONE;
}
privateData=(PPRIVATE_DATA)(dev->priv);
if(privateData==NULL) {
SMSC_WARNING("Smsc9118_stop(privateData==NULL)");
result=-EFAULT;
goto DONE;
}
privateData->StopLinkPolling=TRUE;
del_timer_sync(&(privateData->LinkPollingTimer));
Lan_DisableInterrupt(privateData,INT_EN_GPT_INT_EN_);
Tx_UpdateTxCounters(privateData);
privateData->Running=FALSE;
Lan_DisableIRQ(privateData);
Tx_CompleteDma(privateData);
Tx_StopQueue(privateData,0x01UL);
#ifndef LINUX_2_6_OR_NEWER
MOD_DEC_USE_COUNT;
#endif
if(privateData->TxDmaChReserved) {
Platform_ReleaseDmaChannel(
&(privateData->PlatformData),
privateData->dwTxDmaCh);
privateData->TxDmaChReserved=FALSE;
}
if(privateData->RxDmaChReserved) {
Platform_ReleaseDmaChannel(
&(privateData->PlatformData),
privateData->dwRxDmaCh);
privateData->RxDmaChReserved=FALSE;
}
Platform_FreeIRQ(&(privateData->PlatformData));
release_mem_region(privateData->dwLanBase,LAN_REGISTER_EXTENT);
{
const DWORD dwLanBase=privateData->dwLanBase;
const DWORD dwIdRev=privateData->dwIdRev;
const DWORD dwFpgaRev=privateData->dwFpgaRev;
struct net_device * const tempDev=privateData->dev;
char ifName[SMSC_IF_NAME_SIZE];
PLATFORM_DATA platformDataBackup;
memcpy(ifName,privateData->ifName,SMSC_IF_NAME_SIZE);
memcpy(&platformDataBackup,&(privateData->PlatformData),sizeof(PLATFORM_DATA));
memset(privateData,0,sizeof(PRIVATE_DATA));
privateData->dwLanBase=dwLanBase;
privateData->dwIdRev=dwIdRev;
privateData->dwFpgaRev=dwFpgaRev;
privateData->dev=tempDev;
memcpy(privateData->ifName,ifName,SMSC_IF_NAME_SIZE);
memcpy(&(privateData->PlatformData),&platformDataBackup,sizeof(PLATFORM_DATA));
}
DONE:
SMSC_TRACE("<--Smsc9118_stop, result=%d",result);
return result;
}
int Smsc9118_hard_start_xmit(
struct sk_buff *skb, struct net_device * const dev)
{
int result=0;
PPRIVATE_DATA privateData=NULL;
// SMSC_TRACE("-->Smsc9118_hard_start_xmit(skb=0x%08lX,dev=0x%08lX)",(DWORD)skb,(DWORD)dev);
if(skb==NULL) {
SMSC_WARNING("Smsc9118_hard_start_xmit(skb==NULL)");
result=-EFAULT;
goto DONE;
}
if(dev==NULL) {
SMSC_WARNING("Smsc9118_hard_start_xmit(dev==NULL)");
result=-EFAULT;
goto DONE;
}
if(dev->priv==NULL) {
SMSC_WARNING("Smsc9118_hard_start_xmit(dev->priv==NULL)");
result=-EFAULT;
goto DONE;
}
privateData=(PPRIVATE_DATA)(dev->priv);
// SET_GPIO(GP_TX);
Tx_SendSkb(privateData,skb);
// CLEAR_GPIO(GP_TX);
DONE:
// SMSC_TRACE("<--Smsc9118_hard_start_xmit, result=%d",result);
return result;
}
struct net_device_stats * Smsc9118_get_stats(struct net_device * const dev)
{
PPRIVATE_DATA privateData=NULL;
if(dev==NULL) {
SMSC_WARNING("Smsc9118_get_stats(dev==NULL)");
return NULL;
}
if(dev->priv==NULL) {
// SMSC_WARNING("Smsc9118_get_stats(dev->priv==NULL)");
return NULL;
}
privateData=(PPRIVATE_DATA)(dev->priv);
if(privateData->Running) {
privateData->stats.rx_dropped+=Lan_GetRegDW(RX_DROP);
Tx_UpdateTxCounters(privateData);
}
return &(privateData->stats);
}
void Smsc9118_set_multicast_list(struct net_device *dev)
{
SMSC_ASSERT(dev!=NULL);
Rx_SetMulticastList(dev);
}
int Smsc9118_do_ioctl(
struct net_device *dev,
struct ifreq *ifr,
int cmd)
{
PPRIVATE_DATA privateData=NULL;
PSMSC9118_IOCTL_DATA ioctlData=NULL;
BOOLEAN success=FALSE;
// SMSC_TRACE("-->Smsc9118_do_ioctl");
// SMSC_TRACE("cmd=%d,SIOCGMIIPHY=%d,SIOCDEVPRIVATE=%d",
// cmd,SIOCGMIIPHY,SIOCDEVPRIVATE);
SMSC_ASSERT(dev!=NULL);
SMSC_ASSERT(dev->priv!=NULL);
privateData=((PPRIVATE_DATA)dev->priv);
if(ifr==NULL) {
// SMSC_WARNING("Smsc9118_do_ioctl(ifr==NULL)");
goto DONE;
}
if(privateData->LanInitialized) {
// standard MII IOC's
struct mii_ioctl_data * const data=
(struct mii_ioctl_data *) & ifr->ifr_data;
switch(cmd) {
case SIOCGMIIPHY:
case SIOCDEVPRIVATE:
data->phy_id=1;
// SMSC_TRACE("SIOCGMIIPHY: phy_id set to 0x%04X",data->phy_id);
return 0;
case SIOCGMIIREG:
case SIOCDEVPRIVATE+1:
{
DWORD dwIntFlags=0;
VL_KEY keyCode=Vl_WaitForLock(&(privateData->MacPhyLock),&dwIntFlags);
data->val_out=Phy_GetRegW(
privateData,data->reg_num,keyCode);
Vl_ReleaseLock(&(privateData->MacPhyLock),keyCode,&dwIntFlags);
}
// SMSC_TRACE("SIOCGMIIREG: phy_id=0x%04X, reg_num=0x%04X, val_out set to 0x%04X",
// data->phy_id,data->reg_num,data->val_out);
return 0;
case SIOCSMIIREG:
case SIOCDEVPRIVATE+2:
// SMSC_TRACE("SIOCSMIIREG: phy_id=0x%04X, reg_num=0x%04X, val_in=0x%04X",
// data->phy_id,data->reg_num,data->val_in);
{
DWORD dwIntFlags=0;
VL_KEY keyCode=Vl_WaitForLock(&(privateData->MacPhyLock),&dwIntFlags);
Phy_SetRegW(
privateData,data->reg_num,((WORD)(data->val_in)),keyCode);
Vl_ReleaseLock(&(privateData->MacPhyLock),keyCode,&dwIntFlags);
}
return 0;
default:break;//make lint happy
}
}
if(ifr->ifr_data==NULL) {
// SMSC_WARNING("Smsc9118_do_ioctl(ifr->ifr_data==NULL)");
goto DONE;
}
if(cmd!=((int)SMSC9118_IOCTL)) goto DONE;
ioctlData=(PSMSC9118_IOCTL_DATA)(ifr->ifr_data);
if(ioctlData->dwSignature!=SMSC9118_APP_SIGNATURE) {
goto DONE;
}
switch(ioctlData->dwCommand) {
case COMMAND_GET_SIGNATURE:
success=TRUE;
break;
case COMMAND_GET_FLOW_PARAMS:
ioctlData->Data[0]=privateData->RxFlowMeasuredMaxThroughput;
ioctlData->Data[1]=privateData->RxFlowMeasuredMaxPacketCount;
ioctlData->Data[2]=privateData->RxFlowParameters.MaxThroughput;
ioctlData->Data[3]=privateData->RxFlowParameters.MaxPacketCount;
ioctlData->Data[4]=privateData->RxFlowParameters.PacketCost;
ioctlData->Data[5]=privateData->RxFlowParameters.BurstPeriod;
ioctlData->Data[6]=privateData->RxFlowMaxWorkLoad;
ioctlData->Data[7]=Lan_GetRegDW(INT_CFG)>>24;
privateData->RxFlowMeasuredMaxThroughput=0;
privateData->RxFlowMeasuredMaxPacketCount=0;
success=TRUE;
break;
case COMMAND_SET_FLOW_PARAMS:
if(!(privateData->RxFlowControlActive)) {
privateData->RxFlowParameters.MaxThroughput=ioctlData->Data[2];
privateData->RxFlowParameters.MaxPacketCount=ioctlData->Data[3];
privateData->RxFlowParameters.PacketCost=ioctlData->Data[4];
privateData->RxFlowParameters.BurstPeriod=ioctlData->Data[5];
if(ioctlData->Data[6]==0xFFFFFFFFUL) {
privateData->RxFlowMaxWorkLoad=
privateData->RxFlowParameters.MaxThroughpu
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -