patch-2.4.23 linux-2.4.23/arch/ppc/8xx_io/uart.c

Next file: linux-2.4.23/arch/ppc/Makefile
Previous file: linux-2.4.23/arch/ppc/8xx_io/fec.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.22/arch/ppc/8xx_io/uart.c linux-2.4.23/arch/ppc/8xx_io/uart.c
@@ -81,7 +81,11 @@
 #define TX_WAKEUP	ASYNC_SHARE_IRQ
 
 static char *serial_name = "CPM UART driver";
-static char *serial_version = "0.03";
+static char *serial_version = "0.04";
+
+/* TX buffer length used by my_console_write.
+   Assume minumun length until it gets set by this driver */
+static int console_tx_buf_len = 1;
 
 static DECLARE_TASK_QUEUE(tq_serial);
 
@@ -126,10 +130,27 @@
  * type of SMC or SCC.
  * The SMCs do not support any modem control signals.
  */
-#define smc_scc_num	hub6
-#define NUM_IS_SCC	((int)0x00010000)
-#define PORT_NUM(P)	((P) & 0x0000ffff)
-#define PORT_IS_SCC(P)	((P) & NUM_IS_SCC)
+#define smc_scc_num	     hub6
+#define NUM_IS_SCC	     ((int)0x000100000)
+#define NUM_BRG              ((int)0x0000FF00)
+#define NUM_BRG_SHIFT        8
+#define NUM                  ((int)0x000000FF)
+#define NUM_SHIFT            0
+#define PORT_NUM(P)	     ((P) & NUM)
+#define PORT_NUM_SET(N)      (((N)-1) << NUM_SHIFT)
+#define PORT_IS_SCC(P)	     ((P) & NUM_IS_SCC)
+#define PORT_BRG(P)          (((P) & NUM_BRG) >> NUM_BRG_SHIFT)
+#define PORT_BRG_SET(P,B)    (P) = (((P) & ~NUM_BRG) | ((B) << NUM_BRG_SHIFT))
+
+/* Short names for the ports
+*/
+#define QUICC_CPM_SMC1  (PORT_NUM_SET(1))
+#define QUICC_CPM_SMC2  (PORT_NUM_SET(2))
+#define QUICC_CPM_SCC1  (PORT_NUM_SET(1)|NUM_IS_SCC)
+#define QUICC_CPM_SCC2  (PORT_NUM_SET(2)|NUM_IS_SCC)
+#define QUICC_CPM_SCC3  (PORT_NUM_SET(3)|NUM_IS_SCC)
+#define QUICC_CPM_SCC4  (PORT_NUM_SET(4)|NUM_IS_SCC)
+#define QUICC_MAX_BRG   3  /* BRG1..BRG4 */
 
 /* The serial port to use for KGDB. */
 #ifdef CONFIG_KGDB_TTYS1
@@ -151,22 +172,24 @@
  */
 static struct serial_state rs_table[] = {
 	/* UART CLK   PORT          IRQ      FLAGS  NUM   */
-#ifndef CONFIG_SCC3_ENET	/* SMC1 not usable with Ethernet on SCC3 */
-  	{ 0,     0, PROFF_SMC1, CPMVEC_SMC1,   0,    0 },    /* SMC1 ttyS0 */
+#ifdef CONFIG_8xx_SMC1
+  	{ 0,     0, PROFF_SMC1, CPMVEC_SMC1,   0,    QUICC_CPM_SMC1 },    /* SMC1 ttySx */
+#endif
+#ifdef CONFIG_8xx_SMC2
+  	{ 0,     0, PROFF_SMC2, CPMVEC_SMC2,   0,    QUICC_CPM_SMC2 },    /* SMC2 ttySx */
+#endif
+#ifdef CONFIG_8xx_SCC1
+  	{ 0,     0, PROFF_SCC1, CPMVEC_SCC1,   0,    QUICC_CPM_SCC1 },    /* SCC1 ttySx */
+#endif
+#ifdef CONFIG_8xx_SCC2
+  	{ 0,     0, PROFF_SCC2, CPMVEC_SCC2,   0,    QUICC_CPM_SCC2 },    /* SCC2 ttySx */
+#endif
+#ifdef CONFIG_8xx_SCC3
+  	{ 0,     0, PROFF_SCC3, CPMVEC_SCC3,   0,    QUICC_CPM_SCC3 },    /* SCC3 ttySx */
+#endif
+#ifdef CONFIG_8xx_SCC4
+  	{ 0,     0, PROFF_SCC4, CPMVEC_SCC4,   0,    QUICC_CPM_SCC4 },    /* SCC4 ttySx */
 #endif
-#if !defined(CONFIG_USB_MPC8xx) && !defined(CONFIG_USB_CLIENT_MPC8xx)
-# ifdef CONFIG_SMC2_UART
-  	{ 0,     0, PROFF_SMC2, CPMVEC_SMC2,   0,    1 },    /* SMC2 ttyS1 */
-# endif
-# ifdef CONFIG_USE_SCC_IO
-  	{ 0,     0, PROFF_SCC2, CPMVEC_SCC2,   0,    (NUM_IS_SCC | 1) },    /* SCC2 ttyS2 */
-  	{ 0,     0, PROFF_SCC3, CPMVEC_SCC3,   0,    (NUM_IS_SCC | 2) },    /* SCC3 ttyS3 */
-# endif
-  #else /* CONFIG_USB_xxx */
-# ifdef CONFIG_USE_SCC_IO
-  	{ 0,     0, PROFF_SCC3, CPMVEC_SCC3,   0,    (NUM_IS_SCC | 2) },    /* SCC3 ttyS3 */
-# endif
-#endif	/* CONFIG_USB_xxx */
 };
 
 #define NR_PORTS	(sizeof(rs_table)/sizeof(struct serial_state))
@@ -177,6 +200,7 @@
 
 /* The number of buffer descriptors and their sizes.
 */
+#define EARLY_BUF_SIZE	4
 #define RX_NUM_FIFO	4
 #define RX_BUF_SIZE	32
 #define TX_NUM_FIFO	4
@@ -218,6 +242,12 @@
 	cbd_t			*rx_cur;
 	cbd_t			*tx_bd_base;
 	cbd_t			*tx_cur;
+
+	/* Virtual addresses for the FIFOs because we can't __va() a
+	 * physical address anymore.
+	 */
+	 unsigned char		*rx_va_base;
+	 unsigned char		*tx_va_base;
 } ser_info_t;
 
 static struct console sercons = {
@@ -394,13 +424,13 @@
 		/* Get the number of characters and the buffer pointer.
 		*/
 		i = bdp->cbd_datlen;
-		cp = (unsigned char *)__va(bdp->cbd_bufaddr);
+		cp = info->rx_va_base + ((bdp - info->rx_bd_base) * RX_BUF_SIZE);
 		status = bdp->cbd_sc;
 
 #ifdef CONFIG_KGDB
-		if (info->state->smc_scc_num == KGDB_SER_IDX) {
-			if (*cp == 0x03 || *cp == '$')
-				breakpoint();
+		if (info->state->smc_scc_num == KGDB_SER_IDX &&
+				(*cp == 0x03 || *cp == '$')) {
+			breakpoint();
 			return;
 		}
 #endif
@@ -420,7 +450,7 @@
 			icount->rx++;
 
 #ifdef SERIAL_DEBUG_INTR
-			printk("DR%02x:%02x...", ch, status);
+                        printk("DR%02x:%02x...", ch, status);
 #endif
 			*tty->flip.flag_buf_ptr = 0;
 			if (status & (BD_SC_BR | BD_SC_FR |
@@ -1033,7 +1063,7 @@
 			smcp->smc_smcmr = new_mode;
 	}
 
-	m8xx_cpm_setbrg((state - rs_table), baud_rate);
+	m8xx_cpm_setbrg(PORT_BRG(state->smc_scc_num), baud_rate);
 
 	restore_flags(flags);
 }
@@ -1042,6 +1072,8 @@
 {
 	ser_info_t *info = (ser_info_t *)tty->driver_data;
 	volatile cbd_t	*bdp;
+	unsigned char *cp;
+	unsigned long flags;
 
 	if (serial_paranoia_check(info, tty->device, "rs_put_char"))
 		return;
@@ -1049,21 +1081,22 @@
 	if (!tty)
 		return;
 
+	local_irq_save(flags);
 	bdp = info->tx_cur;
-	while (bdp->cbd_sc & BD_SC_READY);
-
-	*((char *)__va(bdp->cbd_bufaddr)) = ch;
-	bdp->cbd_datlen = 1;
-	bdp->cbd_sc |= BD_SC_READY;
-
 	/* Get next BD.
 	*/
 	if (bdp->cbd_sc & BD_SC_WRAP)
-		bdp = info->tx_bd_base;
+		info->tx_cur = info->tx_bd_base;
 	else
-		bdp++;
+		info->tx_cur = (cbd_t *)bdp + 1;
+	local_irq_restore(flags);
 
-	info->tx_cur = (cbd_t *)bdp;
+	while (bdp->cbd_sc & BD_SC_READY);
+
+	cp = info->tx_va_base + ((bdp - info->tx_bd_base) * TX_BUF_SIZE);
+	*cp = ch;
+	bdp->cbd_datlen = 1;
+	bdp->cbd_sc |= BD_SC_READY;
 
 }
 
@@ -1073,6 +1106,8 @@
 	int	c, ret = 0;
 	ser_info_t *info = (ser_info_t *)tty->driver_data;
 	volatile cbd_t *bdp;
+	unsigned char	*cp;
+	unsigned long flags;
 
 #ifdef CONFIG_KGDB_CONSOLE
         /* Try to let stub handle output. Returns true if it did. */
@@ -1086,43 +1121,50 @@
 	if (!tty)
 		return 0;
 
-	bdp = info->tx_cur;
-
 	while (1) {
 		c = MIN(count, TX_BUF_SIZE);
 
 		if (c <= 0)
 			break;
 
+		local_irq_save(flags);
+		bdp = info->tx_cur;
 		if (bdp->cbd_sc & BD_SC_READY) {
 			info->flags |= TX_WAKEUP;
+			local_irq_restore(flags);
 			break;
 		}
+		/* Get next BD.
+		 */
+		if (bdp->cbd_sc & BD_SC_WRAP)
+			info->tx_cur = info->tx_bd_base;
+		else
+			info->tx_cur = (cbd_t *)bdp + 1;
+		local_irq_restore(flags);
 
-		if (from_user) {
-			if (copy_from_user(__va(bdp->cbd_bufaddr), buf, c)) {
-				if (!ret)
-					ret = -EFAULT;
-				break;
-			}
-		} else {
-			memcpy(__va(bdp->cbd_bufaddr), buf, c);
-		}
+		cp = info->tx_va_base + ((bdp - info->tx_bd_base) *
+				TX_BUF_SIZE);
+		if (from_user)
+			c -= copy_from_user((void *)cp, buf, c);
+		else
+			memcpy((void *)cp, buf, c);
 
-		bdp->cbd_datlen = c;
-		bdp->cbd_sc |= BD_SC_READY;
+		if (c) {
+			bdp->cbd_datlen = c;
+			bdp->cbd_sc |= BD_SC_READY;
+		} else {
+			/* Need to TX at least 1 char to keep CPM sane */
+			bdp->cbd_datlen = 1;
+			*cp = 0;
+			bdp->cbd_sc |= BD_SC_READY;
 
+			if (!ret)
+				ret = -EFAULT;
+			break;
+		}
 		buf += c;
 		count -= c;
 		ret += c;
-
-		/* Get next BD.
-		*/
-		if (bdp->cbd_sc & BD_SC_WRAP)
-			bdp = info->tx_bd_base;
-		else
-			bdp++;
-		info->tx_cur = (cbd_t *)bdp;
 	}
 	return ret;
 }
@@ -1181,27 +1223,29 @@
 static void rs_8xx_send_xchar(struct tty_struct *tty, char ch)
 {
 	volatile cbd_t	*bdp;
+	unsigned char	*cp;
+	unsigned long flags;
 
 	ser_info_t *info = (ser_info_t *)tty->driver_data;
 
 	if (serial_paranoia_check(info, tty->device, "rs_send_char"))
 		return;
 
+	local_irq_save(flags);
 	bdp = info->tx_cur;
-	while (bdp->cbd_sc & BD_SC_READY);
-
-	*((char *)__va(bdp->cbd_bufaddr)) = ch;
-	bdp->cbd_datlen = 1;
-	bdp->cbd_sc |= BD_SC_READY;
-
 	/* Get next BD.
 	*/
 	if (bdp->cbd_sc & BD_SC_WRAP)
-		bdp = info->tx_bd_base;
+		info->tx_cur = info->tx_bd_base;
 	else
-		bdp++;
+		info->tx_cur = (cbd_t *)bdp + 1;
+	local_irq_restore(flags);
+	while (bdp->cbd_sc & BD_SC_READY);
 
-	info->tx_cur = (cbd_t *)bdp;
+	cp = info->tx_va_base + ((bdp - info->tx_bd_base) * TX_BUF_SIZE);
+	*cp = ch;
+	bdp->cbd_datlen = 1;
+	bdp->cbd_sc |= BD_SC_READY;
 }
 
 /*
@@ -1772,7 +1816,7 @@
 static void rs_8xx_wait_until_sent(struct tty_struct *tty, int timeout)
 {
 	ser_info_t *info = (ser_info_t *)tty->driver_data;
-	unsigned long orig_jiffies, char_time;
+	unsigned long orig_jiffies, char_time, tst_res;
 	/*int lsr;*/
 	volatile cbd_t *bdp;
 
@@ -1807,6 +1851,7 @@
 	 * are empty.
 	 */
 	do {
+		unsigned long flags;
 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
 		printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
 #endif
@@ -1824,12 +1869,15 @@
 		 * is the buffer is available.  There are still characters
 		 * in the CPM FIFO.
 		 */
+		local_irq_save(flags);
 		bdp = info->tx_cur;
 		if (bdp == info->tx_bd_base)
 			bdp += (TX_NUM_FIFO-1);
 		else
 			bdp--;
-	} while (bdp->cbd_sc & BD_SC_READY);
+		tst_res = !!(bdp->cbd_sc & BD_SC_READY);
+		local_irq_restore(flags);
+	} while (tst_res);
 	current->state = TASK_RUNNING;
 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
 	printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
@@ -2217,6 +2265,11 @@
 
 #ifdef CONFIG_SERIAL_CONSOLE
 
+/* I need this just so I can store the virtual addresses and have
+ * common functions for the early console printing.
+ */
+static ser_info_t consinfo;
+
 /*
  * Print a string to the serial port trying not to disturb any possible
  * real use of the port...
@@ -2226,10 +2279,11 @@
 {
 	struct		serial_state	*ser;
 	ser_info_t			*info;
-	unsigned			i;
+	unsigned			i, c, cr_missing, max_tx_size;
 	volatile	cbd_t		*bdp, *bdbase;
 	volatile	smc_uart_t	*up;
 	volatile	u_char		*cp;
+	unsigned long                   flags;
 
 	ser = rs_table + idx;
 
@@ -2238,82 +2292,72 @@
 	 * we simply use the single buffer allocated.
 	 */
 	if ((info = (ser_info_t *)ser->info) != NULL) {
-		bdp = info->tx_cur;
 		bdbase = info->tx_bd_base;
-	}
-	else {
-		/* Pointer to UART in parameter ram.
-		*/
+	} else {
+		/* Pointer to UART in parameter ram. */
 		up = (smc_uart_t *)&cpmp->cp_dparam[ser->port];
 
-		/* Get the address of the host memory buffer.
-		 */
-		bdp = bdbase = (cbd_t *)&cpmp->cp_dpmem[up->smc_tbase];
-	}
+		/* Get the address of the host memory buffer.*/
+		info = &consinfo;
+		info->tx_bd_base = (cbd_t *)bdbase = (cbd_t *)&cpmp->cp_dpmem[up->smc_tbase];
+		info->tx_cur = (cbd_t *)bdbase;
+	}
+	max_tx_size = console_tx_buf_len;
+	cr_missing = 0;
+	while (1){
+		c = MIN(max_tx_size, count);
+		if (c <= 0)
+			break;
 
-	/*
-	 * We need to gracefully shut down the transmitter, disable
-	 * interrupts, then send our bytes out.
-	 */
+		local_irq_save(flags);
+		bdp = info->tx_cur;
+		bdbase = info->tx_bd_base;
+		if (bdp->cbd_sc & BD_SC_WRAP)
+			info->tx_cur = (cbd_t *)bdbase;
+		else
+			info->tx_cur = (cbd_t *)(bdp+1);
+		local_irq_restore(flags);
 
-	/*
-	 * Now, do each character.  This is not as bad as it looks
-	 * since this is a holding FIFO and not a transmitting FIFO.
-	 * We could add the complexity of filling the entire transmit
-	 * buffer, but we would just wait longer between accesses......
-	 */
-	for (i = 0; i < count; i++, s++) {
 		/* Wait for transmitter fifo to empty.
 		 * Ready indicates output is ready, and xmt is doing
 		 * that, not that it is ready for us to send.
 		 */
 		while (bdp->cbd_sc & BD_SC_READY);
 
-		/* Send the character out.
+		/* Send the characters out.
 		 * If the buffer address is in the CPM DPRAM, don't
 		 * convert it.
 		 */
 		if ((uint)(bdp->cbd_bufaddr) > (uint)IMAP_ADDR)
 			cp = (u_char *)(bdp->cbd_bufaddr);
 		else
-			cp = __va(bdp->cbd_bufaddr);
-		*cp = *s;
+			cp = info->tx_va_base + ((bdp - info->tx_bd_base) * TX_BUF_SIZE);
 
-		bdp->cbd_datlen = 1;
+		i=1; /* Keeps track of consumed TX buffer space */
+		if (cr_missing) {
+			/* Previus loop didn't have room for the CR, insert it first in this */
+			*cp++ = '\r';
+			i++;
+		}
+		cr_missing = 0;
+		for (; i <= c; i++) {
+			if ((*cp++ = *s++) != '\n')
+				continue; /* Copy bytes until a NewLine is found */
+			/* NewLine found, see if there is space in the TX buffer to add a CR */
+			if (i < max_tx_size) {
+				*cp++ = '\r'; /* yes, there is space to add a CR */
+				i++;
+			} else
+				cr_missing = 1; /* No space in the TX buffer,
+						   rember it so it can be inserted in the next loop */
+		}
+		count -= (c-cr_missing);
+		bdp->cbd_datlen = i-1;
 		bdp->cbd_sc |= BD_SC_READY;
 
-		if (bdp->cbd_sc & BD_SC_WRAP)
-			bdp = bdbase;
-		else
-			bdp++;
-
-		/* if a LF, also do CR... */
-		if (*s == 10) {
-			while (bdp->cbd_sc & BD_SC_READY);
-			cp = __va(bdp->cbd_bufaddr);
-			*cp = 13;
-			bdp->cbd_datlen = 1;
-			bdp->cbd_sc |= BD_SC_READY;
-
-			if (bdp->cbd_sc & BD_SC_WRAP) {
-				bdp = bdbase;
-			}
-			else {
-				bdp++;
-			}
-		}
 	}
-
-	/*
-	 * Finally, Wait for transmitter & holding register to empty
-	 *  and restore the IER
-	 */
-	while (bdp->cbd_sc & BD_SC_READY);
-
-	if (info)
-		info->tx_cur = (cbd_t *)bdp;
+	/* while (bdp->cbd_sc & BD_SC_READY); is this really needed? */
 }
-
 static void serial_console_write(struct console *c, const char *s,
 				unsigned count)
 {
@@ -2358,10 +2402,13 @@
 	 * If the port has been initialized for general use, we must
 	 * use information from the port structure.
 	 */
-	if ((info = (ser_info_t *)ser->info))
+	if ((info = (ser_info_t *)ser->info)) {
 		bdp = info->rx_cur;
-	else
+	}
+	else {
 		bdp = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase];
+		info = &consinfo;
+	}
 
 	/*
 	 * We need to gracefully shut down the receiver, disable
@@ -2383,7 +2430,7 @@
 	if ((uint)(bdp->cbd_bufaddr) > (uint)IMAP_ADDR)
 		cp = (u_char *)(bdp->cbd_bufaddr);
 	else
-		cp = __va(bdp->cbd_bufaddr);
+		cp = info->rx_va_base + ((bdp - info->rx_bd_base) * RX_BUF_SIZE);
 
 	if (obuf) {
 		i = c = bdp->cbd_datlen;
@@ -2522,6 +2569,43 @@
 /*
  * The serial driver boot-time initialization code!
  */
+
+int __init rs_8xx_alloc_brg(int port)
+{
+    static int brg = 0;
+    volatile cpm8xx_t *cp = cpmp;
+    int res = brg;
+
+    /* "Wire" the BRG to the specified port
+    */
+    switch (port) {
+    case QUICC_CPM_SMC1:
+        cp->cp_simode = (cp->cp_simode & ~(0x07<<12)) | (brg<<12);
+        break;
+    case QUICC_CPM_SMC2:
+        cp->cp_simode = (cp->cp_simode & ~(0x07<<28)) | (brg<<28);
+        break;
+    case QUICC_CPM_SCC1:
+        cp->cp_sicr = (cp->cp_sicr & ~(0xFF<<0)) | (((brg<<3)|(brg<<0))<<0);
+        break;
+    case QUICC_CPM_SCC2:
+        cp->cp_sicr = (cp->cp_sicr & ~(0xFF<<8)) | (((brg<<3)|(brg<<0))<<8);
+        break;
+    case QUICC_CPM_SCC3:
+        cp->cp_sicr = (cp->cp_sicr & ~(0xFF<<16)) | (((brg<<3)|(brg<<0))<<16);
+        break;
+    case QUICC_CPM_SCC4:
+        cp->cp_sicr = (cp->cp_sicr & ~(0xFF<<24)) | (((brg<<3)|(brg<<0))<<24);
+        break;
+    }
+    /* Consume this BRG - Note: the last BRG will be reused if this
+    */
+    /* function is called too many times!
+    */
+    if (brg < QUICC_MAX_BRG) brg++;
+    return res;
+}
+
 int __init rs_8xx_init(void)
 {
 	struct serial_state * state;
@@ -2668,9 +2752,12 @@
 		state->icount.rx = state->icount.tx = 0;
 		state->icount.frame = state->icount.parity = 0;
 		state->icount.overrun = state->icount.brk = 0;
-		printk(KERN_INFO "ttyS%02d at 0x%04x is a %s\n",
+                PORT_BRG_SET(state->smc_scc_num, rs_8xx_alloc_brg(state->smc_scc_num));
+		printk(KERN_INFO "ttyS%d at 0x%04x is on %s%d using BRG%d\n",
 		       i, (unsigned int)(state->port),
-		       PORT_IS_SCC(state->smc_scc_num) ? "SCC" : "SMC");
+		       PORT_IS_SCC(state->smc_scc_num) ? "SCC" : "SMC",
+                       PORT_NUM(state->smc_scc_num)+1,
+                       PORT_BRG(state->smc_scc_num)+1);
 #ifdef CONFIG_SERIAL_CONSOLE
 		/* If we just printed the message on the console port, and
 		 * we are about to initialize it for general use, we have
@@ -2704,6 +2791,7 @@
 			/* Allocate space for FIFOs in the host memory.
 			*/
 			mem_addr = m8xx_cpm_hostalloc(RX_NUM_FIFO * RX_BUF_SIZE);
+			info->rx_va_base = (unsigned char *)mem_addr;
 
 			/* Set the physical address of the host memory
 			 * buffers in the buffer descriptors, and the
@@ -2713,12 +2801,12 @@
 			info->rx_cur = info->rx_bd_base = (cbd_t *)bdp;
 
 			for (j=0; j<(RX_NUM_FIFO-1); j++) {
-				bdp->cbd_bufaddr = __pa(mem_addr);
+				bdp->cbd_bufaddr = iopa(mem_addr);
 				bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT;
 				mem_addr += RX_BUF_SIZE;
 				bdp++;
 			}
-			bdp->cbd_bufaddr = __pa(mem_addr);
+			bdp->cbd_bufaddr = iopa(mem_addr);
 			bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
 
 			idx = PORT_NUM(info->state->smc_scc_num);
@@ -2738,6 +2826,7 @@
 			/* Allocate space for FIFOs in the host memory.
 			*/
 			mem_addr = m8xx_cpm_hostalloc(TX_NUM_FIFO * TX_BUF_SIZE);
+			info->tx_va_base = (unsigned char *)mem_addr;
 
 			/* Set the physical address of the host memory
 			 * buffers in the buffer descriptors, and the
@@ -2747,12 +2836,12 @@
 			info->tx_cur = info->tx_bd_base = (cbd_t *)bdp;
 
 			for (j=0; j<(TX_NUM_FIFO-1); j++) {
-				bdp->cbd_bufaddr = __pa(mem_addr);
+				bdp->cbd_bufaddr = iopa(mem_addr);
 				bdp->cbd_sc = BD_SC_INTRPT;
 				mem_addr += TX_BUF_SIZE;
 				bdp++;
 			}
-			bdp->cbd_bufaddr = __pa(mem_addr);
+			bdp->cbd_bufaddr = iopa(mem_addr);
 			bdp->cbd_sc = (BD_SC_WRAP | BD_SC_INTRPT);
 
 			if (PORT_IS_SCC(info->state->smc_scc_num)) {
@@ -2846,12 +2935,14 @@
 				}
 #endif /* CONFIG_ALTSMC2 */
 
+#if 0
 				/* Connect the baud rate generator to the
 				 * SMC based upon index in rs_table.  Also
 				 * make sure it is connected to NMSI.
 				 */
 				cp->cp_simode &= ~(0xffff << (idx * 16));
 				cp->cp_simode |= (i << ((idx * 16) + 12));
+#endif
 
 				up->smc_tbase = dp_addr;
 
@@ -2903,11 +2994,11 @@
 
 			/* Set up the baud rate generator.
 			*/
-			m8xx_cpm_setbrg(i, baud_table[baud_idx]);
+                        m8xx_cpm_setbrg(PORT_BRG(state->smc_scc_num), baud_table[baud_idx]);
 
 		}
 	}
-
+	console_tx_buf_len = TX_BUF_SIZE;
 	return 0;
 }
 
@@ -2959,20 +3050,28 @@
 	 * from dual port ram, and a character buffer area from host mem.
 	 */
 
+	/* Allocate space for two FIFOs.  We can't allocate from host
+	 * memory yet because vm allocator isn't initialized
+	 * during this early console init.
+	 */
+	dp_addr = m8xx_cpm_dpalloc(2*EARLY_BUF_SIZE);
+	mem_addr = (uint)(&cpmp->cp_dpmem[dp_addr]);
+
 	/* Allocate space for two buffer descriptors in the DP ram.
 	*/
 	dp_addr = m8xx_cpm_dpalloc(sizeof(cbd_t) * 2);
 
-	/* Allocate space for two 2 byte FIFOs in the host memory.
-	*/
-	mem_addr = m8xx_cpm_hostalloc(8);
-
 	/* Set the physical address of the host memory buffers in
 	 * the buffer descriptors.
 	 */
 	bdp = (cbd_t *)&cp->cp_dpmem[dp_addr];
-	bdp->cbd_bufaddr = __pa(mem_addr);
-	(bdp+1)->cbd_bufaddr = __pa(mem_addr+4);
+	bdp->cbd_bufaddr = iopa(mem_addr);
+	(bdp+1)->cbd_bufaddr = iopa(mem_addr+4);
+
+	consinfo.rx_va_base = (unsigned char *) mem_addr;
+	consinfo.rx_bd_base = (cbd_t *) bdp;
+	consinfo.tx_va_base = (unsigned char *) (mem_addr + EARLY_BUF_SIZE);
+	consinfo.tx_bd_base = (cbd_t *) (bdp+1);
 
 	/* For the receive, set empty and wrap.
 	 * For transmit, set wrap.
@@ -3073,7 +3172,7 @@
 	/* Set up the baud rate generator.
 	*/
 	m8xx_cpm_setbrg((ser - rs_table), bd->bi_baudrate);
-
+	console_tx_buf_len = EARLY_BUF_SIZE;
 	return 0;
 }
 

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