📄 dm9000end.c
字号:
pDrvCtrl->unit = atoi (tok);
#ifdef DM_DEBUG_PRINT
logMsg("dm9000Parse: unit = %x\n ",pDrvCtrl->unit, 0, 0, 0, 0, 0);
#endif
/* IO Base */
tok = strtok_r (NULL, ":", &pHolder);
if (tok == NULL) return ERROR;
address = strtoul (tok, NULL, 16);
pDrvCtrl->IOBase = (UINT)address;
#ifdef DM_DEBUG_PRINT
logMsg("dm9000Parse: IOBase = %x\n ",pDrvCtrl->IOBase, 0, 0, 0, 0, 0);
#endif
/* Interrupt level. */
tok = strtok_r (NULL, ":", &pHolder);
if (tok == NULL) return ERROR;
pDrvCtrl->ilevel = (UINT)strtoul (tok,NULL,16);
#ifdef DM_DEBUG_PRINT
logMsg("dm9000Parse: ilevel = %d\n ",pDrvCtrl->ilevel, 0, 0, 0, 0, 0);
#endif
/*Interrupt vector*/
pDrvCtrl->ivec = INT_VEC_EINT_0;
#ifdef DM_DEBUG_PRINT
logMsg("dm9000Parse: ivec = %d\n ",pDrvCtrl->ivec, 0, 0, 0, 0, 0);
#endif
return OK;
}
/*******************************************************************************
*
* dm9000MemInit - initialize memory for the chip
*
* This routine is highly specific to the device.
*
* RETURNS: OK or ERROR.
*/
static STATUS dm9000MemInit( END_DEVICE *pDrvCtrl ) /* device to be initialized */
{
if ((pDrvCtrl->end.pNetPool = malloc (sizeof(NET_POOL))) == NULL)
return (ERROR);
/* Calculate the total memory for all the M-Blks and CL-Blks. */
dm9000MclBlkConfig.memSize = (dm9000MclBlkConfig.mBlkNum *
(M_BLK_SZ + sizeof (long))) +
(dm9000MclBlkConfig.clBlkNum *
(CL_BLK_SZ + sizeof(long)));
if ((dm9000MclBlkConfig.memArea = (char *) memalign (sizeof(long),
dm9000MclBlkConfig.memSize)) == NULL)
return (ERROR);
/* Calculate the memory size of all the clusters. */
dm9000ClDescTbl[0].memSize = (dm9000ClDescTbl[0].clNum * (2048 + 8)) + sizeof(int);
/* Allocate the memory for the clusters from cache safe memory. */
dm9000ClDescTbl[0].memArea = (char *) cacheDmaMalloc (dm9000ClDescTbl[0].memSize) ;
if (dm9000ClDescTbl[0].memArea == NULL)
{
#ifdef DM_DEBUG_PRINT
logMsg("dm9000MemInit: system memory unavailable!\n",
0, 0, 0, 0, 0, 0);
#endif
return (ERROR);
}
/* Initialize the memory pool. */
if (netPoolInit(pDrvCtrl->end.pNetPool, &dm9000MclBlkConfig,
&dm9000ClDescTbl[0], dm9000ClDescTblNumEnt,NULL) == ERROR)
{
#ifdef DM_DEBUG_PRINT
logMsg("dm9000MemInit: Could not init buffering!\n",
0, 0, 0, 0, 0, 0);
#endif
return (ERROR);
}
/*
* If you need clusters to store received packets into then get them
* here ahead of time.
*/
if ((pDrvCtrl->pClPoolId = netClPoolIdGet (pDrvCtrl->end.pNetPool,2048, (BOOL)FALSE))== NULL)
{
#ifdef DM_DEBUG_PRINT
logMsg("dm9000MemInit: Could not memory cluster ID!\n",
0,0,0,0,0,0);
#endif
return (ERROR);
}
#ifdef DM_DEBUG_PRINT
logMsg("dm9000MemInit: Memory setup complete!\n",
0, 0, 0, 0, 0, 0);
#endif
return OK;
}
/*******************************************************************************
*
* dm9000Start - start the device
*
* This function calls BSP functions to connect interrupts and start the
* device running in interrupt mode.
*
* RETURNS: OK or ERROR
*
*/
static STATUS dm9000Start( END_DEVICE *pV ) /* device ID */
{
END_DEVICE *pDrvCtrl;
pDrvCtrl=(END_DEVICE *)pV;
s3cExtIntPinEnable ();
/*Setup the interrupt handler and IDT table entry*/
if(intConnect(INUM_TO_IVEC(pDrvCtrl->ivec), dm9000Int, (int)pDrvCtrl) == ERROR)
{
#ifdef DM_DEBUG_PRINT
logMsg("dm9000Start:Can not connect interrupt!\n",
0, 0, 0, 0, 0, 0);
#endif
return ERROR;
}
/*Enable DM9000 interrupt at the systerm lecel*/
if(intEnable(pDrvCtrl->ilevel)==ERROR)
{
#ifdef DM_DEBUG_PRINT
logMsg("dm9000Start: Can not enable interrupt!\n ",
0, 0, 0, 0, 0, 0);
#endif
return ERROR;
}
/*Mark the interface as up and running*/
END_FLAGS_SET (&pDrvCtrl->end, (IFF_UP | IFF_RUNNING));
/* Activate DM9000 */
DM9000_OUT_REG( 0x05, DM9000_REG05 ); /* RX enable */
DM9000_OUT_REG( 0xff, DM9000_REGFF ); /* Enable TX/RX interrupt mask */
return (OK);
}
/*******************************************************************************
*
* dm9000Int - handle controller interrupt
*
* This routine is called at interrupt level in response to an interrupt from
* the controller.
*
* RETURNS: N/A.
*/
static void dm9000Int( END_DEVICE *pDrvCtrl ) /* interrupting device */
{
UCHAR stat, reg_save,isr_status,TX_comple_status,tx_status;
/*clear s3c2410 external intpand reg */
intDisable (pDrvCtrl->ilevel);
rpINTMSK |= 1;
rpINTPND |= 1;
rpSRCPND |= 1;
/*save previous register address */
DM9000_IN_ADDR( reg_save );
DM9000_OUT_REG( 0xff, DM9000_REGFF_OFF );
/* Read and Clear ISR status */
DM9000_IN_REG( 0xfe, isr_status );
DM9000_OUT_REG( 0xfe, isr_status );
#ifdef DM_DEBUG_PRINT
logMsg("dm9000Int: got interrupt!\n", 0, 0, 0, 0, 0, 0);
#endif
/*
* enable interrupts, clear receive and/or transmit interrupts, and clear
* any errors that may be set.
*/
if( isr_status & 0x02 )
{
/*Clear Tx Packet Complete Status*/
DM9000_IN_REG(0x01, TX_comple_status);
if (TX_comple_status & 0xc)
{
if (TX_comple_status & 0x4) pDrvCtrl->tx_pkt_cnt--;
if (TX_comple_status & 0x8) pDrvCtrl->tx_pkt_cnt--;
}
else
{
DM9000_IN_REG( 0x02, tx_status );
while(tx_status & 0x1){DM9000_IN_REG( 0x02, tx_status );}
}
/*if not complete tranmission*/
if(pDrvCtrl->tx_pkt_cnt>0)
{
/* Set TX length to DM9000 */
DM9000_OUT_REG( 0xfc, pDrvCtrl->queue_pkt_len & 0xff );
DM9000_OUT_REG( 0xfd, (pDrvCtrl->queue_pkt_len >> 8) & 0xff );
/* Issue TX polling command */
DM9000_OUT_REG( 0x2, 0x01 ); /* Cleared after TX complete */
}
}
/* Have netTask handle any input packets */
if (isr_status & 0x01 )
{
if ( pDrvCtrl->rxHandling != TRUE )
{
pDrvCtrl->rxHandling = TRUE;
netJobAdd ((FUNCPTR)dm9000Recv, (int)pDrvCtrl, 0, 0, 0, 0);
}
}
/* Re-enable interrupt mask */
DM9000_OUT_REG( 0xff, DM9000_REGFF );
DM9000_OUT_REG( 0x05, 0x11 );
/* Restore previous register address */
DM9000_OUT_ADDR( reg_save );
rpINTMSK &= ~1;
intEnable (pDrvCtrl->ilevel);
}
/*******************************************************************************
*
* dm9000Recv - process the next incoming packet
*
* Handle one incoming packet. The packet is checked for errors.
*
* RETURNS: N/A.
*/
static STATUS dm9000Recv( END_DEVICE *pDrvCtrl )
{
char* pNewCluster = NULL;
M_BLK_ID pMblk;
CL_BLK_ID pClBlk;
int DataLen;
UCHAR status;
while((status=dmfe_Get_NextPacket()) != 0)
{
/*
* We implicitly are loaning here, if copying is necessary this
* step may be skipped, but the data must be copied before being
* passed up to the protocols.
*/
/* Get a receive frame buffer */
pNewCluster = netClusterGet (pDrvCtrl->end.pNetPool, pDrvCtrl->pClPoolId);
/* Grab a cluster block to marry to the cluster we received. */
pClBlk = netClBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT);
/* OK we've got a spare, let's get an M_BLK_ID and marry it to the one in the ring.*/
pMblk = mBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT, MT_DATA);
if(pNewCluster == NULL || pClBlk == NULL || pMblk == NULL)
{
if(pNewCluster){
netClFree(pDrvCtrl->end.pNetPool,pNewCluster);
}
if(pClBlk){
netClBlkFree (pDrvCtrl->end.pNetPool, pClBlk);
}
if(pMblk){
netMblkFree(pDrvCtrl->end.pNetPool,pMblk);
}
/* Increment the input error count */
END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
return;
}
END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);
DataLen = dmfe_Copy_RxFrame(pDrvCtrl, pNewCluster+2, status);
/* Join the cluster to the MBlock */
netClBlkJoin (pClBlk, pNewCluster, DataLen, NULL, 0, 0, 0);
netMblkClJoin (pMblk, pClBlk);
/*pMblk->mBlkHdr.mData += pDrvCtrl->offset;*/
pMblk->mBlkHdr.mData += 2;
pMblk->mBlkHdr.mLen = DataLen;
pMblk->mBlkHdr.mFlags |= M_PKTHDR;
pMblk->mBlkPktHdr.len = DataLen;
/* Call the upper layer's receive routine. */
END_RCV_RTN_CALL(&pDrvCtrl->end, pMblk);
pNewCluster = NULL;
if(pNewCluster) netClFree(pDrvCtrl->end.pNetPool,pNewCluster);
}
pDrvCtrl->rxHandling = FALSE;
return (OK);
cleanRXD:
pDrvCtrl->rxHandling = FALSE;
return (ERROR);
}
/*******************************************************************************
*
* dm9000Send - the driver send routine
*
* This routine takes a M_BLK_ID sends off the data in the M_BLK_ID.
* The buffer must already have the addressing information properly installed
* in it. This is done by a higher layer. The last arguments are a free
* routine to be called when the device is done with the buffer and a pointer
* to the argument to pass to the free routine.
*
* RETURNS: OK, ERROR, or END_ERR_BLOCK.
*/
static STATUS dm9000Send( END_DEVICE *pV, /* device ptr */
M_BLK_ID pMblk ) /* data to send */
{
static UCHAR txBuf[DM9000_FRAME_BUFSIZE];
int oldLevel = 0;
int length = 0;
int TxStatus = 0;
END_DEVICE *pDrvCtrl;
pDrvCtrl=(END_DEVICE *)pV;
/*
* Obtain exclusive access to transmitter. This is necessary because
* we might have more than one stack transmitting at once.
*/
if (!(pDrvCtrl->flags & DM9000_POLLING))
{
END_TX_SEM_TAKE (&pDrvCtrl->end, WAIT_FOREVER);
}
/* Get data from Mblk to tx buffer. */
length = netMblkToBufCopy (pMblk, (char *)txBuf, NULL);
if (!(pDrvCtrl->flags & DM9000_POLLING))
{
oldLevel = intLock (); /* protect dm9000Int */
}
/*transmit packet*/
TxStatus=dmfe_Copy_TxFrame(pDrvCtrl, txBuf, length);
/* unlock interrupt*/
if (!((pDrvCtrl->flags) & DM9000_POLLING))
intUnlock (oldLevel);
/* Advance our management index */
if (!((pDrvCtrl->flags) & DM9000_POLLING))
END_TX_SEM_GIVE (&pDrvCtrl->end);
/*transmit packet error handle*/
if(TxStatus == ERROR)
{
logMsg("dm9000Send: Transmit packet is failed!\n", 0, 0, 0, 0, 0, 0);
netMblkClChainFree (pMblk);
END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_ERRS, +1);
return(END_ERR_BLOCK);
}
/* Bump the statistics counters. */
END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, +1);
/*
* Cleanup. The driver must either free the packet now or
* set up a structure so it can be freed later after a transmit
* interrupt occurs.
*/
netMblkClChainFree (pMblk);
return (OK);
}
/*******************************************************************************
*
* dm9000Ioctl - the driver I/O control routine
*
* Process an ioctl request.
*
* RETURNS: A command specific response, usually OK or ERROR.
*/
static int dm9000Ioctl( END_DEVICE *pV, /* device receiving command */
int cmd, /* ioctl command code */
caddr_t data ) /* command argument */
{
int status = 0;
long value;
END_DEVICE *pDrvCtrl;
pDrvCtrl=(END_DEVICE *)pV;
switch (cmd)
{
case EIOCSADDR:
if (data == NULL)
return (EINVAL);
bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->end),
END_HADDR_LEN(&pDrvCtrl->end));
break;
case EIOCGADDR:
if (data == NULL)
return (EINVAL);
bcopy ((char *)END_HADDR(&pDrvCtrl->end), (char *)data,
END_HADDR_LEN(&pDrvCtrl->end));
break;
case EIOCSFLAGS:
value = (long)data;
if (value < 0)
{
value = -(--value);
END_FLAGS_CLR (&pDrvCtrl->end, value);
}
else
{
END_FLAGS_SET (&pDrvCtrl->end, value);
}
dm9000Config (pDrvCtrl);
break;
case EIOCGFLAGS:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -