patch-2.2.15 linux/drivers/char/generic_serial.c

Next file: linux/drivers/char/generic_serial.h
Previous file: linux/drivers/char/esp.c
Back to the patch index
Back to the overall index

diff -u --new-file --recursive --exclude-from ../../exclude v2.2.14/drivers/char/generic_serial.c linux/drivers/char/generic_serial.c
@@ -19,93 +19,11 @@
 #include <linux/mm.h>
 #include <asm/semaphore.h>
 #include <linux/version.h>
+#include <linux/module.h>
+#include <linux/compatmac.h>
+#include <linux/generic_serial.h>
 
-
-#if LINUX_VERSION_CODE < 0x020100    /* Less than 2.1.0 */
-#define TWO_ZERO
-#else
-#if LINUX_VERSION_CODE < 0x020200   /* less than 2.2.x */
-#warning "Please use a 2.2.x kernel. "
-#else
-#if LINUX_VERSION_CODE < 0x020300   /* less than 2.2.x */
-#define TWO_TWO
-#else
-#define TWO_THREE
-#endif
-#endif
-#endif
-
-#ifdef TWO_ZERO
-
-/* Here is the section that makes the 2.2 compatible driver source 
-   work for 2.0 too! We mostly try to adopt the "new thingies" from 2.2, 
-   and provide for compatibility stuff here if possible. */
-
-/* Some 200 days (on intel) */
-#define MAX_SCHEDULE_TIMEOUT     ((long)(~0UL>>1))
-
-
-#ifndef MODULE
-
-#define copy_to_user(a,b,c)          memcpy_tofs(a,b,c)
-
-static inline int copy_from_user(void *to,const void *from, int c) 
-{
-	memcpy_fromfs(to, from, c);
-	return 0;
-}
-
-
-#define capable(x)                   suser()
-
-#define queue_task                   queue_task_irq_off
-#define tty_flip_buffer_push(tty)    queue_task(&tty->flip.tqueue, &tq_timer)
-#define signal_pending(current)      (current->signal & ~current->blocked)
-#define schedule_timeout(to)         do {current->timeout = jiffies + (to);schedule ();} while (0)
-#define time_after(t1,t2)            (((long)t1-t2) > 0)
-
-#define test_and_set_bit(nr, addr)   set_bit(nr, addr)
-#define test_and_clear_bit(nr, addr) clear_bit(nr, addr)
-
-/* Not yet implemented on 2.0 */
-#define ASYNC_SPD_SHI  -1
-#define ASYNC_SPD_WARP -1
-
-
-
-/* Ugly hack: the driver_name doesn't exist in 2.0.x . So we define it
-   to the "name" field that does exist. As long as the assignments are
-   done in the right order, there is nothing to worry about. */
-#define driver_name           name 
-
-
-/* Should be in a header somewhere. */
-#define TTY_HW_COOK_OUT       14 /* Flag to tell ntty what we can handle */
-#define TTY_HW_COOK_IN        15 /* in hardware - output and input       */
-#endif
-
-#endif
-
-#ifndef TWO_ZERO
-/* This include is new with 2.2  (and required!) */
-#include <asm/uaccess.h>
-#endif
-
-#ifndef TWO_THREE
-/* These are new in 2.3. The source now uses 2.3 syntax, and here is 
-   the compatibility define... */
-#define wait_queue_head_t struct wait_queue *
-#define DECLARE_MUTEX(name) struct semaphore name = MUTEX
-#define DECLARE_WAITQUEUE(wait, current) struct wait_queue wait = { current, NULL }
-
-#endif
-
-#include "generic_serial.h"
-
-
-#ifndef MODULE
-extern void my_hd (unsigned char *ptr, int n);
-#endif
+#define DEBUG 
 
 static char *                  tmp_buf; 
 static DECLARE_MUTEX(tmp_buf_sem);
@@ -119,8 +37,8 @@
 #define gs_dprintk(f, str...) /* nothing */
 #endif
 
-#define func_enter() gs_dprintk (SX_DEBUG_FLOW, "gs: enter " __FUNCTION__ "\n")
-#define func_exit()  gs_dprintk (SX_DEBUG_FLOW, "gs: exit  " __FUNCTION__ "\n")
+#define func_enter() gs_dprintk (GS_DEBUG_FLOW, "gs: enter " __FUNCTION__ "\n")
+#define func_exit()  gs_dprintk (GS_DEBUG_FLOW, "gs: exit  " __FUNCTION__ "\n")
 
 
 
@@ -135,6 +53,27 @@
 #endif
 
 
+#ifdef DEBUG
+static void my_hd (unsigned char *addr, int len)
+{
+	int i, j, ch;
+
+	for (i=0;i<len;i+=16) {
+		printk ("%08x ", (int) addr+i);
+		for (j=0;j<16;j++) {
+			printk ("%02x %s", addr[j+i], (j==7)?" ":"");
+		}
+		for (j=0;j<16;j++) {
+			ch = addr[j+i];
+			printk ("%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch));
+		}
+		printk ("\n");
+	}
+}
+#else
+#define my_hd(addr,len) 
+#endif
+
 
 void gs_put_char(struct tty_struct * tty, unsigned char ch)
 {
@@ -397,16 +336,19 @@
 	if (!tty) return 0;
 	port = tty->driver_data;
 
+	if (!port->rd) return 0;
+	if (!port->rd->chars_in_buffer) return 0;
+
 	func_exit ();
 	return port->xmit_cnt + port->rd->chars_in_buffer (port);
 }
 
 
-static void gs_wait_tx_flushed (void * ptr, int timeout) 
+static int gs_wait_tx_flushed (void * ptr, int timeout) 
 {
 	struct gs_port *port = ptr;
 	long end_jiffies;
-	int jiffies_to_transmit, charsleft;
+	int jiffies_to_transmit, charsleft = 0, rv = 0;
 	int to, rcib;
 
 	func_enter();
@@ -420,7 +362,7 @@
 	if (!port || port->xmit_cnt < 0 || !port->xmit_buf) {
 		gs_dprintk (GS_DEBUG_FLUSH, "ERROR: !port, !port->xmit_buf or prot->xmit_cnt < 0.\n");
 	func_exit();
-		return;  /* This is an error which we don't know how to handle. */
+		return -EINVAL;  /* This is an error which we don't know how to handle. */
 	}
 	gs_dprintk (GS_DEBUG_FLUSH, "checkpoint 1\n");
 
@@ -430,8 +372,8 @@
 
 	if(rcib <= 0) {
 		gs_dprintk (GS_DEBUG_FLUSH, "nothing to wait for.\n");
-	func_exit();
-	return;
+		func_exit();
+		return rv;
 	}
 	gs_dprintk (GS_DEBUG_FLUSH, "checkpoint 3\n");
 
@@ -464,14 +406,18 @@
 
 		current->state = TASK_INTERRUPTIBLE;
 		schedule_timeout(jiffies_to_transmit);
-		if (signal_pending (current))
+		if (signal_pending (current)) {
+			gs_dprintk (GS_DEBUG_FLUSH, "Signal pending. Bombing out: "); 
+			rv = -EINTR;
 			break;
+		}
 	}
 
 	gs_dprintk (GS_DEBUG_FLUSH, "charsleft = %d.\n", charsleft); 
 	current->state = TASK_RUNNING;
 
 	func_exit();
+	return rv;
 }
 
 
@@ -488,6 +434,7 @@
 	restore_flags(flags);
 
 	wake_up_interruptible(&tty->write_wait);
+	wake_up_interruptible(&tty->poll_wait);
 	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
 	    tty->ldisc.write_wakeup)
 		(tty->ldisc.write_wakeup)(tty);
@@ -545,7 +492,7 @@
 void gs_shutdown_port (struct gs_port *port)
 {
 	long flags;
-
+	func_enter();
 	if (!(port->flags & ASYNC_INITIALIZED))
 		return;
 
@@ -564,6 +511,7 @@
 
 	port->flags &= ~ASYNC_INITIALIZED;
 	restore_flags (flags);
+	func_exit();
 }
 
 
@@ -601,6 +549,7 @@
 		    tty->ldisc.write_wakeup)
 			(tty->ldisc.write_wakeup)(tty);
 		wake_up_interruptible(&tty->write_wait);
+		wake_up_interruptible(&tty->poll_wait);
 	}
 	func_exit ();
 }
@@ -750,8 +699,10 @@
 		func_exit();
 		return;
 	}
+
 	if (!port->tty) {
-		printk (KERN_WARNING "gs: Odd: port->tty is NULL\n");
+		/* This seems to happen when this is called from vhangup. */
+		gs_dprintk (GS_DEBUG_CLOSE, "gs: Odd: port->tty is NULL\n");
 		port->tty = tty;
 	}
 
@@ -775,6 +726,7 @@
 		port->count = 0;
 	}
 	if (port->count) {
+		gs_dprintk(GS_DEBUG_CLOSE, "gs_close: count: %d\n", port->count);
 		restore_flags(flags);
 		func_exit ();
 		return;
@@ -806,6 +758,7 @@
 
 	port->rd->disable_rx_interrupts (port);
 
+	/* close has no way of returning "EINTR", so discard return value */
 	if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
 		gs_wait_tx_flushed (port, port->closing_wait); 
 
@@ -816,8 +769,12 @@
 	if (tty->ldisc.flush_buffer)
 		tty->ldisc.flush_buffer(tty);
 	tty->closing = 0;
+
 	port->event = 0;
+	port->rd->close (port);
+	port->rd->shutdown_port (port);
 	port->tty = 0;
+
 	if (port->blocked_open) {
 		if (port->close_delay) {
 			current->state = TASK_INTERRUPTIBLE;
@@ -829,8 +786,6 @@
 	                 ASYNC_CLOSING | ASYNC_INITIALIZED);
 	wake_up_interruptible(&port->close_wait);
 
-	port->rd->close (port);
-	port->rd->shutdown_port (port);
 	restore_flags(flags);
 	func_exit ();
 }
@@ -846,7 +801,7 @@
                      struct termios * old_termios)
 {
 	struct gs_port *port = tty->driver_data;
-	int baudrate, tmp;
+	int baudrate, tmp, rv;
 	struct termios *tiosp;
 
 	func_enter();
@@ -872,7 +827,7 @@
 		   && (tiosp->c_line  == old_termios->c_line)
 		   && (memcmp(tiosp->c_cc, old_termios->c_cc, NCC) == 0)) {
 			gs_dprintk(GS_DEBUG_TERMIOS, "gs_set_termios: optimized away\n");
-			return;
+			return /* 0 */;
 		}
 	} else 
 		gs_dprintk(GS_DEBUG_TERMIOS, "gs_set_termios: no old_termios: "
@@ -928,9 +883,11 @@
 
 	/* We should really wait for the characters to be all sent before
 	   changing the settings. -- CAL */
-	gs_wait_tx_flushed (port, MAX_SCHEDULE_TIMEOUT);
+	rv = gs_wait_tx_flushed (port, MAX_SCHEDULE_TIMEOUT);
+	if (rv < 0) return /* rv */;
 
-	port->rd->set_real_termios(port);
+	rv = port->rd->set_real_termios(port);
+	if (rv < 0) return /* rv */;
 
 	if ((!old_termios || 
 	     (old_termios->c_cflag & CRTSCTS)) &&
@@ -948,7 +905,7 @@
 #endif
 
 	func_exit();
-	return;
+	return /* 0 */;
 }
 
 
@@ -1072,3 +1029,15 @@
 	copy_to_user(sp, &sio, sizeof(struct serial_struct));
 }
 
+
+#ifdef MODULE
+int init_module (void)
+{
+  return 0;
+}
+
+int cleanup_module (void)
+{
+  return 0;
+}
+#endif

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)