diff options
Diffstat (limited to 'sys/arch/i386')
-rw-r--r-- | sys/arch/i386/conf/files.i386 | 5 | ||||
-rw-r--r-- | sys/arch/i386/i386/kgdb_machdep.c | 260 | ||||
-rw-r--r-- | sys/arch/i386/i386/locore.s | 20 | ||||
-rw-r--r-- | sys/arch/i386/i386/machdep.c | 72 | ||||
-rw-r--r-- | sys/arch/i386/i386/trap.c | 44 | ||||
-rw-r--r-- | sys/arch/i386/include/db_machdep.h | 17 | ||||
-rw-r--r-- | sys/arch/i386/isa/pccom.c | 309 | ||||
-rw-r--r-- | sys/arch/i386/isa/pccomvar.h | 15 |
8 files changed, 645 insertions, 97 deletions
diff --git a/sys/arch/i386/conf/files.i386 b/sys/arch/i386/conf/files.i386 index cc0a5582421..69141251db9 100644 --- a/sys/arch/i386/conf/files.i386 +++ b/sys/arch/i386/conf/files.i386 @@ -1,4 +1,4 @@ -# $OpenBSD: files.i386,v 1.72 2000/11/07 18:21:21 mickey Exp $ +# $OpenBSD: files.i386,v 1.73 2001/01/24 09:38:00 hugh Exp $ # $NetBSD: files.i386,v 1.73 1996/05/07 00:58:36 thorpej Exp $ # # new style config file for i386 architecture @@ -15,7 +15,7 @@ file arch/i386/i386/autoconf.c file arch/i386/i386/conf.c file arch/i386/i386/db_disasm.c ddb file arch/i386/i386/db_interface.c ddb -file arch/i386/i386/db_memrw.c ddb +file arch/i386/i386/db_memrw.c ddb | kgdb file arch/i386/i386/db_trace.c ddb file arch/i386/i386/db_magic.s ddb file arch/i386/i386/disksubr.c disk @@ -23,6 +23,7 @@ file arch/i386/i386/gdt.c file arch/i386/i386/in_cksum.s inet file arch/i386/i386/ipx_cksum.c ipx file arch/i386/i386/machdep.c +file arch/i386/i386/kgdb_machdep.c kgdb file arch/i386/i386/math_emulate.c math_emulate file arch/i386/i386/mem.c file arch/i386/i386/i686_mem.c mtrr diff --git a/sys/arch/i386/i386/kgdb_machdep.c b/sys/arch/i386/i386/kgdb_machdep.c new file mode 100644 index 00000000000..690c83a794e --- /dev/null +++ b/sys/arch/i386/i386/kgdb_machdep.c @@ -0,0 +1,260 @@ +/* $OpenBSD: kgdb_machdep.c,v 1.1 2001/01/24 09:37:58 hugh Exp $ */ +/* $NetBSD: kgdb_machdep.c,v 1.6 1998/08/13 21:36:03 thorpej Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1996 Matthias Pfaller. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Matthias Pfaller. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(DDB) +#error "Can't build DDB and KGDB together." +#endif + +/* + * Machine-dependent functions for remote KGDB. Originally written + * for NetBSD/pc532 by Matthias Pfaller. Modified for NetBSD/i386 + * by Jason R. Thorpe. + */ + +#include <sys/param.h> +#include <sys/kgdb.h> +#include <sys/systm.h> + +#include <vm/vm.h> + +#include <machine/pte.h> +#include <machine/reg.h> +#include <machine/trap.h> + +/* + * Determine if the memory at va..(va+len) is valid. + */ +int +kgdb_acc(va, len) + vaddr_t va; + size_t len; +{ + vaddr_t last_va; + pt_entry_t *pte; + + last_va = va + len; + va &= ~PGOFSET; + last_va &= ~PGOFSET; + + do { + pte = kvtopte(va); + if ((*pte & PG_V) == 0) + return (0); + va += NBPG; + } while (va < last_va); + + return (1); +} + +/* + * Translate a trap number into a unix compatible signal value. + * (gdb only understands unix signal numbers). + */ +int +kgdb_signal(type) + int type; +{ + switch (type) { + case T_NMI: + return (SIGINT); + + case T_ALIGNFLT: + return (SIGILL); + + case T_BPTFLT: + case T_TRCTRAP: + return (SIGTRAP); + + case T_ASTFLT: + case T_DOUBLEFLT: + return (SIGEMT); + + case T_ARITHTRAP: + case T_DIVIDE: + case T_OFLOW: + case T_DNA: + case T_FPOPFLT: + return (SIGFPE); + + case T_PRIVINFLT: + case T_PROTFLT: + case T_PAGEFLT: + case T_TSSFLT: + case T_SEGNPFLT: + case T_STKFLT: + return (SIGSEGV); + + case T_BOUND: + return (SIGURG); + + default: + return (SIGEMT); + } +} + +/* + * Translate the values stored in the kernel regs struct to the format + * understood by gdb. + */ +void +kgdb_getregs(regs, gdb_regs) + db_regs_t *regs; + kgdb_reg_t *gdb_regs; +{ + + gdb_regs[ 0] = regs->tf_eax; + gdb_regs[ 1] = regs->tf_ecx; + gdb_regs[ 2] = regs->tf_edx; + gdb_regs[ 3] = regs->tf_ebx; + gdb_regs[ 5] = regs->tf_ebp; + gdb_regs[ 6] = regs->tf_esi; + gdb_regs[ 7] = regs->tf_edi; + gdb_regs[ 8] = regs->tf_eip; + gdb_regs[ 9] = regs->tf_eflags; + gdb_regs[10] = regs->tf_cs; + gdb_regs[12] = regs->tf_ds; + gdb_regs[13] = regs->tf_es; + + if (KERNELMODE(regs->tf_cs, regs->tf_eflags)) { + /* + * Kernel mode - esp and ss not saved. + */ + gdb_regs[ 4] = (kgdb_reg_t)®s->tf_esp; /* kernel stack + pointer */ + __asm __volatile("movw %%ss,%w0" : "=r" (gdb_regs[11])); + } +} + +/* + * Reverse the above. + */ +void +kgdb_setregs(regs, gdb_regs) + db_regs_t *regs; + kgdb_reg_t *gdb_regs; +{ + + regs->tf_eax = gdb_regs[ 0]; + regs->tf_ecx = gdb_regs[ 1]; + regs->tf_edx = gdb_regs[ 2]; + regs->tf_ebx = gdb_regs[ 3]; + regs->tf_ebp = gdb_regs[ 5]; + regs->tf_esi = gdb_regs[ 6]; + regs->tf_edi = gdb_regs[ 7]; + regs->tf_eip = gdb_regs[ 8]; + regs->tf_eflags = gdb_regs[ 9]; + regs->tf_cs = gdb_regs[10]; + regs->tf_ds = gdb_regs[12]; + regs->tf_es = gdb_regs[13]; + + if (KERNELMODE(regs->tf_cs, regs->tf_eflags) == 0) { + /* + * Trapped in user mode - restore esp and ss. + */ + regs->tf_esp = gdb_regs[ 4]; + regs->tf_ss = gdb_regs[11]; + } +} + +/* + * Trap into kgdb to wait for debugger to connect, + * noting on the console why nothing else is going on. + */ +void +kgdb_connect(verbose) + int verbose; +{ + + if (kgdb_dev < 0) + return; + + if (verbose) + printf("kgdb waiting..."); + + breakpoint(); + + if (verbose) + printf("connected.\n"); + + kgdb_debug_panic = 1; +} + +/* + * Decide what to do on panic. + * (This is called by panic, like Debugger()) + */ +void +kgdb_panic() +{ + if (kgdb_dev >= 0 && kgdb_debug_panic) { + printf("entering kgdb\n"); + kgdb_connect(kgdb_active == 0); + } +} diff --git a/sys/arch/i386/i386/locore.s b/sys/arch/i386/i386/locore.s index 956811b66d2..08a593267b2 100644 --- a/sys/arch/i386/i386/locore.s +++ b/sys/arch/i386/i386/locore.s @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.s,v 1.52 2000/06/16 19:11:25 millert Exp $ */ +/* $OpenBSD: locore.s,v 1.53 2001/01/24 09:37:58 hugh Exp $ */ /* $NetBSD: locore.s,v 1.145 1996/05/03 19:41:19 christos Exp $ */ /*- @@ -1984,13 +1984,8 @@ ENTRY(savectx) #define TRAP(a) pushl $(a) ; jmp _alltraps #define ZTRAP(a) pushl $0 ; TRAP(a) -#ifdef KGDB -#define BPTTRAP(a) testb $(PSL_I>>8),13(%esp) ; jz 1f ; sti ; 1: ; \ - pushl $(a) ; jmp _bpttraps -#else #define BPTTRAP(a) testb $(PSL_I>>8),13(%esp) ; jz 1f ; sti ; 1: ; \ TRAP(a) -#endif .text IDTVEC(div) @@ -2140,19 +2135,6 @@ calltrap: 4: .asciz "WARNING: SPL NOT LOWERED ON TRAP EXIT\n" #endif /* DIAGNOSTIC */ -#ifdef KGDB -/* - * This code checks for a kgdb trap, then falls through - * to the regular trap code. - */ -NENTRY(bpttraps) - INTRENTRY - testb $SEL_RPL,TF_CS(%esp) - jne calltrap - call _kgdb_trap_glue - jmp calltrap -#endif /* KGDB */ - /* * Old call gate entry for syscall */ diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c index 86a6155977a..dd19bcbb836 100644 --- a/sys/arch/i386/i386/machdep.c +++ b/sys/arch/i386/i386/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.142 2001/01/23 21:59:18 deraadt Exp $ */ +/* $OpenBSD: machdep.c,v 1.143 2001/01/24 09:37:58 hugh Exp $ */ /* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */ /*- @@ -112,6 +112,10 @@ #include <sys/shm.h> #endif +#ifdef KGDB +#include <sys/kgdb.h> +#endif + #include <dev/cons.h> #include <stand/boot/bootarg.h> @@ -169,6 +173,18 @@ extern struct proc *npxproc; #endif #include "bios.h" +#include "com.h" +#include "pccom.h" + +#if (NCOM > 0 || NPCCOM > 0) +#include <sys/termios.h> +#include <dev/ic/comreg.h> +#if NCOM > 0 +#include <dev/ic/comvar.h> +#elif NPCCOM > 0 +#include <arch/i386/isa/pccomvar.h> +#endif +#endif /* NCOM > 0 || NPCCOM > 0 */ /* * The following defines are for the code in setup_buffers that tries to @@ -270,6 +286,32 @@ void consinit __P((void)); int bus_mem_add_mapping __P((bus_addr_t, bus_size_t, int, bus_space_handle_t *)); +#ifdef KGDB +#ifndef KGDB_DEVNAME +#ifdef __i386__ +#define KGDB_DEVNAME "pccom" +#else +#define KGDB_DEVNAME "com" +#endif +#endif /* KGDB_DEVNAME */ +char kgdb_devname[] = KGDB_DEVNAME; +#if (NCOM > 0 || NPCCOM > 0) +#ifndef KGDBADDR +#define KGDBADDR 0x3f8 +#endif +int comkgdbaddr = KGDBADDR; +#ifndef KGDBRATE +#define KGDBRATE TTYDEF_SPEED +#endif +int comkgdbrate = KGDBRATE; +#ifndef KGDBMODE +#define KGDBMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */ +#endif +int comkgdbmode = KGDBMODE; +#endif /* NCOM || NPCCOM */ +void kgdb_port_init __P((void)); +#endif /* KGDB */ + #ifdef APERTURE #ifdef INSECURE int allowaperture = 1; @@ -327,7 +369,7 @@ cpu_startup() printf("%s", version); startrtclock(); - + identifycpu(); printf("real mem = %u (%uK)\n", ctob(physmem), ctob(physmem)/1024); @@ -1555,7 +1597,7 @@ boot(howto) if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) { /* Save registers. */ savectx(&dumppcb); - + dumpsys(); } @@ -2196,9 +2238,12 @@ init386(first_avail) Debugger(); #endif #ifdef KGDB - if (boothowto & RB_KDB) - kgdb_connect(0); -#endif + kgdb_port_init(); + if (boothowto & RB_KDB) { + kgdb_debug_init = 1; + kgdb_connect(1); + } +#endif /* KGDB */ } struct queue { @@ -2272,6 +2317,21 @@ consinit() cninit(); } +#ifdef KGDB +void +kgdb_port_init() +{ + +#if (NCOM > 0 || NPCCOM > 0) + if (!strcmp(kgdb_devname, "com") || !strcmp(kgdb_devname, "pccom")) { + bus_space_tag_t tag = I386_BUS_SPACE_IO; + com_kgdb_attach(tag, comkgdbaddr, comkgdbrate, COM_FREQ, + comkgdbmode); + } +#endif +} +#endif /* KGDB */ + void cpu_reset() { diff --git a/sys/arch/i386/i386/trap.c b/sys/arch/i386/i386/trap.c index df749a07675..c2ae880fa02 100644 --- a/sys/arch/i386/i386/trap.c +++ b/sys/arch/i386/i386/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.34 2000/11/10 18:15:38 art Exp $ */ +/* $OpenBSD: trap.c,v 1.35 2001/01/24 09:37:59 hugh Exp $ */ /* $NetBSD: trap.c,v 1.95 1996/05/05 06:50:02 mycroft Exp $ */ #undef DEBUG @@ -76,6 +76,10 @@ #include <machine/db_machdep.h> #endif +#ifdef KGDB +#include <sys/kgdb.h> +#endif + #ifdef COMPAT_IBCS2 #include <compat/ibcs2/ibcs2_errno.h> #include <compat/ibcs2/ibcs2_exec.h> @@ -231,7 +235,7 @@ trap(frame) /* trace trap */ case T_TRCTRAP: { -#ifdef DDB +#if defined(DDB) || defined(KGDB) /* Make sure nobody is single stepping into kernel land. * The syscall has to turn off the trace bit itself. The * easiest way, is to simply not call the debugger, until @@ -251,6 +255,21 @@ trap(frame) default: we_re_toast: +#ifdef KGDB + if (kgdb_trap(type, &frame)) + return; + else { + /* + * If this is a breakpoint, don't panic + * if we're not connected. + */ + if (type == T_BPTFLT) { + printf("kgdb: ignored %s\n", trap_type[type]); + return; + } + } +#endif + #ifdef DDB if (kdb_trap(type, 0, &frame)) return; @@ -512,6 +531,15 @@ trap(frame) break; } +#if 0 /* Should this be left out? */ +#if !defined(DDB) && !defined(KGDB) + /* XXX need to deal with this when DDB is present, too */ + case T_TRCTRAP: /* kernel trace trap; someone single stepping lcall's */ + /* syscall has to turn off the trace bit itself */ + return; +#endif +#endif + case T_BPTFLT|T_USER: /* bpt instruction fault */ sv.sival_int = rcr2(); trapsignal(p, SIGTRAP, type &~ T_USER, TRAP_BRKPT, sv); @@ -524,16 +552,22 @@ trap(frame) trapsignal(p, SIGTRAP, type &~ T_USER, TRAP_TRACE, sv); break; -#include "isa.h" #if NISA > 0 case T_NMI: case T_NMI|T_USER: -#ifdef DDB +#if defined(DDB) || defined(KGDB) /* NMI can be hooked up to a pushbutton for debugging */ printf ("NMI ... going to debugger\n"); - if (kdb_trap (type, 0, &frame)) +#ifdef KGDB + if (kgdb_trap(type, &frame)) return; #endif +#ifdef DDB + if (kdb_trap(type, 0, &frame)) + return; +#endif + return; +#endif /* DDB || KGDB */ /* machine/parity/power fail/"kitchen sink" faults */ if (isa_nmi() == 0) return; diff --git a/sys/arch/i386/include/db_machdep.h b/sys/arch/i386/include/db_machdep.h index 17dfa3ea682..277477aed04 100644 --- a/sys/arch/i386/include/db_machdep.h +++ b/sys/arch/i386/include/db_machdep.h @@ -1,4 +1,4 @@ -/* $OpenBSD: db_machdep.h,v 1.4 1997/08/07 09:09:38 niklas Exp $ */ +/* $OpenBSD: db_machdep.h,v 1.5 2001/01/24 09:38:01 hugh Exp $ */ /* $NetBSD: db_machdep.h,v 1.9 1996/05/03 19:23:59 christos Exp $ */ /* @@ -38,8 +38,8 @@ #include <vm/vm.h> #include <machine/trap.h> -typedef vm_offset_t db_addr_t; /* address - unsigned */ -typedef int db_expr_t; /* expression - signed */ +typedef vaddr_t db_addr_t; /* address - unsigned */ +typedef long db_expr_t; /* expression - signed */ typedef struct trapframe db_regs_t; db_regs_t ddb_regs; /* register state */ @@ -87,8 +87,8 @@ db_regs_t ddb_regs; /* register state */ ((user) && (addr) < VM_MAX_ADDRESS)) #if 0 -boolean_t db_check_access __P((vm_offset_t, int, task_t)); -boolean_t db_phys_eq __P((task_t, vm_offset_t, task_t, vm_offset_t)); +boolean_t db_check_access __P((vaddr_t, int, task_t)); +boolean_t db_phys_eq __P((task_t, vaddr_t, task_t, vaddr_t)); #endif /* macros for printing OS server dependent task name */ @@ -98,6 +98,13 @@ boolean_t db_phys_eq __P((task_t, vm_offset_t, task_t, vm_offset_t)); #define DB_TASK_NAME_LEN 23 #define DB_NULL_TASK_NAME "? " +/* + * Constants for KGDB. + */ +typedef long kgdb_reg_t; +#define KGDB_NUMREGS 14 +#define KGDB_BUFLEN 512 + #if 0 void db_task_name(/* task_t */); #endif diff --git a/sys/arch/i386/isa/pccom.c b/sys/arch/i386/isa/pccom.c index b114e47be10..8472de06ab0 100644 --- a/sys/arch/i386/isa/pccom.c +++ b/sys/arch/i386/isa/pccom.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pccom.c,v 1.35 2000/08/16 19:15:35 mickey Exp $ */ +/* $OpenBSD: pccom.c,v 1.36 2001/01/24 09:38:01 hugh Exp $ */ /* $NetBSD: com.c,v 1.82.4.1 1996/06/02 09:08:00 mrg Exp $ */ /* @@ -165,11 +165,16 @@ int comsopen = 0; int comevents = 0; #ifdef KGDB -#include <machine/remote-sl.h> -extern int kgdb_dev; -extern int kgdb_rate; -extern int kgdb_debug_init; -#endif +#include <sys/kgdb.h> + +static int com_kgdb_addr; +static bus_space_tag_t com_kgdb_iot; +static bus_space_handle_t com_kgdb_ioh; +static int com_kgdb_attached; + +int com_kgdb_getc __P((void *)); +void com_kgdb_putc __P((void *, int)); +#endif /* KGDB */ #define DEVUNIT(x) (minor(x) & 0x7f) #define DEVCUA(x) (minor(x) & 0x80) @@ -356,6 +361,11 @@ comprobe(parent, match, aux) #endif return(0); /* This cannot happen */ +#ifdef KGDB + if (iobase == com_kgdb_addr) + goto out; +#endif /* KGDB */ + /* if it's in use as console, it's there. */ if (iobase == comconsaddr && !comconsattached) goto out; @@ -417,11 +427,24 @@ comattach(parent, self, aux) /* No console support! */ ioh = ia->ia_ioh; } else { +#ifdef KGDB + if ((iobase != comconsaddr) && + (iobase != com_kgdb_addr)) { +#else if (iobase != comconsaddr) { +#endif /* KGDB */ if (bus_space_map(iot, iobase, COM_NPORTS, 0, &ioh)) panic("comattach: io mapping failed"); } else +#ifdef KGDB + if (iobase == comconsaddr) { + ioh = comconsioh; + } else { + ioh = com_kgdb_ioh; + } +#else ioh = comconsioh; +#endif /* KGDB */ } irq = ia->ia_irq; } else @@ -636,33 +659,40 @@ comattach(parent, self, aux) if (IS_ISA(parent) || IS_ISAPNP(parent)) { struct isa_attach_args *ia = aux; +#ifdef KGDB + if (iobase == com_kgdb_addr) { + sc->sc_ih = isa_intr_establish(ia->ia_ic, irq, + IST_EDGE, IPL_HIGH, kgdbintr, sc, + sc->sc_dev.dv_xname); + } else { + sc->sc_ih = isa_intr_establish(ia->ia_ic, irq, + IST_EDGE, IPL_HIGH, comintr, sc, + sc->sc_dev.dv_xname); + } +#else sc->sc_ih = isa_intr_establish(ia->ia_ic, irq, IST_EDGE, IPL_HIGH, comintr, sc, sc->sc_dev.dv_xname); +#endif /* KGDB */ } else #endif panic("comattach: IRQ but can't have one"); } #ifdef KGDB - if (kgdb_dev == makedev(commajor, unit)) { - if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) - kgdb_dev = -1; /* can't debug over console port */ - else { - cominit(iot, ioh, kgdb_rate); - if (kgdb_debug_init) { - /* - * Print prefix of device name, - * let kgdb_connect print the rest. - */ - printf("%s: ", sc->sc_dev.dv_xname); - kgdb_connect(1); - } else - printf("%s: kgdb enabled\n", - sc->sc_dev.dv_xname); - } + /* + * Allow kgdb to "take over" this port. If this is + * the kgdb device, it has exclusive use. + */ + + if (iot == com_kgdb_iot && iobase == com_kgdb_addr && + !ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) { + printf("%s: kgdb\n", sc->sc_dev.dv_xname); + SET(sc->sc_hwflags, COM_HW_KGDB); + com_enable_debugport(sc); + com_kgdb_attached = 1; } -#endif +#endif /* KGDB */ /* XXX maybe move up some? */ if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) @@ -678,6 +708,24 @@ comattach(parent, self, aux) sc->enabled = 1; } +#ifdef KGDB +void +com_enable_debugport(sc) + struct com_softc *sc; +{ + int s; + + /* Turn on line break interrupt, set carrier. */ + s = splhigh(); + SET(sc->sc_ier, IER_ERXRDY); + bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_ier, sc->sc_ier); + SET(sc->sc_mcr, MCR_DTR | MCR_RTS | MCR_IENABLE); + bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_mcr, sc->sc_mcr); + + splx(s); +} +#endif /* KGDB */ + int com_detach(self, flags) struct device *self; @@ -727,11 +775,11 @@ com_activate(self, act) break; case DVACT_DEACTIVATE: -#ifdef notyet +#ifdef KGDB if (sc->sc_hwflags & (COM_HW_CONSOLE|COM_HW_KGDB)) { #else - if (sc->sc_hwflags & (COM_HW_CONSOLE)) { -#endif + if (sc->sc_hwflags & COM_HW_CONSOLE) { +#endif /* KGDB */ rv = EBUSY; break; } @@ -766,6 +814,14 @@ comopen(dev, flag, mode, p) if (!sc) return ENXIO; +#ifdef KGDB + /* + * If this is the kgdb port, no other use is permitted. + */ + if (ISSET(sc->sc_hwflags, COM_HW_KGDB)) + return (EBUSY); +#endif /* KGDB */ + s = spltty(); if (!sc->sc_tty) { tp = sc->sc_tty = ttymalloc(); @@ -1642,6 +1698,62 @@ comsoft() } } +#ifdef KGDB + +/* + * If a line break is set, or data matches one of the characters + * gdb uses to signal a connection, then start up kgdb. Just gobble + * any other data. Done in a stand alone function because comintr + * does tty stuff and we don't have one. + */ + +int +kgdbintr(arg) + void *arg; +{ + struct com_softc *sc = arg; + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; + u_char lsr, data, msr, delta; + + if (!ISSET(sc->sc_hwflags, COM_HW_KGDB)) + return(0); + + for (;;) { + lsr = bus_space_read_1(iot, ioh, com_lsr); + if (ISSET(lsr, LSR_RXRDY)) { + do { + data = bus_space_read_1(iot, ioh, com_data); + if (data == 3 || data == '$' || data == '+' || + ISSET(lsr, LSR_BI)) { + kgdb_connect(1); + data = 0; + } + lsr = bus_space_read_1(iot, ioh, com_lsr); + } while (ISSET(lsr, LSR_RXRDY)); + + } + if (ISSET(lsr, LSR_BI|LSR_FE|LSR_PE|LSR_OE)) + printf("weird lsr %02x\n", lsr); + + msr = bus_space_read_1(iot, ioh, com_msr); + + if (msr != sc->sc_msr) { + delta = msr ^ sc->sc_msr; + sc->sc_msr = msr; + if (ISSET(delta, MSR_DCD)) { + if (!ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) { + CLR(sc->sc_mcr, sc->sc_dtr); + bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr); + } + } + } + if (ISSET(bus_space_read_1(iot, ioh, com_iir), IIR_NOPEND)) + return (1); + } +} +#endif /* KGDB */ + int comintr(arg) void *arg; @@ -1784,6 +1896,58 @@ comcnprobe(cp) #endif } +/* + * The following functions are polled getc and putc routines, shared + * by the console and kgdb glue. + */ + +int +com_common_getc(iot, ioh) + bus_space_tag_t iot; + bus_space_handle_t ioh; +{ + int s = splhigh(); + u_char stat, c; + + /* block until a character becomes available */ + while (!ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY)) + continue; + + c = bus_space_read_1(iot, ioh, com_data); + /* clear any interrupts generated by this transmission */ + stat = bus_space_read_1(iot, ioh, com_iir); + splx(s); + return (c); +} + +void +com_common_putc(iot, ioh, c) + bus_space_tag_t iot; + bus_space_handle_t ioh; + int c; +{ + int s = splhigh(); + int timo; + + /* wait for any pending transmission to finish */ + timo = 150000; + while (!ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_TXRDY) && --timo) + continue; + + bus_space_write_1(iot, ioh, com_data, c); + + /* wait for this transmission to complete */ + timo = 1500000; + while (!ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_TXRDY) && --timo) + continue; + + splx(s); +} + +/* + * Following are all routines needed for COM to act as console + */ + void comcninit(cp) struct consdev *cp; @@ -1793,11 +1957,12 @@ comcninit(cp) XXX NEEDS TO BE FIXED XXX comconsiot = ???; #endif - if (bus_space_map(comconsiot, CONADDR, COM_NPORTS, 0, &comconsioh)) + comconsaddr = CONADDR; + + if (bus_space_map(comconsiot, comconsaddr, COM_NPORTS, 0, &comconsioh)) panic("comcninit: mapping failed"); cominit(comconsiot, comconsioh, comdefaultrate); - comconsaddr = CONADDR; comconsinit = 0; } @@ -1811,12 +1976,14 @@ cominit(iot, ioh, rate) u_int8_t stat; bus_space_write_1(iot, ioh, com_lcr, LCR_DLAB); - rate = comspeed(comdefaultrate); + rate = comspeed(rate); /* XXX not comdefaultrate? */ bus_space_write_1(iot, ioh, com_dlbl, rate); bus_space_write_1(iot, ioh, com_dlbh, rate >> 8); bus_space_write_1(iot, ioh, com_lcr, LCR_8BITS); + bus_space_write_1(iot, ioh, com_mcr, MCR_DTR | MCR_RTS); bus_space_write_1(iot, ioh, com_ier, IER_ERXRDY | IER_ETXRDY); - bus_space_write_1(iot, ioh, com_fifo, FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_4); + bus_space_write_1(iot, ioh, com_fifo, + FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_4); stat = bus_space_read_1(iot, ioh, com_iir); splx(s); } @@ -1825,17 +1992,7 @@ int comcngetc(dev) dev_t dev; { - int s = splhigh(); - bus_space_tag_t iot = comconsiot; - bus_space_handle_t ioh = comconsioh; - u_int8_t stat, c; - - while (!ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY)) - ; - c = bus_space_read_1(iot, ioh, com_data); - stat = bus_space_read_1(iot, ioh, com_iir); - splx(s); - return c; + return (com_common_getc(comconsiot, comconsioh)); } /* @@ -1846,31 +2003,17 @@ comcnputc(dev, c) dev_t dev; int c; { - int s = splhigh(); +#if 0 + /* XXX not needed? */ bus_space_tag_t iot = comconsiot; bus_space_handle_t ioh = comconsioh; - u_int8_t stat; - register int timo; -#ifdef KGDB - if (dev != kgdb_dev) -#endif if (comconsinit == 0) { cominit(iot, ioh, comdefaultrate); comconsinit = 1; } - /* wait for any pending transmission to finish */ - timo = 50000; - while (!ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_TXRDY) && --timo) - ; - bus_space_write_1(iot, ioh, com_data, c); - /* wait for this transmission to complete */ - timo = 1500000; - while (!ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_TXRDY) && --timo) - ; - /* clear any interrupts generated by this transmission */ - stat = bus_space_read_1(iot, ioh, com_iir); - splx(s); +#endif + com_common_putc(comconsiot, comconsioh, c); } void @@ -1880,3 +2023,51 @@ comcnpollc(dev, on) { } + +#ifdef KGDB +int +com_kgdb_attach(iot, iobase, rate, frequency, cflag) + bus_space_tag_t iot; + int iobase; + int rate, frequency; + tcflag_t cflag; +{ + if (iot == comconsiot && iobase == comconsaddr) { + return (EBUSY); /* cannot share with console */ + } + + com_kgdb_iot = iot; + com_kgdb_addr = iobase; + + if (bus_space_map(com_kgdb_iot, com_kgdb_addr, COM_NPORTS, 0, + &com_kgdb_ioh)) + panic("com_kgdb_attach: mapping failed"); + + /* XXX We currently don't respect KGDBMODE? */ + cominit(com_kgdb_iot, com_kgdb_ioh, rate); + + kgdb_attach(com_kgdb_getc, com_kgdb_putc, NULL); + kgdb_dev = 123; /* unneeded, only to satisfy some tests */ + + return (0); +} + +/* ARGSUSED */ +int +com_kgdb_getc(arg) + void *arg; +{ + + return (com_common_getc(com_kgdb_iot, com_kgdb_ioh)); +} + +/* ARGSUSED */ +void +com_kgdb_putc(arg, c) + void *arg; + int c; +{ + + return (com_common_putc(com_kgdb_iot, com_kgdb_ioh, c)); +} +#endif /* KGDB */ diff --git a/sys/arch/i386/isa/pccomvar.h b/sys/arch/i386/isa/pccomvar.h index 1d3dbcfcf09..7f040715b04 100644 --- a/sys/arch/i386/isa/pccomvar.h +++ b/sys/arch/i386/isa/pccomvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pccomvar.h,v 1.10 2000/08/16 19:15:35 mickey Exp $ */ +/* $OpenBSD: pccomvar.h,v 1.11 2001/01/24 09:38:02 hugh Exp $ */ /* $NetBSD: comvar.h,v 1.5 1996/05/05 19:50:47 christos Exp $ */ /* @@ -56,6 +56,7 @@ struct com_softc { int sc_halt; int sc_iobase; + int sc_frequency; #ifdef COM_HAYESP int sc_hayespbase; #endif @@ -81,6 +82,7 @@ struct com_softc { #define COM_HW_FIFO 0x02 #define COM_HW_HAYESP 0x04 #define COM_HW_CONSOLE 0x40 +#define COM_HW_KGDB 0x80 u_char sc_swflags; #define COM_SW_SOFTCAR 0x01 #define COM_SW_CLOCAL 0x02 @@ -131,6 +133,17 @@ void comcninit __P((struct consdev *)); int comcngetc __P((dev_t)); void comcnputc __P((dev_t, int)); void comcnpollc __P((dev_t, int)); +int com_common_getc __P((bus_space_tag_t, bus_space_handle_t)); +void com_common_putc __P((bus_space_tag_t, bus_space_handle_t, int)); + +#if defined(DDB) || defined(KGDB) +void com_enable_debugport __P((struct com_softc *)); +#endif /* DDB || KGDB */ + +#ifdef KGDB +int com_kgdb_attach __P((bus_space_tag_t, int, int, int, tcflag_t)); +int kgdbintr __P((void *)); +#endif /* KGDB */ extern int comconsaddr; extern int comconsinit; |