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

📄 pxa_ir.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		break;	}	__ECHO_OUT;	return ret;}static struct net_device_stats *pxa250_irda_stats(struct net_device *dev){	struct pxa250_irda *si = dev->priv;	return &si->stats;}#ifdef CONFIG_ARCH_FS_PXA255  #ifdef CONFIG_LEDS  #include <asm/leds.h>  #define irda_led_start()	leds_event(led_amber_on)  #define irda_led_stop()	leds_event(led_amber_off)  #else  #define irda_led_start()	//use gpio operations(GPIO12)  #define irda_led_stop()	//use gpio operations(GPIO12)  #endif#endifstatic int pxa250_irda_start(struct net_device *dev){	struct pxa250_irda *si = dev->priv;	int err;	unsigned long flags;	#ifdef CONFIG_ARCH_FS_PXA255	irda_led_start();#endif	__ECHO_IN;	si->speed = 9600;	//modified by hzh, 9600->115200	local_irq_save(flags);		err = request_irq(si->fir_irq, pxa250_irda_fir_irq, 0,  dev->name, dev);	if (err)		goto err_fir_irq;	err = request_irq(dev->irq, pxa250_irda_irq, 0, dev->name, dev);	if (err)		goto err_irq;	/*	 * The interrupt must remain disabled for now.	 */		disable_irq(dev->irq);  	disable_irq(si->fir_irq);	local_irq_restore(flags);	/* Allocate DMA channel for receiver (not used) */	err = pxa_request_dma("IrDA receive", DMA_PRIO_LOW, pxa250_irda_rxdma_irq, dev);	if (err < 0 )	   goto err_rx_dma;	si->rxdma_ch=err;	DRCMRRXICDR = DRCMR_MAPVLD | si->rxdma_ch;		/* Allocate DMA channel for transmit */	err = pxa_request_dma("IrDA transmit", DMA_PRIO_LOW, pxa250_irda_txdma_irq , dev);	if (err < 0 )	   goto err_tx_dma;	si->txdma_ch=err;	/*	 * Make sure that ICP will be able 	 * to assert the transmit dma request bit	 * through the peripherals request bus (PREQ)	 */		DRCMRTXICDR = DRCMR_MAPVLD | si->txdma_ch;	DBG("rx(not used) channel=%d tx channel=%d\n",si->rxdma_ch,si->txdma_ch);		/* allocate consistent buffers for dma access	 * buffers have to be aligned and situated in dma capable memory region;	 */	si->rxbuf_dma_virt = dma_alloc_writecombine(si->dev, HPSIR_MAX_RXLEN, &si->rxbuf_dma, GFP_KERNEL);	if (! si->rxbuf_dma_virt )		goto err_rxbuf_dma;	si->txbuf_dma_virt = dma_alloc_writecombine(si->dev, HPSIR_MAX_TXLEN, &si->txbuf_dma, GFP_KERNEL);	if (! si->txbuf_dma_virt )		goto err_txbuf_dma;	/* Alocate skb for receiver */	err=pxa250_irda_rx_alloc(si);	if (err)	   goto err_rx_alloc;		/*	 * Setup the serial port for the specified config.	 */	err = pxa250_irda_startup(dev);	if (err)		goto err_startup;	pxa250_irda_set_speed(dev,si->speed = 9600);	//modified by hzh, 9600->115200	/*	 * Open a new IrLAP layer instance.	 */	si->irlap = irlap_open(dev, &si->qos, "pxa250");	err = -ENOMEM;	if (!si->irlap)		goto err_irlap;	/*	 * Now enable the interrupt and start the queue	 */	si->open = 1;	enable_irq(dev->irq);	netif_start_queue(dev);	return 0;err_irlap:	si->open = 0;	pxa250_sir_irda_shutdown(si);err_startup:	dev_kfree_skb(si->rxskb);err_rx_alloc:		dma_free_writecombine(si->dev, HPSIR_MAX_TXLEN, si->txbuf_dma_virt, si->txbuf_dma);err_txbuf_dma:	dma_free_writecombine(si->dev, HPSIR_MAX_RXLEN, si->rxbuf_dma_virt, si->rxbuf_dma);err_rxbuf_dma:	pxa_free_dma(si->txdma_ch);err_tx_dma:	pxa_free_dma(si->rxdma_ch);err_rx_dma:	free_irq(dev->irq, dev);err_irq:	free_irq(si->fir_irq, dev);err_fir_irq:	//	MOD_DEC_USE_COUNT;	return err;}static int pxa250_irda_stop(struct net_device *dev){	struct pxa250_irda *si = dev->priv;		printk(KERN_ERR "Irda stop... RX = %d TX = %d\n",rx_count,tx_count);	disable_irq(dev->irq);  	disable_irq(si->fir_irq); /*  	pxa250_irda_shutdown(si); */	/*	 * If we have been doing DMA receive, make sure we	 * tidy that up cleanly.	 */	if (si->rxskb) {	        dev_kfree_skb(si->rxskb);		si->rxskb = NULL;	}	/* Stop IrLAP */	if (si->irlap) {		irlap_close(si->irlap);		si->irlap = NULL;	}	dma_free_writecombine(si->dev, HPSIR_MAX_TXLEN, si->txbuf_dma_virt, si->txbuf_dma);	dma_free_writecombine(si->dev, HPSIR_MAX_RXLEN, si->rxbuf_dma_virt, si->rxbuf_dma);	pxa_free_dma(si->txdma_ch);	pxa_free_dma(si->rxdma_ch);	netif_stop_queue(dev);	si->open = 0;	/*	 * Free resources	 */	free_irq(dev->irq, dev);	free_irq(si->fir_irq, dev);#ifdef CONFIG_ARCH_FS_PXA255	irda_led_stop();#endif	return 0;}static int pxa250_irda_init_iobuf(iobuff_t *io, int size){	io->head = kmalloc(size, GFP_KERNEL | GFP_DMA);	if (io->head != NULL) {		io->truesize = size;		io->in_frame = FALSE;		io->state    = OUTSIDE_FRAME;		io->data     = io->head;	}	return io->head ? 0 : -ENOMEM;}static int pxa250_stop_fir(struct net_device *dev){   struct pxa250_irda *si = dev->priv;   unsigned int flag;   save_flags(flag);   cli();      pxa250_dma_stop(si->txdma_ch);   pxa250_dma_stop(si->rxdma_ch);   if (si->txskb)      dev_kfree_skb_irq(si->txskb);   ICCR0 &= ~(ICCR0_RXE | ICCR0_TXE );   disable_irq(si->fir_irq);   CKEN &= ~CKEN13_FICP;   restore_flags(flag);   return 0;}static int pxa250_irda_set_speed(struct net_device *dev, int speed){   struct pxa250_irda *si = dev->priv;   int brd, ret = -EINVAL;   static int last_fir_speed=0;   __ECHO_IN;      switch (speed) {      case 9600:	case 19200:	case 38400:      case 57600:	case 115200:	   	 /* Baud rate fixed - Clo */	 /*	  * FIXME	  */	 if (last_fir_speed) 	 {	    pxa250_stop_fir(dev);	    pxa_gpio_mode (GPIO46_STRXD_MD);	    pxa_gpio_mode (GPIO47_STTXD_MD);   	    enable_irq(dev->irq);	    netif_wake_queue(dev);	    last_fir_speed=0;	 }	 #ifndef CONFIG_ARCH_FS_PXA255	//we don't remap FPGA, so can't do this,hzh	 LUB_MISC_WR &= ~(1 << 4);#endif	 brd = 14745600 / (16 * speed); 	 STLCR |= LCR_DLAB;	 STDLH = brd >> 8; /* Clo: set Divisor Latch High */	 STDLL = brd & 0xFF; /* Clo: set Devisor Latch Low */			 STLCR &= ~LCR_DLAB; /* Clo: clear DLAB bit */ 	 STMCR = MCR_OUT2;	 CKEN |= CKEN5_STUART;	 ICMR |= ( 1 << 20 );			 STLCR = LCR_WLS1 | LCR_WLS0;	 SET_SIR_MODE;			 STFCR = FCR_TRFIFOE |  FCR_RESETTF | FCR_RESETRF | FCR_ITL_1 ;// | FCR_ITL_16;	 STIER = IER_UUE | IER_RAVIE | IER_RTIOE;	 si->speed = speed;	 ret = 0;	 break;      case 4000000:	 if (last_fir_speed)	    goto speed_out;	 	 disable_irq(dev->irq);	 pxa250_sir_irda_shutdown(si);	 pxa250_fir_irda_startup(si);	 pxa250_irda_rx_alloc(si);	 ICCR0=0;	 pxa250_start_rx_dma(dev);	 pxa250_ficp_rx_start();	 	 enable_irq(si->fir_irq);	 DBG("enable FIR \n");	 si->speed = speed;	 netif_wake_queue(dev);	 last_fir_speed=1;speed_out:	 	 ret=0;	 	 break;      default:	 break;   }   __ECHO_OUT;   return ret;}static int pxa250_irda_net_init(struct net_device *dev, struct platform_device *pdev){	struct pxa250_irda *si = dev->priv;	unsigned int baudrate_mask;	int err = -ENOMEM;	si->dev = &pdev->dev;	/*	 * Initialise the HP-SIR buffers	 */	err = pxa250_irda_init_iobuf(&si->rx_buff, 14384);	if (err)		goto out;	err = pxa250_irda_init_iobuf(&si->tx_buff, 4000);	if (err)		goto out_free_rx;	si->fir_irq		= IRQ_ICP;	dev->priv = si;	dev->hard_start_xmit	= pxa250_irda_hard_xmit;	dev->open		= pxa250_irda_start;	dev->stop		= pxa250_irda_stop;	dev->do_ioctl		= pxa250_irda_ioctl;	dev->get_stats		= pxa250_irda_stats;	dev->irq    		= IRQ_STUART;	irda_init_max_qos_capabilies(&si->qos);	/*	 * We support original IRDA up to 115k2. (we don't currently	 * support 4Mbps).  Min Turn Time set to 1ms or greater.	 */	baudrate_mask = IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;  	baudrate_mask |= IR_4000000 << 8; 	si->qos.baud_rate.bits &= baudrate_mask;	si->qos.min_turn_time.bits = 7;	irda_qos_bits_to_value(&si->qos);	//register_netdev in drivers/net/net_init.c, register_netdevice in net/core/...	err = register_netdev(dev);	//err = register_netdevice(dev);	if(err == 0) {		dev_set_drvdata(&pdev->dev, dev);	//use dev not si, error in sa1100_ir.c#ifdef CONFIG_PM		/*		 * Power-Management is optional.		 */		si->pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, pxa250_irda_pmproc);		if (si->pmdev)			si->pmdev->data = dev;#endif	} else {		kfree(si->tx_buff.head);out_free_rx:		kfree(si->rx_buff.head);	}out:	return err;}/* * Remove all traces of this driver module from the kernel, so we can't be * called.  Note that the device has already been stopped, so we don't have * to worry about interrupts or dma. */static void pxa250_irda_net_uninit(struct net_device *dev){	struct pxa250_irda *si = dev->priv;//	dev->hard_start_xmit	= NULL;//	dev->open		= NULL;//	dev->stop		= NULL;//	dev->do_ioctl		= NULL;//	dev->get_stats		= NULL;//	dev->priv		= NULL;//	dev->irq		= 0;#ifdef CONFIG_PM	pm_unregister(si->pmdev);#endif	dev_set_drvdata(si->dev, NULL);	kfree(si->tx_buff.head);	kfree(si->rx_buff.head);}static void __exit pxa25x_irda_release(struct device *dev){}static int __init pxa25x_irda_probe(struct device *_dev){	struct platform_device *pdev = to_platform_device(_dev);	struct net_device *dev;	int err;	/* STUART */	err = request_mem_region(__PREG(STRBR), 0x24, "IrDA") ? 0 : -EBUSY;	if (err)		goto err_mem_1;	/* FIR */	err = request_mem_region(__PREG(ICCR0), 0x1c, "IrDA") ? 0 : -EBUSY;	if (err)		goto err_mem_2;	//rtnl_lock();	//can't register_netdev if rtnl_lock!!!	dev = alloc_irdadev(sizeof(struct pxa250_irda));	if (dev) {		err = pxa250_irda_net_init(dev, pdev);		if (err)			free_netdev(dev);		else {			netdev = dev;			_dev->release = pxa25x_irda_release;		}	}	//rtnl_unlock();	if (err) {		release_mem_region(__PREG(ICCR0), 0x1c);err_mem_2:		release_mem_region(__PREG(STRBR), 0x24);	}err_mem_1:	return err;}static int __exit pxa25x_irda_remove(struct device *_dev){	struct net_device *dev = dev_get_drvdata(_dev);	netdev = NULL;	if (dev) {	//	rtnl_lock();		unregister_netdev(dev);	//unregister_netdevice(dev);		pxa250_irda_net_uninit(dev);		free_netdev(dev);	//	rtnl_unlock();	}        release_mem_region(__PREG(ICCR0), 0x1c);	release_mem_region(__PREG(STRBR), 0x24);	/*	 * We now know that the netdevice is no longer in use, and all	 * references to our driver have been removed.  The only structure	 * which may still be present is the netdevice, which will get	 * cleaned up by net/core/dev.c	 */	return 0;}static struct device_driver pxa25x_ir_driver = {	.name		= "pxa25x-ir",	.bus		= &platform_bus_type,	.probe		= pxa25x_irda_probe,	.remove		= pxa25x_irda_remove,#ifdef CONFIG_PM	.suspend	= pxa250_irda_suspend,	.resume		= pxa250_irda_resume,#endif};static u64 pxa25x_irda_dma_mask = 0xffffffffUL;static struct platform_device pxa25x_ir_device = {	.name		= "pxa25x-ir",	.id		= 0,	.dev		= {		.dma_mask = &pxa25x_irda_dma_mask,		.coherent_dma_mask = 0xffffffff,	},};static int __init pxa25x_irda_init(void){	int ret;	ret = driver_register(&pxa25x_ir_driver);	if (ret == 0) {		ret = platform_device_register(&pxa25x_ir_device);		if (ret)			driver_unregister(&pxa25x_ir_driver);	}	return ret;}static void __exit pxa25x_irda_exit(void){	driver_unregister(&pxa25x_ir_driver);	platform_device_unregister(&pxa25x_ir_device);}module_init(pxa25x_irda_init);module_exit(pxa25x_irda_exit);MODULE_AUTHOR("Alexey Lugovskoy Frasenyak Dmitrij");MODULE_DESCRIPTION("PXA250 SIR/FIR");MODULE_LICENSE("GPL");//EXPORT_NO_SYMBOLS;

⌨️ 快捷键说明

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