patch-2.4.21 linux-2.4.21/arch/ppc/8xx_io/uart.c
Next file: linux-2.4.21/arch/ppc/Makefile
Previous file: linux-2.4.21/arch/ppc/8xx_io/fec.c
Back to the patch index
Back to the overall index
- Lines: 319
- Date:
2003-06-13 07:51:31.000000000 -0700
- Orig file:
linux-2.4.20/arch/ppc/8xx_io/uart.c
- Orig date:
2002-08-02 17:39:43.000000000 -0700
diff -urN linux-2.4.20/arch/ppc/8xx_io/uart.c linux-2.4.21/arch/ppc/8xx_io/uart.c
@@ -1,7 +1,4 @@
/*
- * BK Id: SCCS/s.uart.c 1.23 12/29/01 14:50:03 trini
- */
-/*
* UART driver for MPC860 CPM SCC or SMC
* Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
*
@@ -44,15 +41,13 @@
#include <asm/8xx_immap.h>
#include <asm/mpc8xx.h>
#include <asm/commproc.h>
+#include <asm/irq.h>
+#include <asm/kgdb.h>
#ifdef CONFIG_MAGIC_SYSRQ
#include <linux/sysrq.h>
#endif
-#ifdef CONFIG_KGDB
-extern void breakpoint(void);
-extern void set_debug_traps(void);
-extern int kgdb_output_string (const char* s, unsigned int count);
-#endif
+extern int kgdb_output_string (const char* s, unsigned int count);
#ifdef CONFIG_SERIAL_CONSOLE
#include <linux/console.h>
@@ -134,6 +129,18 @@
#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)
+
+/* The serial port to use for KGDB. */
+#ifdef CONFIG_KGDB_TTYS1
+#define KGDB_SER_IDX 1 /* SCC1/SMC1 */
+#elif CONFIG_KGDB_TTYS2
+#define KGDB_SER_IDX 2 /* SCC2/SMC2 */
+#elif CONFIG_KGDB_TTYS3
+#define KGDB_SER_IDX 3 /* SCC4/SMC4 (future?) */
+#else /* Unset, or ttyS0, use SCC1/SMC1 */
+#define KGDB_SER_IDX 0
+#endif
/* Processors other than the 860 only get SMCs configured by default.
* Either they don't have SCCs or they are allocated somewhere else.
@@ -277,7 +284,7 @@
save_flags(flags); cli();
idx = PORT_NUM(info->state->smc_scc_num);
- if (info->state->smc_scc_num & NUM_IS_SCC) {
+ if (PORT_IS_SCC(info->state->smc_scc_num)) {
sccp = &cpmp->cp_scc[idx];
sccp->scc_sccm &= ~UART_SCCM_TX;
}
@@ -301,7 +308,7 @@
idx = PORT_NUM(info->state->smc_scc_num);
save_flags(flags); cli();
- if (info->state->smc_scc_num & NUM_IS_SCC) {
+ if (PORT_IS_SCC(info->state->smc_scc_num)) {
sccp = &cpmp->cp_scc[idx];
sccp->scc_sccm |= UART_SCCM_TX;
}
@@ -390,6 +397,14 @@
cp = (unsigned char *)__va(bdp->cbd_bufaddr);
status = bdp->cbd_sc;
+#ifdef CONFIG_KGDB
+ if (info->state->smc_scc_num == KGDB_SER_IDX) {
+ if (*cp == 0x03 || *cp == '$')
+ breakpoint();
+ return;
+ }
+#endif
+
/* Check to see if there is room in the tty buffer for
* the characters in our BD buffer. If not, we exit
* now, leaving the BD with the characters. We'll pick
@@ -615,7 +630,7 @@
/*
* This is the serial driver's interrupt routine for a single port
*/
-static void rs_8xx_interrupt(void *dev_id, struct pt_regs *regs)
+static void rs_8xx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
u_char events;
int idx;
@@ -626,7 +641,7 @@
info = (ser_info_t *)dev_id;
idx = PORT_NUM(info->state->smc_scc_num);
- if (info->state->smc_scc_num & NUM_IS_SCC) {
+ if (PORT_IS_SCC(info->state->smc_scc_num)) {
sccp = &cpmp->cp_scc[idx];
events = sccp->scc_scce;
if (events & SMCM_BRKE)
@@ -772,7 +787,7 @@
change_speed(info);
idx = PORT_NUM(info->state->smc_scc_num);
- if (info->state->smc_scc_num & NUM_IS_SCC) {
+ if (PORT_IS_SCC(info->state->smc_scc_num)) {
sccp = &cpmp->cp_scc[idx];
scup = (scc_uart_t *)&cpmp->cp_dparam[state->port];
scup->scc_genscc.scc_mrblr = RX_BUF_SIZE;
@@ -836,7 +851,7 @@
save_flags(flags); cli(); /* Disable interrupts */
idx = PORT_NUM(state->smc_scc_num);
- if (state->smc_scc_num & NUM_IS_SCC) {
+ if (PORT_IS_SCC(state->smc_scc_num)) {
sccp = &cpmp->cp_scc[idx];
sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
#ifdef CONFIG_SERIAL_CONSOLE
@@ -991,7 +1006,7 @@
*/
bits++;
idx = PORT_NUM(state->smc_scc_num);
- if (state->smc_scc_num & NUM_IS_SCC) {
+ if (PORT_IS_SCC(state->smc_scc_num)) {
sccp = &cpmp->cp_scc[idx];
new_mode = (sbits << 12) | scval;
prev_mode = sccp->scc_pmsr;
@@ -1059,7 +1074,7 @@
ser_info_t *info = (ser_info_t *)tty->driver_data;
volatile cbd_t *bdp;
-#ifdef CONFIG_KGDB
+#ifdef CONFIG_KGDB_CONSOLE
/* Try to let stub handle output. Returns true if it did. */
if (kgdb_output_string(buf, count))
return ret;
@@ -1390,7 +1405,7 @@
cp = cpmp;
idx = PORT_NUM(info->state->smc_scc_num);
- if (info->state->smc_scc_num & NUM_IS_SCC)
+ if (PORT_IS_SCC(info->state->smc_scc_num))
chan = scc_chan_map[idx];
else
chan = smc_chan_map[idx];
@@ -1407,7 +1422,7 @@
cp = cpmp;
idx = PORT_NUM(info->state->smc_scc_num);
- if (info->state->smc_scc_num & NUM_IS_SCC)
+ if (PORT_IS_SCC(info->state->smc_scc_num))
chan = scc_chan_map[idx];
else
chan = smc_chan_map[idx];
@@ -1712,7 +1727,7 @@
info->read_status_mask &= ~BD_SC_EMPTY;
if (info->flags & ASYNC_INITIALIZED) {
idx = PORT_NUM(info->state->smc_scc_num);
- if (info->state->smc_scc_num & NUM_IS_SCC) {
+ if (PORT_IS_SCC(info->state->smc_scc_num)) {
sccp = &cpmp->cp_scc[idx];
sccp->scc_sccm &= ~UART_SCCM_RX;
sccp->scc_gsmrl &= ~SCC_GSMRL_ENR;
@@ -1903,7 +1918,7 @@
*/
if ((filp->f_flags & O_NONBLOCK) ||
(tty->flags & (1 << TTY_IO_ERROR)) ||
- !(info->state->smc_scc_num & NUM_IS_SCC)) {
+ !(PORT_IS_SCC(info->state->smc_scc_num))) {
if (info->flags & ASYNC_CALLOUT_ACTIVE)
return -EBUSY;
info->flags |= ASYNC_NORMAL_ACTIVE;
@@ -2081,7 +2096,7 @@
ret = sprintf(buf, "%d: uart:%s port:%X irq:%d",
state->line,
- (state->smc_scc_num & NUM_IS_SCC) ? "SCC" : "SMC",
+ (PORT_IS_SCC(state->smc_scc_num)) ? "SCC" : "SMC",
(unsigned int)(state->port), state->irq);
if (!state->port || (state->type == PORT_UNKNOWN)) {
@@ -2302,7 +2317,7 @@
static void serial_console_write(struct console *c, const char *s,
unsigned count)
{
-#ifdef CONFIG_KGDB
+#ifdef CONFIG_KGDB_CONSOLE
/* Try to let stub handle output. Returns true if it did. */
if (kgdb_output_string(s, count))
return;
@@ -2319,14 +2334,7 @@
}
#endif
-#ifdef CONFIG_KGDB
-void
-putDebugChar(char ch)
-{
- my_console_write(0, &ch, 1);
-}
-#endif
-
+#if defined(CONFIG_KGDB) || defined(CONFIG_XMON)
/*
* Receive character from the serial port. This only works well
* before the port is initialized for real use.
@@ -2399,6 +2407,7 @@
return((int)c);
}
+#endif /* CONFIG_KGDB || CONFIG_XMON */
#ifdef CONFIG_XMON
int
@@ -2418,7 +2427,13 @@
static char kgdb_buf[RX_BUF_SIZE], *kgdp;
static int kgdb_chars;
-unsigned char
+void
+putDebugChar(char ch)
+{
+ my_console_write(0, &ch, 1);
+}
+
+char
getDebugChar(void)
{
if (kgdb_chars <= 0) {
@@ -2430,9 +2445,18 @@
return(*kgdp++);
}
-void kgdb_interruptible(int state)
+void kgdb_interruptible(int yes)
{
+ volatile smc_t *smcp;
+
+ smcp = &cpmp->cp_smc[KGDB_SER_IDX];
+
+ if (yes == 1)
+ smcp->smc_smcm |= SMCM_RX;
+ else
+ smcp->smc_smcm &= ~SMCM_RX;
}
+
void kgdb_map_scc(void)
{
struct serial_state *ser;
@@ -2459,7 +2483,7 @@
/* Allocate space for an input FIFO, plus a few bytes for output.
* Allocate bytes to maintain word alignment.
*/
- mem_addr = (uint)(&cpmp->cp_dpmem[0x1000]);
+ mem_addr = (uint)(&cpmp->cp_dpmem[0xa00]);
/* Set the physical address of the host memory buffers in
* the buffer descriptors.
@@ -2489,7 +2513,7 @@
return kmem_start;
}
-#endif
+#endif /* CONFIG_SERIAL_CONSOLE */
/* Index in baud rate table of the default console baud rate.
*/
@@ -2646,7 +2670,7 @@
state->icount.overrun = state->icount.brk = 0;
printk(KERN_INFO "ttyS%02d at 0x%04x is a %s\n",
i, (unsigned int)(state->port),
- (state->smc_scc_num & NUM_IS_SCC) ? "SCC" : "SMC");
+ PORT_IS_SCC(state->smc_scc_num) ? "SCC" : "SMC");
#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
@@ -2698,7 +2722,7 @@
bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
idx = PORT_NUM(info->state->smc_scc_num);
- if (info->state->smc_scc_num & NUM_IS_SCC) {
+ if (PORT_IS_SCC(info->state->smc_scc_num)) {
scp = &cp->cp_scc[idx];
sup = (scc_uart_t *)&cp->cp_dparam[state->port];
sup->scc_genscc.scc_rbase = dp_addr;
@@ -2731,7 +2755,7 @@
bdp->cbd_bufaddr = __pa(mem_addr);
bdp->cbd_sc = (BD_SC_WRAP | BD_SC_INTRPT);
- if (info->state->smc_scc_num & NUM_IS_SCC) {
+ if (PORT_IS_SCC(info->state->smc_scc_num)) {
sup->scc_genscc.scc_tbase = dp_addr;
/* Set up the uart parameters in the
@@ -2874,7 +2898,8 @@
/* Install interrupt handler.
*/
- cpm_install_handler(state->irq, rs_8xx_interrupt, info);
+ if ((request_irq(CPM_IRQ_OFFSET + state->irq, rs_8xx_interrupt, 0, cpm_int_name[state->irq], info)) != 0)
+ panic("Could not allocate UART IRQ!");
/* Set up the baud rate generator.
*/
@@ -2919,7 +2944,7 @@
cp = cpmp; /* Get pointer to Communication Processor */
idx = PORT_NUM(ser->smc_scc_num);
- if (ser->smc_scc_num & NUM_IS_SCC) {
+ if (PORT_IS_SCC(ser->smc_scc_num)) {
scp = &cp->cp_scc[idx];
sup = (scc_uart_t *)&cp->cp_dparam[ser->port];
}
@@ -2957,7 +2982,7 @@
/* Set up the uart parameters in the parameter ram.
*/
- if (ser->smc_scc_num & NUM_IS_SCC) {
+ if (PORT_IS_SCC(ser->smc_scc_num)) {
sup->scc_genscc.scc_rbase = dp_addr;
sup->scc_genscc.scc_tbase = dp_addr + sizeof(cbd_t);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)