Esempio n. 1
0
/*
 * This is the SIR receive routine.
 *
 * @param   si     IrDA specific structure.
 *
 * @param   dev     pointer to the net_device structure
 *
 * @return  The function returns 0 on success and a non-zero value on
 *          failure.
 */
static int mxc_irda_sir_rxirq(struct mxc_irda *si, struct net_device *dev)
{
	u16 data, status;
	volatile u16 sr2;

	sr2 = readl(si->uart_base + MXC_UARTUSR2);
	while ((sr2 & MXC_UARTUSR2_RDR) == 1) {
		data = readl(si->uart_base + MXC_UARTURXD);
		status = data & 0xf400;
		if (status & MXC_UARTURXD_ERR) {
			dev_err(si->dev, "Receive an incorrect data =0x%x.\n",
				data);
			si->stats.rx_errors++;
			if (status & MXC_UARTURXD_OVRRUN) {
				si->stats.rx_fifo_errors++;
				dev_err(si->dev, "Rx overrun.\n");
			}
			if (status & MXC_UARTURXD_FRMERR) {
				si->stats.rx_frame_errors++;
				dev_err(si->dev, "Rx frame error.\n");
			}
			if (status & MXC_UARTURXD_PRERR) {
				dev_err(si->dev, "Rx parity error.\n");
			}
			/* Other: it is the Break char.
			 * Do nothing for it. throw out the data.
			 */
			async_unwrap_char(dev, &si->stats, &si->rx_buff,
					  (data & 0xFF));
		} else {
			/* It is correct data. */
			data &= 0xFF;
			async_unwrap_char(dev, &si->stats, &si->rx_buff, data);

			dev->last_rx = jiffies;
		}
		sr2 = readl(si->uart_base + MXC_UARTUSR2);

		writel(0xFFFF, si->uart_base + MXC_UARTUSR1);
		writel(0xFFFF, si->uart_base + MXC_UARTUSR2);
	}	/* while */
	return 0;

}
Esempio n. 2
0
/* Receive callback function */
static void ks959_rcv_irq(struct urb *urb)
{
	struct ks959_cb *kingsun = urb->context;
	int ret;

	/* in process of stopping, just drop data */
	if (!netif_running(kingsun->netdev)) {
		kingsun->receiving = 0;
		return;
	}

	/* unlink, shutdown, unplug, other nasties */
	if (urb->status != 0) {
		err("kingsun_rcv_irq: urb asynchronously failed - %d",
		    urb->status);
		kingsun->receiving = 0;
		return;
	}

	if (urb->actual_length > 0) {
		__u8 *bytes = urb->transfer_buffer;
		unsigned int i;

		for (i = 0; i < urb->actual_length; i++) {
			/* De-obfuscation implemented here: variable portion of
			   xormask is incremented, and then used with the encoded
			   byte for the XOR. The result of the operation is used
			   to unwrap the SIR frame. */
			kingsun->rx_variable_xormask++;
			bytes[i] =
			    bytes[i] ^ kingsun->rx_variable_xormask ^ 0x55u;

			/* rx_variable_xormask doubles as an index counter so we
			   can skip the byte at 0xff (wrapped around to 0).
			 */
			if (kingsun->rx_variable_xormask != 0) {
				async_unwrap_char(kingsun->netdev,
						  &kingsun->netdev->stats,
						  &kingsun->rx_unwrap_buff,
						  bytes[i]);
			}
		}
		do_gettimeofday(&kingsun->rx_time);
		kingsun->receiving =
		    (kingsun->rx_unwrap_buff.state != OUTSIDE_FRAME) ? 1 : 0;
	}

	/* This urb has already been filled in kingsun_net_open. Setup
	   packet must be re-filled, but it is assumed that urb keeps the
	   pointer to the initial setup packet, as well as the payload buffer.
	   Setup packet is already pre-filled at ks959_probe.
	 */
	urb->status = 0;
	ret = usb_submit_urb(urb, GFP_ATOMIC);
}
Esempio n. 3
0
static void bfin_sir_dma_rx_chars(struct net_device *dev)
{
	struct bfin_sir_self *self = netdev_priv(dev);
	struct bfin_sir_port *port = self->sir_port;
	int i;

	SIR_UART_CLEAR_LSR(port);

	for (i = port->rx_dma_buf.head; i < port->rx_dma_buf.tail; i++)
		async_unwrap_char(dev, &self->stats, &self->rx_buff, port->rx_dma_buf.buf[i]);
}
Esempio n. 4
0
static void bfin_sir_rx_chars(struct net_device *dev)
{
	struct bfin_sir_self *self = netdev_priv(dev);
	struct bfin_sir_port *port = self->sir_port;
	unsigned char ch;

	SIR_UART_CLEAR_LSR(port);
	ch = SIR_UART_GET_CHAR(port);
	async_unwrap_char(dev, &self->stats, &self->rx_buff, ch);
	dev->last_rx = jiffies;
}
Esempio n. 5
0
/* Receive callback function */
static void kingsun_rcv_irq(struct urb *urb)
{
	struct kingsun_cb *kingsun = urb->context;
	int ret;

	/* in process of stopping, just drop data */
	if (!netif_running(kingsun->netdev)) {
		kingsun->receiving = 0;
		return;
	}

	/* unlink, shutdown, unplug, other nasties */
	if (urb->status != 0) {
		dev_err(&kingsun->usbdev->dev,
			"kingsun_rcv_irq: urb asynchronously failed - %d\n",
			urb->status);
		kingsun->receiving = 0;
		return;
	}

	if (urb->actual_length == kingsun->max_rx) {
		__u8 *bytes = urb->transfer_buffer;
		int i;

		/* The very first byte in the buffer indicates the length of
		   valid data in the read. This byte must be in the range
		   1..kingsun->max_rx -1 . Values outside this range indicate
		   an uninitialized Rx buffer when the dongle has just been
		   plugged in. */
		if (bytes[0] >= 1 && bytes[0] < kingsun->max_rx) {
			for (i = 1; i <= bytes[0]; i++) {
				async_unwrap_char(kingsun->netdev,
						  &kingsun->netdev->stats,
						  &kingsun->rx_buff, bytes[i]);
			}
			do_gettimeofday(&kingsun->rx_time);
			kingsun->receiving =
				(kingsun->rx_buff.state != OUTSIDE_FRAME)
				? 1 : 0;
		}
	} else if (urb->actual_length > 0) {
		dev_err(&kingsun->usbdev->dev,
			"%s(): Unexpected response length, expected %d got %d\n",
			__func__, kingsun->max_rx, urb->actual_length);
	}
	/* This urb has already been filled in kingsun_net_open */
	ret = usb_submit_urb(urb, GFP_ATOMIC);
}
Esempio n. 6
0
int sirdev_receive(struct sir_dev *dev, const unsigned char *cp, size_t count) 
{
	if (!dev || !dev->netdev) {
		IRDA_WARNING("%s(), not ready yet!\n", __func__);
		return -1;
	}

	if (!dev->irlap) {
		IRDA_WARNING("%s - too early: %p / %zd!\n",
			     __func__, cp, count);
		return -1;
	}

	if (cp==NULL) {
		/* error already at lower level receive
		 * just update stats and set media busy
		 */
		irda_device_set_media_busy(dev->netdev, TRUE);
		dev->netdev->stats.rx_dropped++;
		IRDA_DEBUG(0, "%s; rx-drop: %zd\n", __func__, count);
		return 0;
	}

	/* Read the characters into the buffer */
	if (likely(atomic_read(&dev->enable_rx))) {
		while (count--)
			/* Unwrap and destuff one byte */
			async_unwrap_char(dev->netdev, &dev->netdev->stats,
					  &dev->rx_buff, *cp++);
	} else {
		while (count--) {
			/* rx not enabled: save the raw bytes and never
			 * trigger any netif_rx. The received bytes are flushed
			 * later when we re-enable rx but might be read meanwhile
			 * by the dongle driver.
			 */
			dev->rx_buff.data[dev->rx_buff.len++] = *cp++;

			/* What should we do when the buffer is full? */
			if (unlikely(dev->rx_buff.len == dev->rx_buff.truesize))
				dev->rx_buff.len = 0;
		}
	}

	return 0;
}
static void kingsun_rcv_irq(struct urb *urb)
{
	struct kingsun_cb *kingsun = urb->context;
	int ret;

	
	if (!netif_running(kingsun->netdev)) {
		kingsun->receiving = 0;
		return;
	}

	
	if (urb->status != 0) {
		err("kingsun_rcv_irq: urb asynchronously failed - %d",
		    urb->status);
		kingsun->receiving = 0;
		return;
	}

	if (urb->actual_length == kingsun->max_rx) {
		__u8 *bytes = urb->transfer_buffer;
		int i;

		if (bytes[0] >= 1 && bytes[0] < kingsun->max_rx) {
			for (i = 1; i <= bytes[0]; i++) {
				async_unwrap_char(kingsun->netdev,
						  &kingsun->netdev->stats,
						  &kingsun->rx_buff, bytes[i]);
			}
			do_gettimeofday(&kingsun->rx_time);
			kingsun->receiving =
				(kingsun->rx_buff.state != OUTSIDE_FRAME)
				? 1 : 0;
		}
	} else if (urb->actual_length > 0) {
		err("%s(): Unexpected response length, expected %d got %d",
		    __func__, kingsun->max_rx, urb->actual_length);
	}
	
	ret = usb_submit_urb(urb, GFP_ATOMIC);
}
Esempio n. 8
0
/* Receive callback function */
static void ksdazzle_rcv_irq(struct urb *urb)
{
	struct ksdazzle_cb *kingsun = urb->context;
	struct net_device *netdev = kingsun->netdev;

	/* in process of stopping, just drop data */
	if (!netif_running(netdev)) {
		kingsun->receiving = 0;
		return;
	}

	/* unlink, shutdown, unplug, other nasties */
	if (urb->status != 0) {
		err("ksdazzle_rcv_irq: urb asynchronously failed - %d",
		    urb->status);
		kingsun->receiving = 0;
		return;
	}

	if (urb->actual_length > 0) {
		__u8 *bytes = urb->transfer_buffer;
		unsigned int i;

		for (i = 0; i < urb->actual_length; i++) {
			async_unwrap_char(netdev, &netdev->stats,
					  &kingsun->rx_unwrap_buff, bytes[i]);
		}
		kingsun->receiving =
		    (kingsun->rx_unwrap_buff.state != OUTSIDE_FRAME) ? 1 : 0;
	}

	/* This urb has already been filled in ksdazzle_net_open. It is assumed that
	   urb keeps the pointer to the payload buffer.
	 */
	urb->status = 0;
	usb_submit_urb(urb, GFP_ATOMIC);
}
Esempio n. 9
0
/* SIR interrupt service routine. */
static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id)
{
	struct net_device *dev = dev_id;
	struct pxa_irda *si = netdev_priv(dev);
	int iir, lsr, data;

	iir = STIIR;

	switch  (iir & 0x0F) {
	case 0x06: /* Receiver Line Status */
	  	lsr = STLSR;
		while (lsr & LSR_FIFOE) {
			data = STRBR;
			if (lsr & (LSR_OE | LSR_PE | LSR_FE | LSR_BI)) {
				printk(KERN_DEBUG "pxa_ir: sir receiving error\n");
				si->stats.rx_errors++;
				if (lsr & LSR_FE)
					si->stats.rx_frame_errors++;
				if (lsr & LSR_OE)
					si->stats.rx_fifo_errors++;
			} else {
				si->stats.rx_bytes++;
				async_unwrap_char(dev, &si->stats, &si->rx_buff, data);
			}
			lsr = STLSR;
		}
		dev->last_rx = jiffies;
		si->last_oscr = OSCR;
		break;

	case 0x04: /* Received Data Available */
	  	   /* forth through */

	case 0x0C: /* Character Timeout Indication */
	  	do  {
		    si->stats.rx_bytes++;
	            async_unwrap_char(dev, &si->stats, &si->rx_buff, STRBR);
	  	} while (STLSR & LSR_DR);
	  	dev->last_rx = jiffies;
		si->last_oscr = OSCR;
	  	break;

	case 0x02: /* Transmit FIFO Data Request */
	    	while ((si->tx_buff.len) && (STLSR & LSR_TDRQ)) {
	    		STTHR = *si->tx_buff.data++;
			si->tx_buff.len -= 1;
	    	}

		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. */
			while ((STLSR & LSR_TEMT) == 0)
				cpu_relax();
			si->last_oscr = OSCR;

			/*
		 	* Ok, we've finished transmitting.  Now enable
		 	* the receiver.  Sometimes we get a receive IRQ
		 	* immediately after a transmit...
		 	*/
			if (si->newspeed) {
				pxa_irda_set_speed(si, si->newspeed);
				si->newspeed = 0;
			} else {
				/* enable IR Receiver, disable IR Transmitter */
				STISR = IrSR_IR_RECEIVE_ON | IrSR_XMODE_PULSE_1_6;
				/* enable STUART and receive interrupts */
				STIER = IER_UUE | IER_RLSE | IER_RAVIE | IER_RTIOE;
			}
			/* I'm hungry! */
			netif_wake_queue(dev);
		}
		break;
	}

	return IRQ_HANDLED;
}
Esempio n. 10
0
/*
 * HP-SIR format interrupt service routines.
 */
static void sa1100_irda_hpsir_irq(struct net_device *dev)
{
	struct sa1100_irda *si = dev->priv;
	int status;

	status = Ser2UTSR0;

	/*
	 * Deal with any receive errors first.  The bytes in error may be
	 * the only bytes in the receive FIFO, so we do this first.
	 */
	while (status & UTSR0_EIF) {
		int stat, data;

		stat = Ser2UTSR1;
		data = Ser2UTDR;

		if (stat & (UTSR1_FRE | UTSR1_ROR)) {
			si->stats.rx_errors++;
			if (stat & UTSR1_FRE)
				si->stats.rx_frame_errors++;
			if (stat & UTSR1_ROR)
				si->stats.rx_fifo_errors++;
		} else
			async_unwrap_char(dev, &si->stats, &si->rx_buff, data);

		status = Ser2UTSR0;
	}

	/*
	 * We must clear certain bits.
	 */
	Ser2UTSR0 = status & (UTSR0_RID | UTSR0_RBB | UTSR0_REB);

	if (status & UTSR0_RFS) {
		/*
		 * There are at least 4 bytes in the FIFO.  Read 3 bytes
		 * and leave the rest to the block below.
		 */
		async_unwrap_char(dev, &si->stats, &si->rx_buff, Ser2UTDR);
		async_unwrap_char(dev, &si->stats, &si->rx_buff, Ser2UTDR);
		async_unwrap_char(dev, &si->stats, &si->rx_buff, Ser2UTDR);
	}

	if (status & (UTSR0_RFS | UTSR0_RID)) {
		/*
		 * Fifo contains more than 1 character.
		 */
		do {
			async_unwrap_char(dev, &si->stats, &si->rx_buff,
					  Ser2UTDR);
		} while (Ser2UTSR1 & UTSR1_RNE);

		dev->last_rx = jiffies;
	}

	if (status & UTSR0_TFS && si->tx_buff.len) {
		/*
		 * Transmitter FIFO is not full
		 */
		do {
			Ser2UTDR = *si->tx_buff.data++;
			si->tx_buff.len -= 1;
		} while (Ser2UTSR1 & UTSR1_TNF && 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
				rmb();
			while (Ser2UTSR1 & UTSR1_TBY);

			/*
			 * Ok, we've finished transmitting.  Now enable
			 * the receiver.  Sometimes we get a receive IRQ
			 * immediately after a transmit...
			 */
			Ser2UTSR0 = UTSR0_REB | UTSR0_RBB | UTSR0_RID;
			Ser2UTCR3 = UTCR3_RIE | UTCR3_RXE | UTCR3_TXE;

			if (si->newspeed) {
				sa1100_irda_set_speed(si, si->newspeed);
				si->newspeed = 0;
			}

			/* I'm hungry! */
			netif_wake_queue(dev);
		}
	}
}
Esempio n. 11
0
static void pxa250_irda_hpsir_irq(struct net_device *dev)
{
	struct pxa250_irda *si = dev->priv;

	/*
	 * 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; 
	
	while (STLSR & LSR_FIFOE)
	{
		int stat, data;

		stat = STLSR; 
		data = STRBR;
               
		
                if (stat & (LSR_FE | LSR_OE | LSR_PE)) 
		
		{
		        si->stats.rx_errors++;
			if (stat & LSR_FE) 
				si->stats.rx_frame_errors++;
			if (stat & LSR_OE) 
				si->stats.rx_fifo_errors++;
			
		} else
		{
		   rx_count++;
		   async_unwrap_char(dev, &si->stats, &si->rx_buff, data);
                }
		
	}

	/*
	 * We must clear certain bits.
	 */
	 
	if (STLSR & (LSR_DR)) 
	{
		/*
		 * Fifo contains at least 1 character.
		 */
		do
		{
		   int data;
		   
		   data = STRBR;
		   
		   async_unwrap_char(dev, &si->stats, &si->rx_buff,
					  data); /* was Ser2UTDR); Clo */
		   rx_count++;
		   
		} while (STLSR & LSR_DR); 
		
		dev->last_rx = jiffies;
	}

  	__ECHO_OUT; 
}
Esempio n. 12
0
int sirdev_receive(struct sir_dev *dev, const unsigned char *cp, size_t count) 
{


	int i;
	unsigned char c[32];

	unsigned char *eofp, *ebufp;
	int	framelen;




	if (!dev || !dev->netdev) {
		IRDA_WARNING("%s(), not ready yet!\n", __func__);
		return -1;
	}

	if (!dev->irlap) {
		IRDA_WARNING("%s - too early: %p / %zd!\n",
			     __func__, cp, count);
		return -1;
	}

	if (cp==NULL) {
		/* error already at lower level receive
		 * just update stats and set media busy
		 */
		irda_device_set_media_busy(dev->netdev, TRUE);
		dev->netdev->stats.rx_dropped++;
		IRDA_DEBUG(0, "%s; rx-drop: %zd\n", __func__, count);
		return 0;
	}



	IRDA_DEBUG(3, "%s; get rx: %zd\n", __func__, count);



	/* Read the characters into the buffer */
	if (likely(atomic_read(&dev->enable_rx))) {

		
		rx_count_log = count;
		
		
		if (count >0){
			for(i= 0; i<32; i ++){
				if (i<count){
					c[i] = cp[i];
				}
				else {
					c[i] = 0x00;
				}
			}
			IRDA_DEBUG(3, "RcvData= %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x", 
					 c[0], c[1], c[2], c[3], c[4], c[5],c[6], c[7], c[8], c[9], c[10], c[11], c[12], c[13],c[14],c[15],
					 c[16], c[17], c[18], c[19], c[20], c[21],c[22], c[23], c[24], c[25], c[26], c[27], c[28], c[29],c[30],c[31]
					 );
		}
		if (count >= 32){
			for(i= 0; i<32; i ++){
				if ( i < count-32){
					c[i] = cp[i+32];
				}
				else {
					c[i] = 0x00;
				}
			}
			IRDA_DEBUG(3, "RcvData= %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x", 
					 c[0], c[1], c[2], c[3], c[4], c[5],c[6], c[7], c[8], c[9], c[10], c[11], c[12], c[13],c[14],c[15],
					 c[16], c[17], c[18], c[19], c[20], c[21],c[22], c[23], c[24], c[25], c[26], c[27], c[28], c[29],c[30],c[31]
					 );
		}
		if (count >= 64){
			for(i= 0; i< 32; i ++){
				if ( i < count-64){
					c[i] = cp[i+64];
				}
				else {
					c[i] = 0x00;
				}
			}
			IRDA_DEBUG(3, "RcvData= %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x", 
					 c[0], c[1], c[2], c[3], c[4], c[5],c[6], c[7], c[8], c[9], c[10], c[11], c[12], c[13],c[14],c[15],
					 c[16], c[17], c[18], c[19], c[20], c[21],c[22], c[23], c[24], c[25], c[26], c[27], c[28], c[29],c[30],c[31]
					 );
		}
		if (count >=96){
			for(i= 0; i<32; i ++){
				if ( i < count-96){
					c[i] = cp[i+96];
				}
				else {
					c[i] = 0x00;
				}
			}
			IRDA_DEBUG(3, "RcvData= %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x", 
					 c[0], c[1], c[2], c[3], c[4], c[5],c[6], c[7], c[8], c[9], c[10], c[11], c[12], c[13],c[14],c[15],
					 c[16], c[17], c[18], c[19], c[20], c[21],c[22], c[23], c[24], c[25], c[26], c[27], c[28], c[29],c[30],c[31]
					 );
		}
		



		ebufp = localechobuf;

		if ( ( count < 20) && localechodata > 0 && dev->rx_buff.state == OUTSIDE_FRAME){
			if ( count > localechodata){
				if (!memcmp(localechobuf, cp + count - localechodata, localechodata)){
					IRDA_DEBUG(4, "%s; data mutch trush %d byte!\n", __func__, count);
					localechodata = 0;
					cp += count;
					count = 0;
				}
			}
			else {
				if (!memcmp(localechobuf + localechodata - count, cp , count)){
					IRDA_DEBUG(4, "%s; data mutch trush %d byte!\n", __func__, count);
					localechodata = 0;
					cp += count;
					count = 0;
				}
			}
		}
		while (count--){
			
			if (localechodata > 0 && dev->rx_buff.state == OUTSIDE_FRAME){
				switch(*cp) {
				case BOF:

					if ( count > 1 && *(cp + 1) == BOF){
						ebufp ++;
						localechodata--;
						cp++;
						continue;
						break;
					}
					else {
						eofp = (unsigned char *)memchr( (void *)cp, (int)EOF, count);
						if ( eofp  == NULL){
							IRDA_DEBUG(4, "%s; not find eof, get start of next frame.\n", __func__);
							localechodata = 0;
							break;
						}
						else {
							framelen = eofp - cp +1 ;
							if ( framelen <= localechodata &&
								   !memcmp((void *)cp, ebufp + localechodata - framelen, framelen)){
								IRDA_DEBUG(4, "%s; find one frame, skip it\n", __func__);
								cp += framelen;
								count -= framelen;
								localechodata = 0;
								break;
							}
							else {
								IRDA_DEBUG(4, "%s; frame line =%d, localechodata = %d.\n", __func__, framelen, localechodata);
								IRDA_DEBUG(4, "%s; find start of next frame.\n", __func__);
								localechodata = 0;
								break;
							}
						}
					}





				case EOF:
					IRDA_DEBUG(4, "%s; find end of trush data!\n", __func__);
					ebufp ++;		
					localechodata = 0;
					cp++;
					continue;
					break;
				default:
					ebufp ++;		
					localechodata--;
					cp++;
					continue;
					break;
				}
			}
			async_unwrap_char(dev->netdev, &dev->netdev->stats,
					  &dev->rx_buff, *cp++);
		}







	} else {
		while (count--) {
			/* rx not enabled: save the raw bytes and never
			 * trigger any netif_rx. The received bytes are flushed
			 * later when we re-enable rx but might be read meanwhile
			 * by the dongle driver.
			 */
			dev->rx_buff.data[dev->rx_buff.len++] = *cp++;

			/* What should we do when the buffer is full? */
			if (unlikely(dev->rx_buff.len == dev->rx_buff.truesize))
				dev->rx_buff.len = 0;
		}
	}

	return 0;
}
static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id)
{
	struct net_device *dev = dev_id;
	struct pxa_irda *si = netdev_priv(dev);
	int iir, lsr, data;

	iir = STIIR;

	switch  (iir & 0x0F) {
	case 0x06: 
	  	lsr = STLSR;
		while (lsr & LSR_FIFOE) {
			data = STRBR;
			if (lsr & (LSR_OE | LSR_PE | LSR_FE | LSR_BI)) {
				printk(KERN_DEBUG "pxa_ir: sir receiving error\n");
				dev->stats.rx_errors++;
				if (lsr & LSR_FE)
					dev->stats.rx_frame_errors++;
				if (lsr & LSR_OE)
					dev->stats.rx_fifo_errors++;
			} else {
				dev->stats.rx_bytes++;
				async_unwrap_char(dev, &dev->stats,
						  &si->rx_buff, data);
			}
			lsr = STLSR;
		}
		si->last_oscr = OSCR;
		break;

	case 0x04: 
	  	   

	case 0x0C: 
	  	do  {
		    dev->stats.rx_bytes++;
	            async_unwrap_char(dev, &dev->stats, &si->rx_buff, STRBR);
	  	} while (STLSR & LSR_DR);
		si->last_oscr = OSCR;
	  	break;

	case 0x02: 
	    	while ((si->tx_buff.len) && (STLSR & LSR_TDRQ)) {
	    		STTHR = *si->tx_buff.data++;
			si->tx_buff.len -= 1;
	    	}

		if (si->tx_buff.len == 0) {
			dev->stats.tx_packets++;
			dev->stats.tx_bytes += si->tx_buff.data - si->tx_buff.head;

                        
			while ((STLSR & LSR_TEMT) == 0)
				cpu_relax();
			si->last_oscr = OSCR;

			if (si->newspeed) {
				pxa_irda_set_speed(si, si->newspeed);
				si->newspeed = 0;
			} else {
				
				STISR = IrSR_IR_RECEIVE_ON | IrSR_XMODE_PULSE_1_6;
				
				STIER = IER_UUE | IER_RLSE | IER_RAVIE | IER_RTIOE;
			}
			
			netif_wake_queue(dev);
		}
		break;
	}

	return IRQ_HANDLED;
}
Esempio n. 14
0
/*
 * SIR format interrupt service routines.
 */
static irqreturn_t  s3c_irda_sir_irq(int irq, void *dev_id)
{

        struct net_device *dev = dev_id;
        struct s3c_irda *si = dev->priv;
        int err_status;

        u8 data;
	u32 ucon, ufcon, ufstat;


        err_status = sir_readreg(S3C_UERSTAT);

        if(err_status) {
                printk("Error : 0x%x\n", sir_readreg(S3C_UERSTAT));
                data = sir_readreg(S3C_URXH);
                si->stats.rx_errors++;
                si->stats.rx_frame_errors++;
        }

	if(irq == si->sir_irq_rx){
		DBG("Rx intr : 0x%1x\n", intpnd);

                while ((sir_readreg(S3C_UFSTAT) & 0X3F) > 0) {
                        data = sir_readreg(S3C_URXH);
                        async_unwrap_char(dev, &si->stats, &si->rx_buff, data);
                }
                dev->last_rx = jiffies;

		/* Clear FIFO */
		ufcon = sir_readreg(S3C_UFCON);
		ufcon |= 3;
		sir_writereg(ufcon, S3C_UFCON);
        }

	if(irq == si->sir_irq_tx) {
		DBG("Tx intr : 0x%1x\n", intpnd);
		
		if(si->tx_buff.len > 0) {
               		ufstat = sir_readreg(S3C_UFSTAT);
                
		        /* Transmitter FIFO is not full */
        	       	while (!(ufstat & (1 << 14)) ) {
				while(!(sir_readreg(S3C_UTRSTAT) & 0x02));
				sir_writereg(*si->tx_buff.data++, S3C_UTXH);
	              	 	if(si->tx_buff.len == 0)
        	                	break;
         		        si->tx_buff.len -= 1;
                        	rmb();
	                        ufstat = sir_readreg(S3C_UFSTAT);
				}

                	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 transmit has finished */
                	 do {
                 		rmb();
	                       	ufstat = sir_readreg(S3C_UFSTAT);
        	       	} while (((ufstat >> 8) & 0x3f) > 0);

               
              		/* Transmission complete. Now enable the receiver.  
	 		 * Sometimes we get a receive IRQ immediately 
	 		 * after a transmit 
 		         */
              
	               	ufcon = sir_readreg(S3C_UFCON);
        	       	ufcon |= 7;
               		sir_writereg(ufcon, S3C_UFCON);

	               	ucon = sir_readreg(S3C_UCON);
        	      	ucon &= ~( 3 << 2);
               		sir_writereg(ucon, S3C_UCON);

	               	if(si->newspeed) {
        	               	s3c_irda_set_speed(si, si->newspeed);
                	       	si->newspeed = 0;
               		}

      	 		if(1) {
                      		ucon |= 1;
	                      	sir_writereg(ucon, S3C_UCON);
        	             	}

               		netif_wake_queue(dev);
			}