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

📄 lan91c111.c

📁 CS8900测试文件(整个工程) 环境:VDSP4.0
💻 C
📖 第 1 页 / 共 4 页
字号:
      // Clock Low - output data
      _outpw(MII_REG, mii_reg | bits[i]);
      // Clock Hi - input data
      _outpw(MII_REG, mii_reg | bits[i] | MII_MCLK);
      bits[i] |= _inpw(MII_REG) & MII_MDI;
   }

   // Return to idle state
   // Set clock to low, data to low, and output tristated
   _outpw(MII_REG, mii_reg);

   // Restore original bank select
   _outpw(BSR_REG, oldBank);

   // Recover input data
   phydata = 0;
   for (i = 0; i < 16; ++i)
   {
      phydata <<= 1;
      if (bits[input_idx++] & MII_MDI)
         phydata |= 0x0001;
   }
   return (phydata);
}

/******************************************************************************
 * IRQ Sub Function: SMC_RCV for the LAN91C111
 *
 * Purpose:
 *  There is a packet waiting to be read from 91C111
 *
 * Actions:
 *  - Read the status
 *  - If an error, record it
 *  - otherwise, read in the packet
 *
 *****************************************************************************/
static void LAN91C111_rcv(ADI_ETHER_LAN91C111_DATA *dev )
{
	int     i, chip_id;
	unsigned short    status;
	unsigned short    packet_length;


	unsigned short  *data;
	unsigned short *elnth;
	unsigned char * ptr;

	int ioaddr = dev->base_addr;
 	status = inw(ioaddr + RX_FRAME_PORT);
	if ((status & RX_OK) == 0) {
		ADI_G(("why no packet?\n"));
		return;
	}
  

	packet_length = inw(ioaddr + RX_FRAME_PORT);
     
     /*----------------------*/
   /*  
    status = readword(dev,PP_RxStatus<<1);
    if ((status & RX_OK) == 0) {
      ADI_G(("why no packet?\n"));
      return;
    } 
     
   packet_length =  readword(dev,PP_RxLength<<1);
   */
   
   /*----------------------*/
   
   // store for debug
	dev->LAN_state.rpsize = packet_length;

 
	ADI_ETHER_BUFFER *tmp_q_ele;

  
	tmp_q_ele = dev->m_RxEnqueuedHead;
	if (tmp_q_ele != NULL) {
		elnth = (unsigned short *)tmp_q_ele->Data;
		*elnth = (packet_length + 4);	// add on 4 bytes for the CRC (even if we dont store it)
		tmp_q_ele->ProcessedElementCount = (*elnth+2+tmp_q_ele->ElementWidth-1)/tmp_q_ele->ElementWidth;
	}
     
	if ((tmp_q_ele)&&(tmp_q_ele->ProcessedElementCount <= tmp_q_ele->ElementCount))
	{
		//store packet length
		// assign pointer
		data = (void *)( ((char *)tmp_q_ele->Data) +2);
	}
	else
	{

		ADI_G(("drop it\n"));
		return;
	}


	readblock(dev, (char *)data, packet_length);
      
	ptr = (unsigned char * )data;
	ADI_G(("CS8900: received %d byte packet of type %x\n",
	packet_length, (ptr[ETH_ALEN+ETH_ALEN] << 8) | ptr[ETH_ALEN+ETH_ALEN+1]));


	/* Change the Enqueued head */
	dev->m_RxEnqueuedHead = (ADI_ETHER_BUFFER*)tmp_q_ele->pNext;
	dev->m_RxEnqueuedCount--;
	if (dev->m_RxEnqueuedCount == 0)
		dev->m_RxEnqueuedTail = NULL;

	/* Add the packet to dequeued list*/
	if (dev->m_RxDequeuedCount)
		dev->m_RxDequeuedTail->pNext = (ADI_ETHER_BUFFER *)tmp_q_ele;
	else
		dev->m_RxDequeuedHead = tmp_q_ele;

	//No matter what this is also the tail.
	dev->m_RxDequeuedTail = tmp_q_ele;
	//And tail->next should point to NULL
	tmp_q_ele->pNext = NULL;
	dev->m_RxDequeuedCount++;
      
	// finally we have to update the status word etc
	tmp_q_ele->ProcessedFlag = 1;
	tmp_q_ele->StatusWord = 0x3000 + (packet_length+4);
	
	return;
}

/******************************************************************************
 * TX IRQ Error Handler Function for SMSC91C111
 *
 * Purpose:  Handle the transmit error message.
 *  This is only called when an TX error occured because of
 *  the AUTO_RELEASE mode.
 *
 * Actions:
 *  - Save pointer and packet no
 *  - Get the packet no from the top of the queue
 *  - check if it's valid ( if not, is this an error??? )
 *  - read the status word
 *  - record the error
 *  - ( resend?  Not really, since we don't want old packets around )
 *  - Restore saved values
 *
 *****************************************************************************/
static void LAN91C111_tx(ADI_ETHER_LAN91C111_DATA * dev)
{
   volatile unsigned char saved_packet;
   volatile unsigned char packet_no;
   volatile unsigned short tx_status;

  
   // one less packet waiting for me
   dev->LAN_state.packets_waiting--;



   return;
}

/******************************************************************************
 * IRQ Sub Function: smc_phy_interrupt for the LAN91C111
 *
 * Purpose:
 *  Handle interrupts relating to PHY register 18.
 *
 * Actions:
 *  Log last Phy18 Interrupt Source
 *
 *****************************************************************************/
static void LAN91C111_phy_interrupt(ADI_ETHER_LAN91C111_DATA * cptr)
{
   volatile unsigned short phy18;

   while (1)
   {
      // Read PHY Register 18, Status Output
      phy18 = LAN91C111_read_phy_register(PHY_INT_REG);

      // Exit if no more changes
      if (phy18 == cptr->LAN_state.lastPhy18)
         break;

      // Update the last phy 18 variable
      cptr->LAN_state.lastPhy18 = phy18;
   } // end while
}
/******************************************************************************
 * LANC91C111: LAN91C111_hardware_send_packet
 *
 * Purpose:
 *  This sends the actual packet to the SMC9xxx chip.
 *
 *  - First, see if a pending packet is available.
 *      this should NOT be called if there is none
 *  - Find the packet number that the chip allocated
 *  - Point the data pointers at it in memory
 *  - Set the length word in the chip's memory
 *  - Dump the packet to chip memory
 *  - Check if a last byte is needed ( odd length packet )
 *      if so, set the control flag right
 *  - Tell the LAn 91C111 to send it
 *  - Enable the transmit interrupt, so I know if it failed
 *  - Free the packet data if I actually sent it.
 *
 *****************************************************************************/
 #pragma section("Merge") 
static unsigned char LAN91C111_hardware_send_packet(ADI_ETHER_LAN91C111_DATA * cptr)
{
   int     i;
   unsigned char    packet_no;
   unsigned short   length;

    unsigned short  *buf;

   unsigned short	 *elnth;
   unsigned short	 lnth_first;
   ADI_ETHER_BUFFER  *bf = cptr->m_TxEnqueuedHead;


   buf = (unsigned short *)(((char *)bf->Data)+2);



   // the length is held in the first two bytes of the 'frame', the ElementCount says the number of elements in the first buffer
   
   // get length
   elnth = (unsigned short *)bf->Data;
   length = *elnth;
   writeblock(dev_g, (char *)buf, length);
   bf->ProcessedFlag = 1;
   bf->ProcessedElementCount = (*elnth+2 + bf->ElementWidth-1)/bf->ElementWidth;
   bf->StatusWord = 0x3;   // completed and OK
   
   cptr->LAN_state.alloc_success = CS89X0_ALLOC_IDLE;
     

   return LAN91C111_TX_SUCCESS;
}
/******************************************************************************
 * LANC91C111: LAN91C111_wait_to_send_packet()
 *
 * Purpose:
 *    Attempt to allocate memory for a packet, if chip-memory is not
 *    available, then tell the card to generate an interrupt when it
 *    is available.
 *****************************************************************************/
 #pragma section("Merge") 
static unsigned char LAN91C111_wait_to_send_packet(ADI_ETHER_LAN91C111_DATA * cptr)
{
   unsigned short    length;
   unsigned short    numPages;
   unsigned short    time_out;
   unsigned short    status;
   unsigned short	 *elnth;
   

   elnth = (unsigned short *)cptr->m_TxEnqueuedHead->Data;
   length = *elnth;

 
   #if 0
    
 //	writereg(dev_g, PP_BusCTL, 0x0);
  //  writereg(dev_g, PP_BusCTL, readreg(dev_g, PP_BusCTL) | ENABLE_IRQ);

    ADI_G(("CS8900: sent out data\n"));
   // either way, a packet is waiting now
   cptr->LAN_state.packets_waiting++;

   //rev > 'F'
   writeword(dev_g, TX_CMD_PORT, TX_AFTER_ALL);//TX_AFTER_ALL);//for the revison>F
   writeword(dev_g, TX_LEN_PORT, length);

   time_out =1; // 7.25
   
   while(time_out)
   {
   if ((readreg(dev_g, PP_BusST) & READY_FOR_TX_NOW) == 0) {
   		
   		ADI_G(("TX buf not free\n"));
   		//return 1;
   		time_out--;
  
    }
    else break;
   }
   
   if(!time_out) {  	
   		
	    return 1;
	}
   
   
   cptr->LAN_state.alloc_success = 1;
   return (LAN91C111_hardware_send_packet(cptr));
#endif
    /*********************/
 
   
   /***********************/
 #if 1
    
 	//writereg(dev_g, PP_BusCTL, 0x0);
    //writereg(dev_g, PP_BusCTL, readreg(dev_g, PP_BusCTL) | ENABLE_IRQ);

    ADI_G(("CS8900: sent out data\n"));
   // either way, a packet is waiting now
   cptr->LAN_state.packets_waiting++;
RETRY_P:
   //rev > 'F'
   writeword(dev_g, TX_CMD_PORT, TX_NOW);//TX_AFTER_ALL);//TX_AFTER_381//for the revison>F
   writeword(dev_g, TX_LEN_PORT, length);

   time_out =5000; // 7.25
   
   while(time_out)
   {
   if ((readreg(dev_g, PP_BusST) & READY_FOR_TX_NOW) == 0) {
   		
   		ADI_G(("TX buf not free\n"));
   		//return 1;
   		time_out--;
  
    }
    else break;
   }
   
   if(!time_out) {  	
   	#if 1
   		writereg(dev_g, PP_BusCTL, 0x0);
	    writereg(dev_g, PP_BusCTL, readreg(dev_g, PP_BusCTL) | ENABLE_IRQ); //RETRY
	    //printf("RETRY\n");
	    goto RETRY_P;
	#endif
	
//	return 1;
	}
   
   //printf("%d\n",time_out);
   cptr->LAN_state.alloc_success = 1;
   return (LAN91C111_hardware_send_packet(cptr));
#endif
    /*********************/
   
#if 0
	/////////////////////*error die *************************/   
 	//writereg(dev_g, PP_BusCTL, 0x0);
    //writereg(dev_g, PP_BusCTL, readreg(dev_g, PP_BusCTL) | ENABLE_IRQ);

    ADI_G(("CS8900: sent out data\n"));
   // either way, a packet is waiting now
   cptr->LAN_state.packets_waiting++;

   //rev > 'F'
   
   if(cptr->LAN_state.alloc_success ==CS89X0_ALLOC_SUCE)
   {
   		printf("directly send\n");
   }
   if( cptr->LAN_state.alloc_success == CS89X0_ALLOC_IDLE)
   {
   	
   
   	
   writeword(dev_g, TX_CMD_PORT, dev_g->send_cmd);//TX_AFTER_ALL);//for the revison>F
   writeword(dev_g, TX_LEN_PORT, length);
   
   time_out =1; // 7.25
   
   while(time_out)
   {
   if ((readreg(dev_g, PP_BusST) & READY_FOR_TX_NOW) == 0) {
   		
   		ADI_G(("TX buf not free\n"));
   		//return 1;
   		
   		time_out--;
  
    }
    else break;
   }
   
   if(!time_out) { 
   	
   		ADI_G ((" RETRY \n")) ; 
   		cptr->LAN_state.alloc_success = CS89X0_ALLOC_WAIT;
   		
   } //RETRY  
   
   else cptr->LAN_state.alloc_success = CS89X0_ALLOC_SUCE;
   
   }
  
   
   if(cptr->LAN_state.alloc_success == CS89X0_ALLOC_WAIT)
   {
   		//ADI_G("RETRY %d\n",length);
   		return 1;
   		//smsc_sleep(10);
   }
   


   return (LAN91C111_hardware_send_packet(cptr));
 #endif/************************/
}



/******************************************************************************
 * 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 short    stat,st;
      volatile unsigned short   card_status;
      volatile unsigned char    mask;
      volatile unsigned short   saved_bank;
      volatile unsigned short   saved_pointer;
	  ADI_DCB_RESULT            result;
      
	  ADI_G(("interrupt +++.\n"));
 

      // read IRQ status register
      mask = ISQ_EVENT_MASK;

 
		st = readword(dev, ISQ_PORT);
      // read the status flag and mask it
   	   stat= st & mask;
   	 //stat= readword(dev, PP_ISQ)& mask;
   	  
   	 //int tst=0;
      while (st)
      {
      	
		 //printf("%d\n",tst++);
         if (stat == ISQ_RECEIVER_EVENT)
         {
         	ADI_G(("states ISQ_RECEIVER_EVENT\n"));
            // 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 {
					
					
					/*************************************/
					if(dev->m_RxDequeuedHead)
					(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;  
				}

⌨️ 快捷键说明

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