コード例 #1
0
ファイル: sa1100_ir.c プロジェクト: ena30/snake-os
static void sa1100_irda_fir_error(struct sa1100_irda *si, struct net_device *dev)
{
	struct sk_buff *skb = si->rxskb;
	dma_addr_t dma_addr;
	unsigned int len, stat, data;

	if (!skb) {
		printk(KERN_ERR "sa1100_ir: SKB is NULL!\n");
		return;
	}

	/*
	 * Get the current data position.
	 */
	dma_addr = sa1100_get_dma_pos(si->rxdma);
	len = dma_addr - si->rxbuf_dma;
	if (len > HPSIR_MAX_RXLEN)
		len = HPSIR_MAX_RXLEN;
	dma_unmap_single(si->dev, si->rxbuf_dma, len, DMA_FROM_DEVICE);

	do {
		/*
		 * Read Status, and then Data.
		 */
		stat = Ser2HSSR1;
		rmb();
		data = Ser2HSDR;

		if (stat & (HSSR1_CRE | HSSR1_ROR)) {
			si->stats.rx_errors++;
			if (stat & HSSR1_CRE)
				si->stats.rx_crc_errors++;
			if (stat & HSSR1_ROR)
				si->stats.rx_frame_errors++;
		} else
			skb->data[len++] = data;

		/*
		 * If we hit the end of frame, there's
		 * no point in continuing.
		 */
		if (stat & HSSR1_EOF)
			break;
	} while (Ser2HSSR0 & HSSR0_EIF);

	if (stat & HSSR1_EOF) {
		si->rxskb = NULL;

		skb_put(skb, len);
		skb->dev = dev;
		skb->mac.raw = skb->data;
		skb->protocol = htons(ETH_P_IRDA);
		si->stats.rx_packets++;
		si->stats.rx_bytes += len;

		/*
		 * Before we pass the buffer up, allocate a new one.
		 */
		sa1100_irda_rx_alloc(si);

		netif_rx(skb);
		dev->last_rx = jiffies;
	} else {
		/*
		 * Remap the buffer.
		 */
		si->rxbuf_dma = dma_map_single(si->dev, si->rxskb->data,
						HPSIR_MAX_RXLEN,
						DMA_FROM_DEVICE);
	}
}
コード例 #2
0
ファイル: usb_recv.c プロジェクト: granberro/PSjbiPAQ
void ep1_int_hndlr()
{
	dma_addr_t dma_addr;
	unsigned int len;
	int status = Ser0UDCCS1;

	PRINTKD( "[%lu]Ep1 int %d\n", (jiffies-start_time)*10, status);
	
	if ( naking )
		printk( "%sEh? in ISR but naking = %d\n", "usbrx: ", naking );

	// Reive packet complete
	if (status & UDCCS1_RPC) {
		if (!ep1_curdmalen) {
			printk("usb_recv: RPC for non-existent buffer\n");
			naking = 1;
			return;
		}

		sa1100_stop_dma(dmachn_rx);

		if (status & UDCCS1_SST) {
			printk("usb_recv: stall sent OMP=%d\n",Ser0UDCOMP);
			UDC_flip(Ser0UDCCS1, UDCCS1_SST);
			ep1_done(-EIO); // UDC aborted current transfer, so we do
			return;
		}

		if (status & UDCCS1_RPE) {
		    printk("usb_recv: RPError %x\n", status);
			UDC_flip(Ser0UDCCS1, UDCCS1_RPC);
			ep1_done(-EIO);
			return;
		}

		dma_addr = sa1100_get_dma_pos(dmachn_rx);
		pci_unmap_single(NULL, ep1_curdmapos, ep1_curdmalen, PCI_DMA_FROMDEVICE);
		
		len = dma_addr - ep1_curdmapos;

		if (len < ep1_curdmalen) {
			char *buf = ep1_curdmabuf + len;
			while (Ser0UDCCS1 & UDCCS1_RNE) {
				if (len >= ep1_curdmalen) {
					printk("usb_recv: too much data in fifo\n");
					break;
				}
				*buf++ = Ser0UDCDR;
				len++;
			}
		} else if (Ser0UDCCS1 & UDCCS1_RNE) {
			printk("usb_recv: fifo screwed, shouldn't contain data\n");
			len = 0;
		}
		ep1_curdmalen = 0;  /* dma unmap already done */
		ep1_remain -= len;
		naking = 1;
		ep1_done((len) ? 0 : -EPIPE);
	}
	/* else, you can get here if we are holding NAK */
}