patch-2.2.0-pre9 linux/drivers/net/irda/irport.c

Next file: linux/drivers/net/irda/irtty.c
Previous file: linux/drivers/net/irda/esi.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/net/irda/irport.c linux/drivers/net/irda/irport.c
@@ -1,10 +1,8 @@
 /*********************************************************************
  *		  
  * Filename:	  irport.c
- * Version:	  0.1
- * Description:   Serial driver for IrDA. The functions in this file
- *                may be used by FIR drivers, but this file knows
- *                nothing about FIR drivers!!!
+ * Version:	  0.8
+ * Description:   Serial driver for IrDA. 
  * Status:	  Experimental.
  * Author:	  Dag Brattli <dagb@cs.uit.no>
  * Created at:	  Sun Aug  3 13:49:59 1997
@@ -25,38 +23,91 @@
  *     provide warranty for any of this software. This material is 
  *     provided "AS-IS" and at no charge.
  *
+ *     NOTICE:
+ *
+ *     This driver is ment to be a small serial driver to be used for
+ *     IR-chipsets that has a UART (16550) compatibility mode. If your
+ *     chipset is is UART only, you should probably use IrTTY instead since
+ *     the Linux serial driver is probably more robust and optimized.
+ *
+ *     The functions in this file may be used by FIR drivers, but this
+ *     driver knows nothing about FIR drivers so don't ever insert such
+ *     code into this file. Instead you should code your FIR driver in a
+ *     separate file, and then call the functions in this file if
+ *     necessary. This is becase it is difficult to use the Linux serial
+ *     driver with a FIR driver becase they must share interrupts etc. Most
+ *     FIR chipsets can function in advanced SIR mode, and you should
+ *     probably use that mode instead of the UART compatibility mode (and
+ *     then just forget about this file)
+ *
  ********************************************************************/
 
-/* #include <linux/module.h> */
+#include <linux/module.h>
 
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/ioport.h>
-#include <linux/in.h>
 #include <linux/malloc.h>
 #include <linux/string.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <linux/errno.h>
+#include <linux/config.h>
+#include <linux/init.h>
 
 #include <linux/skbuff.h>
 #include <linux/serial_reg.h>
 
-#include "irda.h"
-#include "ircompat.h"
-#include "irport.h"
-#include "timer.h"
-#include "crc.h"
-#include "wrapper.h"
-#include "irlap_frame.h"
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/irport.h>
 
-#define IO_EXTENT	8
+#define IO_EXTENT 8
+
+static unsigned int io[]  = { 0x3e8, ~0, ~0, ~0 };
+static unsigned int irq[] = { 11, 0, 0, 0 };
 
 static void irport_write_wakeup( struct irda_device *idev);
-static int irport_write( int iobase, int fifo_size, __u8 *buf, int len);
+static int  irport_write( int iobase, int fifo_size, __u8 *buf, int len);
 static void irport_receive( struct irda_device *idev);
 
+__initfunc(int irport_init(void))
+{
+/* 	int i; */
+
+/* 	for ( i=0; (io[i] < 2000) && (i < 4); i++) { */
+/* 		int ioaddr = io[i]; */
+/* 		if (check_region(ioaddr, IO_EXTENT)) */
+/* 			continue; */
+/* 		if (irport_open( i, io[i], io2[i], irq[i], dma[i]) == 0) */
+/* 			return 0; */
+/* 	} */
+/* 	return -ENODEV; */
+	return 0;
+}
+
+/*
+ * Function pc87108_cleanup ()
+ *
+ *    Close all configured chips
+ *
+ */
+#ifdef MODULE
+static void irport_cleanup(void)
+{
+	int i;
+
+        DEBUG( 4, __FUNCTION__ "()\n");
+
+	/* for ( i=0; i < 4; i++) { */
+/* 		if ( dev_self[i]) */
+/* 			irport_close( &(dev_self[i]->idev)); */
+/* 	} */
+}
+#endif /* MODULE */
+
 /*
  * Function irport_open (void)
  *
@@ -65,14 +116,14 @@
  */
 int irport_open( int iobase)
 {
+	DEBUG( 0, __FUNCTION__ "(), iobase=%#x\n", iobase);
+
 	/* Initialize UART */
-	outb_p( UART_LCR_WLEN8, iobase+UART_LCR);  /* Reset DLAB */
-	outb_p(( UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), 
-	       iobase+UART_MCR);
+	outb( UART_LCR_WLEN8, iobase+UART_LCR);  /* Reset DLAB */
+	outb(( UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase+UART_MCR);
 	
 	/* Turn on interrups */
-	outb_p(( UART_IER_THRI |UART_IER_RLSI | UART_IER_RDI), 
-	       iobase+UART_IER); 
+	outb(( UART_IER_THRI |UART_IER_RLSI | UART_IER_RDI), iobase+UART_IER); 
 	
 	return 0;
 }
@@ -88,10 +139,10 @@
 	DEBUG( 0, __FUNCTION__ "()\n");
 
 	/* Reset UART */
-	outb_p( 0, iobase+UART_MCR);
+	outb( 0, iobase+UART_MCR);
 
 	/* Turn off interrupts */
-	outb_p( 0, iobase+UART_IER); 
+	outb( 0, iobase+UART_IER); 
 }
 
 /*
@@ -108,8 +159,10 @@
 
 	DEBUG( 0, __FUNCTION__ "(), Setting speed to: %d\n", speed);
 
+	DEBUG( 0, __FUNCTION__ "(), iobase=%#x\n", iobase);
+
 	/* Turn off interrupts */
-	outb_p( 0, iobase+UART_IER); 
+	outb( 0, iobase+UART_IER); 
 
 	divisor = SPEED_MAX/speed;
 	
@@ -118,15 +171,14 @@
 	/* IrDA ports use 8N1 */
 	lcr = UART_LCR_WLEN8;
 	
-	outb_p( UART_LCR_DLAB | lcr, iobase+UART_LCR); /* Set DLAB */
-	outb_p( divisor & 0xff,      iobase+UART_DLL); /* Set speed	*/
-	outb_p( divisor >> 8,	     iobase+UART_DLM);
-	outb_p( lcr,		     iobase+UART_LCR); /* Set 8N1	*/
-	outb_p( fcr,		     iobase+UART_FCR); /* Enable FIFO's */
+	outb( UART_LCR_DLAB | lcr, iobase+UART_LCR); /* Set DLAB */
+	outb( divisor & 0xff,      iobase+UART_DLL); /* Set speed */
+	outb( divisor >> 8,	   iobase+UART_DLM);
+	outb( lcr,		   iobase+UART_LCR); /* Set 8N1	*/
+	outb( fcr,		   iobase+UART_FCR); /* Enable FIFO's */
 
 	/* Turn on interrups */
-	outb_p(( UART_IER_THRI |UART_IER_RLSI | UART_IER_RDI), 
-	       iobase+UART_IER); 
+	outb( UART_IER_THRI|UART_IER_RLSI|UART_IER_RDI, iobase+UART_IER); 
 }
 
 /*
@@ -149,21 +201,25 @@
 		return;
 	}
 
-	iobase = idev->io.iobase;
-	iir    = inb( iobase + UART_IIR);
+	idev->netdev.interrupt = 1;
+
+	iobase = idev->io.iobase2;
 
+	iir = inb(iobase + UART_IIR);
 	do {
 		status = inb( iobase+UART_LSR);
 		
-		if ( status & UART_LSR_DR) {
+		if (status & UART_LSR_DR) {
 	       		/* Receive interrupt */
-			irport_receive( idev);
+			irport_receive(idev);
 		}
-		if ( status & UART_LSR_THRE) {
+		if (status & UART_LSR_THRE) {
 	       		/* Transmitter ready for data */
-			irport_write_wakeup( idev);
+			irport_write_wakeup(idev);
 		}
-	} while ( !(inb( iobase+UART_IIR) & UART_IIR_NO_INT));
+	} while (!(inb(iobase+UART_IIR) & UART_IIR_NO_INT));
+
+	idev->netdev.interrupt = 0;
 }
 
 /*
@@ -179,16 +235,11 @@
 	
 	DEBUG( 4, __FUNCTION__ "() <%ld>\n", jiffies);
 	
-	/* 
-	 *  First make sure we're connected. 
-	 */
 	ASSERT( idev != NULL, return;);
 	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
 
-	/*
-	 *  Finished with frame?
-	 */
-	if ( idev->tx.ptr == idev->tx.len)  {
+	/* Finished with frame?  */
+	if ( idev->tx_buff.offset == idev->tx_buff.len)  {
 
 		/* 
 		 *  Now serial buffer is almost free & we can start 
@@ -201,16 +252,16 @@
 
 		/* Schedule network layer, so we can get some more frames */
 		mark_bh( NET_BH);
+
 		return;
 	}
-	/*
-	 *  Write data left in transmit buffer
-	 */
-	count = idev->tx.len - idev->tx.ptr;
-	actual = irport_write( idev->io.iobase, idev->io.fifo_size, 
-			       idev->tx.head, count);
-	idev->tx.ptr += actual;
-	idev->tx.head += actual;
+
+	/* Write data left in transmit buffer */
+	count = idev->tx_buff.len - idev->tx_buff.offset;
+	actual = irport_write( idev->io.iobase2, idev->io.fifo_size, 
+			       idev->tx_buff.head, count);
+	idev->tx_buff.offset += actual;
+	idev->tx_buff.head += actual;
 }
 
 /*
@@ -223,7 +274,8 @@
 {
 	int actual = 0;
 
-	if (!(inb_p( iobase+UART_LSR) & UART_LSR_THRE)) {
+	/* Tx FIFO should be empty! */
+	if (!(inb( iobase+UART_LSR) & UART_LSR_THRE)) {
 		DEBUG( 0, __FUNCTION__ "(), failed, fifo not empty!\n");
 		return -1;
 	}
@@ -265,19 +317,11 @@
 		return -EBUSY;
 	}
 	
-	idev = (struct irda_device *)  dev->priv;
+	idev = (struct irda_device *) dev->priv;
 
 	ASSERT( idev != NULL, return -1;);
 	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
 
-	if ( skb == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), skb==NULL\n");
-#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,0)
-		dev_tint(dev); 
-#endif
-		return 0;
-	}
-
 	/* Lock transmit buffer */
 	if ( irda_lock( (void *) &dev->tbusy) == FALSE)
 		return -EBUSY;
@@ -285,18 +329,17 @@
         /*  
 	 *  Transfer skb to tx_buff while wrapping, stuffing and making CRC 
 	 */
-	idev->tx.len = async_wrap_skb( skb, idev->tx.buff, idev->tx.buffsize);
-
-	actual = irport_write( idev->io.iobase, idev->io.fifo_size, 
-			       idev->tx.buff, idev->tx.len);
-
-	idev->tx.ptr = actual;
-	idev->tx.head = idev->tx.buff + actual;
-
-	IS_SKB( skb, return 0;);
-	FREE_SKB_MAGIC( skb);
-	DEV_KFREE_SKB( skb, FREE_WRITE);
-
+	idev->tx_buff.len = async_wrap_skb( skb, idev->tx_buff.data, 
+					    idev->tx_buff.truesize);
+	
+	actual = irport_write( idev->io.iobase2, idev->io.fifo_size, 
+			       idev->tx_buff.data, idev->tx_buff.len);
+	
+	idev->tx_buff.offset = actual;
+	idev->tx_buff.head = idev->tx_buff.data + actual;
+	
+	dev_kfree_skb( skb);
+	
 	return 0;
 }
         
@@ -308,54 +351,54 @@
  */
 static void irport_receive( struct irda_device *idev) 
 {
-	__u8 byte = 0x00;
 	int iobase;
 
 	if ( !idev)
 		return;
 
-	DEBUG( 0, __FUNCTION__ "()\n");
-
-	iobase = idev->io.iobase;
+	DEBUG( 4, __FUNCTION__ "()\n");
 
-	if ( idev->rx.len == 0) {
-		idev->rx.head = idev->rx.buff;
-	}
+	iobase = idev->io.iobase2;
 
-	/* 
-	 *  Receive all characters in FIFO 
+	if ( idev->rx_buff.len == 0)
+		idev->rx_buff.head = idev->rx_buff.data;
+	
+	/*  
+	 * Receive all characters in Rx FIFO, unwrap and unstuff them. 
+         * async_unwrap_char will deliver all found frames  
 	 */
 	do {
-		byte = inb_p( iobase+UART_RX);
-		async_unwrap_char( idev, byte);
+		async_unwrap_char( idev, inb( iobase+UART_RX));
 		
-	} while ( inb_p( iobase+UART_LSR) & UART_LSR_DR);	
+	} while ( inb( iobase+UART_LSR) & UART_LSR_DR);	
 }
 
+#ifdef MODULE
+
 /*
  * Function cleanup_module (void)
  *
  *    
  *
  */
-/* void cleanup_module(void) */
-/* { */
-/* 	DEBUG( 3, "IrPORT: cleanup_module!\n"); */
-/* 	irport_cleanup(irport_drv); */
-/* } */
+void cleanup_module(void)
+{
+	irport_cleanup();
+}
 
 /*
  * Function init_module (void)
  *
  *    
- *
  */
-/* int init_module(void) */
-/* { */
-/* 	if (irport_init() < 0) { */
-/* 		cleanup_module(); */
-/* 		return 1; */
-/* 	} */
-/* 	return(0); */
-/* } */
+int init_module(void)
+{
+	if (irport_init() < 0) {
+		cleanup_module();
+		return 1;
+	}
+	return(0);
+}
+
+#endif /* MODULE */
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov