xref: /netbsd/sys/arch/mipsco/obio/zs_kgdb.c (revision ce099b40)
1 /*	$NetBSD: zs_kgdb.c,v 1.7 2008/04/28 20:23:28 martin Exp $	*/
2 
3 /*-
4  * Copyright (c) 1996 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Gordon W. Ross and Wayne Knowles.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33  * Hooks for kgdb when attached via the z8530 driver
34  *
35  * To use this, build a kernel with: option KGDB, and
36  * boot that kernel with "-d".  (The kernel will call
37  * zs_kgdb_init, kgdb_connect.)  When the console prints
38  * "kgdb waiting..." you run "gdb -k kernel" and do:
39  *   (gdb) set remotebaud 19200
40  *   (gdb) target remote /dev/ttyb
41  */
42 
43 #include <sys/cdefs.h>
44 __KERNEL_RCSID(0, "$NetBSD: zs_kgdb.c,v 1.7 2008/04/28 20:23:28 martin Exp $");
45 
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/proc.h>
49 #include <sys/device.h>
50 #include <sys/conf.h>
51 #include <sys/ioctl.h>
52 #include <sys/kernel.h>
53 #include <sys/syslog.h>
54 #include <sys/kgdb.h>
55 
56 #include <dev/ic/z8530reg.h>
57 #include <machine/z8530var.h>
58 
59 /*
60  * Hooks for kgdb when attached via the z8530 driver
61  *
62  * To use this, build a kernel with: option KGDB, and
63  * boot that kernel with "-d".  (The kernel will call
64  * zs_kgdb_init, kgdb_connect.)  When the console prints
65  * "kgdb waiting..." you run "gdb -k kernel" and do:
66  *   (gdb) set remotebaud 19200
67  *   (gdb) target remote /dev/ttyb
68  */
69 
70 void zs_kgdb_init __P((void));
71 void zskgdb __P((struct zs_chanstate *cs));
72 
73 static void	zs_setparam __P((struct zs_chanstate *, int, int));
74 static struct	zsops zsops_kgdb;
75 
76 extern struct	zschan *zs_get_chan_addr (int zs_unit, int channel);
77 extern int	zs_getc __P((void *arg));
78 extern void	zs_putc __P((void *arg, int c));
79 
80 static u_char zs_kgdb_regs[16] = {
81 	0,	/* 0: CMD (reset, etc.) */
82 	0,	/* 1: No interrupts yet. */
83 	0,	/* 2: IVECT */
84 	ZSWR3_RX_8 | ZSWR3_RX_ENABLE,
85 	ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP,
86 	ZSWR5_TX_8 | ZSWR5_TX_ENABLE,
87 	0,	/* 6: TXSYNC/SYNCLO */
88 	0,	/* 7: RXSYNC/SYNCHI */
89 	0,	/* 8: alias for data port */
90 	ZSWR9_MASTER_IE | ZSWR9_NO_VECTOR,
91 	0,	/*10: Misc. TX/RX control bits */
92 	ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD,
93 	14,	/*12: BAUDLO (default=9600) */
94 	0,	/*13: BAUDHI (default=9600) */
95 	ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK,
96 	ZSWR15_BREAK_IE,
97 };
98 
99 static void
100 zs_setparam(cs, iena, rate)
101 	struct zs_chanstate *cs;
102 	int iena;
103 	int rate;
104 {
105 	int s, tconst;
106 
107 	memcpy(cs->cs_preg, zs_kgdb_regs, 16);
108 
109 	if (iena) {
110 		cs->cs_preg[1] = ZSWR1_RIE | ZSWR1_SIE;
111 	}
112 
113 	/* Initialize the speed, etc. */
114 	tconst = BPS_TO_TCONST(cs->cs_brg_clk, rate);
115 
116 	cs->cs_preg[5] |= ZSWR5_DTR | ZSWR5_RTS;
117 	cs->cs_preg[12] = tconst;
118 	cs->cs_preg[13] = tconst >> 8;
119 
120 	s = splhigh();
121 	zs_loadchannelregs(cs);
122 	splx(s);
123 }
124 
125 /*
126  * Set up for kgdb; called at boot time before configuration.
127  * KGDB interrupts will be enabled later when zs0 is configured.
128  * Called after cninit(), so printf() etc. works.
129  */
130 void
131 zs_kgdb_init()
132 {
133 	struct zschan *zc;
134 	int channel, unit;
135 	extern const struct cdevsw zstty_cdevsw;
136 
137 	if (cdevsw_lookup(kgdb_dev) != &zstty_cdevsw)
138 		return;
139 
140 	unit = (kgdb_dev & 2) ? 2 : 0;
141 	channel = kgdb_dev & 1;
142 	printf("zs_kgdb_init: attaching serial%d at %d baud\n",
143 		   (kgdb_dev & 3), kgdb_rate);
144 
145 	zc = zs_get_chan_addr(unit, channel);
146 
147 	/* Attach KGDB comms functions to this device */
148 	kgdb_attach(zs_getc, zs_putc, (void *)zc);
149 }
150 
151 /*
152  * This is a "hook" called by the MI zstty_attach driver
153  * to allow the tty to be "taken over" for exclusive use by kgdb.
154  * Return non-zero if this is the kgdb port.
155  *
156  * Set the speed to kgdb_rate, CS8, etc.
157  */
158 int
159 zs_check_kgdb(cs, dev)
160 	struct zs_chanstate *cs;
161 	int dev;
162 {
163 
164 	if (dev != kgdb_dev)
165 		return (0);
166 
167 	/*
168 	 * Yes, this is port in use by kgdb.
169 	 */
170 	cs->cs_private = NULL;
171 	cs->cs_ops = &zsops_kgdb;
172 
173 	/* Now set parameters. (interrupts enabled) */
174 	zs_setparam(cs, 1, kgdb_rate);
175 
176 	return (1);
177 }
178 
179 /*
180  * KGDB framing character received: enter kernel debugger.  This probably
181  * should time out after a few seconds to avoid hanging on spurious input.
182  */
183 void
184 zskgdb(cs)
185 	struct zs_chanstate *cs;
186 {
187 	int unit = minor(kgdb_dev);
188 
189 	printf("zstty%d: kgdb interrupt\n", unit);
190 	/* This will trap into the debugger. */
191 	kgdb_connect(1);
192 }
193 
194 
195 /****************************************************************
196  * Interface to the lower layer (zscc)
197  ****************************************************************/
198 
199 static void zs_kgdb_rxint __P((struct zs_chanstate *));
200 static void zs_kgdb_stint __P((struct zs_chanstate *, int));
201 static void zs_kgdb_txint __P((struct zs_chanstate *));
202 static void zs_kgdb_softint __P((struct zs_chanstate *));
203 
204 static struct zsops zsops_kgdb = {
205 	zs_kgdb_rxint,		/* receive char available */
206 	zs_kgdb_stint,		/* external/status */
207 	zs_kgdb_txint,		/* xmit buffer empty */
208 	zs_kgdb_softint,	/* process software interrupt */
209 };
210 
211 int kgdb_input_lost;
212 
213 static void
214 zs_kgdb_rxint(cs)
215 	struct zs_chanstate *cs;
216 {
217 	register u_char c, rr1;
218 
219 	/*
220 	 * First read the status, because reading the received char
221 	 * destroys the status of this char.
222 	 */
223 	rr1 = zs_read_reg(cs, 1);
224 	c = zs_read_data(cs);
225 
226 	if (rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) {
227 		/* Clear the receive error. */
228 		zs_write_csr(cs, ZSWR0_RESET_ERRORS);
229 	}
230 
231 	if (c == KGDB_START) {
232 		zskgdb(cs);
233 	} else {
234 		kgdb_input_lost++;
235 	}
236 }
237 
238 static void
239 zs_kgdb_txint(cs)
240 	register struct zs_chanstate *cs;
241 {
242 	register int rr0;
243 
244 	rr0 = zs_read_csr(cs);
245 	zs_write_csr(cs, ZSWR0_RESET_TXINT);
246 }
247 
248 static void
249 zs_kgdb_stint(cs, force)
250 	register struct zs_chanstate *cs;
251 	int force;
252 {
253 	register int rr0;
254 
255 	rr0 = zs_read_csr(cs);
256 	zs_write_csr(cs, ZSWR0_RESET_STATUS);
257 
258 	/*
259 	 * Check here for console break, so that we can abort
260 	 * even when interrupts are locking up the machine.
261 	 */
262 	if (rr0 & ZSRR0_BREAK) {
263 		zskgdb(cs);
264 	}
265 }
266 
267 static void
268 zs_kgdb_softint(cs)
269 	struct zs_chanstate *cs;
270 {
271 	printf("zs_kgdb_softint?\n");
272 }
273 
274 
275