?? dm9000end.c
字號:
}
DRV_LOG (DRV_DEBUG_LOAD, "Interrupt connected.", 1, 2, 3, 4, 5, 6);
DRV_LOG (DRV_DEBUG_LOAD, "interrupt enabled.", 1, 2, 3, 4, 5, 6);
/* Activate DM9000 */
DM9000_OUT_CHAR( 0x05, DM9000_REG05 ); /* RX enable */
DM9000_OUT_CHAR( 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, nsr_status; /* tx_status, */
UCHAR TX_comple_status;
/* Save previous register address */
DM9000_IN_ADDR( reg_save );
DM9000_OUT_CHAR( 0xff, DM9000_REGFF_OFF ); /*temp*/
/* Read the device status register */
stat = dm9000StatusRead (pDrvCtrl);
/* 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);
/*
* enable interrupts, clear receive and/or transmit interrupts, and clear
* any errors that may be set.
*/
/* 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);
DRV_SP( DRV_PK,"x" );
DM9000_IN_CHAR(0x1, TX_comple_status);
/* if (TX_comple_status & 0x4) pDrvCtrl->tx_pkt_cnt--;
if (TX_comple_status & 0x8) pDrvCtrl->tx_pkt_cnt--; */
if (TX_comple_status & 0xc)
{
/* 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, 0x01 );
}
}
}
intRet:
/*--sailor*/
rEINTPEND =( rEINTPEND|(1<<7));/*clear status for eint7*/
rEINTMASK=(rEINTMASK&(~( 1<<7) )); /*enable intr7*/
/* Re-enable interrupt mask */
DM9000_OUT_CHAR( 0xff, DM9000_REGFF );
/* Restore previous register address */
DM9000_OUT_ADDR( reg_save );
}
/*******************************************************************************
*
* 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_CHAR( 0xf0, 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);
/*
* 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;
}
/* Join the cluster to the MBlock */
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);
END_RCV_RTN_CALL(&pDrvCtrl->end, pMblk);
#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;
pDrvCtrl->rxHandling = TRUE;
while (OK==dm9000PacketGet (pDrvCtrl))
{
if(dm9000Recv (pDrvCtrl, (char*)NULL ) == ERROR)
{
break;
}
}
pDrvCtrl->rxHandling = FALSE;
}
/*******************************************************************************
*
* 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 ) )
{
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);
netMblkClChainFree (pMblk);
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)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -