File: /usr/src/linux/arch/mips/mips-boards/generic/gdb_hook.c

1     /*
2      * Carsten Langgaard, carstenl@mips.com
3      * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
4      *
5      * ########################################################################
6      *
7      *  This program is free software; you can distribute it and/or modify it
8      *  under the terms of the GNU General Public License (Version 2) as
9      *  published by the Free Software Foundation.
10      *
11      *  This program is distributed in the hope it will be useful, but WITHOUT
12      *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13      *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14      *  for more details.
15      *
16      *  You should have received a copy of the GNU General Public License along
17      *  with this program; if not, write to the Free Software Foundation, Inc.,
18      *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
19      *
20      * ########################################################################
21      *
22      * This is the interface to the remote debugger stub.
23      *
24      */
25     
26     #include <linux/serialP.h>
27     #include <linux/serial_reg.h>
28     
29     #include <asm/serial.h>
30     #include <asm/io.h>
31     
32     static struct serial_state rs_table[RS_TABLE_SIZE] = {
33     	SERIAL_PORT_DFNS	/* Defined in serial.h */
34     };
35     
36     static struct async_struct kdb_port_info = {0};
37     
38     int (*generic_putDebugChar)(char);
39     char (*generic_getDebugChar)(void);
40     
41     static __inline__ unsigned int serial_in(struct async_struct *info, int offset)
42     {
43     	return inb(info->port + offset);
44     }
45     
46     static __inline__ void serial_out(struct async_struct *info, int offset,
47     				int value)
48     {
49     	outb(value, info->port+offset);
50     }
51     
52     void rs_kgdb_hook(int tty_no) {
53     	int t;
54     	struct serial_state *ser = &rs_table[tty_no];
55     
56     	kdb_port_info.state = ser;
57     	kdb_port_info.magic = SERIAL_MAGIC;
58     	kdb_port_info.port = ser->port;
59     	kdb_port_info.flags = ser->flags;
60     
61     	/*
62     	 * Clear all interrupts
63     	 */
64     	serial_in(&kdb_port_info, UART_LSR);
65     	serial_in(&kdb_port_info, UART_RX);
66     	serial_in(&kdb_port_info, UART_IIR);
67     	serial_in(&kdb_port_info, UART_MSR);
68     
69     	/*
70     	 * Now, initialize the UART 
71     	 */
72     	serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8);	/* reset DLAB */
73     	if (kdb_port_info.flags & ASYNC_FOURPORT) {
74     		kdb_port_info.MCR = UART_MCR_DTR | UART_MCR_RTS;
75     		t = UART_MCR_DTR | UART_MCR_OUT1;
76     	} else {
77     		kdb_port_info.MCR 
78     			= UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
79     		t = UART_MCR_DTR | UART_MCR_RTS;
80     	}
81     
82     	kdb_port_info.MCR = t;		/* no interrupts, please */
83     	serial_out(&kdb_port_info, UART_MCR, kdb_port_info.MCR);
84     	
85     	/*
86     	 * and set the speed of the serial port
87     	 * (currently hardwired to 9600 8N1
88     	 */
89     
90     	/* baud rate is fixed to 9600 (is this sufficient?)*/
91     	t = kdb_port_info.state->baud_base / 9600;	
92     	/* set DLAB */
93     	serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8 | UART_LCR_DLAB);
94     	serial_out(&kdb_port_info, UART_DLL, t & 0xff);/* LS of divisor */
95     	serial_out(&kdb_port_info, UART_DLM, t >> 8);  /* MS of divisor */
96     	/* reset DLAB */
97     	serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8);
98     }
99     
100     int putDebugChar(char c)
101     {
102     	return generic_putDebugChar(c);
103     }
104     
105     char getDebugChar(void) 
106     {
107     	return generic_getDebugChar();
108     }
109     
110     int rs_putDebugChar(char c)
111     {
112     
113     	if (!kdb_port_info.state) { 	/* need to init device first */
114     		return 0;
115     	}
116     
117     	while ((serial_in(&kdb_port_info, UART_LSR) & UART_LSR_THRE) == 0)
118     		;
119     
120     	serial_out(&kdb_port_info, UART_TX, c);
121     
122     	return 1;
123     }
124     
125     char rs_getDebugChar(void)
126     {
127     	if (!kdb_port_info.state) { 	/* need to init device first */
128     		return 0;
129     	}
130     
131     	while (!(serial_in(&kdb_port_info, UART_LSR) & 1))
132     		;
133     
134     	return(serial_in(&kdb_port_info, UART_RX));
135     }
136     
137     
138     #ifdef CONFIG_MIPS_ATLAS
139     
140     #include <asm/mips-boards/atlas.h>
141     #include <asm/mips-boards/saa9730_uart.h>
142     
143     #define INB(a)     inb((unsigned long)a)
144     #define OUTB(x,a)  outb(x,(unsigned long)a)
145     
146     /*
147      * This is the interface to the remote debugger stub
148      * if the Philips part is used for the debug port,
149      * called from the platform setup code.
150      *
151      * PCI init will not have been done yet, we make a
152      * universal assumption about the way the bootloader (YAMON)
153      * have located and set up the chip.
154      */
155     static t_uart_saa9730_regmap *kgdb_uart = (void *)(ATLAS_SAA9730_REG + SAA9730_UART_REGS_ADDR);
156     
157     static int saa9730_kgdb_active = 0;
158     
159     void saa9730_kgdb_hook(void) 
160     {
161             volatile unsigned char t;
162     
163             /*
164              * Clear all interrupts
165              */
166     	t = INB(&kgdb_uart->Lsr);
167     	t += INB(&kgdb_uart->Msr);
168     	t += INB(&kgdb_uart->Thr_Rbr);
169     	t += INB(&kgdb_uart->Iir_Fcr);
170     
171             /*
172              * Now, initialize the UART
173              */
174     	/* 8 data bits, one stop bit, no parity */
175     	OUTB(SAA9730_LCR_DATA8, &kgdb_uart->Lcr);
176     
177             /* baud rate is fixed to 9600 (is this sufficient?)*/
178     	OUTB(0, &kgdb_uart->BaudDivMsb); /* HACK - Assumes standard crystal */
179     	OUTB(23, &kgdb_uart->BaudDivLsb); /* HACK - known for MIPS Atlas */
180     
181     	/* Set RTS/DTR active */
182     	OUTB(SAA9730_MCR_DTR | SAA9730_MCR_RTS, &kgdb_uart->Mcr);
183     	saa9730_kgdb_active = 1;
184     }
185     
186     int saa9730_putDebugChar(char c)
187     {
188     
189             if (!saa9730_kgdb_active) {     /* need to init device first */
190                     return 0;
191             }
192     
193             while (!(INB(&kgdb_uart->Lsr) & SAA9730_LSR_THRE))
194                     ;
195     	OUTB(c, &kgdb_uart->Thr_Rbr);
196     
197             return 1;
198     }
199     
200     char saa9730_getDebugChar(void)
201     {
202     	char c;
203     
204             if (!saa9730_kgdb_active) {     /* need to init device first */
205                     return 0;
206             }
207             while (!(INB(&kgdb_uart->Lsr) & SAA9730_LSR_DR))
208                     ;
209     
210     	c = INB(&kgdb_uart->Thr_Rbr);
211             return(c);
212     }
213     
214     #endif
215