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

📄 lan91c111.c

📁 lwip tcp/ip 协议栈 adsp BF533 DSP 移植 用 visual dsp++ 编译
💻 C
📖 第 1 页 / 共 4 页
字号:

   // or YES - I got my memory now...
   cptr->LAN_state.alloc_success = 1;

   return (LAN91C111_hardware_send_packet(cptr));
}



/******************************************************************************
 * LAN Interrupt Handler
 *****************************************************************************/
int LAN91C111_InterruptHandler(ADI_ETHER_LAN91C111_DATA *dev)
{
      /*
       * This is the main routine of the driver, to handle the
       * net_device when it needs some attention.
       * So:
       *  first, save state of the chipset
       *  branch off into routines to handle each case,
       *  and acknowledge each to the interrupt register
       *  and finally restore state.
       */
      volatile unsigned char    stat;
      volatile unsigned short   card_status;
      volatile unsigned char    mask;
      volatile unsigned short   saved_bank;
      volatile unsigned short   saved_pointer;
	  ADI_DCB_RESULT            result;
      

      // save current bank
      saved_bank = _inpw(BSR_REG);

      // switch to bank 2 and save pointer
      _outpw(BSR_REG, 2);
      saved_pointer = _inpw(PTR_REG);

      // read IRQ status register
      mask = _inp(IM_REG);

      // disable all LAN IRQs
      _outp(IM_REG, 0x0);

      // read the status flag and mask it
      stat = _inp(INT_REG)& mask;
      while (stat)
      {

         if (stat & IM_RCV_INT)
         {
            // store debug
            dev->LAN_state.last_IRQ_serviced = IM_RCV_INT;
            // Got a packet(s), receive them
            LAN91C111_rcv(dev);
			if (dev->m_RxDequeuedHead != NULL) {
				if (dev->DCBHandle!=NULL) {
	            	result = adi_dcb_Post(dev->DCBHandle,ik_ivg12,dev->DMCallback,dev->DeviceHandle,ADI_ETHER_EVENT_FRAME_RCVD,dev->m_RxDequeuedHead->CallbackParameter);
				} else {
					(dev->DMCallback)(dev->DeviceHandle,ADI_ETHER_EVENT_FRAME_RCVD,dev->m_RxDequeuedHead->CallbackParameter);
					result = ADI_DCB_RESULT_SUCCESS;
				}
				if (result == ADI_DCB_RESULT_SUCCESS) {
					//## what happens if a packet is received while in the callback
		            	dev->m_RxDequeuedHead = NULL;
	      			dev->m_RxDequeuedTail = NULL;
	  			dev->m_RxDequeuedCount = 0;  
				}
			}
         
         }
         else if (stat & IM_TX_INT )
         {
            // store debug
            dev->LAN_state.last_IRQ_serviced = IM_TX_INT;
            LAN91C111_tx(dev);
            // Acknowledge the interrupt
            _outp(INT_REG, IM_TX_INT);
         }
         else if (stat & IM_TX_EMPTY_INT )
         {
            // store debug
            dev->LAN_state.last_IRQ_serviced = IM_TX_EMPTY_INT;

            _outpw(BSR_REG, 0);
            card_status = _inpw(COUNTER_REG );

#if LAN91C111_LOG_NET_ERRORS
            // multiple collisions
            dev->Stats->cEMAC_TX_CNT_ABORTC += card_status & 0xF;
            card_status >>= 4;
            // multiple collisions
            dev->Stats->cEMAC_TX_CNT_ABORTC += card_status & 0xF;
#endif

            _outpw(BSR_REG, 2);
            // Acknowledge the interrupt
            _outp(INT_REG, IM_TX_EMPTY_INT);
            mask &= ~IM_TX_EMPTY_INT;

#if LAN91C111_LOG_NET_ERRORS
			// Delayed tx packets
            dev->Stats->cEMAC_TX_CNT_DEFER += dev->LAN_state.packets_waiting;
#endif
            // clear state of waiting packets
            dev->LAN_state.packets_waiting = 0;

         }
         else if (stat & IM_ALLOC_INT )
         {
            // store debug
            dev->LAN_state.last_IRQ_serviced = IM_ALLOC_INT;

            // allocation IRQ
            dev->LAN_state.alloc_success = 1;

            // clear this interrupt so it doesn't happen again
            mask &= ~IM_ALLOC_INT;

            /* enable xmit interrupts based on this */
            mask |= ( IM_TX_EMPTY_INT | IM_TX_INT );

         }
         else if (stat & IM_RX_OVRN_INT )
         {
            // store debug
            dev->LAN_state.last_IRQ_serviced = IM_RX_OVRN_INT;

#if LAN91C111_LOG_NET_ERRORS
            //dev->stats.rx_errors++;
            //dev->stats.rx_fifo_errors++; // XXX: FIFO errors?>
			dev->Stats->cEMAC_RX_CNT_IRL++;
#endif
            // Acknowledge the interrupt
            _outp(INT_REG, IM_RX_OVRN_INT);

         }
         else if (stat & IM_EPH_INT )
         {
            // currently unsupported IRQ
            // store debug
            dev->LAN_state.last_IRQ_serviced = IM_EPH_INT;

         }
         else if (stat & IM_MDINT )
         {
            // store debug
            dev->LAN_state.last_IRQ_serviced = IM_MDINT;
            LAN91C111_phy_interrupt(dev);
            // Acknowledge the interrupt
            _outp(INT_REG, IM_MDINT);

         }
         else if (stat & IM_ERCV_INT )
         {
            // store debug
            // currently unsupported IRQ
            dev->LAN_state.last_IRQ_serviced = IM_ERCV_INT;
            // Acknowledge the interrupt
            _outp(INT_REG, IM_ERCV_INT);
         }

         // read the status flag and mask it
         stat = _inp(INT_REG)& mask;
      }

      //restore found register states
      _outpw(BSR_REG, 2);
      _outp(IM_REG, mask);

      _outpw(PTR_REG, saved_pointer);
      _outpw(BSR_REG, saved_bank);


	  // Acknowledge interrupt
	  ACK_LAN_INT(dev->pf);
     return 1;
}

/******************************************************************************
 * LAN Initialization routine
 *****************************************************************************/

static SetPhy(ADI_ETHER_LAN91C111_DATA *dev)
{
	u16 phydat;
	
    phydat = LAN91C111_read_phy_register(PHY_CNTL_REG);
    LAN91C111_write_phy_register(PHY_CNTL_REG, 0x8000);   // get phy from reset
	phydat = 0x8000;
	while (phydat&0x8000) {
		phydat = LAN91C111_read_phy_register(PHY_CNTL_REG);
	}
	//		Program PHY registers
	phydat = 0;
	int pha;
	
	phydat = 0;
	if (dev->Auto) {
		phydat |= 0x1000;		// enable auto negotiation
	} else {
		if (dev->FullDuplex) {
			phydat |= (1 << 8);		// full duplex
		} else {
			phydat &= (~(1 << 8));	// half duplex
		}
		if (dev->Port100) {
			phydat |= (1 << 13);	// 100 Mbps
		} else {
			phydat &= (~(1 << 13));	// 10 Mbps
		}
	}
	LAN91C111_write_phy_register(PHY_CNTL_REG, phydat);
	phydat = LAN91C111_read_phy_register(PHY_CNTL_REG);
	if (dev->Loopback) {
		phydat |= (1 << 14);	// enable TX->RX loopback
	}

	LAN91C111_write_phy_register(PHY_CNTL_REG, phydat);

}


static int  StartMac(ADI_ETHER_LAN91C111_DATA *dev)
{
      int i;
      short wtmp, wstat;

	 

      //init SMSC
      _outpw(BSR_REG, 0);                             // select bank 0
      _outpw(RCR_REG, RCR_SOFTRST);                   // issue soft reset
      LAN91C111_write_phy_register(PHY_CNTL_REG, 0x8000);   // get phy from reset
      _outpw(RCR_REG, 0);                             // clear reset

	  smsc_sleep(250);
	 
	  // Hook interrupt handler.Same interrupt for all RXIVG/TXIVG/ERRIVG
	  //
	  adi_int_CECHook(dev->RXIVG,(ADI_INT_HANDLER_FN)LAN91C111_InterruptHandler,&EtherDev,FALSE);	 

	  SetDevicePFConfig(dev);

	  // Enable interrupts in SIC PFB flag pin is mapped to lan interrupt
	  //
      adi_int_SICSetIVG(ADI_INT_PFB,dev->RXIVG);
	  adi_int_SICEnable(ADI_INT_PFB);

      // disable TX and RX functionality
      _outpw(RCR_REG, 0);                             // clear RX
      _outpw(TCR_REG, 0);                             // clear TX

      // init MAC address
      _outpw(BSR_REG, 1);                             // select bank 1
      _outpw(CFG_REG, CFG_EPH_POWER_EN);              // get out of low power mode
      _outpw(CFG_REG, _inpw(CFG_REG)|CFG_NOWAIT);     // set NO_WAIT

      if(memcmp(dev->phyAddr,"\x00\x00\x00\x00\x00\x00",6))
      {	
      	//set MAC Addr
      	wtmp = (((dev->phyAddr[1])<<8)|(dev->phyAddr[0]));
      	_outpw(ADDR0_REG, wtmp);
      	wtmp = (((dev->phyAddr[3])<<8)|(dev->phyAddr[2]));
      	_outpw(ADDR1_REG, wtmp);
      	wtmp = (((dev->phyAddr[5])<<8)|(dev->phyAddr[4]));
      	_outpw(ADDR2_REG, wtmp); 
      }
      else // get mac from the EEPROM
      {
      		wtmp = _inpw(ADDR0_REG);
      		dev->phyAddr[0] = wtmp & 0x00FF;
      		dev->phyAddr[1] = wtmp >>8 & 0x00FF;
      
		      wtmp = _inpw(ADDR1_REG);  
      		dev->phyAddr[2] = wtmp & 0x00FF;
      		dev->phyAddr[3] = wtmp >>8 & 0x00FF;
      
      		wtmp = _inpw(ADDR2_REG);
      		dev->phyAddr[4] = wtmp & 0x00FF;
      		dev->phyAddr[5] = wtmp >>8 & 0x00FF;
      }
      
      // release all pending packets
      _outpw(CTL_REG, _inpw(CTL_REG)|CTL_AUTO_RELEASE);

      // reset MMU
      _outpw(BSR_REG, 2);
      _outpw(MMU_CMD_REG, MC_RESET);

      // disable all IRQs
      _outp(IM_REG, 0);

      // autonego + LEDs
      _outpw(BSR_REG, 0);
      _outpw(RPC_REG, RPC_ANEG | 0x80);

      // turn off isolation mode
      LAN91C111_write_phy_register(PHY_CNTL_REG, 0x3000 | (dev->Loopback?PHY_CNTL_LPBK:0));

      // read PHY_STAT once due to update latency
      LAN91C111_read_phy_register(PHY_STAT_REG);

      i= 250;
      while (i>0) {
      	wtmp = LAN91C111_read_phy_register(PHY_STAT_REG);
      	if (wtmp & PHY_STAT_LINK) break; // the link is up
      	smsc_sleep(100);
      	i--;
      }

        

#if LAN91C111_DBG
      printf("\n");
      wtmp = LAN91C111_read_phy_register(PHY_CNTL_REG);
      printf("PHY_CNTL_REG: 0x%x\n", wtmp);

      wtmp = LAN91C111_read_phy_register(PHY_STAT_REG);
      printf("PHY_STAT_REG: 0x%x\n", wtmp);

      wtmp = LAN91C111_read_phy_register(PHY_ID1_REG);
      printf("PHY_ID1_REG:  0x%x\n", wtmp);

      wtmp = LAN91C111_read_phy_register(PHY_ID2_REG);
      printf("PHY_ID2_REG:  0x%x\n", wtmp);

      wtmp = LAN91C111_read_phy_register(PHY_AD_REG);
      printf("PHY_AD_REG:   0x%x\n", wtmp);

      wtmp = LAN91C111_read_phy_register(PHY_RMT_REG);
      printf("PHY_RMT_REG:  0x%x\n", wtmp);

      wtmp = LAN91C111_read_phy_register(PHY_CFG1_REG);
      printf("PHY_CFG1_REG: 0x%x\n", wtmp);

      wtmp = LAN91C111_read_phy_register(PHY_CFG2_REG);
      printf("PHY_CFG2_REG: 0x%x\n", wtmp);

      wtmp = LAN91C111_read_phy_register(PHY_INT_REG);
      printf("PHY_INT_REG:  0x%x\n", wtmp);

      wtmp = LAN91C111_read_phy_register(PHY_STAT_REG);
      printf("PHY_STAT_REG: 0x%x\n", wtmp);
#endif //LAN91C111_DBG

      // check anego bits
      wtmp = LAN91C111_read_phy_register(PHY_STAT_REG);
      if ((wtmp & (PHY_STAT_LINK|PHY_STAT_ANEG_ACK)) == (PHY_STAT_LINK|PHY_STAT_ANEG_ACK))
      {   // success
         wstat = LAN91C111_read_phy_register(PHY_INT_REG);
#if LAN91C111_DBG
         printf("\nANEG success, Status = 0x%x", wstat);
#endif

         // read transmit register
         wtmp = _inpw(TCR_REG);

         // check for full duplex FDX
         if ((wstat & PHY_INT_DPLXDET) == PHY_INT_DPLXDET)
            wtmp |= TCR_SWFDUP;
         else
            wtmp &= ~TCR_SWFDUP;

         // write FDX result
         _outpw(TCR_REG, wtmp);
      }
      else
      {   // fail
         wstat = LAN91C111_read_phy_register(PHY_INT_REG);
#if LAN91C111_DBG
         printf("\nANEG failed, Status = 0x%x", wstat);
#endif
      }

	  // device is started and active now.
	  dev->Started = true;

      // enable RX and TX
      _outpw(BSR_REG, 0);
      _outpw(TCR_REG, _inpw(TCR_REG)|TCR_DEFAULT);  // enable TX
      _outpw(RCR_REG, _inpw(RCR_REG)|RCR_DEFAULT);  // enable RX

      // enable IRQs
      _outpw(BSR_REG, 2);
      _outp(IM_REG, SMC_INTERRUPT_MASK);                 // standard IRQ mask
      _outpw(BSR_REG, 0);
	return 1;
}

#pragma optimize_for_speed
static int QueueNewRcvFrames(ADI_ETHER_LAN91C111_DATA *dev,ADI_ETHER_BUFFER *bufs)
{
      ADI_ETHER_BUFFER *tmp_q_ele;
	  void *CriticalResult;

      if (bufs == NULL)
         return (0);

      ENTER_CRITICAL_REGION();
	 //CriticalResult = adi_int_EnterCriticalRegion(dev->CriticalData);
      
      tmp_q_ele = bufs;
      tmp_q_ele->ProcessedFlag = 0;
      
      if (dev->m_RxEnqueuedCount)
         dev->m_RxEnqueuedTail->pNext = (ADI_ETHER_BUFFER*)tmp_q_ele;
      else
         dev->m_RxEnqueuedHead = tmp_q_ele;

      //We have attached one
      dev->m_RxEnqueuedCount++;

      //Now look for rest
      while (tmp_q_ele->pNext != NULL)
      {
         // increment the count
         dev->m_RxEnqueuedCount++;
         tmp_q_ele = (ADI_ETHER_BUFFER*)tmp_q_ele->pNext;
	     tmp_q_ele->ProcessedFlag = 0;
      }

      //Amd update tail
      dev->m_RxEnqueuedTail = tmp_q_ele;
      dev->RxStarted = 1;

      EXIT_CRTICIAL_REGION();
	 //adi_int_ExitCriticalRegion(CriticalResult);
	  return 1;
}

static int QueueNewXmtFrames(ADI_ETHER_LAN91C111_DATA *dev,ADI_ETHER_BUFFER *bufs)
{
    int mr = 0;
    ADI_ETHER_BUFFER *tmp_q_ele;
	ADI_DCB_RESULT   result;

      // if the incoming element is NULL throw an error
      if (bufs == NULL)
         return (0);

      ENTER_CRITICAL_REGION();

	 //CriticalResult = adi_int_EnterCriticalRegion(dev->CriticalData);
      
      tmp_q_ele = bufs;
      tmp_q_ele->ProcessedFlag = 0;
    
      if (dev->m_TxEnqueuedCount)
         dev->m_TxEnqueuedTail->pNext = (ADI_ETHER_BUFFER*)tmp_q_ele;
      else
         dev->m_TxEnqueuedHead = tmp_q_ele;

      //We have attached one
      dev->m_TxEnqueuedCount++;

      //Now look for rest
      while (tmp_q_ele->pNext != NULL)
      {
         // increment the count
         dev->m_TxEnqueuedCount++;
         tmp_q_ele = (ADI_ETHER_BUFFER*)tmp_q_ele->pNext;
	     tmp_q_ele->ProcessedFlag = 0;
      }

      //And update tail
      dev->m_TxEnqueuedTail = tmp_q_ele;
      {
         int cont = 1;
         while(cont)
         {
            unsigned char status;

            status = LAN91C111_wait_to_send_packet(dev);

            if (status == LAN91C111_TX_RETRY)
            {
               /* Keep the packet in the queue and retry next time */
               cont = 0;
			   mr =0;
   			   dev->Stats->cEMAC_TX_CNT_DEFER++;
            }
            else  // If transmission attempt is an unrecoverable error or if it completed successfully
            {    
          
   				dev->Stats->cEMAC_TX_CNT_OK++;

      			tmp_q_ele = dev->m_TxEnqueuedHead;

⌨️ 快捷键说明

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