patch-2.1.79 linux/drivers/macintosh/macserial.c

Next file: linux/drivers/macintosh/nvram.c
Previous file: linux/drivers/macintosh/mackeymap.map
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.78/linux/drivers/macintosh/macserial.c linux/drivers/macintosh/macserial.c
@@ -104,6 +104,7 @@
 
 static void probe_sccs(void);
 static void change_speed(struct mac_serial *info);
+static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
 
 static struct tty_struct *serial_table[NUM_CHANNELS];
 static struct termios *serial_termios[NUM_CHANNELS];
@@ -325,7 +326,7 @@
 
 		if (!tty)
 			continue;
-		queue_task(&tty->flip.tqueue, &tq_timer);
+		tty_flip_buffer_push(tty);
 
 		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
 			static int flip_buf_ovf;
@@ -398,7 +399,8 @@
 		if (status & DCD) {
 			wake_up_interruptible(&info->open_wait);
 		} else if (!(info->flags & ZILOG_CALLOUT_ACTIVE)) {
-			queue_task(&info->tqueue_hangup, &tq_scheduler);
+			if (info->tty)
+				tty_hangup(info->tty);
 		}
 	}
 
@@ -548,27 +550,6 @@
 	}
 }
 
-/*
- * This routine is called from the scheduler tqueue when the interrupt
- * routine has signalled that a hangup has occurred.  The path of
- * hangup processing is:
- *
- * 	serial interrupt routine -> (scheduler tqueue) ->
- * 	do_serial_hangup() -> tty->hangup() -> rs_hangup()
- * 
- */
-static void do_serial_hangup(void *private_)
-{
-	struct mac_serial	*info = (struct mac_serial *) private_;
-	struct tty_struct	*tty;
-	
-	tty = info->tty;
-	if (!tty)
-		return;
-
-	tty_hangup(tty);
-}
-
 static void rs_timer(void)
 {
 }
@@ -1196,21 +1177,25 @@
 }
 
 /*
- * This routine sends a break character out the serial port.
+ * rs_break - turn transmit break condition on/off
  */
-static void send_break(	struct mac_serial * info, int duration)
+static void rs_break(struct tty_struct *tty, int break_state)
 {
+	struct mac_serial *info = (struct mac_serial *) tty->driver_data;
+	unsigned long flags;
+
+	if (serial_paranoia_check(info, tty->device, "rs_break"))
+		return;
 	if (!info->port)
 		return;
-	current->state = TASK_INTERRUPTIBLE;
-	current->timeout = jiffies + duration;
-	cli();
-	info->curregs[5] |= SND_BRK;
-	write_zsreg(info->zs_channel, 5, info->curregs[5]);
-	schedule();
-	info->curregs[5] &= ~SND_BRK;
+
+	save_flags(flags); cli();
+	if (break_state == -1)
+		info->curregs[5] |= SND_BRK;
+	else
+		info->curregs[5] &= ~SND_BRK;
 	write_zsreg(info->zs_channel, 5, info->curregs[5]);
-	sti();
+	restore_flags(flags);
 }
 
 static int rs_ioctl(struct tty_struct *tty, struct file * file,
@@ -1218,7 +1203,6 @@
 {
 	int error;
 	struct mac_serial * info = (struct mac_serial *)tty->driver_data;
-	int retval;
 
 	if (serial_paranoia_check(info, tty->device, "rs_ioctl"))
 		return -ENODEV;
@@ -1231,31 +1215,6 @@
 	}
 	
 	switch (cmd) {
-		case TCSBRK:	/* SVID version: non-zero arg --> no break */
-			retval = tty_check_change(tty);
-			if (retval)
-				return retval;
-			tty_wait_until_sent(tty, 0);
-			if (!arg)
-				send_break(info, HZ/4);	/* 1/4 second */
-			return 0;
-		case TCSBRKP:	/* support for POSIX tcsendbreak() */
-			retval = tty_check_change(tty);
-			if (retval)
-				return retval;
-			tty_wait_until_sent(tty, 0);
-			send_break(info, arg ? arg*(HZ/10) : HZ/4);
-			return 0;
-		case TIOCGSOFTCAR:
-			return put_user(C_CLOCAL(tty) ? 1 : 0, (int *) arg);
-		case TIOCSSOFTCAR:
-			error = get_user(arg, (int *) arg);
-			if (error)
-				return error;
-			tty->termios->c_cflag =
-				((tty->termios->c_cflag & ~CLOCAL) |
-				 (arg ? CLOCAL : 0));
-			return 0;
 		case TIOCMGET:
 			error = verify_area(VERIFY_WRITE, (void *) arg,
 				sizeof(unsigned int));
@@ -1326,7 +1285,6 @@
 {
 	struct mac_serial * info = (struct mac_serial *)tty->driver_data;
 	unsigned long flags;
-	unsigned long timeout;
 
 	if (!info || serial_paranoia_check(info, tty->device, "rs_close"))
 		return;
@@ -1395,14 +1353,7 @@
 		 * Before we drop DTR, make sure the SCC transmitter
 		 * has completely drained.
 		 */
-		timeout = jiffies+HZ;
-		while ((read_zsreg(info->zs_channel, 1) & ALL_SNT) == 0) {
-			current->state = TASK_INTERRUPTIBLE;
-			current->timeout = jiffies + info->timeout;
-			schedule();
-			if (jiffies > timeout)
-				break;
-		}
+		rs_wait_until_sent(tty, info->timeout);
 	}
 
 	shutdown(info);
@@ -1413,14 +1364,6 @@
 	tty->closing = 0;
 	info->event = 0;
 	info->tty = 0;
-	if (tty->ldisc.num != ldiscs[N_TTY].num) {
-		if (tty->ldisc.close)
-			(tty->ldisc.close)(tty);
-		tty->ldisc = ldiscs[N_TTY];
-		tty->termios->c_line = N_TTY;
-		if (tty->ldisc.open)
-			(tty->ldisc.open)(tty);
-	}
 	if (info->blocked_open) {
 		if (info->close_delay) {
 			current->state = TASK_INTERRUPTIBLE;
@@ -1436,6 +1379,42 @@
 }
 
 /*
+ * rs_wait_until_sent() --- wait until the transmitter is empty
+ */
+static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+	struct mac_serial *info = (struct mac_serial *) tty->driver_data;
+	unsigned long orig_jiffies, char_time;
+
+	if (serial_paranoia_check(info, tty->device, "rs_wait_until_sent"))
+		return;
+
+	orig_jiffies = jiffies;
+	/*
+	 * Set the check interval to be 1/5 of the estimated time to
+	 * send a single character, and make it at least 1.  The check
+	 * interval should also be less than the timeout.
+	 */
+	char_time = (info->timeout - HZ/50) / info->xmit_fifo_size;
+	char_time = char_time / 5;
+	if (char_time == 0)
+		char_time = 1;
+	if (timeout)
+		char_time = MIN(char_time, timeout);
+	while ((read_zsreg(info->zs_channel, 1) & ALL_SNT) == 0) {
+		current->state = TASK_INTERRUPTIBLE;
+		current->counter = 0;	/* make us low-priority */
+		current->timeout = jiffies + char_time;
+		schedule();
+		if (signal_pending(current))
+			break;
+		if (timeout && ((orig_jiffies + timeout) < jiffies))
+			break;
+	}
+	current->state = TASK_RUNNING;
+}
+
+/*
  * rs_hangup() --- called by tty_hangup() when a hangup is signaled.
  */
 void rs_hangup(struct tty_struct *tty)
@@ -1473,10 +1452,8 @@
 	if (info->flags & ZILOG_CLOSING) {
 		interruptible_sleep_on(&info->close_wait);
 #ifdef SERIAL_DO_RESTART
-		if (info->flags & ZILOG_HUP_NOTIFY)
-			return -EAGAIN;
-		else
-			return -ERESTARTSYS;
+		return ((info->flags & ZILOG_HUP_NOTIFY) ?
+			-EAGAIN : -ERESTARTSYS);
 #else
 		return -EAGAIN;
 #endif
@@ -1618,6 +1595,21 @@
 	info->tty = tty;
 
 	/*
+	 * If the port is the middle of closing, bail out now
+	 */
+	if (tty_hung_up_p(filp) ||
+	    (info->flags & ZILOG_CLOSING)) {
+		if (info->flags & ZILOG_CLOSING)
+			interruptible_sleep_on(&info->close_wait);
+#ifdef SERIAL_DO_RESTART
+		return ((info->flags & ZILOG_HUP_NOTIFY) ?
+			-EAGAIN : -ERESTARTSYS);
+#else
+		return -EAGAIN;
+#endif
+	}
+
+	/*
 	 * Start up serial port
 	 */
 	retval = startup(info);
@@ -1757,6 +1749,8 @@
 	serial_driver.stop = rs_stop;
 	serial_driver.start = rs_start;
 	serial_driver.hangup = rs_hangup;
+	serial_driver.break_ctl = rs_break;
+	serial_driver.wait_until_sent = rs_wait_until_sent;
 
 	/*
 	 * The callout device is just like normal device except for
@@ -1809,8 +1803,6 @@
 		info->blocked_open = 0;
 		info->tqueue.routine = do_softint;
 		info->tqueue.data = info;
-		info->tqueue_hangup.routine = do_serial_hangup;
-		info->tqueue_hangup.data = info;
 		info->callout_termios =callout_driver.init_termios;
 		info->normal_termios = serial_driver.init_termios;
 		info->open_wait = 0;

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