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

Next file: linux/drivers/macintosh/macserial.h
Previous file: linux/drivers/macintosh/macio-adb.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.16/drivers/macintosh/macserial.c linux/drivers/macintosh/macserial.c
@@ -129,6 +129,22 @@
 
 #define _INLINE_ inline
 
+#ifdef SERIAL_DEBUG_OPEN
+#define OPNDBG(fmt, arg...)	printk(KERN_INFO fmt , ## arg)
+#else
+#define OPNDBG(fmt, arg...)	do { } while (0)
+#endif
+#ifdef SERIAL_DEBUG_POWER
+#define PWRDBG(fmt, arg...)	printk(KERN_INFO fmt , ## arg)
+#else
+#define PWRDBG(fmt, arg...)	do { } while (0)
+#endif
+#ifdef SERIAL_DEBUG_BAUDS
+#define BAUDBG(fmt, arg...)	printk(KERN_INFO fmt , ## arg)
+#else
+#define BAUDBG(fmt, arg...)	do { } while (0)
+#endif
+
 static void probe_sccs(void);
 static void change_speed(struct mac_serial *info, struct termios *old);
 static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
@@ -318,7 +334,7 @@
 	 * to it. - paulus)
 	 */
 	for (i = 200; i > 0; --i)
-		if (ld_le32(&dma->control) & RUN)
+		if (ld_le32(&dma->status) & RUN)
 			udelay(1);
 }
 
@@ -398,7 +414,7 @@
 			continue;
 		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
 			tty_flip_buffer_push(tty);
-			
+
 		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
 			static int flip_buf_ovf;
 			if (++flip_buf_ovf <= 1)
@@ -489,7 +505,7 @@
 			if (info->tx_stopped) {
 #ifdef SERIAL_DEBUG_FLOW
 				printk("CTS up\n");
-#endif			
+#endif
 				info->tx_stopped = 0;
 				if (!info->tx_active)
 					transmit_chars(info);
@@ -497,7 +513,7 @@
 		} else {
 #ifdef SERIAL_DEBUG_FLOW
 			printk("CTS down\n");
-#endif			
+#endif
 			info->tx_stopped = 1;
 		}
 	}
@@ -520,7 +536,7 @@
 	    == virt_to_bus(info->rx_cmds[info->rx_cbuf] + 1))
 		where -= in_le16(&info->rx->res_count);
 	where--;
-	
+
 	stat = read_zsreg(info->zs_channel, R1);
 
 	flag = stat_to_flag(stat);
@@ -566,7 +582,7 @@
 #ifdef SERIAL_DEBUG_INTR
 		printk("rs_interrupt: irq %d, zs_intreg 0x%x\n",
 		       irq, (int)zs_intreg);
-#endif	
+#endif
 
 		if ((zs_intreg & CHAN_IRQMASK) == 0)
 			break;
@@ -643,7 +659,7 @@
 
 	if (serial_paranoia_check(info, tty->device, "rs_stop"))
 		return;
-	
+
 #if 0
 	save_flags(flags); cli();
 	if (info->curregs[5] & TxENAB) {
@@ -659,7 +675,7 @@
 {
 	struct mac_serial *info = (struct mac_serial *)tty->driver_data;
 	unsigned long flags;
-	
+
 #ifdef SERIAL_DEBUG_STOP
 	printk("rs_start %ld....\n", 
 	       tty->ldisc.chars_in_buffer(tty));
@@ -667,7 +683,7 @@
 
 	if (serial_paranoia_check(info, tty->device, "rs_start"))
 		return;
-	
+
 	save_flags(flags); cli();
 #if 0
 	if (info->xmit_cnt && info->xmit_buf && !(info->curregs[5] & TxENAB)) {
@@ -701,7 +717,7 @@
 {
 	struct mac_serial	*info = (struct mac_serial *) private_;
 	struct tty_struct	*tty;
-	
+
 	tty = info->tty;
 	if (!tty)
 		return;
@@ -719,14 +735,10 @@
 {
 	int delay;
 
-#ifdef SERIAL_DEBUG_OPEN
-	printk("startup() (ttyS%d, irq %d)\n", info->line, info->irq);
-#endif
+	OPNDBG("startup() (ttyS%d, irq %d)\n", info->line, info->irq);
  
 	if (info->flags & ZILOG_INITIALIZED) {
-#ifdef SERIAL_DEBUG_OPEN
-		printk(" -> already inited\n");
-#endif
+		OPNDBG(" -> already inited\n");
  		return 0;
 	}
 
@@ -736,22 +748,17 @@
 			return -ENOMEM;
 	}
 
-#ifdef SERIAL_DEBUG_OPEN
-	printk("starting up ttyS%d (irq %d)...\n", info->line, info->irq);
-#endif
+	OPNDBG("starting up ttyS%d (irq %d)...\n", info->line, info->irq);
 
 	delay = set_scc_power(info, 1);
-	
+
 	setup_scc(info);
 
-#ifdef SERIAL_DEBUG_OPEN
-	printk("enabling IRQ on ttyS%d (irq %d)...\n", info->line, info->irq);
-#endif
+	OPNDBG("enabling IRQ on ttyS%d (irq %d)...\n", info->line, info->irq);
 
 	info->flags |= ZILOG_INITIALIZED;
 	enable_irq(info->irq);
 	if (info->dma_initted) {
-//		enable_irq(info->tx_dma_irq);
 		enable_irq(info->rx_dma_irq);
 	}
 
@@ -874,8 +881,6 @@
 	volatile struct dbdma_cmd *cd;
 	unsigned char *p;
 
-//printk(KERN_DEBUG "SCC: dma_init\n");
-
 	info->rx_nbuf = 8;
 
 	/* various mem set up */
@@ -951,12 +956,10 @@
 static int setup_scc(struct mac_serial * info)
 {
 	unsigned long flags;
-	
-#ifdef SERIAL_DEBUG_OPEN
-	printk("setting up ttys%d SCC...\n", info->line);
-#endif
 
-	save_flags(flags); cli(); /* Disable interrupts */	
+	OPNDBG("setting up ttys%d SCC...\n", info->line);
+
+	save_flags(flags); cli(); /* Disable interrupts */
 
 	/*
 	 * Reset the chip.
@@ -987,7 +990,8 @@
 	/*
 	 * Turn on RTS and DTR.
 	 */
-	zs_rtsdtr(info, 1);
+	if (!info->is_irda)
+		zs_rtsdtr(info, 1);
 
 	/*
 	 * Finally, enable sequencing and interrupts
@@ -1051,16 +1055,11 @@
  */
 static void shutdown(struct mac_serial * info)
 {
-#ifdef SERIAL_DEBUG_OPEN
-	printk("Shutting down serial port %d (irq %d)....\n", info->line,
+	OPNDBG("Shutting down serial port %d (irq %d)....\n", info->line,
 	       info->irq);
-#endif
-	
+
 	if (!(info->flags & ZILOG_INITIALIZED)) {
-#ifdef SERIAL_DEBUG_OPEN
-		printk("(already shutdown)\n");
-#endif
-	
+		OPNDBG("(already shutdown)\n");
 		return;
 	}
 
@@ -1124,86 +1123,63 @@
 	/* The timings looks strange but that's the ones MacOS seems
 	   to use for the internal modem. I think we can use a lot faster
 	   ones, at least whe not using the modem, this should be tested.
-	 */				
+	 */
 	if (state) {
-#ifdef SERIAL_DEBUG_POWER
-		printk(KERN_INFO "ttyS%02d: powering up hardware\n", info->line);
-#endif
+		PWRDBG("ttyS%02d: powering up hardware\n", info->line);
 		if (feature_test(info->dev_node, FEATURE_Serial_enable) == 0) {
-			feature_clear(info->dev_node, FEATURE_Serial_reset);
-			mdelay(5);
 			feature_set(info->dev_node, FEATURE_Serial_enable);
+			mdelay(10);
+			feature_set(info->dev_node, FEATURE_Serial_reset);
+			mdelay(15);
+			feature_clear(info->dev_node, FEATURE_Serial_reset);
+			mdelay(10);
 		}
 		if (info->zs_chan_a == info->zs_channel)
 			feature_set(info->dev_node, FEATURE_Serial_IO_A);
 		else
 			feature_set(info->dev_node, FEATURE_Serial_IO_B);
-		delay = 1;
-		
+		delay = 10;
 		if (info->is_cobalt_modem){
-			feature_set(info->dev_node, FEATURE_Modem_Reset);
+			mdelay(300);
+			feature_set(info->dev_node, FEATURE_Modem_power);
 	   		mdelay(5);
-			feature_clear(info->dev_node, FEATURE_Modem_Reset);
+			feature_clear(info->dev_node, FEATURE_Modem_power);
+	   		mdelay(10);
+			feature_set(info->dev_node, FEATURE_Modem_power);
 			delay = 2500;	/* wait for 2.5s before using */
 		}
 #ifdef CONFIG_PMAC_PBOOK
-		if (info->is_pwbk_ir)
+		if (info->is_irda)
 			pmu_enable_irled(1);
 #endif /* CONFIG_PMAC_PBOOK */
 	} else {
-#ifdef SERIAL_DEBUG_POWER
-		printk(KERN_INFO "ttyS%02d: shutting down hardware\n", info->line);
-#endif
-#ifdef CONFIG_KGDB
-		if (info->kgdb_channel) {
-#ifdef SERIAL_DEBUG_POWER
-			printk(KERN_INFO "        (canceled by KGDB)\n");
-#endif
-			return 0;
-		}
-#endif
-#ifdef CONFIG_XMON
-		if (!info->is_cobalt_modem) {
-#ifdef SERIAL_DEBUG_POWER
-			printk(KERN_INFO "        (canceled by XMON)\n");
-#endif
-			return 0;
-		}
-#endif
+		PWRDBG("ttyS%02d: shutting down hardware\n", info->line);
 		if (info->is_cobalt_modem) {
-#ifdef SERIAL_DEBUG_POWER
-			printk(KERN_INFO "ttyS%02d: shutting down modem\n", info->line);
-#endif
-			feature_set(info->dev_node, FEATURE_Modem_Reset);
-			mdelay(15);
-			feature_clear(info->dev_node, FEATURE_Modem_Reset);
-			mdelay(25);
+			PWRDBG("ttyS%02d: shutting down modem\n", info->line);
+			feature_clear(info->dev_node, FEATURE_Modem_power);
+			mdelay(10);
 		}
 #ifdef CONFIG_PMAC_PBOOK
-		if (info->is_pwbk_ir)
+		if (info->is_irda)
 			pmu_enable_irled(0);
 #endif /* CONFIG_PMAC_PBOOK */
-			
-		if (info->zs_chan_a == info->zs_channel) {
-#ifdef SERIAL_DEBUG_POWER
-			printk(KERN_INFO "ttyS%02d: shutting down SCC channel A\n", info->line);
-#endif
+
+		if (info->zs_chan_a == info->zs_channel && !info->is_irda) {
+			PWRDBG("ttyS%02d: shutting down SCC channel A\n", info->line);
 			feature_clear(info->dev_node, FEATURE_Serial_IO_A);
-		} else {
-#ifdef SERIAL_DEBUG_POWER
-			printk(KERN_INFO "ttyS%02d: shutting down SCC channel B\n", info->line);
-#endif
+		} else if (!info->is_irda) {
+			PWRDBG("ttyS%02d: shutting down SCC channel B\n", info->line);
 			feature_clear(info->dev_node, FEATURE_Serial_IO_B);
 		}
 		/* XXX for now, shut down SCC core only on powerbooks */
 		if (is_powerbook
 		    && !(feature_test(info->dev_node, FEATURE_Serial_IO_A) ||
 			 feature_test(info->dev_node, FEATURE_Serial_IO_B))) {
-#ifdef SERIAL_DEBUG_POWER
-			printk(KERN_INFO "ttyS%02d: shutting down SCC core\n", info->line);
-#endif
+			PWRDBG("ttyS%02d: shutting down SCC core\n", info->line);
 			feature_set(info->dev_node, FEATURE_Serial_reset);
-			mdelay(10);
+			mdelay(15);
+			feature_clear(info->dev_node, FEATURE_Serial_reset);
+			mdelay(25);
 			feature_clear(info->dev_node, FEATURE_Serial_enable);
 			mdelay(5);
 		}
@@ -1211,6 +1187,113 @@
 	return delay;
 }
 
+static void irda_rts_pulses(struct mac_serial *info, int w)
+{
+	unsigned long flags;
+
+	udelay(w);
+	save_flags(flags); cli();
+	write_zsreg(info->zs_channel, 5, Tx8 | TxENAB);
+	udelay(2);
+	write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS);
+	udelay(8);
+	write_zsreg(info->zs_channel, 5, Tx8 | TxENAB);
+	udelay(4);
+	write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS);
+	restore_flags(flags);
+}
+
+/*
+ * Set the irda codec on the imac to the specified baud rate.
+ */
+static void irda_setup(struct mac_serial *info)
+{
+	int code, speed, t;
+	unsigned long flags;
+
+	speed = info->tty->termios->c_cflag & CBAUD;
+	if (speed < B2400 || speed > B115200)
+		return;
+	code = 0x4d + B115200 - speed;
+
+	/* disable serial interrupts and receive DMA */
+	write_zsreg(info->zs_channel, 1, info->curregs[1] & ~0x9f);
+
+	/* wait for transmitter to drain */
+	t = 10000;
+	while ((read_zsreg(info->zs_channel, 0) & Tx_BUF_EMP) == 0
+	       || (read_zsreg(info->zs_channel, 1) & ALL_SNT) == 0) {
+		if (--t <= 0) {
+			printk(KERN_ERR "transmitter didn't drain\n");
+			return;
+		}
+		udelay(10);
+	}
+	udelay(100);
+
+	/* set to 8 bits, no parity, 19200 baud, RTS on, DTR off */
+	write_zsreg(info->zs_channel, 4, X16CLK | SB1);
+	write_zsreg(info->zs_channel, 11, TCBR | RCBR);
+	t = BPS_TO_BRG(19200, ZS_CLOCK/16);
+	write_zsreg(info->zs_channel, 12, t);
+	write_zsreg(info->zs_channel, 13, t >> 8);
+	write_zsreg(info->zs_channel, 14, BRENABL);
+	write_zsreg(info->zs_channel, 3, Rx8 | RxENABLE);
+	write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS);
+
+	/* set TxD low for ~104us and pulse RTS */
+	udelay(1000);
+	save_flags(flags); cli();
+	write_zsdata(info->zs_channel, 0xfe);
+	irda_rts_pulses(info, 150);
+	restore_flags(flags);
+	irda_rts_pulses(info, 180);
+	irda_rts_pulses(info, 50);
+	udelay(100);
+
+	/* assert DTR, wait 30ms, talk to the chip */
+	write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS | DTR);
+	udelay(30000);
+	while (read_zsreg(info->zs_channel, 0) & Rx_CH_AV)
+		read_zsdata(info->zs_channel);
+
+	write_zsdata(info->zs_channel, 1);
+	t = 1000;
+	while ((read_zsreg(info->zs_channel, 0) & Rx_CH_AV) == 0) {
+		if (--t <= 0) {
+			printk(KERN_ERR "irda_setup timed out on 1st byte\n");
+			goto out;
+		}
+		udelay(10);
+	}
+	t = read_zsdata(info->zs_channel);
+	if (t != 4)
+		printk(KERN_ERR "irda_setup 1st byte = %x\n", t);
+
+	write_zsdata(info->zs_channel, code);
+	t = 1000;
+	while ((read_zsreg(info->zs_channel, 0) & Rx_CH_AV) == 0) {
+		if (--t <= 0) {
+			printk(KERN_ERR "irda_setup timed out on 2nd byte\n");
+			goto out;
+		}
+		udelay(10);
+	}
+	t = read_zsdata(info->zs_channel);
+	if (t != code)
+		printk(KERN_ERR "irda_setup 2nd byte = %x (%x)\n", t, code);
+
+	/* Drop DTR again and do some more RTS pulses */
+ out:
+	udelay(100);
+	write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS);
+	irda_rts_pulses(info, 80);
+
+	/* We should be right to go now.  We assume that load_zsregs
+	   will get called soon to load up the correct baud rate etc. */
+	info->curregs[5] = (info->curregs[5] | RTS) & ~DTR;
+	info->pendregs[5] = info->curregs[5];
+}
 
 /*
  * This routine is called to set the UART divisor registers to match
@@ -1218,7 +1301,6 @@
  */
 static void change_speed(struct mac_serial *info, struct termios *old_termios)
 {
-	unsigned short port;
 	unsigned cflag;
 	int	bits;
 	int	brg, baud;
@@ -1226,8 +1308,6 @@
 
 	if (!info->tty || !info->tty->termios)
 		return;
-	if (!(port = info->port))
-		return;
 
 	cflag = info->tty->termios->c_cflag;
 	baud = tty_get_baud_rate(info->tty);
@@ -1250,9 +1330,7 @@
 	info->zs_baud = baud;
 	info->clk_divisor = 16;
 
-#ifdef SERIAL_DEBUG_BAUDS
-	printk("set speed to %d bds, ", baud);
-#endif
+	BAUDBG("set speed to %d bds, ", baud);
 
 	switch (baud) {
 	case ZS_CLOCK/16:	/* 230400 */
@@ -1279,34 +1357,26 @@
 	case CS5:
 		info->curregs[3] |= Rx5;
 		info->curregs[5] |= Tx5;
-#ifdef SERIAL_DEBUG_BAUDS
-		printk("5 bits, ");
-#endif
+		BAUDBG("5 bits, ");
 		bits = 7;
 		break;
 	case CS6:
 		info->curregs[3] |= Rx6;
 		info->curregs[5] |= Tx6;
-#ifdef SERIAL_DEBUG_BAUDS
-		printk("6 bits, ");
-#endif
+		BAUDBG("6 bits, ");
 		bits = 8;
 		break;
 	case CS7:
 		info->curregs[3] |= Rx7;
 		info->curregs[5] |= Tx7;
-#ifdef SERIAL_DEBUG_BAUDS
-		printk("7 bits, ");
-#endif
+		BAUDBG("7 bits, ");
 		bits = 9;
 		break;
 	case CS8:
 	default: /* defaults to 8 bits */
 		info->curregs[3] |= Rx8;
 		info->curregs[5] |= Tx8;
-#ifdef SERIAL_DEBUG_BAUDS
-		printk("8 bits, ");
-#endif
+		BAUDBG("8 bits, ");
 		bits = 10;
 		break;
 	}
@@ -1317,21 +1387,15 @@
 	if (cflag & CSTOPB) {
 		info->curregs[4] |= SB2;
 		bits++;
-#ifdef SERIAL_DEBUG_BAUDS
-		printk("2 stop, ");
-#endif
+		BAUDBG("2 stop, ");
 	} else {
 		info->curregs[4] |= SB1;
-#ifdef SERIAL_DEBUG_BAUDS
-		printk("1 stop, ");
-#endif
+		BAUDBG("1 stop, ");
 	}
 	if (cflag & PARENB) {
 		bits++;
  		info->curregs[4] |= PAR_ENA;
-#ifdef SERIAL_DEBUG_BAUDS
-		printk("parity, ");
-#endif
+		BAUDBG("parity, ");
 	}
 	if (!(cflag & PARODD)) {
 		info->curregs[4] |= PAR_EVEN;
@@ -1361,9 +1425,12 @@
 	info->timeout = ((info->xmit_fifo_size*HZ*bits) / baud);
 	info->timeout += HZ/50+1;	/* Add .02 seconds of slop */
 
-#ifdef SERIAL_DEBUG_BAUDS
-	printk("timeout=%d/%ds, base:%d\n", (int)info->timeout, (int)HZ, (int)info->baud_base);
-#endif
+	BAUDBG("timeout=%d/%ds, base:%d\n", (int)info->timeout, (int)HZ,
+	       (int)info->baud_base);
+
+	/* set the irda codec to the right rate */
+	if (info->is_irda)
+		irda_setup(info);
 
 	/* Load up the new values */
 	load_zsregs(info->zs_channel, info->curregs);
@@ -1431,7 +1498,7 @@
 	} else {
 		while (1) {
 			save_flags(flags);
-			cli();		
+			cli();
 			c = MIN(count,
 				MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
 				    SERIAL_XMIT_SIZE - info->xmit_head));
@@ -1459,7 +1526,7 @@
 {
 	struct mac_serial *info = (struct mac_serial *)tty->driver_data;
 	int	ret;
-				
+
 	if (serial_paranoia_check(info, tty->device, "rs_write_room"))
 		return 0;
 	ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
@@ -1471,7 +1538,7 @@
 static int rs_chars_in_buffer(struct tty_struct *tty)
 {
 	struct mac_serial *info = (struct mac_serial *)tty->driver_data;
-				
+
 	if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer"))
 		return 0;
 	return info->xmit_cnt;
@@ -1481,7 +1548,7 @@
 {
 	struct mac_serial *info = (struct mac_serial *)tty->driver_data;
 	unsigned long flags;
-				
+
 	if (serial_paranoia_check(info, tty->device, "rs_flush_buffer"))
 		return;
 	save_flags(flags); cli();
@@ -1507,13 +1574,13 @@
 	struct mac_serial *info = (struct mac_serial *)tty->driver_data;
 	unsigned long flags;
 #ifdef SERIAL_DEBUG_THROTTLE
-	
+
 	printk("throttle %ld....\n",tty->ldisc.chars_in_buffer(tty));
 #endif
 
 	if (serial_paranoia_check(info, tty->device, "rs_throttle"))
 		return;
-	
+
 	if (I_IXOFF(tty)) {
 		save_flags(flags); cli();
 		info->x_char = STOP_CHAR(tty);
@@ -1543,13 +1610,13 @@
 	struct mac_serial *info = (struct mac_serial *)tty->driver_data;
 	unsigned long flags;
 #ifdef SERIAL_DEBUG_THROTTLE
-	
+
 	printk("unthrottle %s: %d....\n",tty->ldisc.chars_in_buffer(tty));
 #endif
 
 	if (serial_paranoia_check(info, tty->device, "rs_unthrottle"))
 		return;
-	
+
 	if (I_IXOFF(tty)) {
 		save_flags(flags); cli();
 		if (info->x_char)
@@ -1726,8 +1793,6 @@
 
 	if (serial_paranoia_check(info, tty->device, "rs_break"))
 		return;
-	if (!info->port)
-		return;
 
 	save_flags(flags); cli();
 	if (break_state == -1)
@@ -1755,7 +1820,7 @@
 		if (tty->flags & (1 << TTY_IO_ERROR))
 		    return -EIO;
 	}
-	
+
 	switch (cmd) {
 		case TIOCMGET:
 			return get_modem_info(info, (unsigned int *) arg);
@@ -1777,7 +1842,7 @@
 					 info, sizeof(struct mac_serial)))
 				return -EFAULT;
 			return 0;
-			
+
 		default:
 			return -ENOIOCTLCMD;
 		}
@@ -1816,18 +1881,16 @@
 
 	if (!info || serial_paranoia_check(info, tty->device, "rs_close"))
 		return;
-	
+
 	save_flags(flags); cli();
-	
+
 	if (tty_hung_up_p(filp)) {
 		MOD_DEC_USE_COUNT;
 		restore_flags(flags);
 		return;
 	}
-	
-#ifdef SERIAL_DEBUG_OPEN
-	printk("rs_close ttys%d, count = %d\n", info->line, info->count);
-#endif
+
+	OPNDBG("rs_close ttys%d, count = %d\n", info->line, info->count);
 	if ((tty->count == 1) && (info->count != 1)) {
 		/*
 		 * Uh, oh.  tty->count is 1, which means that the tty
@@ -1863,9 +1926,7 @@
 	 * Now we wait for the transmit buffer to clear; and we notify 
 	 * the line discipline to only process XON/XOFF characters.
 	 */
-#ifdef SERIAL_DEBUG_OPEN
-	printk("waiting end of Tx... (timeout:%d)\n", info->closing_wait);
-#endif
+	OPNDBG("waiting end of Tx... (timeout:%d)\n", info->closing_wait);
 	tty->closing = 1;
 	if (info->closing_wait != ZILOG_CLOSING_WAIT_NONE) {
 		restore_flags(flags);
@@ -1889,9 +1950,7 @@
 		 * Before we drop DTR, make sure the SCC transmitter
 		 * has completely drained.
 		 */
-#ifdef SERIAL_DEBUG_OPEN
-		printk("waiting end of Rx...\n");
-#endif
+		OPNDBG("waiting end of Rx...\n");
 		restore_flags(flags);
 		rs_wait_until_sent(tty, info->timeout);
 		save_flags(flags); cli();
@@ -2031,7 +2090,7 @@
 		info->flags |= ZILOG_CALLOUT_ACTIVE;
 		return 0;
 	}
-	
+
 	/*
 	 * If non-blocking mode is set, or the port is not enabled,
 	 * then make the check up front and then exit.
@@ -2051,7 +2110,7 @@
 		if (tty->termios->c_cflag & CLOCAL)
 			do_clocal = 1;
 	}
-	
+
 	/*
 	 * Block waiting for the carrier detect and the line to become
 	 * free (i.e., not in use by the callout).  While we are in
@@ -2061,10 +2120,8 @@
 	 */
 	retval = 0;
 	add_wait_queue(&info->open_wait, &wait);
-#ifdef SERIAL_DEBUG_OPEN
-	printk("block_til_ready before block: ttys%d, count = %d\n",
+	OPNDBG("block_til_ready before block: ttys%d, count = %d\n",
 	       info->line, info->count);
-#endif
 	cli();
 	if (!tty_hung_up_p(filp)) 
 		info->count--;
@@ -2073,7 +2130,8 @@
 	while (1) {
 		cli();
 		if (!(info->flags & ZILOG_CALLOUT_ACTIVE) &&
-		    (tty->termios->c_cflag & CBAUD))
+		    (tty->termios->c_cflag & CBAUD) &&
+		    !info->is_irda)
 			zs_rtsdtr(info, 1);
 		sti();
 		current->state = TASK_INTERRUPTIBLE;
@@ -2083,7 +2141,7 @@
 			if (info->flags & ZILOG_HUP_NOTIFY)
 				retval = -EAGAIN;
 			else
-				retval = -ERESTARTSYS;	
+				retval = -ERESTARTSYS;
 #else
 			retval = -EAGAIN;
 #endif
@@ -2097,10 +2155,8 @@
 			retval = -ERESTARTSYS;
 			break;
 		}
-#ifdef SERIAL_DEBUG_OPEN
-		printk("block_til_ready blocking: ttys%d, count = %d\n",
+		OPNDBG("block_til_ready blocking: ttys%d, count = %d\n",
 		       info->line, info->count);
-#endif
 		schedule();
 	}
 	current->state = TASK_RUNNING;
@@ -2108,15 +2164,13 @@
 	if (!tty_hung_up_p(filp))
 		info->count++;
 	info->blocked_open--;
-#ifdef SERIAL_DEBUG_OPEN
-	printk("block_til_ready after blocking: ttys%d, count = %d\n",
+	OPNDBG("block_til_ready after blocking: ttys%d, count = %d\n",
 	       info->line, info->count);
-#endif
 	if (retval)
 		return retval;
 	info->flags |= ZILOG_NORMAL_ACTIVE;
 	return 0;
-}	
+}
 
 /*
  * This routine is called whenever a serial port is opened.  It
@@ -2146,10 +2200,8 @@
 #endif
 	if (serial_paranoia_check(info, tty->device, "rs_open"))
 		return -ENODEV;
-#ifdef SERIAL_DEBUG_OPEN
-	printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line,
+	OPNDBG("rs_open %s%d, count = %d\n", tty->driver.name, info->line,
 	       info->count);
-#endif
 
 	info->count++;
 	tty->driver_data = info;
@@ -2190,10 +2242,8 @@
 
 	retval = block_til_ready(tty, filp, info);
 	if (retval) {
-#ifdef SERIAL_DEBUG_OPEN
-		printk("rs_open returning after block_til_ready with %d\n",
+		OPNDBG("rs_open returning after block_til_ready with %d\n",
 			retval);
-#endif
 		return retval;
 	}
 
@@ -2215,9 +2265,7 @@
 	info->session = current->session;
 	info->pgrp = current->pgrp;
 
-#ifdef SERIAL_DEBUG_OPEN
-	printk("rs_open ttys%d successful...\n", info->line);
-#endif
+	OPNDBG("rs_open ttys%d successful...\n", info->line);
 	return 0;
 }
 
@@ -2239,11 +2287,15 @@
 	struct device_node *ch = zss->dev_node;
 	char *conn;
 	int len;
+	struct slot_names_prop {
+		int	count;
+		char	name[1];
+	} *slots;
 
 	zss->irq = ch->intrs[0].line;
 	zss->has_dma = 0;
 #if !defined(CONFIG_KGDB) && defined(SUPPORT_SERIAL_DMA)
-	if (ch->n_addrs == 3 && ch->n_intrs == 3)
+	if (ch->n_addrs >= 3 && ch->n_intrs == 3)
 		zss->has_dma = 1;
 #endif
 	zss->dma_initted = 0;
@@ -2263,7 +2315,11 @@
 	/* XXX tested only with wallstreet PowerBook,
 	   should do no harm anyway */
 	conn = get_property(ch, "AAPL,connector", &len);
-	zss->is_pwbk_ir = conn && (strcmp(conn, "infrared") == 0);
+	zss->is_irda = conn && (strcmp(conn, "infrared") == 0);
+	/* 1999 Powerbook G3 has slot-names property instead */
+	slots = (struct slot_names_prop *)get_property(ch, "slot-names", &len);
+	if (slots && slots->count > 0 && strcmp(slots->name, "IrDA") == 0)
+		zss->is_irda = 1;
 
 	if (zss->has_dma) {
 		zss->dma_priv = NULL;
@@ -2453,7 +2509,7 @@
 		zs_soft[channel].clk_divisor = 16;
 /* -- we are not sure the SCC is powered ON at this point
  		zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]);
-*/		
+*/
 		zs_soft[channel].zs_baud = 38400;
 
 		/* If console serial line, then enable interrupts. */
@@ -2504,20 +2560,17 @@
 			printk(", port = %s", connector);
 		if (info->is_cobalt_modem)
 			printk(" (cobalt modem)");
-		if (info->is_pwbk_ir)
-			printk(" (powerbook IR)");
+		if (info->is_irda)
+			printk(" (IrDA)");
 		printk("\n");
 
+#ifndef CONFIG_XMON
 #ifdef CONFIG_KGDB
-		if (info->kgdb_channel)
-			continue;
-#endif			
-#ifdef CONFIG_XMON
-		if (!info->is_cobalt_modem)
-			continue;
-#endif			
-		/* By default, disable the port */
-		set_scc_power(info, 0);
+		if (!info->kgdb_channel)
+#endif /* CONFIG_KGDB */
+			/* By default, disable the port */
+			set_scc_power(info, 0);
+#endif /* CONFIG_XMON */
  	}
 	tmp_buf = 0;
 
@@ -2613,7 +2666,7 @@
 			while ((read_zsreg(info->zs_channel, 0) & Tx_BUF_EMP)
                                 == 0)
 				eieio();
-			
+
 			write_zsdata(info->zs_channel, 13);
 		}
 	}
@@ -2922,7 +2975,7 @@
 		probe_sccs();
 
 	set_scc_power(&zs_soft[tty_num], 1);
-	
+
 	zs_kgdbchan = zs_soft[tty_num].zs_channel;
 	zs_soft[tty_num].change_needed = 0;
 	zs_soft[tty_num].clk_divisor = 16;
@@ -2944,12 +2997,12 @@
 serial_notify_sleep(struct pmu_sleep_notifier *self, int when)
 {
 	int i;
-	
+
 	switch (when) {
 	case PBOOK_SLEEP_REQUEST:
 	case PBOOK_SLEEP_REJECT:
 		break;
-		
+
 	case PBOOK_SLEEP_NOW:
 		for (i=0; i<zs_channels_found; i++) {
 			struct mac_serial *info = &zs_soft[i];

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