summaryrefslogtreecommitdiff
path: root/sys/arch/i386
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/i386')
-rw-r--r--sys/arch/i386/conf/files.i3865
-rw-r--r--sys/arch/i386/i386/kgdb_machdep.c260
-rw-r--r--sys/arch/i386/i386/locore.s20
-rw-r--r--sys/arch/i386/i386/machdep.c72
-rw-r--r--sys/arch/i386/i386/trap.c44
-rw-r--r--sys/arch/i386/include/db_machdep.h17
-rw-r--r--sys/arch/i386/isa/pccom.c309
-rw-r--r--sys/arch/i386/isa/pccomvar.h15
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)&regs->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;