import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / 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 #include <linux/config.h>
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