⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lan91c111end.c

📁 lan91c111芯片的驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
*
* RETURNS: N/A.
*/

 void lan91c111HandleRcvInt
    (
    LAN91C111END_DEVICE *pDrvCtrl	/* interrupting device */
    )
    {
    UINT receiveReady;
	int loopCount=0;

    pDrvCtrl->rxHandling = TRUE;


    do {

        lan91c111Recv (pDrvCtrl);
        receiveReady = pDrvCtrl->pRxReadIndex->pData ? 1 : 0;
	    loopCount++;

       }  while ((receiveReady != 0) && (loopCount <= 30));
	   
       pDrvCtrl->rxHandling = FALSE;

		return;
    }
#endif

#define CLCHAIN_DBG 1

#if CLCHAIN_DBG
M_BLK_ID myMblk;
#endif
/******************************************************************************
* lan91c111Send - end send routine
*
* This routine will be called by the network stack whenever the upper layer want
* to send the datagram. It takes a pointer to mbuf. It extacts the data from the
* mbuf and writes in chip.
*
* RETURNS: status of the write operation
*/

STATUS lan91c111Send(END_OBJ *pEnd,M_BLK_ID pMblk)
{
    LAN91C111END_DEVICE  	*pDrvCtrl = (LAN91C111END_DEVICE *)pEnd;
    BOOLEAN status;

	M_BLK_ID curMblk;
	int currentKey;
	DRV_LOG (DRV_DEBUG_TX, "lan91c111Send: called \n",1, 2, 3, 4, 5, 6);

/* This Block is to put the packet sent by the upper layers in a ring Buffer.Here
 we are using ReadIndex and WriteIndex instead of allocpending and writepending Queues*/

/* He is not checking for null since he is sending null  in the TX Int case...
    I think we have to check for null ..ask kumar about this.. */

	if(pMblk ==(M_BLK_ID) 1)
	{

			currentKey = intLock();
			pDrvCtrl->AllocPending =FALSE;
			curMblk = pDrvCtrl->pTxReadIndex->pMblk;

            END_TX_SEM_TAKE (&pDrvCtrl->endObj,WAIT_FOREVER);
	        pDrvCtrl->sendDatalen = netMblkToBufCopy(curMblk,pDrvCtrl->sendBuf,NULL);
			pDrvCtrl->sendDatalen = (ETHER_ZLEN < pDrvCtrl->sendDatalen) ? pDrvCtrl->sendDatalen : ETHER_ZLEN;
			pDrvCtrl->pTxReadIndex->pMblk = NULL;
			netMblkClChainFree(curMblk);
	        if ( pDrvCtrl->pTxReadIndex < pDrvCtrl->pTxBase + TX_PACKETS - 2)
				pDrvCtrl->pTxReadIndex++;
   			else
     			pDrvCtrl->pTxReadIndex = pDrvCtrl->pTxBase;
		    lan91c111WriteToChip(pDrvCtrl);
			intUnlock(currentKey);
            END_TX_SEM_GIVE (&pDrvCtrl->endObj);
		    return OK;
	}
    else if(pMblk)   /* put in ring buffer */
    {
		if(pDrvCtrl->pTxWriteIndex->pMblk)
		{
			/* TX fifo full, drop packet */
			netMblkClChainFree(pMblk);
		}
		else
		{
			/* TX fifo not full, queue packet */
	 	   	pDrvCtrl->pTxWriteIndex->pMblk = pMblk;
/*
			DRV_LOG(DRV_DEBUG_TX,"TxWriteIndex : %d\n",pDrvCtrl->pTxWriteIndex,2,3,4,5,6);
*/
	 	   	if(pDrvCtrl->pTxWriteIndex < (pDrvCtrl->pTxBase + TX_PACKETS - 2))
		        pDrvCtrl->pTxWriteIndex++;
	  	  	else
	      		pDrvCtrl->pTxWriteIndex = pDrvCtrl->pTxBase;
        }
    }

/* This Block calls two Functions one allocates the memory
 from the MMU and other copies the stuff from clusters to the chip*/
			curMblk = pDrvCtrl->pTxReadIndex->pMblk;
	 	  	if(!curMblk)
			{
            DRV_LOG (DRV_DEBUG_ERR, "lan91c111Send: Current MBlk is NULL \n",1, 2, 3, 4, 5, 6);
			return OK;
			}
	        status = DoAllocate(pDrvCtrl);
            if(status)
            {
					DRV_LOG(DRV_DEBUG_TX, "lan91c111Send : Got Access to MMU\n",1,2,3,4,5,6);
  			        END_TX_SEM_TAKE (&pDrvCtrl->endObj,WAIT_FOREVER);
					currentKey = intLock();
	    		    pDrvCtrl->sendDatalen = netMblkToBufCopy(curMblk,pDrvCtrl->sendBuf,NULL);
					pDrvCtrl->sendDatalen = (ETHER_ZLEN < pDrvCtrl->sendDatalen) ? pDrvCtrl->sendDatalen : ETHER_ZLEN;
					pDrvCtrl->pTxReadIndex->pMblk = NULL;
	 				netMblkClChainFree(curMblk);
   			        if ( pDrvCtrl->pTxReadIndex < pDrvCtrl->pTxBase + TX_PACKETS - 2)
   						pDrvCtrl->pTxReadIndex++;
		   			else
  		     			pDrvCtrl->pTxReadIndex = pDrvCtrl->pTxBase;
					lan91c111WriteToChip(pDrvCtrl);
					intUnlock(currentKey);
            }
            else
            {
                    USHORT OldMask;
					int key;
					key = intLock();
                    pDrvCtrl->AllocPending = TRUE;
                    SYS_IN_SHORT(pDrvCtrl->IOBase + BANK2_INT_STS, (PUSHORT)&OldMask);
                    SYS_OUT_SHORT(pDrvCtrl->IOBase + BANK2_INT_STS, 0);
                    OldMask |= ( INT_ALLOC << 8 );
                    OldMask &= 0xFF00;  /* Do not ACK interrupts */
                    SYS_OUT_SHORT(pDrvCtrl->IOBase + BANK2_INT_STS, OldMask);
					intUnlock(key);
					DRV_LOG(DRV_DEBUG_TX, "lan91c111Send : Set Alloc Int bit\n",1,2,3,4,5,6);
            }
			END_TX_SEM_GIVE (&pDrvCtrl->endObj);

            return OK;
}

/*****************************************************************************
* DoAllocate - allocates the memory for write operation
*
* This routine makes a request MMU for 2k bytes of memory for packet
* transmition.
*
* RETIRNS: status of the request
*/

BOOLEAN DoAllocate(LAN91C111END_DEVICE  *pDrvCtrl)
 {

	UINT            AllocateOk;         /*  Delay loop control */
 	UINT            IOBase;

	USHORT		AllocSts;

        IOBase = pDrvCtrl->IOBase;

		SYS_OUT_SHORT(IOBase + BANK_SELECT, 2);

        SYS_OUT_SHORT(IOBase + BANK2_MMU_CMD,(USHORT)((((pDrvCtrl->sendDatalen + FRAME_OVERHEAD) & 0xfffe) >> 8)|CMD_ALLOC));

		AllocateOk = MMU_WAIT;

        while(AllocateOk)
        {
               SYS_IN_SHORT(IOBase + BANK2_INT_STS,(PUSHORT) &AllocSts);
     		   if(AllocSts & INT_ALLOC)
     		       break;
     		   AllocateOk--;
   		}

		/* Check whether the allocation result is a pass or fail */
        return((BOOLEAN) (AllocSts & INT_ALLOC));

}

/***********************************************************************
* writeToChip - write data to the chip
*
* This routine will writes the data to the chip and the transmission for
* transmition.
*
* RETURNS: N/A
*/
void lan91c111WriteToChip(LAN91C111END_DEVICE  *pDrvCtrl)
{
        UINT        IOBase;
        UINT        DataPort;
        USHORT TempWord;
        BYTE TempByte;

        USHORT length = pDrvCtrl->sendDatalen ;
        char *p = pDrvCtrl->sendBuf ;
		int key;


#if PING_DEBUG
	if(length <= 100)
		memcpy((void *)TxBuff, (void *)p, length);
#endif
        /*-----------------3/13/01 2:38PM-------------------
         * For faster data access
         * --------------------------------------------------*/

		if(pDrvCtrl->EarlyTransmit == TRUE) 
		{
				EarlyTransmit(pDrvCtrl);
		}
		else
		{
        IOBase   = pDrvCtrl->IOBase;
        DataPort = IOBase + BANK2_DATA1;

		key = intLock();
		SYS_OUT_SHORT(IOBase + BANK_SELECT, 2);
        /*-----------------3/13/01 2:35PM-------------------
         * The next 3 lines of code reads the Alloc Result register
         * and writes into the packet Number Register
         * --------------------------------------------------*/

        SYS_IN_SHORT( IOBase + BANK2_PNR,(PUSHORT) &TempWord );

        TempByte = HIBYTE(TempWord);

        SYS_OUT_SHORT(IOBase + BANK2_PNR,TempByte);
        /*-----------------3/13/01 2:38PM-------------------
         * From here we are writing the packet into the Chip
         * --------------------------------------------------*/
        SYS_OUT_SHORT(IOBase + BANK2_PTR,(USHORT) PTR_AUTO);

        SYS_OUT_SHORT(DataPort,(USHORT) 0);

                       /* force byte count even 3/25/96 NW */
        SYS_OUT_SHORT((DataPort), (USHORT) (0xfffe & (length + FRAME_OVERHEAD )) );


		while(length > 3)
		{
			SYS_OUT_LONG((DataPort),(*((PULONG) p)));
			length -= sizeof(ULONG);
			p += sizeof(ULONG);
		}
		if(length > 1)
		{
			SYS_OUT_SHORT((DataPort),(*((PUSHORT) p)));
			length -= sizeof(USHORT);
			p += sizeof(USHORT);
		}


        if(length)
        {
		    sysOutByte((DataPort),(*p));lan91c111Delay();
			sysOutByte((DataPort),(UCHAR)( CTL_BYTE_ODD | CTL_BYTE_CRC));lan91c111Delay();
        }
        else
        {
            SYS_OUT_SHORT((DataPort),((USHORT)CTL_BYTE_CRC<<8));
        }

        SYS_OUT_SHORT(( IOBase + BANK2_MMU_CMD),(USHORT) CMD_ENQ_TX );
		intUnlock(key);
		}

		DRV_LOG (DRV_DEBUG_TX, "lan91c111Send : Out of Write Function \n",1, 2, 3, 4, 5, 6);

}

/*******************************************************************************
*
* ln7990HandleError - handle controller interrupt errors
*
* This routine is called to process controller errors at a task level that
* were detecected in interrupt context.
*
* RETURNS: N/A.
*/

 void lan91c111HandleError(LAN91C111END_DEVICE  *pDrvCtrl, USHORT PacketStatus)
{


    pDrvCtrl->errorHandling = FALSE;
	pDrvCtrl->lastError.errCode = END_ERR_WARN;

    if(PacketStatus & TFS_UNDERRUN)
	{
		pDrvCtrl->lastError.pMesg = "Tx UnderRuns";
	}
   	if(PacketStatus & TFS_CARRIER)
	{
		pDrvCtrl->lastError.pMesg = "Lost Carrier Sense";
	}
   	if(PacketStatus & TFS_LATE)
	{
		pDrvCtrl->lastError.pMesg = "Late Collisions";
	}
   	if(PacketStatus & TFS_16COL)
	{
		pDrvCtrl->lastError.pMesg = "16 Collisions";
	}
   	if(PacketStatus & TFS_SQET)
	{
		pDrvCtrl->lastError.pMesg = "SQET Error";
	}
	END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1);
	END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, -1);
	muxError (&pDrvCtrl->endObj, &pDrvCtrl->lastError);
    return;
}
/*******************************************************************************
*
* lan91c111Ioctl - the driver I/O control routine
*
* Process an ioctl request.
*
* RETURNS: A command specific response, usually OK or ERROR.
*/
 int lan91c111Ioctl
    (
    END_OBJ * pEnd,		/* device receiving command */
    int cmd,			/* ioctl command code */
    caddr_t data		/* command argument */
    )
    {
    int error = 0;
    long value;
    LAN91C111END_DEVICE *pDrvCtrl = (LAN91C111END_DEVICE *)pEnd;

    switch (cmd)
        {
        case EIOCSADDR:
		    if (data == NULL)
				return (EINVAL);
            bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->endObj),
			END_HADDR_LEN(&pDrvCtrl->endObj));
   	        break;

        case EIOCGADDR:
		    if (data == NULL)
				return (EINVAL);
	        bcopy ((char *)END_HADDR(&pDrvCtrl->endObj), (char *)data,
		    END_HADDR_LEN(&pDrvCtrl->endObj));
            break;

        case EIOCSFLAGS:
		    value = (long)data;
		    if (value < 0)
				{
				value = -(--value);
				END_FLAGS_CLR (&pDrvCtrl->endObj, value);
				}
    		else
				{
				END_FLAGS_SET (&pDrvCtrl->endObj, value);
				}
   			lan91c111Config (pDrvCtrl);
           break;

        case EIOCGFLAGS:
		    *(int *)data = END_FLAGS_GET(&pDrvCtrl->endObj);
	        break;

		case EIOCPOLLSTART:	/* Begin polled operation */
		    lan91c111PollStart (pDrvCtrl);
 		    break;

		case EIOCPOLLSTOP:	/* End polled operation */
		    lan91c111PollStop (pDrvCtrl);
    		break;

        case EIOCGMIB2:		/* return MIB information */
            if (data == NULL)
                return (EINVAL);
            bcopy((char *)&pDrvCtrl->endObj.mib2Tbl, (char *)data,
                  sizeof(pDrvCtrl->endObj.mib2Tbl));
            break;

        case EIOCGFBUF:		/* return minimum First Buffer for chaining */
            if (data == NULL)
                return (EINVAL);
            *(int *)data = LAN91C111_MIN_FBUF;
            break;

        case EIOCGHDRLEN:
            if (data == NULL)
                return (EINVAL);
            *(int *)data = EH_SIZE;
            break;

        default:
            error = EINVAL;
        }

    return (error);
    }


/************************************************

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -