void SMSC9218_RX_ISR()
{       
    DWORD RxStatus, packet_len, dw;
    DWORD numPacketReceived;
    DWORD RxFFCountDW;
    DCU msg;
    unsigned char* recv_packet;
    unsigned long temp;
    int tries = 0;

    dw = RX_FIFO_INF;
    numPacketReceived = (dw & 0x00FF0000) >> 16;

    while(numPacketReceived)
    {
        tries = 0;
        RxStatus = RX_STS_FIFO_PORT;
        packet_len = (RxStatus & 0x3FFF0000) >> 16;

        if (!(RxStatus & RX_STS_ERROR) && 
            !(((RxStatus & RX_STS_LEN_ERROR) == RX_STS_LEN_ERROR) && 
            ((RxStatus & RX_STS_FRAME_TYPE) == 0)))
        {   
            do
            {
                msg = os_alloc_packet_input(packet_len - 2, DRIVER_ALLOC);
                if(!msg)
                    for(int i = 0; i < 500; i++);       //delay
            }while(!msg && tries++ < 50);
                    
            if(msg)
            {
                unsigned long *rxbpl    = (unsigned long *) RX_BUFFER;
                unsigned char *rx_ptr   = (unsigned char *) RX_BUFFER;
                int ndx;
                    
                for (ndx = ((packet_len + 2 + 3) >> 2); ndx > 0; ndx--)
                {
                    temp = RX_DATA_FIFO_PORT;
                    *rxbpl++ = BIT_EDIANDW(temp);
                }

                recv_packet = (unsigned char*)DCUTODATA(msg);
                msg->length = packet_len - 2;
                memcpy(recv_packet, rx_ptr + 2, packet_len - 2);
                rtp_net_invoke_input(iface, msg, msg->length);              
            }
            else
            {
                // Read off and discard the packet.
                RxFFCountDW = (packet_len + 2 + 3) >> 2;
                SMSC9218_RX_Fast_Forward(RxFFCountDW);
            }
        }
        else
        {
Ejemplo n.º 2
0
void davicom_interrupt(int minor_no)
{
dword status;
PDAVICOM_SOFTC softc;
PDESCRIPTOR pdesc;
DCU msg;
int pkt_len;

    softc = off_to_davicom_softc(minor_no);
    if (!softc)
        return;

     status = READ_CR(DC_STATUS_ISR_CR5);
     WRITE_CR(DC_STATUS_ISR_CR5, status);

     status &= DC_STATUS_MASK;  /* keep only bits we are interested in */

     if (status & DC_ISR_RX_DONE)
         while (1)
         {
            pdesc = softc->rx_desc + softc->this_rx;
            if (pdesc->buffer == 0)
               break;
            if (pdesc->status & OWN_BIT)
               break;
            if ((pdesc->status & (ES_BIT|PLE_BIT|AE_BIT)) == 0) /* no error */
            {
                pkt_len = (pdesc->status >> 16) & 2047;
                msg = softc->rx_dcus[softc->this_rx];

                /* set up length of packet; MUST be set to actual size      */
                /* not including crc etc even if allocated a larger         */
                /* packet above                                             */
                DCUTOPACKET(msg)->length = pkt_len;

                softc->stats.packets_in++;
                softc->stats.bytes_in += pkt_len;

                /* signal IP layer that a packet is on its exchange'      */
                /* send packet from ring buffer                           */
                ks_invoke_input(softc->iface, msg);

                /* replace current DCU from ring buffer just passed to      */
                /* IP task with a new DCU                                   */
                softc->rx_dcus[softc->this_rx] = msg = os_alloc_packet_input(CFG_MAX_PACKETSIZE+4, DRIVER_ALLOC);
                if (msg)
                   pdesc->buffer = (dword) DCUTODATA(msg);
                else
                {
                   pdesc->buffer = 0; /* out of buffers */
                   DEBUG_ERROR("davicom_interrupt: out of DCUs", NOVAR, 0, 0);
                }
            }
            else /* error receive, discard */
            {
Ejemplo n.º 3
0
void timeout(void * vsc)
{
   PDAVICOM_SOFTC softc = vsc;

   if (softc->OutOfBuffers)
   {
      int i;

      softc->OutOfBuffers = 0;

      for (i=0; i<DC_RX_RING_SIZE; i++)
      {
         PDESCRIPTOR pdesc = softc->rx_desc + i;

         if (pdesc->buffer == 0)
         {
            DCU msg;

            softc->rx_dcus[i] = msg = os_alloc_packet_input(CFG_MAX_PACKETSIZE+4, DRIVER_ALLOC);
            if (msg)
            {
               pdesc->buffer = (dword) DCUTODATA(msg);
               pdesc->status = OWN_BIT;
#if DEBUG_DAVICOM
               DEBUG_ERROR("davicom_timeout: added new receive DCU", NOVAR, 0, 0);
#endif
            }
            else
            {
#if DEBUG_DAVICOM
               DEBUG_ERROR("davicom_timeout: out of DCUs", NOVAR, 0, 0);
#endif
            }
         }
      }

      /* get receiver going again   */
#if DEBUG_DAVICOM
      DEBUG_ERROR("davicom_timeout: restart receiver stalled at ", EBS_INT1, softc->this_rx, 0);
#endif
      softc->this_rx = 0;
      WRITE_CR(DC_RX_BASE_ADDR_CR3, (dword)(softc->rx_desc));
      WRITE_CR(DC_RX_START_CR2, 0xFFFFFFFF);
   }
   ebs_start_timer(&softc->timer);
}
Ejemplo n.º 4
0
void SH7619_EDMAC_recv(PIFACE pi)
{
	DCU               	msg;
	RTP_UINT16         	FrameLength = 0;
	long 				leng;
	UINT16             	BufferLength;
	UINT32  			tmpIdx = rxTd.idx;
	char*				recv_packet;
	int					tries = 100;
	BOOL				recv_error = FALSE;
	BOOL				mem_error = FALSE;
	EmacTDescriptor 	*pRxTd;
	BOOL isFrame = FALSE;
	
	GLOBAL_LOCK(encIrq);

	pRxTd = *(rxTd.td + rxTd.idx);

	while ((pRxTd->status & ACT) != 0 && tries-- > 0)
	{
		for(int i = 0; i < 500; i++);
	}

	if(tries <= 0)
	{
		//while ((pRxTd->status & ACT) != 0 && tries++ < RX_BUFFERS)
		//{
		//	CIRC_INC(rxTd.idx, RX_BUFFERS);
		//	pRxTd = *(rxTd.td + rxTd.idx);
		//}
		//tmpIdx = rxTd.idx;
		return;
	}

	while ((pRxTd->status & ACT) == 0)
	{
		leng = pRxTd->RDL;
		// A start of frame has been received
		if((pRxTd->status & FP1) != 0) 
		{
			// Skip previous fragment
			while (tmpIdx != rxTd.idx)
			{
				pRxTd = *(rxTd.td + rxTd.idx);
				pRxTd->status |= ACT;
				CIRC_INC(rxTd.idx, RX_BUFFERS);
			}

			FrameLength = 0;

			// Start to gather buffers in a frame
			isFrame = TRUE;
		}

		// Increment the pointer
		CIRC_INC(tmpIdx, RX_BUFFERS);

		if(isFrame)
		{
			if (tmpIdx == rxTd.idx) 
			{
				hal_printf("Receive buffer is too small for the current frame!\r\n");
				do
				{
					//FrameLength += pRxTd->RDL;
					pRxTd = *(rxTd.td + rxTd.idx);
					pRxTd->status |= ACT;
					CIRC_INC(rxTd.idx, RX_BUFFERS);
				} while(tmpIdx != rxTd.idx);
			}

			if((pRxTd->status & FE) != 0) 
			{
				recv_error = TRUE;
			}

			FrameLength += leng;

			// An end of frame has been received
			if((pRxTd->status & FP0) != 0)
			{
				tries = 0;

				if(recv_error == FALSE)
				{				
					do
					{
						msg = os_alloc_packet_input(FrameLength, DRIVER_ALLOC);
						if(!msg)
							for(int i = 0; i < 5000; i++);		//delay
					}while(!msg && tries++ < 50);

					if (msg)
					{
						recv_packet = (char*)DCUTODATA(msg);
						msg->length = FrameLength;
					}
					else
					{
						mem_error = TRUE;
					}
				}
				else
				{
					mem_error = TRUE;
				}

				BufferLength = EMAC_RX_UNITSIZE;
				// Get all the data
				while (rxTd.idx != tmpIdx)
				{                   
					pRxTd = *(rxTd.td + rxTd.idx);

					if(mem_error == FALSE)
					{
						if(BufferLength >= FrameLength)
						{
							memcpy(recv_packet, (void*)(pRxTd->TRBA), FrameLength);
						}
						else
						{
							memcpy(recv_packet, (void*)(pRxTd->TRBA), BufferLength);
							FrameLength -= BufferLength;
							recv_packet += BufferLength;
						}
					}

					pRxTd->status |= ACT;
					CIRC_INC(rxTd.idx, RX_BUFFERS);
				}
                
				// signal IP layer that a packet is on its exchange
				if(mem_error == FALSE)
					rtp_net_invoke_input(pi, msg, msg->length);

				// Prepare for the next Frame
				isFrame = FALSE;
				recv_error = FALSE;
				mem_error = FALSE;
			}
		}// if(isFrame) ends
		else
		{
			pRxTd->status |= ACT;
			rxTd.idx = tmpIdx;		   
		}

		// Process the next buffer
		pRxTd = *(rxTd.td + tmpIdx);
	}
}
Ejemplo n.º 5
0
RTIP_BOOLEAN davicom_open(PIFACE pi)
{
PDAVICOM_SOFTC softc;
int  i;
unsigned short w;
PFBYTE p;

    if (davicom_softc[pi->minor_number] == NULL)
    {
       p = ks_malloc(sizeof(*softc)+16-1-4, PACKET_POOL_MALLOC, DRV_MALLOC);

       /* make sure on 16 byte boundary first         */
       while (((dword)p) & 15)
           p++;

       davicom_softc[pi->minor_number] = (PDAVICOM_SOFTC) p;
    }
    softc = iface_to_davicom_softc(pi);
    if (!softc)
    {
        set_errno(ENUMDEVICE);
        return (FALSE);
    }
    tc_memset((PFBYTE)softc, 0, sizeof(*softc));

    /* Set up the private data structure so that it points to the global interface      */
    /* structure. (address is needed later when returning packets)                      */
    softc->iface = pi;
    pi->driver_stats.ether_stats = (PETHER_STATS)&(softc->stats);

    /* ************************************************************     */
#if (CFG_DAVICOM_PCI)
    /* read/write suitable values for the PCI configuration registers     */
    if (!davicom_pci_init(pi, softc))
    {
        DEBUG_ERROR("davicom_open: PCI register configuration failed", NOVAR, 0, 0);
        set_errno(EPROBEFAIL);      /* ??check for a PCI init failed error code?? */
        return(FALSE);
    }
#endif /* CFG_DAVICOM_PCI */

    /* ************************************************************      */
    /* reset the Davicom chip                                            */
    WRITE_CR(DC_SCR_CR0, DC_SCR_SW_RESET);

    /* wait at least 32 PCI clock cycles     */
    ks_sleep(2);

    /* ************************************************************      */
    /* read local Ethernet address from EEPROM                           */
    w = davicom_read_srom_word( softc, 10 );    /* was 20 */
    pi->addr.my_hw_addr[0] = (unsigned char) w;
    pi->addr.my_hw_addr[1] = (unsigned char) (w >> 8);
    w = davicom_read_srom_word( softc, 11 );    /* was 22 */
    pi->addr.my_hw_addr[2] = (unsigned char) w;
    pi->addr.my_hw_addr[3] = (unsigned char) (w >> 8);
    w = davicom_read_srom_word( softc, 12 );    /* was 24 */
    pi->addr.my_hw_addr[4] = (unsigned char) w;
    pi->addr.my_hw_addr[5] = (unsigned char) (w >> 8);
#if (DEBUG_DAVICOM)
    DEBUG_ERROR("ETHERNET ADDRESS: ", ETHERADDR, pi->addr.my_hw_addr, 0);
#endif
    /* ************************************************************      */
    /* create the Tx descriptors                                         */
    for (i=0; i < DC_TX_RING_SIZE; i++)
       softc->tx_desc[i].nxt_desc = (dword) (softc->tx_desc + ((i+1) & DC_TX_RING_MASK));

    /* create the Rx descriptors      */
    for (i=0; i < DC_RX_RING_SIZE; i++)
    {
        softc->rx_dcus[i] = os_alloc_packet_input(CFG_MAX_PACKETSIZE+4, DRIVER_ALLOC);
        if (!softc->rx_dcus[i])
        {
            DEBUG_ERROR("davicom_init: out of DCUs", NOVAR, 0, 0);
            return(set_errno(ENOPKTS));
        }

        softc->rx_desc[i].buffer = (dword) DCUTODATA(softc->rx_dcus[i]);
        softc->rx_desc[i].ctrl_flags = (CFG_MAX_PACKETSIZE+4) | (1<<24);

        softc->rx_desc[i].nxt_desc = (dword) (softc->rx_desc + ((i+1) & DC_RX_RING_MASK));
        softc->rx_desc[i].status = OWN_BIT;
    }

    /* write CR3 and CR4 to provide the starting address of each descriptor      */
    /* list                                                                      */
    WRITE_CR(DC_RX_BASE_ADDR_CR3, (dword)(softc->rx_desc));
    WRITE_CR(DC_TX_BASE_ADDR_CR4, (dword)(softc->tx_desc));

    /* ************************************************************      */
    /* Write CR0 to set global host bus operation parameters             */
    WRITE_CR( DC_SCR_CR0, 0 );

    /* ************************************************************      */
    /* hook the interrupt based up PCI values read                       */
    ks_hook_interrupt(softc->dav_irq, (PFVOID) pi, 
                      (RTIPINTFN_POINTER)davicom_interrupt,
                      (RTIPINTFN_POINTER)davicom_pre_interrupt,
                      pi->minor_number);

    /* ************************************************************      */
    /* write CR7 to mask causes of unnecessary interrupt                 */
    WRITE_CR(DC_ISR_MASK_CR7, 
        /* normal     */
        DC_IMR_NISE   |         /* Normal interrupt enable */
        DC_IMR_RXCIE  |         /* Receive complete interrupt */
/*      DC_IMR_TXDUE  |       */  /* Transmit buffer unavailable enabled */
        DC_IMR_TXCIE  |         /* Transmit complete interrupt enable */

        /* abnormal     */
        DC_IMR_AISE   |         /* Abnormal interrupt enable */
        DC_IMR_RXDUE  |         /* Receive buffer unavailable */
        DC_IMR_TXFUE);          /* Transmit fifo underrun enabled */

#define DC_STATUS_MASK (DC_ISR_RX_DONE  | DC_ISR_TX_DONE | DC_ISR_ABNORMAL | DC_ISR_TX_UNDERRUN | DC_ISR_RX_NOBUF)

#if (DEBUG_DAVICOM)
   DEBUG_ERROR("davicom_init: start rcv and xmit", NOVAR, 0, 0);
#endif

    /* ************************************************************
     * write CR6 to set global parameters and start both receive and transmit
     * processes; start receive
     * DC_MODE_TX_SC - start transmitter
     * DC_MODE_RX_RC - start receiver
     * DC_MODE_PAM - receive multicasts
     * DC_MODE_1_PKT
    */
    WRITE_CR(DC_MODE_CR6, (1<<26) |
       DC_MODE_SFT_XMIT | /* wait with transmit until all data is in fifo (disable threshold) */
       DC_MODE_1_PKT |    /* only one packet in transmit fifo */
       (3<<14)       |    /* max threshohld */
       DC_MODE_TX_SC |    /* start transmit */
/*     DC_MODE_PAM |      // receive multicasts   */
       DC_MODE_RX_RC |    /* start receive */
       0);

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

    softc->timer.func = timeout;   /* routine to execute every second */
    softc->timer.arg = softc;
    ebs_set_timer(&softc->timer, 1, TRUE);
    ebs_start_timer(&softc->timer);

    return(TRUE);
}