1*c363a9cbScegger /* $NetBSD: zs_kgdb.c,v 1.12 2009/03/18 16:00:13 cegger Exp $ */ 20ac46816Sdbj 30ac46816Sdbj /*- 40ac46816Sdbj * Copyright (c) 1996 The NetBSD Foundation, Inc. 50ac46816Sdbj * All rights reserved. 60ac46816Sdbj * 70ac46816Sdbj * This code is derived from software contributed to The NetBSD Foundation 80ac46816Sdbj * by Gordon W. Ross. 90ac46816Sdbj * 100ac46816Sdbj * Redistribution and use in source and binary forms, with or without 110ac46816Sdbj * modification, are permitted provided that the following conditions 120ac46816Sdbj * are met: 130ac46816Sdbj * 1. Redistributions of source code must retain the above copyright 140ac46816Sdbj * notice, this list of conditions and the following disclaimer. 150ac46816Sdbj * 2. Redistributions in binary form must reproduce the above copyright 160ac46816Sdbj * notice, this list of conditions and the following disclaimer in the 170ac46816Sdbj * documentation and/or other materials provided with the distribution. 180ac46816Sdbj * 190ac46816Sdbj * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 200ac46816Sdbj * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 210ac46816Sdbj * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 220ac46816Sdbj * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 230ac46816Sdbj * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 240ac46816Sdbj * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 250ac46816Sdbj * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 260ac46816Sdbj * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 270ac46816Sdbj * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 280ac46816Sdbj * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 290ac46816Sdbj * POSSIBILITY OF SUCH DAMAGE. 300ac46816Sdbj */ 310ac46816Sdbj 320ac46816Sdbj /* 330ac46816Sdbj * Hooks for kgdb when attached via the z8530 driver 340ac46816Sdbj * 350ac46816Sdbj * To use this, build a kernel with: option KGDB, and 360ac46816Sdbj * boot that kernel with "-d". (The kernel will call 370ac46816Sdbj * zs_kgdb_init, kgdb_connect.) When the console prints 380ac46816Sdbj * "kgdb waiting..." you run "gdb -k kernel" and do: 390ac46816Sdbj * (gdb) set remotebaud 19200 400ac46816Sdbj * (gdb) target remote /dev/ttyb 410ac46816Sdbj */ 420ac46816Sdbj 434b2744bfSlukem #include <sys/cdefs.h> 44*c363a9cbScegger __KERNEL_RCSID(0, "$NetBSD: zs_kgdb.c,v 1.12 2009/03/18 16:00:13 cegger Exp $"); 454b2744bfSlukem 460ac46816Sdbj #include <sys/param.h> 470ac46816Sdbj #include <sys/systm.h> 480ac46816Sdbj #include <sys/proc.h> 490ac46816Sdbj #include <sys/device.h> 500ac46816Sdbj #include <sys/conf.h> 510ac46816Sdbj #include <sys/ioctl.h> 520ac46816Sdbj #include <sys/kernel.h> 530ac46816Sdbj #include <sys/syslog.h> 540ac46816Sdbj #include <sys/kgdb.h> 550ac46816Sdbj 560ac46816Sdbj #include <dev/ofw/openfirm.h> 570ac46816Sdbj #include <dev/ic/z8530reg.h> 580ac46816Sdbj #include <machine/z8530var.h> 590ac46816Sdbj 6002cdf4d2Sdsl static void zs_setparam(struct zs_chanstate *, int, int); 6102cdf4d2Sdsl static void zskgdb(struct zs_chanstate *); 620ac46816Sdbj 630ac46816Sdbj struct zsops zsops_kgdb; 640ac46816Sdbj 650ac46816Sdbj static u_char zs_kgdb_regs[16] = { 660ac46816Sdbj 0, /* 0: CMD (reset, etc.) */ 670ac46816Sdbj 0, /* 1: ~(ZSWR1_RIE | ZSWR1_TIE | ZSWR1_SIE) */ 680ac46816Sdbj 0, /* IVECT */ 690ac46816Sdbj ZSWR3_RX_8 | ZSWR3_RX_ENABLE, 700ac46816Sdbj ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP, 710ac46816Sdbj ZSWR5_TX_8 | ZSWR5_TX_ENABLE, 720ac46816Sdbj 0, /* 6: TXSYNC/SYNCLO */ 730ac46816Sdbj 0, /* 7: RXSYNC/SYNCHI */ 740ac46816Sdbj 0, /* 8: alias for data port */ 750ac46816Sdbj ZSWR9_MASTER_IE, 760ac46816Sdbj 0, /*10: Misc. TX/RX control bits */ 770ac46816Sdbj ZSWR11_TXCLK_BAUD | ZSWR11_RXCLK_BAUD, 780ac46816Sdbj ((PCLK/32)/38400)-2, /*12: BAUDLO (default=38400) */ 790ac46816Sdbj 0, /*13: BAUDHI (default=38400) */ 800ac46816Sdbj ZSWR14_BAUD_ENA, 810ac46816Sdbj ZSWR15_BREAK_IE, 820ac46816Sdbj }; 830ac46816Sdbj 840ac46816Sdbj /* 850ac46816Sdbj * This replaces "zs_reset()" in the sparc driver. 860ac46816Sdbj */ 870ac46816Sdbj static void 88454af1c0Sdsl zs_setparam(struct zs_chanstate *cs, int iena, int rate) 890ac46816Sdbj { 900ac46816Sdbj int s, tconst; 910ac46816Sdbj 920ac46816Sdbj bcopy(zs_kgdb_regs, cs->cs_preg, 16); 930ac46816Sdbj 940ac46816Sdbj if (iena) { 950ac46816Sdbj cs->cs_preg[1] = ZSWR1_RIE | ZSWR1_SIE; 960ac46816Sdbj } 970ac46816Sdbj 980ac46816Sdbj /* Initialize the speed, etc. */ 990ac46816Sdbj tconst = BPS_TO_TCONST(cs->cs_brg_clk, rate); 1000ac46816Sdbj cs->cs_preg[5] |= ZSWR5_DTR | ZSWR5_RTS; 1010ac46816Sdbj cs->cs_preg[12] = tconst; 1020ac46816Sdbj cs->cs_preg[13] = tconst >> 8; 1030ac46816Sdbj 1040ac46816Sdbj s = splhigh(); 1050ac46816Sdbj zs_loadchannelregs(cs); 1060ac46816Sdbj splx(s); 1070ac46816Sdbj } 1080ac46816Sdbj 1090ac46816Sdbj #ifndef KGDB_DEVNAME 1100ac46816Sdbj #define KGDB_DEVNAME "scca" 1110ac46816Sdbj #endif 1120ac46816Sdbj char *zs_kgdb_devname = KGDB_DEVNAME; 1130ac46816Sdbj /* 1140ac46816Sdbj * Set up for kgdb; called at boot time before configuration. 1150ac46816Sdbj * KGDB interrupts will be enabled later when zs0 is configured. 1160ac46816Sdbj * Called after cninit(), so printf() etc. works. 1170ac46816Sdbj */ 1180ac46816Sdbj void 119df7f595eScegger zs_kgdb_init(void) 1200ac46816Sdbj { 12177a6b82bSgehenna extern const struct cdevsw zstty_cdevsw; 1220ac46816Sdbj struct zs_chanstate cs; 1230ac46816Sdbj volatile struct zschan *zc; 1240ac46816Sdbj int escc, escc_ch, obio, zs_offset; 1250ac46816Sdbj int channel = 0; 1260ac46816Sdbj u_int32_t reg[5]; 1270ac46816Sdbj char name[16]; 1280ac46816Sdbj 1290ac46816Sdbj if ((escc_ch = OF_finddevice(zs_kgdb_devname)) == -1) 1300ac46816Sdbj return; 1310ac46816Sdbj 1320ac46816Sdbj memset(name, 0, sizeof(name)); 1330ac46816Sdbj if (OF_getprop(escc_ch, "device_type", name, sizeof(name)) == -1) 1340ac46816Sdbj return; 1350ac46816Sdbj 1360ac46816Sdbj if (strcmp(name, "serial") != 0) 1370ac46816Sdbj return; 1380ac46816Sdbj 1390ac46816Sdbj memset(name, 0, sizeof(name)); 1400ac46816Sdbj if (OF_getprop(escc_ch, "name", name, sizeof(name)) == -1) 1410ac46816Sdbj return; 1420ac46816Sdbj 1430ac46816Sdbj if (strcmp(name, "ch-b") == 0) 1440ac46816Sdbj channel = 1; 1450ac46816Sdbj 1460ac46816Sdbj if (OF_getprop(escc_ch, "reg", reg, sizeof(reg)) < 4) 1470ac46816Sdbj return; 1480ac46816Sdbj zs_offset = reg[0]; 1490ac46816Sdbj 1500ac46816Sdbj escc = OF_parent(escc_ch); 1510ac46816Sdbj obio = OF_parent(escc); 1520ac46816Sdbj 1530ac46816Sdbj if (OF_getprop(obio, "assigned-addresses", reg, sizeof(reg)) < 12) 1540ac46816Sdbj return; 1550ac46816Sdbj zc = (struct zschan *)(reg[2] + zs_offset); 1560ac46816Sdbj 15777a6b82bSgehenna kgdb_dev = makedev(cdevsw_lookup_major(&zstty_cdevsw), channel); 1580ac46816Sdbj 1590ac46816Sdbj printf("zs_kgdb_init: attaching tty%02d at %d baud\n", 1600ac46816Sdbj channel, kgdb_rate); 1610ac46816Sdbj 1620ac46816Sdbj /* Setup temporary chanstate. */ 163*c363a9cbScegger memset((void *)&cs, 0, sizeof(cs)); 1640ac46816Sdbj cs.cs_channel = channel; 1650ac46816Sdbj cs.cs_brg_clk = PCLK / 16; 1660ac46816Sdbj cs.cs_reg_csr = &zc->zc_csr; 1670ac46816Sdbj cs.cs_reg_data = &zc->zc_data; 1680ac46816Sdbj 1690ac46816Sdbj /* Now set parameters. (interrupts disabled) */ 1700ac46816Sdbj zs_setparam(&cs, 0, kgdb_rate); 1710ac46816Sdbj 1720ac46816Sdbj /* Store the getc/putc functions and arg. */ 1733d7f38ecShauke kgdb_attach(zs_getc, zs_putc, __UNVOLATILE(zc)); 1740ac46816Sdbj } 1750ac46816Sdbj 1760ac46816Sdbj /* 1770ac46816Sdbj * This is a "hook" called by zstty_attach to allow the tty 1780ac46816Sdbj * to be "taken over" for exclusive use by kgdb. 1790ac46816Sdbj * Return non-zero if this is the kgdb port. 1800ac46816Sdbj * 1810ac46816Sdbj * Set the speed to kgdb_rate, CS8, etc. 1820ac46816Sdbj */ 1830ac46816Sdbj int 184454af1c0Sdsl zs_check_kgdb(struct zs_chanstate *cs, int dev) 1850ac46816Sdbj { 1860ac46816Sdbj 1870ac46816Sdbj if (dev != kgdb_dev) 1880ac46816Sdbj return (0); 1890ac46816Sdbj 1900ac46816Sdbj /* 1910ac46816Sdbj * Yes, this is port in use by kgdb. 1920ac46816Sdbj */ 1930ac46816Sdbj cs->cs_private = NULL; 1940ac46816Sdbj cs->cs_ops = &zsops_kgdb; 1950ac46816Sdbj 1960ac46816Sdbj /* Now set parameters. (interrupts enabled) */ 1970ac46816Sdbj zs_setparam(cs, 1, kgdb_rate); 1980ac46816Sdbj 1990ac46816Sdbj return (1); 2000ac46816Sdbj } 2010ac46816Sdbj 2020ac46816Sdbj /* 2030ac46816Sdbj * KGDB framing character received: enter kernel debugger. This probably 2040ac46816Sdbj * should time out after a few seconds to avoid hanging on spurious input. 2050ac46816Sdbj */ 2060ac46816Sdbj static void 207454af1c0Sdsl zskgdb(struct zs_chanstate *cs) 2080ac46816Sdbj { 2090ac46816Sdbj int unit = minor(kgdb_dev); 2100ac46816Sdbj 2110ac46816Sdbj printf("zstty%d: kgdb interrupt\n", unit); 2120ac46816Sdbj /* This will trap into the debugger. */ 2130ac46816Sdbj kgdb_connect(1); 2140ac46816Sdbj } 2150ac46816Sdbj 2160ac46816Sdbj 2170ac46816Sdbj /**************************************************************** 2180ac46816Sdbj * Interface to the lower layer (zscc) 2190ac46816Sdbj ****************************************************************/ 2200ac46816Sdbj 22102cdf4d2Sdsl static void zs_kgdb_rxint(struct zs_chanstate *); 22202cdf4d2Sdsl static void zs_kgdb_stint(struct zs_chanstate *, int); 22302cdf4d2Sdsl static void zs_kgdb_txint(struct zs_chanstate *); 22402cdf4d2Sdsl static void zs_kgdb_softint(struct zs_chanstate *); 2250ac46816Sdbj 2260ac46816Sdbj int kgdb_input_lost; 2270ac46816Sdbj 2280ac46816Sdbj static void 229454af1c0Sdsl zs_kgdb_rxint(struct zs_chanstate *cs) 2300ac46816Sdbj { 2310ac46816Sdbj register u_char c, rr1; 2320ac46816Sdbj 2330ac46816Sdbj /* 2340ac46816Sdbj * First read the status, because reading the received char 2350ac46816Sdbj * destroys the status of this char. 2360ac46816Sdbj */ 2370ac46816Sdbj rr1 = zs_read_reg(cs, 1); 2380ac46816Sdbj c = zs_read_data(cs); 2390ac46816Sdbj 2400ac46816Sdbj if (rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) { 2410ac46816Sdbj /* Clear the receive error. */ 2420ac46816Sdbj zs_write_csr(cs, ZSWR0_RESET_ERRORS); 2430ac46816Sdbj } 2440ac46816Sdbj 2450ac46816Sdbj if (c == KGDB_START) { 2460ac46816Sdbj zskgdb(cs); 2470ac46816Sdbj } else { 2480ac46816Sdbj kgdb_input_lost++; 2490ac46816Sdbj } 2500ac46816Sdbj } 2510ac46816Sdbj 2520ac46816Sdbj static void 253454af1c0Sdsl zs_kgdb_txint(register struct zs_chanstate *cs) 2540ac46816Sdbj { 2550ac46816Sdbj register int rr0; 2560ac46816Sdbj 2570ac46816Sdbj rr0 = zs_read_csr(cs); 2580ac46816Sdbj zs_write_csr(cs, ZSWR0_RESET_TXINT); 2590ac46816Sdbj } 2600ac46816Sdbj 2610ac46816Sdbj static void 262454af1c0Sdsl zs_kgdb_stint(register struct zs_chanstate *cs, int force) 2630ac46816Sdbj { 2640ac46816Sdbj register int rr0; 2650ac46816Sdbj 2660ac46816Sdbj rr0 = zs_read_csr(cs); 2670ac46816Sdbj zs_write_csr(cs, ZSWR0_RESET_STATUS); 2680ac46816Sdbj 2690ac46816Sdbj /* 2700ac46816Sdbj * Check here for console break, so that we can abort 2710ac46816Sdbj * even when interrupts are locking up the machine. 2720ac46816Sdbj */ 2730ac46816Sdbj if (rr0 & ZSRR0_BREAK) { 2740ac46816Sdbj zskgdb(cs); 2750ac46816Sdbj } 2760ac46816Sdbj } 2770ac46816Sdbj 2780ac46816Sdbj static void 279454af1c0Sdsl zs_kgdb_softint(struct zs_chanstate *cs) 2800ac46816Sdbj { 2810ac46816Sdbj printf("zs_kgdb_softint?\n"); 2820ac46816Sdbj } 2830ac46816Sdbj 2840ac46816Sdbj struct zsops zsops_kgdb = { 2850ac46816Sdbj zs_kgdb_rxint, /* receive char available */ 2860ac46816Sdbj zs_kgdb_stint, /* external/status */ 2870ac46816Sdbj zs_kgdb_txint, /* xmit buffer empty */ 2880ac46816Sdbj zs_kgdb_softint, /* process software interrupt */ 2890ac46816Sdbj }; 290