📄 dm9000end.c
字号:
EXTINT|=1<<3; /* clear eint3 */
/*if( !PIC_CHECK_EXT1() )
return;
PIC_CLEAR_EXT1();*/
/* TODO */
/* Save previous register address */
/*printf("in Interrupt\n");*/
SYS_INT_DISABLE (pDrvCtrl);
DM9000_IN_ADDR( reg_save );
/* Disable all interrupt */
/*DM9000_OUT_CHAR( 0x05, 0x00 );*/
DM9000_OUT_CHAR( 0xff, 0x80 );
/* Read the device status register */
stat = dm9000StatusRead (pDrvCtrl);
/* Clear NSR status */
DM9000_IN_CHAR( 0x01, nsr_status );
/* Clear ISR status */
DM9000_IN_CHAR( 0xfe, isr_status );
DM9000_OUT_CHAR( 0xfe, isr_status );
DRV_LOG (DRV_DEBUG_INT, "Got an interrupt!", 1, 2, 3, 4, 5, 6);
if( (!(nsr_status & 0x40)) || (pDrvCtrl->device_wait_reset == 1) )
{
DRV_LOG (DRV_DEBUG_STATUS, "Got an link failed interrupt!", 1, 2, 3, 4, 5, 6);
netJobAdd ((FUNCPTR) muxError, (int) &(pDrvCtrl->end),
(int) &(pDrvCtrl->err), 0, 0, 0);
netJobAdd ((FUNCPTR)dm9000needreset, (int)(pDrvCtrl),
0, 0, 0, 0);
logMsg("reset 9000\n",0,0,0,0,0,0);
goto intRet;
}
/*
* enable interrupts, clear receive and/or transmit interrupts, and clear
* any errors that may be set.
*/
/* TODO - Check for errors */
/* Have netTask handle any input packets */
if( (isr_status & 1 )&&(stat & DM9000_RXON) )
{
DRV_LOG (DRV_DEBUG_INT, "Handle an RX interrupt!", 1, 2, 3, 4, 5, 6);
if ( pDrvCtrl->rxHandling != TRUE )
{
pDrvCtrl->rxHandling = TRUE;
/*dm9000HandleRcvInt(pDrvCtrl);*/
#ifdef DRV_DEBUG
g_IntrNum++;
#endif
netJobAdd ((FUNCPTR)dm9000HandleRcvInt, (int)pDrvCtrl,
0,0,0,0);
DRV_SP( DRV_PK,"^" );
}
}
/* TODO - handle transmit interrupts */
if( isr_status & 2 )
{
DRV_LOG (DRV_DEBUG_INT, "Got an TX interrupt!", pDrvCtrl->tx_pkt_cnt, 2, 3, 4, 5, 6);
/* Trnasmit Interrupt check */
/*DM9000_IN_CHAR( 0x01, tx_status ); Got TX status */
/*if( tx_status & 0xc) */
if( pDrvCtrl->tx_pkt_cnt > 0 )
{
DRV_SP( DRV_PK,"x" );
/* One packet sent complete */
pDrvCtrl->tx_pkt_cnt--;
/* Queue packet check & send */
if( pDrvCtrl->tx_pkt_cnt > 0)
{
DM9000_OUT_CHAR( 0xfc, pDrvCtrl->queue_pkt_len & 0xff );
DM9000_OUT_CHAR( 0xfd, (pDrvCtrl->queue_pkt_len >> 8) & 0xff );
DM9000_OUT_CHAR( 0x2, 0x1 );
}
}
pDrvCtrl->tbusy=0;
/*printf("dm9000Int tbusy=0\n");*/
}
intRet:
/* Re-enable interrupt mask */
DM9000_OUT_CHAR( 0xff, 0x83 );
/*DM9000_OUT_CHAR( 0x05, 0x11 );*/
/* Restore previous register address */
DM9000_OUT_ADDR( reg_save );
SYS_INT_ENABLE (pDrvCtrl);
/* sysIntEnablePIC (pDrvCtrl->ilevel); */
}
/*******************************************************************************
*
* dm9000PacketGet - get next received message
*
* Get next received message. Returns NULL if none are
* ready.
*
* RETURNS: ptr to next packet, or NULL if none ready.
*/
STATUS dm9000PacketGet( END_DEVICE *pDrvCtrl )
{
UCHAR rxbyte;
/* TODO - get next received packet */
/* Check packet ready or not */
DM9000_IN_CHAR( 0xf0, rxbyte ); /* Dummy read */
DM9000_IN_BYTE( rxbyte ); /* Got most updated data */
/* packet ready to receive check */
if( rxbyte == DM9000_PKT_RDY )
{
DRV_LOG (DRV_DEBUG_LOAD, "dm9000PacketGet() != NULL", 1, 2, 3, 4, 5, 6);
return OK;
}
DRV_LOG (DRV_DEBUG_LOAD, "dm9000PacketGet() == NULL", 1, 2, 3, 4, 5, 6);
return ERROR;
}
/*******************************************************************************
*
* 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, /* device structure */
char* pData ) /* packet to process */
{
char* pClusterData;
M_BLK_ID pMblk;
char* pNewCluster;
CL_BLK_ID pClBlk;
PKT skb;
DRV_LOG (DRV_DEBUG_LOAD, "dm9000Recv()", 1, 2, 3, 4, 5, 6);
/* TODO - Packet must be checked for errors. */
/* Add one to our unicast data.
END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1); */
/*
* 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.
*/
#ifdef DRV_DEBUG
g_RecvNumError++;
#endif
pNewCluster = netClusterGet (pDrvCtrl->end.pNetPool, pDrvCtrl->pClPoolId);
if (pNewCluster == NULL)
{
DRV_LOG (DRV_DEBUG_RX, "Cannot loan!", 1, 2, 3, 4, 5, 6);
END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
goto cleanRXD;
}
/* Grab a cluster block to marry to the cluster we received. */
if ((pClBlk = netClBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT)) == NULL)
{
netClFree (pDrvCtrl->end.pNetPool, pNewCluster);
DRV_LOG (DRV_DEBUG_RX, "Out of Cluster Blocks!", 1, 2, 3, 4, 5, 6);
END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
goto cleanRXD;
}
/*
* OK we've got a spare, let's get an M_BLK_ID and marry it to the
* one in the ring.
*/
if ((pMblk = mBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT, MT_DATA)) == NULL)
{
netClBlkFree (pDrvCtrl->end.pNetPool, pClBlk);
netClFree (pDrvCtrl->end.pNetPool, pNewCluster);
DRV_LOG (DRV_DEBUG_RX, "Out of M Blocks!", 1, 2, 3, 4, 5, 6);
END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
goto cleanRXD;
}
END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);
/* align IP header at 32-bit boundary, this is reqired by VxWorks
** TCP/IP stack
*/
pClusterData = (char*)((((unsigned long)pNewCluster + 1) & (~1)) | 2 );
/* move packet from Ethernet on-board SRAM to the mbuf pre-allocated
** in system memory
*/
skb.pData = pClusterData;
skb.len = 0;
if( dmfe_packet_receive( (PKT*)(&skb), pDrvCtrl ) )
{
mBlkFree (pDrvCtrl->end.pNetPool, pMblk);
netClBlkFree (pDrvCtrl->end.pNetPool, pClBlk);
netClFree (pDrvCtrl->end.pNetPool, pNewCluster);
DRV_LOG (DRV_DEBUG_RX, "no data!", 1, 2, 3, 4, 5, 6);
END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
goto cleanRXD;
}
/*pCluster = END_CACHE_PHYS_TO_VIRT (pData); */
/* Join the cluster to the MBlock */
/*netClBlkJoin (pClBlk, pCluster, len, NULL, 0, 0, 0);*/
netClBlkJoin (pClBlk, pNewCluster, skb.len, NULL, 0, 0, 0);
netMblkClJoin (pMblk, pClBlk);
pMblk->mBlkHdr.mData = pClusterData;
pMblk->mBlkHdr.mLen = skb.len;
pMblk->mBlkHdr.mFlags |= M_PKTHDR;
pMblk->mBlkPktHdr.len = skb.len;
/* make the packet data coherent */
END_CACHE_INVALIDATE (pMblk->mBlkHdr.mData, skb.len);
DRV_LOG (DRV_DEBUG_NO, "Calling upper layer!", 1, 2, 3, 4, 5, 6);
/* TODO - Done with processing, clean up and pass it up. */
/* Call the upper layer's receive routine. */
END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);
/* DM9000_OUT_CHAR( 0x05, DM9000_REG05 ); */ /* RX disable */
/*DM9000_OUT_CHAR( 0xff, 80 ); */ /* disable TX/RX interrupt mask */
END_RCV_RTN_CALL(&pDrvCtrl->end, pMblk);
/*DM9000_OUT_CHAR( 0x05, DM9000_REG05 | 1 ); */ /* RX enable */
/*DM9000_OUT_CHAR( 0xff, DM9000_REGFF ); */ /* Enable TX/RX interrupt mask */
#ifdef DRV_DEBUG
g_RecvNum++;
g_RecvNumError--;
#endif
return (OK);
cleanRXD:
return (ERROR);
}
/*******************************************************************************
*
* dm9000HandleRcvInt - task level interrupt service for input packets
*
* This routine is called at task level indirectly by the interrupt
* service routine to do any message received processing.
*
* The double loop is to protect against a race condition where the interrupt
* code see rxHandling as TRUE, but it is then turned off by task code.
* This race is not fatal, but does cause occassional delays until a second
* packet is received and then triggers the netTask to call this routine again.
*
* RETURNS: N/A.
*/
static void dm9000HandleRcvInt( END_DEVICE *pDrvCtrl ) /* interrupting device */
{
char* pData;
int i;
unsigned short tmp3;
/* DRV_LOG (0xFFFF, "dm9000HandleRcvInt()_IN", 1, 2, 3, 4, 5, 6);*/
/* do*/
/* {*/
pDrvCtrl->rxHandling = TRUE;
while (OK==dm9000PacketGet (pDrvCtrl))
{
if(dm9000Recv (pDrvCtrl, (char*)NULL ) == ERROR)
{
break;
}
}
pDrvCtrl->rxHandling = FALSE;
/* }while (dm9000PacketGet (pDrvCtrl) != NULL); */
/* DRV_LOG (0xFFFF, "dm9000HandleRcvInt()_OUT", 1, 2, 3, 4, 5, 6);*/
}
/*******************************************************************************
*
* 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 * pDrvCtrl, /* device ptr */
M_BLK_ID pMblk ) /* data to send */
{
int oldLevel = 0;
BOOL freeNow = TRUE;
PKT skb;
int len;
DRV_LOG (DRV_DEBUG_LOAD, "dm9000Send()", (pDrvCtrl->flags), 2, 3, 4, 5, 6);
/*
* 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);
/* This is the normal case where all the data is in one M_BLK_ID */
/* Set pointers in local structures to point to data. */
/*
* If no buffers are available,
* release the semaphore and return END_ERR_BLOCK.
* Do not free packet
*/
/* place a transmit request */
/*if (!((pDrvCtrl->flags) & DM9000_POLLING))*/
oldLevel = intLock (); /* protect dm9000Int */
/* TODO - initiate device transmit */
len = netMblkToBufCopy (pMblk, (char*)(pDrvCtrl->txBuf), NULL);
len = max (len, ETHERSMALL);
skb.len = len;
skb.pData = (char*)pDrvCtrl->txBuf;
if( dmfe_start_xmit( &skb, pDrvCtrl ) )
{
/* printf("dm9000Send() fail. packet len: %d\n",len); */
DRV_LOG (DRV_DEBUG_STATUS, "dm9000Send() fail", 1, 2, 3, 4, 5, 6);
freeNow = FALSE;
/* Advance our management index(es) */
/*if (!((pDrvCtrl->flags) & DM9000_POLLING))*/
intUnlock (oldLevel);
if (!((pDrvCtrl->flags) & DM9000_POLLING))
END_TX_SEM_GIVE (&pDrvCtrl->end);
return(END_ERR_BLOCK);
}
/* Advance our management index(es) */
/*if (!((pDrvCtrl->flags) & DM9000_POLLING))*/
intUnlock (oldLevel);
if (!((pDrvCtrl->flags) & DM9000_POLLING))
END_TX_SEM_GIVE (&pDrvCtrl->end);
/* 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.
*/
if (freeNow)
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 * pDrvCtrl, /* device receiving command */
int cmd, /* ioctl command code */
caddr_t data ) /* command argument */
{
int error = 0;
long value;
DRV_LOG (DRV_DEBUG_LOAD, "dm9000Ioctl()", 1, 2, 3, 4, 5, 6);
switch (cmd)
{
case EIOCSADDR:
DRV_LOG (DRV_DEBUG_LOAD, "EIOICSADDR", 1, 2, 3, 4, 5, 6);
if (data == NULL)
return (EINVAL);
bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->end),
END_HADDR_LEN(&pDrvCtrl->end));
break;
case EIOCGADDR:
DRV_LOG (DRV_DEBUG_LOAD, "EIOCGADDR", 1, 2, 3, 4, 5, 6);
if (data == NULL)
return (EINVAL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -