lone Xin | 4 Aug 2006 04:55
Picon

Re: IrDA-USB Bridge Issue

On 7/13/06, WangHe <hewang-NO6DMxOfsFcFoECaAgFIynS5uNuOjpZe@public.gmane.org> wrote:

Hi

 

Does anybody know what brand of IrDA-USB bridge product that support by Linux can be find in China market?

I only know one brand, but it only supports Windows OS.


One of it, ZK-ID6, is based on MA-620(with PL2303), which is partially supported by current kernel.

 

www.z-tek.com.cn

 

Thanks!

WangHe

2006-7-13

 



-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642


_______________________________________________
irda-users mailing list
irda-users-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
http://lists.sourceforge.net/lists/listinfo/irda-users



-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
irda-users mailing list
irda-users@...
http://lists.sourceforge.net/lists/listinfo/irda-users
Komal Shah | 7 Aug 2006 11:12
Picon
Favicon

[PATCH] OMAP: Add support for IrDA driver

Samuel/Tony,

I have attached the OMAP IrDA patch for OMAP1610/1710 and OMAP242x
for review. See that for IrDA driver to work on H3 and H4, we need
gpio-expander functions to go in mainline, but it can work on H2.

FYI...we are in process of submitting OMAP I2C driver to mainline,
and right now I am working on the 2nd round of review comments
from Jean.

---Komal Shah
http://komalshah.blogspot.com

--

-- 
http://www.fastmail.fm - Choose from over 50 domains or use your own

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
irda-users mailing list
irda-users@...
http://lists.sourceforge.net/lists/listinfo/irda-users
Samuel Ortiz | 11 Aug 2006 07:47

Re: [PATCH] OMAP: Add support for IrDA driver

Hi Komal,

On Mon, Aug 07, 2006 at 02:42:33PM +0530, Komal Shah wrote:
> Samuel/Tony,
> 
> I have attached the OMAP IrDA patch for OMAP1610/1710 and OMAP242x
> for review. See that for IrDA driver to work on H3 and H4, we need
> gpio-expander functions to go in mainline, but it can work on H2.
Overall the patch looks good, I have some comments though. See below:

> +++ b/drivers/net/irda/Kconfig
>  <at>  <at>  -432,5 +432,15  <at>  <at>  config MCS_FIR
>  	  To compile it as a module, choose M here: the module will be called
>  	  mcs7780.
>  
> +config OMAP_IR
> +	tristate "OMAP IrDA(SIR/MIR/FIR)"
> +	depends on IRDA && ARCH_OMAP
> +	select GPIOEXPANDER_OMAP if (MACH_OMAP_H3 || MACH_OMAP_H4)
> +        help
> +	  Say Y here if you want to build support for the Teaxas Instruments
s/Teaxas/Texas/ ;-)

> diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile
> index 5be09f1..89c6389 100644
> --- a/drivers/net/irda/Makefile
> +++ b/drivers/net/irda/Makefile
>  <at>  <at>  -20,6 +20,7  <at>  <at>  obj-$(CONFIG_VLSI_FIR)		+= vlsi_ir.o
>  obj-$(CONFIG_VIA_FIR)		+= via-ircc.o
>  obj-$(CONFIG_PXA_FICP)	        += pxaficp_ir.o
>  obj-$(CONFIG_MCS_FIR)	        += mcs7780.o
> +obj-$(CONFIG_OMAP_IR)		+= omap-ir.o
>  # Old dongle drivers for old SIR drivers
>  obj-$(CONFIG_ESI_DONGLE_OLD)		+= esi.o
>  obj-$(CONFIG_TEKRAM_DONGLE_OLD)	+= tekram.o
> diff --git a/drivers/net/irda/omap-ir.c b/drivers/net/irda/omap-ir.c
> new file mode 100644
> index 0000000..c51fb48
> --- /dev/null
> +++ b/drivers/net/irda/omap-ir.c
>  <at>  <at>  -0,0 +1,903  <at>  <at> 
> +/*
> + * BRIEF MODULE DESCRIPTION
> + *
> + *	Infra-red driver for the OMAP1610-H2 and OMAP1710-H3 and H4 Platforms
> + *	  (SIR/MIR/FIR modes)
> + *	  (based on omap-sir.c)
> + *
> + * Copyright 2003 MontaVista Software Inc.
> + * Author: MontaVista Software, Inc.
> + *	   source@...
> + *
> + * Copyright 2004 Texas Instruments.
> + *
> + *  This program is free software; you can redistribute	 it and/or modify it
> + *  under  the terms of	 the GNU General  Public License as published by the
> + *  Free Software Foundation;  either version 2 of the	License, or (at your
> + *  option) any later version.
> + *
> + *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
> + *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
> + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
> + *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
> + *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
> + *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
> + *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
> + *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + *
> + *  You should have received a copy of the  GNU General Public License along
> + *  with this program; if not, write  to the Free Software Foundation, Inc.,
> + *  675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + Modifications:
> + Feb 2004, Texas Instruments
> + - Ported to 2.6 kernel (Feb 2004).
> + *
> + Apr 2004, Texas Instruments
> + - Added support for H3 (Apr 2004).
> + Nov 2004, Texas Instruments
> + - Added support for Power Management.
> + */
> +
> +#include <linux/config.h>
> +#include <linux/module.h>
> +#include <linux/types.h>
> +#include <linux/init.h>
> +#include <linux/errno.h>
> +#include <linux/netdevice.h>
> +#include <linux/slab.h>
> +#include <linux/rtnetlink.h>
> +#include <linux/interrupt.h>
> +#include <linux/delay.h>
> +#include <linux/ioport.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/platform_device.h>
> +#include <linux/i2c.h>
> +
> +#include <net/irda/irda.h>
> +#include <net/irda/irmod.h>
> +#include <net/irda/wrapper.h>
> +#include <net/irda/irda_device.h>
> +
> +#include <asm/irq.h>
> +#include <asm/io.h>
> +#include <asm/hardware.h>
> +#include <asm/serial.h>
> +#include <asm/mach-types.h>
> +#include <asm/dma.h>
> +#include <asm/arch/mux.h>
> +#include <asm/arch/gpio.h>
> +#include <asm/arch/irda.h>
> +
> +#define UART3_EFR_EN			(1 << 4)
> +#define UART3_MCR_EN_TCR_TLR		(1 << 6)
> +
> +#define UART3_LCR_WL_8			(3 << 0)
> +#define UART3_LCR_SP2			(1 << 2)
> +#define UART3_LCR_DIVEN			(1 << 7)
> +
> +#define UART3_FCR_FIFO_EN		(1 << 0)
> +#define UART3_FCR_FIFO_RX		(1 << 1)
> +#define UART3_FCR_FIFO_TX		(1 << 2)
> +#define UART3_FCR_FIFO_DMA1		(1 << 3)
> +#define UART3_FCR_FIFO_TX_TRIG16	(1 << 4)
> +#define UART3_FCR_FIFO_RX_TRIG16	(1 << 6)
> +#define UART3_FCR_CONFIG	(\
> +		UART3_FCR_FIFO_EN | UART3_FCR_FIFO_RX	|\
> +		UART3_FCR_FIFO_TX | UART3_FCR_FIFO_DMA1 |\
> +		UART3_FCR_FIFO_TX_TRIG16		|\
> +		UART3_FCR_FIFO_RX_TRIG16)
> +
> +#define UART3_SCR_TX_TRIG1		(1 << 6)
> +#define UART3_SCR_RX_TRIG1		(1 << 7)
> +
> +#define UART3_MDR1_RESET		(0x07)
> +#define UART3_MDR1_SIR			(1 << 0)
> +#define UART3_MDR1_MIR			(4 << 0)
> +#define UART3_MDR1_FIR			(5 << 0)
> +#define UART3_MDR1_SIP_AUTO		(1 << 6)
> +
> +#define UART3_MDR2_TRIG1		(0 << 1)
> +#define UART3_MDR2_IRTX_UNDERRUN	(1 << 0)
> +
> +#define UART3_ACERG_TX_UNDERRUN_DIS	(1 << 4)
> +#define UART3_ACERG_SD_MODE_LOW		(1 << 6)
> +#define UART3_ACERG_DIS_IR_RX		(1 << 5)
> +
> +#define UART3_IER_EOF			(1 << 5)
> +#define UART3_IER_CTS			(1 << 7)
> +
> +#define UART3_IIR_TX_STATUS		(1 << 5)
> +#define UART3_IIR_EOF			(0x80)
> +
> +#define IS_FIR(si)		((si)->speed >= 4000000)
> +#define IRDA_FRAME_SIZE_LIMIT	4096
You should use IRDA_SKB_MAX_MTU and IRDA_SIR_MAX_FRAME for respectively your
max Rx and Tx sizes.

> +static int rx_state = 0;	/* RX state for IOCTL */
rx_state could probably be part of omap_irda.

> +struct omap_irda {
> +	unsigned char open;
> +	int speed;		/* Current IrDA speed */
> +	int newspeed;
> +
> +	struct net_device_stats stats;
> +	struct irlap_cb *irlap;
> +	struct qos_info qos;
> +
> +	int rx_dma_channel;
> +	int tx_dma_channel;
> +
> +	dma_addr_t rx_buf_dma_phys;	/* Physical address of RX DMA buffer */
> +	dma_addr_t tx_buf_dma_phys;	/* Physical address of TX DMA buffer */
> +
> +	void *rx_buf_dma_virt;		/* Virtual address of RX DMA buffer */
> +	void *tx_buf_dma_virt;		/* Virtual address of TX DMA buffer */
> +
> +	struct device *dev;
> +	struct omap_irda_config *pdata;
You forgot to define omap_irda_config.
Same thing for IR_SEL, IR_SIRMODE, IR_FIRMODE and IR_MIRMODE.

> +};
> +
> +static void inline uart_reg_out(int idx, u8 val)
> +{
> +	omap_writeb(val, idx);
> +}
> +
> +static u8 inline uart_reg_in(int idx)
> +{
> +	u8 b = omap_readb(idx);
> +	return b;
> +}
> +
> +/* forward declarations */
> +extern void irda_device_setup(struct net_device *dev);
This is useless as you don't use this function anywhere in the code below.

> +extern void omap_stop_dma(int lch);
> +static int omap_irda_set_speed(struct net_device *dev, int speed);
> +
> +static void omap_irda_start_rx_dma(struct omap_irda *si)
> +{
> +	/* Configure DMA */
> +	omap_set_dma_src_params(si->rx_dma_channel, 0x3, 0x0,
> +				si->pdata->src_start,
> +				0, 0);
> +
> +	omap_enable_dma_irq(si->rx_dma_channel, 0x01);
> +
> +	omap_set_dma_dest_params(si->rx_dma_channel, 0x0, 0x1,
> +				si->rx_buf_dma_phys,
> +				0, 0);
> +
> +	omap_set_dma_transfer_params(si->rx_dma_channel, 0x0,
> +				IRDA_FRAME_SIZE_LIMIT, 0x1,
> +				0x0, si->pdata->rx_trigger, 0);
> +	omap_start_dma(si->rx_dma_channel);
> +}
> +
> +static void omap_start_tx_dma(struct omap_irda *si, int size)
> +{
> +	/* Configure DMA */
> +	omap_set_dma_dest_params(si->tx_dma_channel, 0x03, 0x0,
> +				si->pdata->dest_start, 0, 0);
> +
> +	omap_enable_dma_irq(si->tx_dma_channel, 0x01);
> +
> +	omap_set_dma_src_params(si->tx_dma_channel, 0x0, 0x1,
> +				si->tx_buf_dma_phys,
> +				0, 0);
> +
> +	omap_set_dma_transfer_params(si->tx_dma_channel, 0x0, size, 0x1,
> +				0x0, si->pdata->tx_trigger, 0);
> +
> +	/* Start DMA */
> +	omap_start_dma(si->tx_dma_channel);
> +}
> +
> +/* DMA RX callback - normally, we should not go here,
> + * it calls only if something is going wrong
> + */
> +static void omap_irda_rx_dma_callback(int lch, u16 ch_status, void *data)
> +{
> +	struct net_device *dev = data;
> +	struct omap_irda *si = dev->priv;
A detail here, but I think that "si" for a variable name is a bit meaningless. 

> +	printk(KERN_ERR "RX Transfer error or very big frame\n");
> +
> +	/* Clear interrupts */
> +	uart_reg_in(UART3_IIR);
> +
> +	si->stats.rx_frame_errors++;
> +
> +	uart_reg_in(UART3_RESUME);
> +
> +	/* Re-init RX DMA */
> +	omap_irda_start_rx_dma(si);
> +}
> +
> +/* DMA TX callback - calling when frame transfer has been finished */
> +static void omap_irda_tx_dma_callback(int lch, u16 ch_status, void *data)
> +{
> +	struct net_device *dev = data;
> +	struct omap_irda *si = dev->priv;
> +
> +	/*Stop DMA controller */
> +	omap_stop_dma(si->tx_dma_channel);
> +}
> +
> +/*
> + * Set the IrDA communications speed.
> + * Interrupt have to be disabled here.
> + */
> +static int omap_irda_startup(struct net_device *dev)
> +{
> +	struct omap_irda *si = dev->priv;
> +
> +
> +	/* FIXME: use clk_* apis for UART3 clock*/
> +	/* Enable UART3 clock and set UART3 to IrDA mode */
> +	if (machine_is_omap_h2() || machine_is_omap_h3())
> +		omap_writel(omap_readl(MOD_CONF_CTRL_0) | (1 << 31) | (1 << 15),
> +				MOD_CONF_CTRL_0);
> +
> +	/* Only for H2?
> +	 */
> +	if (si->pdata->transceiver_mode && machine_is_omap_h2()) {
> +		/* Is it select_irda on H2 ? */
> +		omap_writel(omap_readl(FUNC_MUX_CTRL_A) | 7,
> +					FUNC_MUX_CTRL_A);
> +		si->pdata->transceiver_mode(si->dev, IR_SIRMODE);
> +	}
> +
> +	uart_reg_out(UART3_MDR1, UART3_MDR1_RESET);	/* Reset mode */
> +
> +	/* Clear DLH and DLL */
> +	uart_reg_out(UART3_LCR, UART3_LCR_DIVEN);
> +
> +	uart_reg_out(UART3_DLL, 0);
> +	uart_reg_out(UART3_DLH, 0);
> +	uart_reg_out(UART3_LCR, 0xbf);	/* FIXME: Add #define */
> +
> +	uart_reg_out(UART3_EFR, UART3_EFR_EN);
> +	uart_reg_out(UART3_LCR, UART3_LCR_DIVEN);
> +
> +	/* Enable access to UART3_TLR and UART3_TCR registers */
> +	uart_reg_out(UART3_MCR, UART3_MCR_EN_TCR_TLR);
> +
> +	uart_reg_out(UART3_SCR, 0);
> +	/* Set Rx trigger to 1 and Tx trigger to 1 */
> +	uart_reg_out(UART3_TLR, 0);
> +
> +	/* Set LCR to 8 bits and 1 stop bit */
> +	uart_reg_out(UART3_LCR, 0x03);
> +
> +	/* Clear RX and TX FIFO and enable FIFO */
> +	/* Use DMA Req for transfers */
> +	uart_reg_out(UART3_FCR, UART3_FCR_CONFIG);
> +
> +	uart_reg_out(UART3_MCR, 0);
> +
> +	uart_reg_out(UART3_SCR, UART3_SCR_TX_TRIG1 |
> +			UART3_SCR_RX_TRIG1);
> +
> +	/* Enable UART3 SIR Mode,(Frame-length method to end frames) */
> +	uart_reg_out(UART3_MDR1, UART3_MDR1_SIR);
> +
> +	/* Set Status FIFO trig to 1 */
> +	uart_reg_out(UART3_MDR2, 0);
> +
> +	/* Enables RXIR input */
> +	/* and disable TX underrun */
> +	/* SEND_SIP pulse */
> +	uart_reg_out(UART3_ACREG, UART3_ACERG_SD_MODE_LOW |
> +			UART3_ACERG_TX_UNDERRUN_DIS);
> +
> +	/* Enable EOF Interrupt only */
> +	uart_reg_out(UART3_IER, UART3_IER_CTS | UART3_IER_EOF);
> +
> +	/* Set Maximum Received Frame size to 2048 bytes */
> +	uart_reg_out(UART3_RXFLL, 0x00);
> +	uart_reg_out(UART3_RXFLH, 0x08);
> +
> +	uart_reg_in(UART3_RESUME);
> +
> +	return 0;
> +}
> +
> +static int omap_irda_shutdown(struct omap_irda *si)
> +{
> +	unsigned long flags;
> +
> +	local_irq_save(flags);
> +
> +	/* Disable all UART3 Interrupts */
> +	uart_reg_out(UART3_IER, 0);
> +
> +	/* Disable UART3 and disable baud rate generator */
> +	uart_reg_out(UART3_MDR1, UART3_MDR1_RESET);
> +
> +	/* set SD_MODE pin to high and Disable RX IR */
> +	uart_reg_out(UART3_ACREG, (UART3_ACERG_DIS_IR_RX |
> +			~(UART3_ACERG_SD_MODE_LOW)));
> +
> +	/* Clear DLH and DLL */
> +	uart_reg_out(UART3_LCR, UART3_LCR_DIVEN);
> +	uart_reg_out(UART3_DLL, 0);
> +	uart_reg_out(UART3_DLH, 0);
> +
> +	local_irq_restore(flags);
> +
> +	return 0;
> +}
> +
> +static irqreturn_t
> +omap_irda_irq(int irq, void *dev_id, struct pt_regs *hw_regs)
> +{
> +	struct net_device *dev = dev_id;
> +	struct omap_irda *si = dev->priv;
> +	struct sk_buff *skb;
> +
> +	u8 status;
> +	int w = 0;
> +
> +	/* Clear EOF interrupt */
> +	status = uart_reg_in(UART3_IIR);
> +
> +	if (status & UART3_IIR_TX_STATUS) {
> +		u8 mdr2 = uart_reg_in(UART3_MDR2);
> +		if (mdr2 & UART3_MDR2_IRTX_UNDERRUN)
> +			printk(KERN_ERR "IrDA Buffer underrun error\n");
> +
> +		si->stats.tx_packets++;
> +
> +		if (si->newspeed) {
> +			omap_irda_set_speed(dev, si->newspeed);
> +			si->newspeed = 0;
> +		}
> +
> +		netif_wake_queue(dev);
> +		if (!(status & UART3_IIR_EOF))
> +			return IRQ_HANDLED;
> +	}
> +
> +	/* Stop DMA and if there are no errors, send frame to upper layer */
> +	omap_stop_dma(si->rx_dma_channel);
> +
> +	status = uart_reg_in(UART3_SFLSR);	/* Take a frame status */
> +
> +	if (status != 0) {	/* Bad frame? */
> +		si->stats.rx_frame_errors++;
> +		uart_reg_in(UART3_RESUME);
> +	} else {
> +		/* We got a frame! */
> +		skb = alloc_skb(IRDA_FRAME_SIZE_LIMIT, GFP_ATOMIC);
Use dev_alloc_skb() for allocating RX packets.

> +
> +		if (!skb) {
> +			printk(KERN_ERR "omap_sir: out of memory for RX SKB\n");
> +			return IRQ_HANDLED;
> +		}
> +		/*
> +		 * Align any IP headers that may be contained
> +		 * within the frame.
> +		 */
> +
> +		skb_reserve(skb, 1);
> +
> +		w = OMAP_DMA_CDAC_REG(si->rx_dma_channel);
> +
> +		if (cpu_is_omap16xx())
> +			w -= OMAP1_DMA_CDSA_L_REG(si->rx_dma_channel);
> +		if (cpu_is_omap24xx())
> +			w -= OMAP2_DMA_CDSA_REG(si->rx_dma_channel);
> +
> +		if (!IS_FIR(si)) {
> +			/* Copy DMA buffer to skb */
> +			memcpy(skb_put(skb, w - 2), si->rx_buf_dma_virt, w - 2);
> +		} else {
> +			/* Copy DMA buffer to skb */
> +			memcpy(skb_put(skb, w - 4), si->rx_buf_dma_virt, w - 4);
> +		}
> +
> +		skb->dev = dev;
> +		skb->mac.raw = skb->data;
> +		skb->protocol = htons(ETH_P_IRDA);
> +		si->stats.rx_packets++;
> +		si->stats.rx_bytes += skb->len;
> +		netif_receive_skb(skb);	/* Send data to upper level */
> +	}
> +
> +	/* Re-init RX DMA */
> +	omap_irda_start_rx_dma(si);
> +
> +	dev->last_rx = jiffies;
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int omap_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
> +{
> +	struct omap_irda *si = dev->priv;
> +	int speed = irda_get_next_speed(skb);
> +	int mtt = irda_get_mtt(skb);
> +	int xbofs = irda_get_next_xbofs(skb);
> +
> +
> +	/*
> +	 * 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 (xbofs) /* Set number of addtional BOFS */
> +		uart_reg_out(UART3_EBLR, xbofs + 1);
> +
> +	/*
> +	 * If this is an empty frame, we can bypass a lot.
> +	 */
> +	if (skb->len == 0) {
> +		if (si->newspeed) {
> +			si->newspeed = 0;
> +			omap_irda_set_speed(dev, speed);
> +		}
> +		dev_kfree_skb(skb);
> +		return 0;
> +	}
> +
> +	netif_stop_queue(dev);
> +
> +	/* Copy skb data to DMA buffer */
> +	memcpy(si->tx_buf_dma_virt, skb->data, skb->len);
> +
> +	/* Copy skb data to DMA buffer */
> +	si->stats.tx_bytes += skb->len;
> +
> +	/* Set frame length */
> +	uart_reg_out(UART3_TXFLL, (skb->len & 0xff));
> +	uart_reg_out(UART3_TXFLH, (skb->len >> 8));
> +
> +	if (mtt > 1000)
> +		mdelay(mtt / 1000);
> +	else
> +		udelay(mtt);
> +
> +	/* Start TX DMA transfer */
> +	omap_start_tx_dma(si, skb->len);
> +
> +	/* We can free skb now because it's already in DMA buffer */
> +	dev_kfree_skb(skb);
> +
> +	dev->trans_start = jiffies;
> +
> +	return 0;
> +}
> +
> +static int
> +omap_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)
> +{
> +	struct if_irda_req *rq = (struct if_irda_req *)ifreq;
> +	struct omap_irda *si = dev->priv;
> +	int ret = -EOPNOTSUPP;
> +
> +
> +	switch (cmd) {
> +	case SIOCSBANDWIDTH:
> +		if (capable(CAP_NET_ADMIN)) {
> +			/*
> +			 * We are unable to set the speed if the
> +			 * device is not running.
> +			 */
> +			if (si->open)
> +				ret = omap_irda_set_speed(dev,
> +						rq->ifr_baudrate);
> +			else {
> +				printk(KERN_ERR "omap_irda_ioctl: SIOCSBANDWIDTH: !netif_running\n");
> +				ret = 0;
> +			}
> +		}
> +		break;
> +
> +	case SIOCSMEDIABUSY:
> +		ret = -EPERM;
> +		if (capable(CAP_NET_ADMIN)) {
> +			irda_device_set_media_busy(dev, TRUE);
> +			ret = 0;
> +		}
> +		break;
> +
> +	case SIOCGRECEIVING:
> +		rq->ifr_receiving = rx_state;
> +		break;
rx_state is always set to 0, so this looks a bit useless.

> +	default:
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
> +static struct net_device_stats *omap_irda_stats(struct net_device *dev)
> +{
> +	struct omap_irda *si = dev->priv;
> +	return &si->stats;
> +}
> +
> +static int omap_irda_start(struct net_device *dev)
> +{
> +	struct omap_irda *si = dev->priv;
> +	int err;
> +
> +	si->speed = 9600;
> +
> +	err = request_irq(dev->irq, omap_irda_irq, 0, dev->name, dev);
> +	if (err)
> +		goto err_irq;
> +
> +	/*
> +	 * The interrupt must remain disabled for now.
> +	 */
> +	disable_irq(dev->irq);
> +
> +	/*  Request DMA channels for IrDA hardware */
> +	if (omap_request_dma(si->pdata->rx_channel, "IrDA Rx DMA",
> +			(void *)omap_irda_rx_dma_callback,
> +			dev, &(si->rx_dma_channel))) {
> +		printk(KERN_ERR "Failed to request IrDA Rx DMA\n");
> +		goto err_irq;
> +	}
> +
> +	if (omap_request_dma(si->pdata->tx_channel, "IrDA Tx DMA",
> +			(void *)omap_irda_tx_dma_callback,
> +			dev, &(si->tx_dma_channel))) {
> +		printk(KERN_ERR "Failed to request IrDA Tx DMA\n");
> +		goto err_irq;
> +	}
> +
> +	/* Allocate TX and RX buffers for DMA channels */
> +	si->rx_buf_dma_virt =
> +		dma_alloc_coherent(NULL, IRDA_FRAME_SIZE_LIMIT,
> +				&(si->rx_buf_dma_phys),
> +				GFP_KERNEL);
> +
> +	if (!si->rx_buf_dma_virt) {
> +		printk(KERN_ERR "Unable to allocate memory for rx_buf_dma\n");
> +		goto err_irq;
> +	}
> +
> +	si->tx_buf_dma_virt =
> +		dma_alloc_coherent(NULL, IRDA_FRAME_SIZE_LIMIT,
> +				&(si->tx_buf_dma_phys),
> +				GFP_KERNEL);
> +
> +	if (!si->tx_buf_dma_virt) {
> +		printk(KERN_ERR "Unable to allocate memory for tx_buf_dma\n");
> +		goto err_mem1;
> +	}
> +
> +	/*
> +	 * Setup the serial port for the specified config.
> +	 */
> +	if (si->pdata->select_irda)
> +		si->pdata->select_irda(si->dev, IR_SEL);
> +
> +	err = omap_irda_startup(dev);
> +
> +	if (err)
> +		goto err_startup;
> +
> +	omap_irda_set_speed(dev, si->speed = 9600);
> +
> +	/*
> +	 * Open a new IrLAP layer instance.
> +	 */
> +	si->irlap = irlap_open(dev, &si->qos, "omap_sir");
> +
> +	err = -ENOMEM;
> +	if (!si->irlap)
> +		goto err_irlap;
> +
> +	/* Now enable the interrupt and start the queue  */
> +	si->open = 1;
> +
> +	/* Start RX DMA */
> +	omap_irda_start_rx_dma(si);
> +
> +	enable_irq(dev->irq);
> +	netif_start_queue(dev);
> +
> +	return 0;
> +
> +err_irlap:
> +	si->open = 0;
> +	omap_irda_shutdown(si);
> +err_startup:
> +	dma_free_coherent(NULL, IRDA_FRAME_SIZE_LIMIT,
> +			si->tx_buf_dma_virt, si->tx_buf_dma_phys);
> +err_mem1:
> +	dma_free_coherent(NULL, IRDA_FRAME_SIZE_LIMIT,
> +			si->rx_buf_dma_virt, si->rx_buf_dma_phys);
> +err_irq:
> +	free_irq(dev->irq, dev);
> +	return err;
> +}
> +
> +static int omap_irda_stop(struct net_device *dev)
> +{
> +	struct omap_irda *si = dev->priv;
> +
> +	disable_irq(dev->irq);
> +
> +	netif_stop_queue(dev);
> +
> +	omap_free_dma(si->rx_dma_channel);
> +	omap_free_dma(si->tx_dma_channel);
> +
> +	if (si->rx_buf_dma_virt)
> +		dma_free_coherent(NULL, IRDA_FRAME_SIZE_LIMIT,
> +				si->rx_buf_dma_virt, si->rx_buf_dma_phys);
> +	if (si->tx_buf_dma_virt)
> +		dma_free_coherent(NULL, IRDA_FRAME_SIZE_LIMIT,
> +				si->tx_buf_dma_virt, si->tx_buf_dma_phys);
> +
> +	omap_irda_shutdown(si);
> +
> +	/* Stop IrLAP */
> +	if (si->irlap) {
> +		irlap_close(si->irlap);
> +		si->irlap = NULL;
> +	}
> +
> +	si->open = 0;
> +
> +	/*
> +	 * Free resources
> +	 */
> +	free_irq(dev->irq, dev);
> +
> +	return 0;
> +}
> +
> +static int omap_irda_set_speed(struct net_device *dev, int speed)
> +{
> +	struct omap_irda *si = dev->priv;
> +	int divisor;
> +	unsigned long flags;
> +
> +	/* Set IrDA speed */
> +	if (speed <= 115200) {
> +
> +		local_irq_save(flags);
> +
> +		/* SIR mode */
> +		if (si->pdata->transceiver_mode)
> +			si->pdata->transceiver_mode(si->dev, IR_SIRMODE);
> +
> +		/* Set SIR mode */
> +		uart_reg_out(UART3_MDR1, 1);
> +		uart_reg_out(UART3_EBLR, 1);
> +
> +		divisor = 48000000 / (16 * speed);	/* Base clock 48 MHz */
> +
> +		uart_reg_out(UART3_LCR, UART3_LCR_DIVEN);
> +		uart_reg_out(UART3_DLL, (divisor & 0xff));
> +		uart_reg_out(UART3_DLH, (divisor >> 8));
> +		uart_reg_out(UART3_LCR, 0x03);
> +
> +		uart_reg_out(UART3_MCR, 0);
> +
> +		local_irq_restore(flags);
> +	} else if (speed <= 1152000) {
> +
> +		local_irq_save(flags);
> +
> +		/* Set MIR mode, auto SIP */
> +		uart_reg_out(UART3_MDR1, UART3_MDR1_MIR |
> +				UART3_MDR1_SIP_AUTO);
> +
> +		uart_reg_out(UART3_EBLR, 2);
> +
> +		divisor = 48000000 / (41 * speed);	/* Base clock 48 MHz */
> +
> +		uart_reg_out(UART3_LCR, UART3_LCR_DIVEN);
> +		uart_reg_out(UART3_DLL, (divisor & 0xff));
> +		uart_reg_out(UART3_DLH, (divisor >> 8));
> +		uart_reg_out(UART3_LCR, 0x03);
> +
> +		if (si->pdata->transceiver_mode)
> +			si->pdata->transceiver_mode(si->dev, IR_MIRMODE);
> +
> +		local_irq_restore(flags);
> +	} else {
> +		local_irq_save(flags);
> +
> +		/* FIR mode */
> +		uart_reg_out(UART3_MDR1, UART3_MDR1_FIR |
> +				UART3_MDR1_SIP_AUTO);
> +
> +		if (si->pdata->transceiver_mode)
> +			si->pdata->transceiver_mode(si->dev, IR_FIRMODE);
> +
> +		local_irq_restore(flags);
> +	}
> +
> +	si->speed = speed;
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_PM
> +/*
> + * Suspend the IrDA interface.
> + */
> +static int omap_irda_suspend(struct platform_device *pdev, pm_message_t state)
> +{
> +	struct net_device *dev = platform_get_drvdata(pdev);
> +	struct omap_irda *si = dev->priv;
> +
> +	if (!dev)
> +		return 0;
> +
> +	if (si->open) {
> +		/*
> +		 * Stop the transmit queue
> +		 */
> +		netif_device_detach(dev);
> +		disable_irq(dev->irq);
> +		omap_irda_shutdown(si);
> +	}
> +	return 0;
> +}
> +
> +/*
> + * Resume the IrDA interface.
> + */
> +static int omap_irda_resume(struct platform_device *pdev)
> +{
> +	struct net_device *dev = platform_get_drvdata(pdev);
> +	struct omap_irda *si= dev->priv;
> +
> +	if (!dev)
> +		return 0;
> +
> +	if (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;
> +		}
> +
> +		omap_irda_startup(dev);
> +		omap_irda_set_speed(dev, si->speed);
> +		enable_irq(dev->irq);
> +
> +		/*
> +		 * This automatically wakes up the queue
> +		 */
> +		netif_device_attach(dev);
> +	}
> +
> +	return 0;
> +}
> +#else
> +#define omap_irda_suspend	NULL
> +#define omap_irda_resume	NULL
> +#endif
> +
> +static int omap_irda_probe(struct platform_device *pdev)
> +{
> +	struct net_device *dev;
> +	struct omap_irda *si;
> +	struct omap_irda_config *pdata = pdev->dev.platform_data;
> +	unsigned int baudrate_mask;
> +	int err = 0;
> +	int irq = NO_IRQ;
> +
> +	if (!pdata) {
> +		printk(KERN_ERR "IrDA Platform data not supplied\n");
> +		return -ENOENT;
> +	}
> +
> +	if (!pdata->rx_channel || !pdata->tx_channel) {
> +		printk(KERN_ERR "IrDA invalid rx/tx channel value\n");
> +		return -ENOENT;
> +	}
I see that rx_channel and tx_channel are part of your omap_irda_config, which
seems to be a platform specific structure. However, DMA channels are
architecture specific and could be removed from this structure, isn't it ?

> +
> +	irq = platform_get_irq(pdev, 0);
> +	if (irq <= 0) {
> +		printk(KERN_WARNING "no irq for IrDA\n");
> +		return -ENOENT;
> +	}
> +
> +	dev = alloc_irdadev(sizeof(struct omap_irda));
> +	if (!dev)
> +		goto err_mem_1;
> +
> +
> +	si = dev->priv;
> +	si->dev = &pdev->dev;
> +	si->pdata = pdata;
> +
> +	dev->hard_start_xmit	= omap_irda_hard_xmit;
> +	dev->open		= omap_irda_start;
> +	dev->stop		= omap_irda_stop;
> +	dev->do_ioctl		= omap_irda_ioctl;
> +	dev->get_stats		= omap_irda_stats;
> +	dev->irq		= irq;
> +
> +	irda_init_max_qos_capabilies(&si->qos);
> +
> +	baudrate_mask = 0;
> +	if (si->pdata->transceiver_cap & IR_SIRMODE)
> +		baudrate_mask |= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
> +	if (si->pdata->transceiver_cap & IR_MIRMODE)
> +		baudrate_mask |= IR_57600 | IR_1152000;
> +	if (si->pdata->transceiver_cap & IR_FIRMODE)
> +		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);
> +
> +	/* Any better way to avoid this? No. */
> +	if (machine_is_omap_h3() || machine_is_omap_h4())
> +		INIT_WORK(&si->pdata->gpio_expa, NULL, NULL);
What is this for ?

> +	err = register_netdev(dev);
> +	if (!err)
> +		platform_set_drvdata(pdev, dev);
> +	else
> +		free_netdev(dev);
> +
> +err_mem_1:
> +	return err;
> +}
> +
> +static int omap_irda_remove(struct platform_device *pdev)
> +{
> +	struct net_device *dev = platform_get_drvdata(pdev);
> +
> +	if (pdev) {
> +		unregister_netdev(dev);
> +		free_netdev(dev);
> +	}
> +	return 0;
> +}
> +
> +static struct platform_driver omapir_driver = {
> +	.probe		= omap_irda_probe,
> +	.remove		= omap_irda_remove,
> +	.suspend	= omap_irda_suspend,
> +	.resume		= omap_irda_resume,
> +	.driver		= {
> +		.name	= "omapirda",
> +	},
> +};
> +
> +static char __initdata banner[] = KERN_INFO "OMAP IrDA driver initializing\n";
> +
> +static int __init omap_irda_init(void)
> +{
> +	printk(banner);
> +	return platform_driver_register(&omapir_driver);
> +}
> +
> +static void __exit omap_irda_exit(void)
> +{
> +	platform_driver_unregister(&omapir_driver);
> +}
> +
> +module_init(omap_irda_init);
> +module_exit(omap_irda_exit);
> +
> +MODULE_AUTHOR("MontaVista");
> +MODULE_DESCRIPTION("OMAP IrDA Driver");
> +MODULE_LICENSE("GPL");
> +
> -- 
> 1.3.3

Cheers,
Samuel.

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
Komal Shah | 11 Aug 2006 11:20
Picon
Favicon

Re: [PATCH] OMAP: Add support for IrDA driver

--- Samuel Ortiz <samuel@...> wrote:

> Hi Komal,
> 
> On Mon, Aug 07, 2006 at 02:42:33PM +0530, Komal Shah wrote:
> > Samuel/Tony,
> > 
> > I have attached the OMAP IrDA patch for OMAP1610/1710 and OMAP242x
> > for review. See that for IrDA driver to work on H3 and H4, we need
> > gpio-expander functions to go in mainline, but it can work on H2.
> Overall the patch looks good, I have some comments though. See below:

Thanx for the review.

> > +
> > +#define UART3_IIR_TX_STATUS		(1 << 5)
> > +#define UART3_IIR_EOF			(0x80)
> > +
> > +#define IS_FIR(si)		((si)->speed >= 4000000)
> > +#define IRDA_FRAME_SIZE_LIMIT	4096
> You should use IRDA_SKB_MAX_MTU and IRDA_SIR_MAX_FRAME for
> respectively your
> max Rx and Tx sizes.

I will update this and to all the places where FRAME_SIZE_LIMIT was
used as default ro rx and tx sizes.

> 
> 
> > +static int rx_state = 0;	/* RX state for IOCTL */
> rx_state could probably be part of omap_irda.

I think this can be removed all together, as it remains zero only.

> 
> 
> > +struct omap_irda {
> > +	unsigned char open;
> > +	int speed;		/* Current IrDA speed */
> > +	int newspeed;
> > +
> > +	struct net_device_stats stats;
> > +	struct irlap_cb *irlap;
> > +	struct qos_info qos;
> > +
> > +	int rx_dma_channel;
> > +	int tx_dma_channel;
> > +
> > +	dma_addr_t rx_buf_dma_phys;	/* Physical address of RX DMA buffer
> */
> > +	dma_addr_t tx_buf_dma_phys;	/* Physical address of TX DMA buffer
> */
> > +
> > +	void *rx_buf_dma_virt;		/* Virtual address of RX DMA buffer */
> > +	void *tx_buf_dma_virt;		/* Virtual address of TX DMA buffer */
> > +
> > +	struct device *dev;
> > +	struct omap_irda_config *pdata;
> You forgot to define omap_irda_config.
> Same thing for IR_SEL, IR_SIRMODE, IR_FIRMODE and IR_MIRMODE.

Check include/asm-arm/arch-omap/irda.h

> > +static void omap_irda_rx_dma_callback(int lch, u16 ch_status, void
> *data)
> > +{
> > +	struct net_device *dev = data;
> > +	struct omap_irda *si = dev->priv;
> A detail here, but I think that "si" for a variable name is a bit
> meaningless. 

Ok. I will update this.

> > +
> > +	status = uart_reg_in(UART3_SFLSR);	/* Take a frame status */
> > +
> > +	if (status != 0) {	/* Bad frame? */
> > +		si->stats.rx_frame_errors++;
> > +		uart_reg_in(UART3_RESUME);
> > +	} else {
> > +		/* We got a frame! */
> > +		skb = alloc_skb(IRDA_FRAME_SIZE_LIMIT, GFP_ATOMIC);
> Use dev_alloc_skb() for allocating RX packets.

Ok. Done

> > +
> > +	case SIOCGRECEIVING:
> > +		rq->ifr_receiving = rx_state;
> > +		break;
> rx_state is always set to 0, so this looks a bit useless.

I can remove the "case SIOCGRECEIVING" altogether then.

> > +
> > +	if (!pdata->rx_channel || !pdata->tx_channel) {
> > +		printk(KERN_ERR "IrDA invalid rx/tx channel value\n");
> > +		return -ENOENT;
> > +	}
> I see that rx_channel and tx_channel are part of your
> omap_irda_config, which
> seems to be a platform specific structure. However, DMA channels are
> architecture specific and could be removed from this structure, isn't
> it ?

Correct. Then I have to think passing those information using either
device resources or revert back to #ifdefers in omap-ir.c. Any
suggestions?

> > +
> > +	irda_qos_bits_to_value(&si->qos);
> > +
> > +	/* Any better way to avoid this? No. */
> > +	if (machine_is_omap_h3() || machine_is_omap_h4())
> > +		INIT_WORK(&si->pdata->gpio_expa, NULL, NULL);
> What is this for ?

As H3 and H4 platforms uses gpio_expander (through I2C) for selecting
between IrDA and GPS Module, and that code is being called from IRQ
context, as you know that gpip_expander code ultimately leades to I2C
code and which can sleep.

See these links:

http://linux.omap.com/pipermail/linux-omap-open-source/2005-December/thread.html
http://linux.omap.com/pipermail/linux-omap-open-source/2005-December/005996.html
http://linux.omap.com/pipermail/linux-omap-open-source/2005-December/006019.html

---Komal Shah
http://komalshah.blogspot.com/

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
Jon K Hellan | 13 Aug 2006 23:52
Picon
Favicon

Re: SIR problem with 2.6.17 - probably PNP related

On Tue, 2006-07-18 at 21:15 +0200, Jon K Hellan wrote:
> SIR stopped working for me when I upgraded my Debian sid laptop from
> 2.6.16 to 2.6.17. I can easily work around this by running FIR
> instead. But it would be a shame to lose SIR, as it usually has been
> the easiest mode to set up.
> 
> You can find the long story in
> "http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=377539". Complete
> logs and strace traces are there.
> 
> The short story is that PNP seems to be shutting down the serial
> device I'm using for IRDA. 

I've verified that it was PnP that introduced the problem. I built a
driver version that included the power management changes since 2.6.16,
but not PnP. SIR worked.

> Here's part of the dmesg log:
> 
> nsc_ircc_pnp_probe() : From PnP, found firbase 0x2F8 ; irq 3 ; dma 3.
> nsc-ircc, chip->init
> nsc-ircc, Found chip at base=0x02e
> nsc-ircc, driver loaded (Dag Brattli)
> nsc_ircc_open(), can't get iobase of 0x2f8

Here, PNP is trying to activate the chip. It is trying to initialize it
for FIR and for some reason it is failing. I'm not sure why it fails,
but 

  irattach irda0 none -s

also fails unless I first do

  setserial /dev/ttyS1 uart none

> nsc-ircc, Found chip at base=0x02e
> nsc-ircc, driver loaded (Dag Brattli)
> nsc_ircc_open(), can't get iobase of 0x2f8

Trying again :-)

> pnp: Device 00:14 disabled.

This message comes from pnp_stop_dev. This must be pnp cleaning up after
the failed attempt to activate. As a side effect, this makes /dev/ttyS1
unusable for SIR. Very strange.

Anyway, since 2.6.17, FIR is a bit easier to set up on my system. But
not as easy as SIR used to be.

Is it possible to get rid of the need to call setserial?

In an ideal world, PnP would work. But to be really helpful to the user,
he/she shouldn't have to figure out if PnP was able to set up FIR. Would
it be possible to make irattach able to figure out if FIR was
configured, and fall back to SIR if it wasn't?

Jon

Jon Kåre Hellan, Trondheim, Norway

> and when I run 'irattach /dev/ttyS1 -s', this gets written to
> /var/log/messages:
> 
> Jul  9 21:58:52 localhost kernel: ttyS1: LSR safety check engaged!
> Jul  9 21:58:52 localhost irattach: Stopping device /dev/ttyS1
> Jul  9 21:58:52 localhost irattach: ioctl(SIOCGIFFLAGS): No such device
> Jul  9 21:58:52 localhost irattach: exiting ...
> 
> PnP support for nsc-ircc is new in 2.6.17.
> The laptop is an IBM T23.

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
irda-users mailing list
irda-users <at> lists.sourceforge.net
http://lists.sourceforge.net/lists/listinfo/irda-users
Samuel Ortiz | 15 Aug 2006 07:53

Re: [stir4200]

Hi Jean-Bastien

On Fri, Jul 21, 2006 at 10:56:49AM +0200, Montes Jean-Bastien wrote:
> 15:09:16.209276 i:cmd  > ca=fc pf=1 nr=1 ns=1 LM slsap=17 dlsap=00
> GET_VALUE_BY_CLASS: "IrDA:IrCOMM" "IrDA:TinyTP:LsapSel" (37) 
> 15:09:16.228533 i:rsp  < ca=fc pf=1 nr=2 ns=1 LM slsap=00 dlsap=17
> GET_VALUE_BY_CLASS: Success Integer: 02 (15) 
> 15:09:16.229784 i:cmd  > ca=fc pf=1 nr=2 ns=2 LM slsap=17 dlsap=00 DISC
> (6) 
> 15:09:16.258531 rr:rsp < ca=fc pf=1 nr=3 (2) 
> 15:09:16.258928 i:cmd  > ca=fc pf=1 nr=2 ns=3 LM slsap=18 dlsap=02
> CONN_CMD TTP credits=16 (7) 
> 15:09:16.278490 i:rsp  < ca=fc pf=1 nr=4 ns=2 LM slsap=02 dlsap=18
> CONN_RSP TTP credits=1 
> 	IrCOMM Data Rate=9600 Data Format=03 (17) 
Here it seems that you establish an IrCOMM link at 9600 bps. Do you see the
same with your serial dongle ?

Cheers,
Samuel.

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
Samuel Ortiz | 15 Aug 2006 08:11

Re: irda_extract_integer: invalid parameter length! Expected 1 bytes, but value had 2 bytes!

Hi,

On Tue, Jul 25, 2006 at 02:06:01AM +0000, Alun Wang wrote:
> Hi, All,
>  
>  I am now writing a SIR driver for the UART (which supports both UART and serial
> infrared capability) in my mx31ads board. When the driver is loaded and issuing
> command "ifconfig irda0 up" to bring up the irda0, it can discovery the other
> irda device nearby, however says:
>     irda_extract_integer: invalid parameter length! Expected 1 bytes, but value
> had 2 bytes!
What is the discovered device ? It could be that he discovered device is
sending crappy frames, so have you tried with different devices ?

> And when trying to communicate data with other device, it always fails and reply
> with such message.
If your board cannot extract e.g. a connection parameter from the other end,
then the connection will most likely fail.

Cheers,
Samuel.

>  
> Does anyone have a good idea for this? Your reply are very appreciated.
>  
>  
> Best regards!
>   
> AlunWang
> 
> 
> -------------------------------------------------------------------------
> Take Surveys. Earn Cash. Influence the Future of IT
> Join SourceForge.net's Techsay panel and you'll get the chance to share your
> opinions on IT & business topics through brief surveys -- and earn cash
> http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
> _______________________________________________
> irda-users mailing list
> irda-users@...
> http://lists.sourceforge.net/lists/listinfo/irda-users

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
Komal Shah | 16 Aug 2006 11:43
Picon
Favicon

[PATCH] OMAP: Add support for IrDA driver #2

Samuel/Tony,

I have attached the updated OMAP IrDA patch for OMAP1610/1710 and OMAP242x
for review. See that for IrDA driver to work on H3 and H4, we need
gpio-expander functions to go in mainline, but it can work on H2.

I have addressed your review comments as per the following thread,

http://lkml.org/lkml/2006/8/10/556 

except for dma channels.

---Komal Shah
http://komalshah.blogspot.com

--

-- 
http://www.fastmail.fm - Send your email first class

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
irda-users mailing list
irda-users@...
http://lists.sourceforge.net/lists/listinfo/irda-users
Zert | 23 Aug 2006 17:19
Picon
Gravatar

test (please, no reply)

test

--

-- 
Best regards
Maxim "Zert" Treskin
E-mail: zerthurd@...
JID: Zert@...

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
Samuel Ortiz | 28 Aug 2006 05:54

Re: [PATCH] OMAP: Add support for IrDA driver #2

Hi Komal,

On Wed, Aug 16, 2006 at 03:13:10PM +0530, Komal Shah wrote:
> Samuel/Tony,
> 
> I have attached the updated OMAP IrDA patch for OMAP1610/1710 and OMAP242x
> for review. See that for IrDA driver to work on H3 and H4, we need
> gpio-expander functions to go in mainline, but it can work on H2.
> 
> I have addressed your review comments as per the following thread,
This looks good to me.
Acked-by: Samuel Ortiz <samuel@...>

Cheers,
Samuel.

> http://lkml.org/lkml/2006/8/10/556 
> 
> except for dma channels.
> 
> ---Komal Shah
> http://komalshah.blogspot.com
> 
> -- 
> http://www.fastmail.fm - Send your email first class
> 

> From nobody Mon Sep 17 00:00:00 2001
> From: Komal Shah <komal_shah802003@...>
> Date: Wed, 16 Aug 2006 20:36:29 +0530
> Subject: [PATCH] OMAP: Add support for IrDA driver #2
> 
> Patch adds IrDA driver support for Texas Instruments OMAP
> (http://www.ti.com/omap) based processors like OMAP1610/1710 and OMAP242x.
> 
> Signed-off-by: Komal Shah <komal_shah802003@...>
> 
> ---
> 
>  drivers/net/irda/Kconfig   |   10 
>  drivers/net/irda/Makefile  |    1 
>  drivers/net/irda/omap-ir.c |  904 ++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 915 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/net/irda/omap-ir.c
> 
> 27da3dbdbd7eb4f22237e4e452d08df929010c7c
> diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
> index e9e6d99..88f2c66 100644
> --- a/drivers/net/irda/Kconfig
> +++ b/drivers/net/irda/Kconfig
>  <at>  <at>  -432,5 +432,15  <at>  <at>  config MCS_FIR
>  	  To compile it as a module, choose M here: the module will be called
>  	  mcs7780.
>  
> +config OMAP_IR
> +	tristate "OMAP IrDA(SIR/MIR/FIR)"
> +	depends on IRDA && ARCH_OMAP
> +	select GPIOEXPANDER_OMAP if (MACH_OMAP_H3 || MACH_OMAP_H4)
> +        help
> +	  Say Y here if you want to build support for the Texas Instruments
> +	  OMAP IrDA device driver, which supports SIR/MIR/FIR. This driver
> +	  relies on platform specific helper routines so available capabilities
> +	  may vary from one OMAP target to another.
> +
>  endmenu
>  
> diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile
> index 5be09f1..89c6389 100644
> --- a/drivers/net/irda/Makefile
> +++ b/drivers/net/irda/Makefile
>  <at>  <at>  -20,6 +20,7  <at>  <at>  obj-$(CONFIG_VLSI_FIR)		+= vlsi_ir.o
>  obj-$(CONFIG_VIA_FIR)		+= via-ircc.o
>  obj-$(CONFIG_PXA_FICP)	        += pxaficp_ir.o
>  obj-$(CONFIG_MCS_FIR)	        += mcs7780.o
> +obj-$(CONFIG_OMAP_IR)		+= omap-ir.o
>  # Old dongle drivers for old SIR drivers
>  obj-$(CONFIG_ESI_DONGLE_OLD)		+= esi.o
>  obj-$(CONFIG_TEKRAM_DONGLE_OLD)	+= tekram.o
> diff --git a/drivers/net/irda/omap-ir.c b/drivers/net/irda/omap-ir.c
> new file mode 100644
> index 0000000..e3dc0d6
> --- /dev/null
> +++ b/drivers/net/irda/omap-ir.c
>  <at>  <at>  -0,0 +1,904  <at>  <at> 
> +/*
> + * BRIEF MODULE DESCRIPTION
> + *
> + *	Infra-red driver for the OMAP1610-H2 and OMAP1710-H3 and H4 Platforms
> + *	  (SIR/MIR/FIR modes)
> + *	  (based on omap-sir.c)
> + *
> + * Copyright 2003 MontaVista Software Inc.
> + * Author: MontaVista Software, Inc.
> + *	   source@...
> + *
> + * Copyright 2004 Texas Instruments.
> + *
> + *  This program is free software; you can redistribute	 it and/or modify it
> + *  under  the terms of	 the GNU General  Public License as published by the
> + *  Free Software Foundation;  either version 2 of the	License, or (at your
> + *  option) any later version.
> + *
> + *  THIS  SOFTWARE  IS PROVIDED	  ``AS	IS'' AND   ANY	EXPRESS OR IMPLIED
> + *  WARRANTIES,	  INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
> + *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
> + *  NO	EVENT  SHALL   THE AUTHOR  BE	 LIABLE FOR ANY	  DIRECT, INDIRECT,
> + *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + *  NOT LIMITED	  TO, PROCUREMENT OF  SUBSTITUTE GOODS	OR SERVICES; LOSS OF
> + *  USE, DATA,	OR PROFITS; OR	BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
> + *  ANY THEORY OF LIABILITY, WHETHER IN	 CONTRACT, STRICT LIABILITY, OR TORT
> + *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
> + *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + *
> + *  You should have received a copy of the  GNU General Public License along
> + *  with this program; if not, write  to the Free Software Foundation, Inc.,
> + *  675 Mass Ave, Cambridge, MA 02139, USA.
> + *
> + Modifications:
> + Feb 2004, Texas Instruments
> + - Ported to 2.6 kernel (Feb 2004).
> + *
> + Apr 2004, Texas Instruments
> + - Added support for H3 (Apr 2004).
> + Nov 2004, Texas Instruments
> + - Added support for Power Management.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/types.h>
> +#include <linux/init.h>
> +#include <linux/errno.h>
> +#include <linux/netdevice.h>
> +#include <linux/slab.h>
> +#include <linux/rtnetlink.h>
> +#include <linux/interrupt.h>
> +#include <linux/delay.h>
> +#include <linux/ioport.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/platform_device.h>
> +#include <linux/i2c.h>
> +
> +#include <net/irda/irda.h>
> +#include <net/irda/irmod.h>
> +#include <net/irda/wrapper.h>
> +#include <net/irda/irda_device.h>
> +
> +#include <asm/irq.h>
> +#include <asm/io.h>
> +#include <asm/hardware.h>
> +#include <asm/serial.h>
> +#include <asm/mach-types.h>
> +#include <asm/dma.h>
> +#include <asm/arch/mux.h>
> +#include <asm/arch/gpio.h>
> +#include <asm/arch/irda.h>
> +
> +#define UART3_EFR_EN			(1 << 4)
> +#define UART3_MCR_EN_TCR_TLR		(1 << 6)
> +
> +#define UART3_LCR_WL_8			(3 << 0)
> +#define UART3_LCR_SP2			(1 << 2)
> +#define UART3_LCR_DIVEN			(1 << 7)
> +
> +#define UART3_FCR_FIFO_EN		(1 << 0)
> +#define UART3_FCR_FIFO_RX		(1 << 1)
> +#define UART3_FCR_FIFO_TX		(1 << 2)
> +#define UART3_FCR_FIFO_DMA1		(1 << 3)
> +#define UART3_FCR_FIFO_TX_TRIG16	(1 << 4)
> +#define UART3_FCR_FIFO_RX_TRIG16	(1 << 6)
> +#define UART3_FCR_CONFIG	(\
> +		UART3_FCR_FIFO_EN | UART3_FCR_FIFO_RX	|\
> +		UART3_FCR_FIFO_TX | UART3_FCR_FIFO_DMA1 |\
> +		UART3_FCR_FIFO_TX_TRIG16		|\
> +		UART3_FCR_FIFO_RX_TRIG16)
> +
> +#define UART3_SCR_TX_TRIG1		(1 << 6)
> +#define UART3_SCR_RX_TRIG1		(1 << 7)
> +
> +#define UART3_MDR1_RESET		(0x07)
> +#define UART3_MDR1_SIR			(1 << 0)
> +#define UART3_MDR1_MIR			(4 << 0)
> +#define UART3_MDR1_FIR			(5 << 0)
> +#define UART3_MDR1_SIP_AUTO		(1 << 6)
> +
> +#define UART3_MDR2_TRIG1		(0 << 1)
> +#define UART3_MDR2_IRTX_UNDERRUN	(1 << 0)
> +
> +#define UART3_ACERG_TX_UNDERRUN_DIS	(1 << 4)
> +#define UART3_ACERG_SD_MODE_LOW		(1 << 6)
> +#define UART3_ACERG_DIS_IR_RX		(1 << 5)
> +
> +#define UART3_IER_EOF			(1 << 5)
> +#define UART3_IER_CTS			(1 << 7)
> +
> +#define UART3_IIR_TX_STATUS		(1 << 5)
> +#define UART3_IIR_EOF			(0x80)
> +
> +#define IS_FIR(omap_ir)		((omap_ir)->speed >= 4000000)
> +
> +struct omap_irda {
> +	unsigned char open;
> +	int speed;		/* Current IrDA speed */
> +	int newspeed;
> +
> +	struct net_device_stats stats;
> +	struct irlap_cb *irlap;
> +	struct qos_info qos;
> +
> +	int rx_dma_channel;
> +	int tx_dma_channel;
> +
> +	dma_addr_t rx_buf_dma_phys;	/* Physical address of RX DMA buffer */
> +	dma_addr_t tx_buf_dma_phys;	/* Physical address of TX DMA buffer */
> +
> +	void *rx_buf_dma_virt;		/* Virtual address of RX DMA buffer */
> +	void *tx_buf_dma_virt;		/* Virtual address of TX DMA buffer */
> +
> +	struct device *dev;
> +	struct omap_irda_config *pdata;
> +};
> +
> +static void inline uart_reg_out(int idx, u8 val)
> +{
> +	omap_writeb(val, idx);
> +}
> +
> +static u8 inline uart_reg_in(int idx)
> +{
> +	u8 b = omap_readb(idx);
> +	return b;
> +}
> +
> +/* forward declarations */
> +extern void omap_stop_dma(int lch);
> +static int omap_irda_set_speed(struct net_device *dev, int speed);
> +
> +static void omap_irda_start_rx_dma(struct omap_irda *omap_ir)
> +{
> +	/* Configure DMA */
> +	omap_set_dma_src_params(omap_ir->rx_dma_channel, 0x3, 0x0,
> +				omap_ir->pdata->src_start,
> +				0, 0);
> +
> +	omap_enable_dma_irq(omap_ir->rx_dma_channel, 0x01);
> +
> +	omap_set_dma_dest_params(omap_ir->rx_dma_channel, 0x0, 0x1,
> +				omap_ir->rx_buf_dma_phys,
> +				0, 0);
> +
> +	omap_set_dma_transfer_params(omap_ir->rx_dma_channel, 0x0,
> +				IRDA_SKB_MAX_MTU, 0x1,
> +				0x0, omap_ir->pdata->rx_trigger, 0);
> +
> +	omap_start_dma(omap_ir->rx_dma_channel);
> +}
> +
> +static void omap_start_tx_dma(struct omap_irda *omap_ir, int size)
> +{
> +	/* Configure DMA */
> +	omap_set_dma_dest_params(omap_ir->tx_dma_channel, 0x03, 0x0,
> +				omap_ir->pdata->dest_start, 0, 0);
> +
> +	omap_enable_dma_irq(omap_ir->tx_dma_channel, 0x01);
> +
> +	omap_set_dma_src_params(omap_ir->tx_dma_channel, 0x0, 0x1,
> +				omap_ir->tx_buf_dma_phys,
> +				0, 0);
> +
> +	omap_set_dma_transfer_params(omap_ir->tx_dma_channel, 0x0, size, 0x1,
> +				0x0, omap_ir->pdata->tx_trigger, 0);
> +
> +	/* Start DMA */
> +	omap_start_dma(omap_ir->tx_dma_channel);
> +}
> +
> +/* DMA RX callback - normally, we should not go here,
> + * it calls only if something is going wrong
> + */
> +static void omap_irda_rx_dma_callback(int lch, u16 ch_status, void *data)
> +{
> +	struct net_device *dev = data;
> +	struct omap_irda *omap_ir = netdev_priv(dev);
> +
> +	printk(KERN_ERR "RX Transfer error or very big frame\n");
> +
> +	/* Clear interrupts */
> +	uart_reg_in(UART3_IIR);
> +
> +	omap_ir->stats.rx_frame_errors++;
> +
> +	uart_reg_in(UART3_RESUME);
> +
> +	/* Re-init RX DMA */
> +	omap_irda_start_rx_dma(omap_ir);
> +}
> +
> +/* DMA TX callback - calling when frame transfer has been finished */
> +static void omap_irda_tx_dma_callback(int lch, u16 ch_status, void *data)
> +{
> +	struct net_device *dev = data;
> +	struct omap_irda *omap_ir = netdev_priv(dev);
> +
> +	/*Stop DMA controller */
> +	omap_stop_dma(omap_ir->tx_dma_channel);
> +}
> +
> +/*
> + * Set the IrDA communications speed.
> + * Interrupt have to be disabled here.
> + */
> +static int omap_irda_startup(struct net_device *dev)
> +{
> +	struct omap_irda *omap_ir = netdev_priv(dev);
> +
> +	/* FIXME: use clk_* apis for UART3 clock*/
> +	/* Enable UART3 clock and set UART3 to IrDA mode */
> +	if (machine_is_omap_h2() || machine_is_omap_h3())
> +		omap_writel(omap_readl(MOD_CONF_CTRL_0) | (1 << 31) | (1 << 15),
> +				MOD_CONF_CTRL_0);
> +
> +	/* Only for H2?
> +	 */
> +	if (omap_ir->pdata->transceiver_mode && machine_is_omap_h2()) {
> +		/* Is it select_irda on H2 ? */
> +		omap_writel(omap_readl(FUNC_MUX_CTRL_A) | 7,
> +					FUNC_MUX_CTRL_A);
> +		omap_ir->pdata->transceiver_mode(omap_ir->dev, IR_SIRMODE);
> +	}
> +
> +	uart_reg_out(UART3_MDR1, UART3_MDR1_RESET);	/* Reset mode */
> +
> +	/* Clear DLH and DLL */
> +	uart_reg_out(UART3_LCR, UART3_LCR_DIVEN);
> +
> +	uart_reg_out(UART3_DLL, 0);
> +	uart_reg_out(UART3_DLH, 0);
> +	uart_reg_out(UART3_LCR, 0xbf);	/* FIXME: Add #define */
> +
> +	uart_reg_out(UART3_EFR, UART3_EFR_EN);
> +	uart_reg_out(UART3_LCR, UART3_LCR_DIVEN);
> +
> +	/* Enable access to UART3_TLR and UART3_TCR registers */
> +	uart_reg_out(UART3_MCR, UART3_MCR_EN_TCR_TLR);
> +
> +	uart_reg_out(UART3_SCR, 0);
> +	/* Set Rx trigger to 1 and Tx trigger to 1 */
> +	uart_reg_out(UART3_TLR, 0);
> +
> +	/* Set LCR to 8 bits and 1 stop bit */
> +	uart_reg_out(UART3_LCR, 0x03);
> +
> +	/* Clear RX and TX FIFO and enable FIFO */
> +	/* Use DMA Req for transfers */
> +	uart_reg_out(UART3_FCR, UART3_FCR_CONFIG);
> +
> +	uart_reg_out(UART3_MCR, 0);
> +
> +	uart_reg_out(UART3_SCR, UART3_SCR_TX_TRIG1 |
> +			UART3_SCR_RX_TRIG1);
> +
> +	/* Enable UART3 SIR Mode,(Frame-length method to end frames) */
> +	uart_reg_out(UART3_MDR1, UART3_MDR1_SIR);
> +
> +	/* Set Status FIFO trig to 1 */
> +	uart_reg_out(UART3_MDR2, 0);
> +
> +	/* Enables RXIR input */
> +	/* and disable TX underrun */
> +	/* SEND_SIP pulse */
> +	uart_reg_out(UART3_ACREG, UART3_ACERG_SD_MODE_LOW |
> +			UART3_ACERG_TX_UNDERRUN_DIS);
> +
> +	/* Enable EOF Interrupt only */
> +	uart_reg_out(UART3_IER, UART3_IER_CTS | UART3_IER_EOF);
> +
> +	/* Set Maximum Received Frame size to 2048 bytes */
> +	uart_reg_out(UART3_RXFLL, 0x00);
> +	uart_reg_out(UART3_RXFLH, 0x08);
> +
> +	uart_reg_in(UART3_RESUME);
> +
> +	return 0;
> +}
> +
> +static int omap_irda_shutdown(struct omap_irda *omap_ir)
> +{
> +	unsigned long flags;
> +
> +	local_irq_save(flags);
> +
> +	/* Disable all UART3 Interrupts */
> +	uart_reg_out(UART3_IER, 0);
> +
> +	/* Disable UART3 and disable baud rate generator */
> +	uart_reg_out(UART3_MDR1, UART3_MDR1_RESET);
> +
> +	/* set SD_MODE pin to high and Disable RX IR */
> +	uart_reg_out(UART3_ACREG, (UART3_ACERG_DIS_IR_RX |
> +			~(UART3_ACERG_SD_MODE_LOW)));
> +
> +	/* Clear DLH and DLL */
> +	uart_reg_out(UART3_LCR, UART3_LCR_DIVEN);
> +	uart_reg_out(UART3_DLL, 0);
> +	uart_reg_out(UART3_DLH, 0);
> +
> +	local_irq_restore(flags);
> +
> +	return 0;
> +}
> +
> +static irqreturn_t
> +omap_irda_irq(int irq, void *dev_id, struct pt_regs *hw_regs)
> +{
> +	struct net_device *dev = dev_id;
> +	struct omap_irda *omap_ir = netdev_priv(dev);
> +	struct sk_buff *skb;
> +
> +	u8 status;
> +	int w = 0;
> +
> +	/* Clear EOF interrupt */
> +	status = uart_reg_in(UART3_IIR);
> +
> +	if (status & UART3_IIR_TX_STATUS) {
> +		u8 mdr2 = uart_reg_in(UART3_MDR2);
> +		if (mdr2 & UART3_MDR2_IRTX_UNDERRUN)
> +			printk(KERN_ERR "IrDA Buffer underrun error\n");
> +
> +		omap_ir->stats.tx_packets++;
> +
> +		if (omap_ir->newspeed) {
> +			omap_irda_set_speed(dev, omap_ir->newspeed);
> +			omap_ir->newspeed = 0;
> +		}
> +
> +		netif_wake_queue(dev);
> +		if (!(status & UART3_IIR_EOF))
> +			return IRQ_HANDLED;
> +	}
> +
> +	/* Stop DMA and if there are no errors, send frame to upper layer */
> +	omap_stop_dma(omap_ir->rx_dma_channel);
> +
> +	status = uart_reg_in(UART3_SFLSR);	/* Take a frame status */
> +
> +	if (status != 0) {	/* Bad frame? */
> +		omap_ir->stats.rx_frame_errors++;
> +		uart_reg_in(UART3_RESUME);
> +	} else {
> +		/* We got a frame! */
> +		skb = dev_alloc_skb(IRDA_SKB_MAX_MTU);
> +
> +		if (!skb) {
> +			printk(KERN_ERR "omap_sir: out of memory for RX SKB\n");
> +			return IRQ_HANDLED;
> +		}
> +		/*
> +		 * Align any IP headers that may be contained
> +		 * within the frame.
> +		 */
> +
> +		skb_reserve(skb, 1);
> +
> +		w = OMAP_DMA_CDAC_REG(omap_ir->rx_dma_channel);
> +
> +		if (cpu_is_omap16xx())
> +			w -= OMAP1_DMA_CDSA_L_REG(omap_ir->rx_dma_channel);
> +		if (cpu_is_omap24xx())
> +			w -= OMAP2_DMA_CDSA_REG(omap_ir->rx_dma_channel);
> +
> +		if (!IS_FIR(omap_ir))
> +			/* Copy DMA buffer to skb */
> +			memcpy(skb_put(skb, w - 2), omap_ir->rx_buf_dma_virt,
> +					w - 2);
> +		else
> +			/* Copy DMA buffer to skb */
> +			memcpy(skb_put(skb, w - 4), omap_ir->rx_buf_dma_virt,
> +					w - 4);
> +
> +		skb->dev = dev;
> +		skb->mac.raw = skb->data;
> +		skb->protocol = htons(ETH_P_IRDA);
> +		omap_ir->stats.rx_packets++;
> +		omap_ir->stats.rx_bytes += skb->len;
> +		netif_receive_skb(skb);	/* Send data to upper level */
> +	}
> +
> +	/* Re-init RX DMA */
> +	omap_irda_start_rx_dma(omap_ir);
> +
> +	dev->last_rx = jiffies;
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int omap_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
> +{
> +	struct omap_irda *omap_ir = netdev_priv(dev);
> +	int speed = irda_get_next_speed(skb);
> +	int mtt = irda_get_mtt(skb);
> +	int xbofs = irda_get_next_xbofs(skb);
> +
> +
> +	/*
> +	 * 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 != omap_ir->speed && speed != -1)
> +		omap_ir->newspeed = speed;
> +
> +	if (xbofs) /* Set number of addtional BOFS */
> +		uart_reg_out(UART3_EBLR, xbofs + 1);
> +
> +	/*
> +	 * If this is an empty frame, we can bypass a lot.
> +	 */
> +	if (skb->len == 0) {
> +		if (omap_ir->newspeed) {
> +			omap_ir->newspeed = 0;
> +			omap_irda_set_speed(dev, speed);
> +		}
> +		dev_kfree_skb(skb);
> +		return 0;
> +	}
> +
> +	netif_stop_queue(dev);
> +
> +	/* Copy skb data to DMA buffer */
> +	memcpy(omap_ir->tx_buf_dma_virt, skb->data, skb->len);
> +
> +	/* Copy skb data to DMA buffer */
> +	omap_ir->stats.tx_bytes += skb->len;
> +
> +	/* Set frame length */
> +	uart_reg_out(UART3_TXFLL, (skb->len & 0xff));
> +	uart_reg_out(UART3_TXFLH, (skb->len >> 8));
> +
> +	if (mtt > 1000)
> +		mdelay(mtt / 1000);
> +	else
> +		udelay(mtt);
> +
> +	/* Start TX DMA transfer */
> +	omap_start_tx_dma(omap_ir, skb->len);
> +
> +	/* We can free skb now because it's already in DMA buffer */
> +	dev_kfree_skb(skb);
> +
> +	dev->trans_start = jiffies;
> +
> +	return 0;
> +}
> +
> +static int
> +omap_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)
> +{
> +	struct if_irda_req *rq = (struct if_irda_req *)ifreq;
> +	struct omap_irda *omap_ir = netdev_priv(dev);
> +	int ret = -EOPNOTSUPP;
> +
> +
> +	switch (cmd) {
> +	case SIOCSBANDWIDTH:
> +		if (capable(CAP_NET_ADMIN)) {
> +			/*
> +			 * We are unable to set the speed if the
> +			 * device is not running.
> +			 */
> +			if (omap_ir->open)
> +				ret = omap_irda_set_speed(dev,
> +						rq->ifr_baudrate);
> +			else {
> +				printk(KERN_ERR "omap_ir: SIOCSBANDWIDTH:"
> +						" !netif_running\n");
> +				ret = 0;
> +			}
> +		}
> +		break;
> +
> +	case SIOCSMEDIABUSY:
> +		ret = -EPERM;
> +		if (capable(CAP_NET_ADMIN)) {
> +			irda_device_set_media_busy(dev, TRUE);
> +			ret = 0;
> +		}
> +		break;
> +
> +	case SIOCGRECEIVING:
> +		rq->ifr_receiving = 0;
> +		break;
> +
> +	default:
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
> +static struct net_device_stats *omap_irda_stats(struct net_device *dev)
> +{
> +	struct omap_irda *omap_ir = netdev_priv(dev);
> +	return &omap_ir->stats;
> +}
> +
> +static int omap_irda_start(struct net_device *dev)
> +{
> +	struct omap_irda *omap_ir = netdev_priv(dev);
> +	int err;
> +
> +	omap_ir->speed = 9600;
> +
> +	err = request_irq(dev->irq, omap_irda_irq, 0, dev->name, dev);
> +	if (err)
> +		goto err_irq;
> +
> +	/*
> +	 * The interrupt must remain disabled for now.
> +	 */
> +	disable_irq(dev->irq);
> +
> +	/*  Request DMA channels for IrDA hardware */
> +	if (omap_request_dma(omap_ir->pdata->rx_channel, "IrDA Rx DMA",
> +			(void *)omap_irda_rx_dma_callback,
> +			dev, &(omap_ir->rx_dma_channel))) {
> +		printk(KERN_ERR "Failed to request IrDA Rx DMA\n");
> +		goto err_irq;
> +	}
> +
> +	if (omap_request_dma(omap_ir->pdata->tx_channel, "IrDA Tx DMA",
> +			(void *)omap_irda_tx_dma_callback,
> +			dev, &(omap_ir->tx_dma_channel))) {
> +		printk(KERN_ERR "Failed to request IrDA Tx DMA\n");
> +		goto err_irq;
> +	}
> +
> +	/* Allocate TX and RX buffers for DMA channels */
> +	omap_ir->rx_buf_dma_virt =
> +		dma_alloc_coherent(NULL, IRDA_SKB_MAX_MTU,
> +				&(omap_ir->rx_buf_dma_phys),
> +				GFP_KERNEL);
> +
> +	if (!omap_ir->rx_buf_dma_virt) {
> +		printk(KERN_ERR "Unable to allocate memory for rx_buf_dma\n");
> +		goto err_irq;
> +	}
> +
> +	omap_ir->tx_buf_dma_virt =
> +		dma_alloc_coherent(NULL, IRDA_SIR_MAX_FRAME,
> +				&(omap_ir->tx_buf_dma_phys),
> +				GFP_KERNEL);
> +
> +	if (!omap_ir->tx_buf_dma_virt) {
> +		printk(KERN_ERR "Unable to allocate memory for tx_buf_dma\n");
> +		goto err_mem1;
> +	}
> +
> +	/*
> +	 * Setup the serial port for the specified config.
> +	 */
> +	if (omap_ir->pdata->select_irda)
> +		omap_ir->pdata->select_irda(omap_ir->dev, IR_SEL);
> +
> +	err = omap_irda_startup(dev);
> +
> +	if (err)
> +		goto err_startup;
> +
> +	omap_irda_set_speed(dev, omap_ir->speed = 9600);
> +
> +	/*
> +	 * Open a new IrLAP layer instance.
> +	 */
> +	omap_ir->irlap = irlap_open(dev, &omap_ir->qos, "omap_sir");
> +
> +	err = -ENOMEM;
> +	if (!omap_ir->irlap)
> +		goto err_irlap;
> +
> +	/* Now enable the interrupt and start the queue */
> +	omap_ir->open = 1;
> +
> +	/* Start RX DMA */
> +	omap_irda_start_rx_dma(omap_ir);
> +
> +	enable_irq(dev->irq);
> +	netif_start_queue(dev);
> +
> +	return 0;
> +
> +err_irlap:
> +	omap_ir->open = 0;
> +	omap_irda_shutdown(omap_ir);
> +err_startup:
> +	dma_free_coherent(NULL, IRDA_SIR_MAX_FRAME,
> +			omap_ir->tx_buf_dma_virt, omap_ir->tx_buf_dma_phys);
> +err_mem1:
> +	dma_free_coherent(NULL, IRDA_SKB_MAX_MTU,
> +			omap_ir->rx_buf_dma_virt, omap_ir->rx_buf_dma_phys);
> +err_irq:
> +	free_irq(dev->irq, dev);
> +	return err;
> +}
> +
> +static int omap_irda_stop(struct net_device *dev)
> +{
> +	struct omap_irda *omap_ir = netdev_priv(dev);
> +
> +	disable_irq(dev->irq);
> +
> +	netif_stop_queue(dev);
> +
> +	omap_free_dma(omap_ir->rx_dma_channel);
> +	omap_free_dma(omap_ir->tx_dma_channel);
> +
> +	if (omap_ir->rx_buf_dma_virt)
> +		dma_free_coherent(NULL, IRDA_SKB_MAX_MTU,
> +				omap_ir->rx_buf_dma_virt,
> +				omap_ir->rx_buf_dma_phys);
> +	if (omap_ir->tx_buf_dma_virt)
> +		dma_free_coherent(NULL, IRDA_SIR_MAX_FRAME,
> +				omap_ir->tx_buf_dma_virt,
> +				omap_ir->tx_buf_dma_phys);
> +
> +	omap_irda_shutdown(omap_ir);
> +
> +	/* Stop IrLAP */
> +	if (omap_ir->irlap) {
> +		irlap_close(omap_ir->irlap);
> +		omap_ir->irlap = NULL;
> +	}
> +
> +	omap_ir->open = 0;
> +
> +	/*
> +	 * Free resources
> +	 */
> +	free_irq(dev->irq, dev);
> +
> +	return 0;
> +}
> +
> +static int omap_irda_set_speed(struct net_device *dev, int speed)
> +{
> +	struct omap_irda *omap_ir = netdev_priv(dev);
> +	int divisor;
> +	unsigned long flags;
> +
> +	/* Set IrDA speed */
> +	if (speed <= 115200) {
> +
> +		local_irq_save(flags);
> +
> +		/* SIR mode */
> +		if (omap_ir->pdata->transceiver_mode)
> +			omap_ir->pdata->transceiver_mode(omap_ir->dev,
> +							IR_SIRMODE);
> +
> +		/* Set SIR mode */
> +		uart_reg_out(UART3_MDR1, 1);
> +		uart_reg_out(UART3_EBLR, 1);
> +
> +		divisor = 48000000 / (16 * speed);	/* Base clock 48 MHz */
> +
> +		uart_reg_out(UART3_LCR, UART3_LCR_DIVEN);
> +		uart_reg_out(UART3_DLL, (divisor & 0xff));
> +		uart_reg_out(UART3_DLH, (divisor >> 8));
> +		uart_reg_out(UART3_LCR, 0x03);
> +
> +		uart_reg_out(UART3_MCR, 0);
> +
> +		local_irq_restore(flags);
> +	} else if (speed <= 1152000) {
> +
> +		local_irq_save(flags);
> +
> +		/* Set MIR mode, auto SIP */
> +		uart_reg_out(UART3_MDR1, UART3_MDR1_MIR |
> +				UART3_MDR1_SIP_AUTO);
> +
> +		uart_reg_out(UART3_EBLR, 2);
> +
> +		divisor = 48000000 / (41 * speed);	/* Base clock 48 MHz */
> +
> +		uart_reg_out(UART3_LCR, UART3_LCR_DIVEN);
> +		uart_reg_out(UART3_DLL, (divisor & 0xff));
> +		uart_reg_out(UART3_DLH, (divisor >> 8));
> +		uart_reg_out(UART3_LCR, 0x03);
> +
> +		if (omap_ir->pdata->transceiver_mode)
> +			omap_ir->pdata->transceiver_mode(omap_ir->dev,
> +							IR_MIRMODE);
> +
> +		local_irq_restore(flags);
> +	} else {
> +		local_irq_save(flags);
> +
> +		/* FIR mode */
> +		uart_reg_out(UART3_MDR1, UART3_MDR1_FIR |
> +				UART3_MDR1_SIP_AUTO);
> +
> +		if (omap_ir->pdata->transceiver_mode)
> +			omap_ir->pdata->transceiver_mode(omap_ir->dev,
> +							IR_FIRMODE);
> +
> +		local_irq_restore(flags);
> +	}
> +
> +	omap_ir->speed = speed;
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_PM
> +/*
> + * Suspend the IrDA interface.
> + */
> +static int omap_irda_suspend(struct platform_device *pdev, pm_message_t state)
> +{
> +	struct net_device *dev = platform_get_drvdata(pdev);
> +	struct omap_irda *omap_ir = netdev_priv(dev);
> +
> +	if (!dev)
> +		return 0;
> +
> +	if (omap_ir->open) {
> +		/*
> +		 * Stop the transmit queue
> +		 */
> +		netif_device_detach(dev);
> +		disable_irq(dev->irq);
> +		omap_irda_shutdown(omap_ir);
> +	}
> +	return 0;
> +}
> +
> +/*
> + * Resume the IrDA interface.
> + */
> +static int omap_irda_resume(struct platform_device *pdev)
> +{
> +	struct net_device *dev = platform_get_drvdata(pdev);
> +	struct omap_irda *omap_ir= netdev_priv(dev);
> +
> +	if (!dev)
> +		return 0;
> +
> +	if (omap_ir->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 (omap_ir->newspeed) {
> +			omap_ir->speed = omap_ir->newspeed;
> +			omap_ir->newspeed = 0;
> +		}
> +
> +		omap_irda_startup(dev);
> +		omap_irda_set_speed(dev, omap_ir->speed);
> +		enable_irq(dev->irq);
> +
> +		/*
> +		 * This automatically wakes up the queue
> +		 */
> +		netif_device_attach(dev);
> +	}
> +
> +	return 0;
> +}
> +#else
> +#define omap_irda_suspend	NULL
> +#define omap_irda_resume	NULL
> +#endif
> +
> +static int omap_irda_probe(struct platform_device *pdev)
> +{
> +	struct net_device *dev;
> +	struct omap_irda *omap_ir;
> +	struct omap_irda_config *pdata = pdev->dev.platform_data;
> +	unsigned int baudrate_mask;
> +	int err = 0;
> +	int irq = NO_IRQ;
> +
> +	if (!pdata) {
> +		printk(KERN_ERR "IrDA Platform data not supplied\n");
> +		return -ENOENT;
> +	}
> +
> +	if (!pdata->rx_channel || !pdata->tx_channel) {
> +		printk(KERN_ERR "IrDA invalid rx/tx channel value\n");
> +		return -ENOENT;
> +	}
> +
> +	irq = platform_get_irq(pdev, 0);
> +	if (irq <= 0) {
> +		printk(KERN_WARNING "no irq for IrDA\n");
> +		return -ENOENT;
> +	}
> +
> +	dev = alloc_irdadev(sizeof(struct omap_irda));
> +	if (!dev)
> +		goto err_mem_1;
> +
> +
> +	omap_ir = netdev_priv(dev);
> +	omap_ir->dev = &pdev->dev;
> +	omap_ir->pdata = pdata;
> +
> +	dev->hard_start_xmit	= omap_irda_hard_xmit;
> +	dev->open		= omap_irda_start;
> +	dev->stop		= omap_irda_stop;
> +	dev->do_ioctl		= omap_irda_ioctl;
> +	dev->get_stats		= omap_irda_stats;
> +	dev->irq		= irq;
> +
> +	irda_init_max_qos_capabilies(&omap_ir->qos);
> +
> +	baudrate_mask = 0;
> +	if (omap_ir->pdata->transceiver_cap & IR_SIRMODE)
> +		baudrate_mask |= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
> +	if (omap_ir->pdata->transceiver_cap & IR_MIRMODE)
> +		baudrate_mask |= IR_57600 | IR_1152000;
> +	if (omap_ir->pdata->transceiver_cap & IR_FIRMODE)
> +		baudrate_mask |= IR_4000000 << 8;
> +
> +	omap_ir->qos.baud_rate.bits &= baudrate_mask;
> +	omap_ir->qos.min_turn_time.bits = 7;
> +
> +	irda_qos_bits_to_value(&omap_ir->qos);
> +
> +	/* Any better way to avoid this? No. */
> +	if (machine_is_omap_h3() || machine_is_omap_h4())
> +		INIT_WORK(&omap_ir->pdata->gpio_expa, NULL, NULL);
> +
> +	err = register_netdev(dev);
> +	if (!err)
> +		platform_set_drvdata(pdev, dev);
> +	else
> +		free_netdev(dev);
> +
> +err_mem_1:
> +	return err;
> +}
> +
> +static int omap_irda_remove(struct platform_device *pdev)
> +{
> +	struct net_device *dev = platform_get_drvdata(pdev);
> +
> +	if (pdev) {
> +		unregister_netdev(dev);
> +		free_netdev(dev);
> +	}
> +	return 0;
> +}
> +
> +static struct platform_driver omapir_driver = {
> +	.probe		= omap_irda_probe,
> +	.remove		= omap_irda_remove,
> +	.suspend	= omap_irda_suspend,
> +	.resume		= omap_irda_resume,
> +	.driver		= {
> +		.name	= "omapirda",
> +	},
> +};
> +
> +static char __initdata banner[] = KERN_INFO "OMAP IrDA driver initializing\n";
> +
> +static int __init omap_irda_init(void)
> +{
> +	printk(banner);
> +	return platform_driver_register(&omapir_driver);
> +}
> +
> +static void __exit omap_irda_exit(void)
> +{
> +	platform_driver_unregister(&omapir_driver);
> +}
> +
> +module_init(omap_irda_init);
> +module_exit(omap_irda_exit);
> +
> +MODULE_AUTHOR("MontaVista");
> +MODULE_DESCRIPTION("OMAP IrDA Driver");
> +MODULE_LICENSE("GPL");
> +
> -- 
> 1.3.3
> 

> -------------------------------------------------------------------------
> Using Tomcat but need to do more? Need to support web services, security?
> Get stuff done quickly with pre-integrated technology to make your job easier
> Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
> http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
> _______________________________________________
> irda-users mailing list
> irda-users@...
> http://lists.sourceforge.net/lists/listinfo/irda-users

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642

Gmane