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

📄 pxa_ir.c

📁 linux嵌入式课程实践中的一个关于声卡驱动程序 。
💻 C
📖 第 1 页 / 共 3 页
字号:
 * FIR format interrupt service routine.  We only have to * handle RX events; transmit events go via the TX DMA irq handler. * * No matter what, we disable RX, process, and then restart RX. */static void pxa250_irda_fir_irq(int irq, void *dev_id, struct pt_regs *regs){   struct net_device *dev = dev_id;   struct pxa250_irda *si = dev->priv;   int status;      /*    * Stop RX    */   __ECHO_IN;   pxa250_dma_stop(si->rxdma_ch);      /*    * Framing error - we throw away the packet completely.    * Clearing RXE flushes the error conditions and data    * from the fifo.    */   status=ICSR0;      if (status & (ICSR0_FRE | ICSR0_RAB)) {      DBG_IRQ("Framing error or RAB\n");             si->stats.rx_errors++;      if (ICSR0 & ICSR0_FRE)	 si->stats.rx_frame_errors++;      /* Clear RX fifo       * DMA will be cleared when we restart RX       * Should we check RNE after that?        */      ICCR0 &= ~ICCR0_RXE;            /*       * Clear selected status bits now, so we       * don't miss them next time around.       */      ICSR0 = status & (ICSR0_FRE | ICSR0_RAB);   }      /*    * Deal with any receive errors.  The any of the lowest    * 8 bytes in the FIFO may contain an error.  We must read    * them one by one.  The "error" could even be the end of    * packet!    */   if (ICSR0 & ICSR0_EIF)      pxa250_irda_fir_error(dev);   /*    * No matter what happens, we must restart reception.    */   ICCR0 = 0;   pxa250_start_rx_dma(dev);   pxa250_ficp_rx_start();   __ECHO_OUT;}/************************************************************************** *			SIR 						  * **************************************************************************//* * HP-SIR format interrupt service routines. */static void pxa250_sir_transmit(struct net_device *dev){   struct pxa250_irda *si = dev->priv;      if (si->tx_buff.len)    {	/* Disable receiver and  enable transmiter*/                DBG("tx routine\n");            		STISR &= ~STISR_RCVEIR; 	        STISR |= STISR_XMITIR;		DBG("set STISR tx\n");						                disable_irq(dev->irq);				do 		{		   if (STLSR & LSR_TDRQ)		   {		      STTHR = *si->tx_buff.data++;		      si->tx_buff.len -= 1; 		      tx_count++;		   }		   				         		} while (si->tx_buff.len);						if (si->tx_buff.len == 0) 		{		   		   			si->stats.tx_packets++;			si->stats.tx_bytes += si->tx_buff.data -					      si->tx_buff.head;			/*			 * We need to ensure that the transmitter has			 * finished.			 */					        do			{			   udelay(1);			               		}							while ( ! (STLSR & LSR_TEMT) );                       									/*			 * Ok, we've finished transmitting.  Now enable			 * the receiver.  Sometimes we get a receive IRQ			 * immediately after a transmit...			 */			if (si->newspeed)			{				pxa250_irda_set_speed(dev, si->newspeed);				si->newspeed = 0;			}			/* I'm hungry! */			netif_wake_queue(dev);		}				enable_irq (dev->irq);                STIER = (IER_RAVIE | IER_UUE | IER_RTIOE);		STISR |= STISR_RCVEIR;		STISR &= ~STISR_XMITIR;		DBG("set STISR rx\n");   }}static void pxa250_irda_hpsir_irq(struct net_device *dev){	struct pxa250_irda *si = dev->priv;	int istat; /* this mess is needed since when we read STLSR we destroy it */	/*	 * Deal with any receive errors first.  The bytes in error may be	 * the only bytes in the receive FIFO, so we do this first.	 */  	__ECHO_IN; 	istat = STLSR;	DBG_IRQ("istat is %x\n", istat);		while (1)	{		int stat, data;		if (! (istat & LSR_FIFOE) )		  break; 	/* jump out if no errors */		stat = istat; 		data = STRBR;		DBG_IRQ("stat is %x, data is %x (error)\n", stat, data);                if (stat & LSR_BI) {		  DBG_IRQ("break\n");		}		                if (stat & (LSR_FE | LSR_OE | LSR_PE)) 				{		  DBG_IRQ("error\n");		        si->stats.rx_errors++;			if (stat & LSR_FE) 				si->stats.rx_frame_errors++;			if (stat & LSR_OE) 				si->stats.rx_fifo_errors++;					} else		{		  DBG_IRQ("rxing1\n");		   rx_count++;		   async_unwrap_char(dev, &si->stats, &si->rx_buff, data);                }		istat = STLSR;		DBG_IRQ("istat is %x\n", istat);	}	/*	 * We must clear certain bits.	 */	 	if (istat & (LSR_DR)) 	{		/*		 * Fifo contains at least 1 character.		 */		do		{		   int data;		   		   data = STRBR;		   DBG_IRQ("data is %x, rxing2\n", data);		   		   async_unwrap_char(dev, &si->stats, &si->rx_buff,					  data); /* was Ser2UTDR); Clo */		   rx_count++;		   		   istat = STLSR;		   DBG_IRQ("istat is %x\n", istat);		} while (istat & LSR_DR); 				dev->last_rx = jiffies;	}  	__ECHO_OUT; }static void pxa250_sir_irda_shutdown(struct pxa250_irda *si){   STIER = 0;   STFCR = 0;   STISR = 0;   CKEN &= ~CKEN5_STUART; #ifdef CONFIG_ARCH_H3900H3900_ASIC3_GPIO_B_DIR |=  GPIO3_IR_ON_N;H3900_ASIC3_GPIO_B_OUT |=  GPIO3_IR_ON_N;H3900_ASIC3_GPIO_B_DIR |=  GPIO3_CIR_CTL_PWR_ON;H3900_ASIC3_GPIO_B_OUT &=  ~GPIO3_CIR_CTL_PWR_ON;#endif}/************************************************************************************//*Low level init/uninstall function PM control and IrDA protocol stack registration *//* * Set the IrDA communications speed. * Interrupt have to be disabled here. */static int pxa250_irda_startup(struct net_device *dev){      __ECHO_IN;   /*    * Ensure that the ports for this device are setup correctly.    */   DBG("GPIO sir\n");   set_GPIO_mode (GPIO46_STRXD_MD);   set_GPIO_mode (GPIO47_STTXD_MD);//   STMCR = MCR_OUT2 | (sir_loop?MCR_LOOP:0);   STMCR = MCR_OUT2;   STLCR = LCR_WLS1 | LCR_WLS0;   SET_SIR_MODE;   CKEN |= CKEN5_STUART;   /* enable irq from stuart */   ICMR |= ( 1 << 20 );	   /*reset FIFO*/			STFCR = FCR_TRFIFOE |  FCR_RESETTF | FCR_RESETRF;	STIER = IER_UUE | IER_RAVIE | IER_RTIOE;	   __ECHO_OUT;   return 0;	}#ifdef CONFIG_PM/* * Suspend the IrDA interface. */static int pxa250_irda_shutdown(struct pxa250_irda *si){   pxa250_sir_irda_shutdown(si);   return 0;   }static int pxa250_irda_suspend(struct net_device *dev, int state){	struct pxa250_irda *si = dev->priv;	if (si && si->open) {	   /*	    * Stop the transmit queue	    */	   if (IS_FIR(si))	      return -1;	   netif_stop_queue(dev);	   disable_irq(dev->irq);	   disable_irq(si->fir_irq);	   pxa250_sir_irda_shutdown(si);	}	return 0;}/* * Resume the IrDA interface. */static int pxa250_irda_resume(struct net_device *dev){	struct pxa250_irda *si = dev->priv;	__ECHO_IN;		if (si && si->open) {		/*		 * If we missed a speed change, initialise at the new speed		 * directly.  It is debatable whether this is actually		 * required, but in the interests of continuing from where		 * we left off it is desireable.  The converse argument is		 * that we should re-negotiate at 9600 baud again.		 */		if (si->newspeed) {			si->speed = si->newspeed;			si->newspeed = 0;		}		pxa250_irda_startup(dev);		enable_irq(dev->irq);		/*		 * This automatically wakes up the queue		 */		netif_wake_queue(dev);		pxa250_irda_set_speed(dev,si->speed = 9600);			}	__ECHO_OUT;	return 0;}static int pxa250_irda_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data){	int ret;		if (!dev->data)		return -EINVAL;	switch (rqst) {	case PM_SUSPEND:		ret = pxa250_irda_suspend((struct net_device *)dev->data,					  (int)data);		break;	case PM_RESUME:		ret = pxa250_irda_resume((struct net_device *)dev->data);		break;	default:	   ret = -EINVAL;		break;	}	return ret;}#endifstatic void pxa250_irda_irq(int irq, void *dev_id, struct pt_regs *regs){	struct net_device *dev = dev_id;	DBG("irq\n");		pxa250_irda_hpsir_irq(dev);	}static int pxa250_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev){	struct pxa250_irda *si = dev->priv;	int speed = irda_get_next_speed(skb);	int mtt;	  	__ECHO_IN; 	/*	 * Does this packet contain a request to change the interface	 * speed?  If so, remember it until we complete the transmission	 * of this frame.	 */	if (speed != si->speed && speed != -1)		si->newspeed = speed;	/*	 * If this is an empty frame, we can bypass a lot.	 */	if (skb->len == 0) {		if (si->newspeed) {			si->newspeed = 0;			pxa250_irda_set_speed(dev, speed);		}		dev_kfree_skb(skb);		return 0;	}  	DBG("stop queue\n"); 	netif_stop_queue(dev);	if(!IS_FIR(si))	{	  DBG("sir tx\n");	   	   si->tx_buff.data = si->tx_buff.head;	   si->tx_buff.len  = async_wrap_skb(skb, si->tx_buff.data,						  si->tx_buff.truesize);        	   pxa250_sir_transmit(dev);			   dev_kfree_skb(skb);	   dev->trans_start = jiffies;	   return 0;	}	else /* FIR */	{	   DBG("Enter FIR transmit\n");	   /*	    * We must not be transmitting...	    */	   if (si->txskb)	      BUG();      	   disable_irq(si->fir_irq); 	   	   netif_stop_queue(dev);	   DBG("queue stoped\n");	   si->txskb = skb;	   /* we could not just map so we'll need some triks */	   /* skb->data may be not DMA capable -Sed- */	   if (skb->len > TXBUFF_MAX_SIZE)	   {	      printk (KERN_ERR "skb data too large\n");	      printk (KERN_ERR "len=%d",skb->len);	      BUG();	   }			   DBG("gonna copy %d bytes to txbuf\n",skb->len);	   memcpy (si->txbuf_dma_virt, skb->data , skb->len);	   	   /* Actual sending ;must not be receiving !!! */	   /* Write data and source address */	   DBG("ICSR1 & RNE =%d\n",(ICSR1 & ICSR1_RNE) ? 1 : 0 );	   /*Disable receiver and enable transifer */  	   ICCR0 &= ~ICCR0_RXE;      	   	   if (ICSR1 & ICSR1_TBY)	      BUG();    	   ICCR0 |= ICCR0_TXE;  			   DBG("FICP status %x\n",ICSR0);	   if (0){	      int i;		   	      DBG("sending packet\n");	      for (i=0;i<skb->len;i++)		 (i % 64) ? printk ("%2x ",skb->data[i]) : printk ("%2x \n",skb->data[i]) ;	      DBG(" done\n");   	   }	   /*	    * If we have a mean turn-around time, impose the specified	    * specified delay.  We could shorten this by timing from	    * the point we received the packet.	    */	   	   mtt = irda_get_mtt(skb); 	   if(mtt)    	      udelay(mtt);    	   	   DCSR(si->txdma_ch)=0;	   DCSR(si->txdma_ch)=DCSR_NODESC;	   DSADR(si->txdma_ch) = si->txbuf_dma; /* phisic address */	   DTADR(si->txdma_ch) = __PREG(ICDR);			   DCMD(si->txdma_ch) = DCMD_ENDIRQEN| DCMD_INCSRCADDR | DCMD_FLOWTRG | DCMD_BURST8 | DCMD_WIDTH1 | skb->len;	   DCSR(si->txdma_ch) = DCSR_ENDINTR | DCSR_BUSERR;

⌨️ 快捷键说明

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