NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: kern/40488: Unable to reboot Dell PE 2970
The following reply was made to PR kern/40488; it has been noted by GNATS.
From: "Greg A. Woods" <woods%planix.com@localhost>
To: Christos Zoulas <christos%zoulas.com@localhost>
Cc: NetBSD GNATS <gnats-bugs%NetBSD.org@localhost>
Subject: Re: kern/40488: Unable to reboot Dell PE 2970
Date: Mon, 26 Jan 2009 19:09:14 -0500
--pgp-sign-Multipart_Mon_Jan_26_19:09:13_2009-1
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: quoted-printable
At Mon, 26 Jan 2009 18:17:07 -0500, Christos Zoulas wrote:
Subject: Re: kern/40488: Unable to reboot Dell PE 2970
>=20
> And here's a patch that does that...
I've been using a similar change in netbsd-4 for a while too.
I have been working on one HP Proliant DL360(?) that still begins the
reboot OK, but then reports there's no system ROM and needs a reboot. I
don't know if the order of these attempts, or something else entirely,
might be causing that problem. I will debug it soon next time I get to
the physical machine.
Here are most of the changes I have in machdep.c now, minus the ones for
VGA_APERTURE:
Index: sys/arch/i386/i386/machdep.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvs/master/m-NetBSD/main/src/sys/arch/i386/i386/machdep.c,v
retrieving revision 1.586.2.5
diff -u -r1.586.2.5 machdep.c
--- sys/arch/i386/i386/machdep.c 28 Aug 2007 11:46:26 -0000
1.586.2.5
+++ sys/arch/i386/i386/machdep.c 13 Jan 2009 23:38:59 -0000
@@ -870,6 +891,7 @@
void
cpu_reboot(int howto, char *bootstr)
{
+ int keyval =3D 0;
=20
if (cold) {
howto |=3D RB_HALT;
@@ -877,6 +899,10 @@
}
=20
boothowto =3D howto;
+ /*
+ * XXX this bit, except for the "cold" check above, should be MI --
+ * i.e. back in kern/kern_xxx.c:sys_reboot()
+ */
if ((howto & RB_NOSYNC) =3D=3D 0 && waittime < 0) {
waittime =3D 0;
vfs_shutdown();
@@ -888,7 +914,7 @@
resettodr();
}
=20
- /* Disable interrupts. */
+ /* block interrupts. */
splhigh();
=20
/* Do a dump if requested. */
@@ -921,17 +947,16 @@
apm_set_powstate(NULL, APM_DEV_ALLDEVS, APM_SYS_OFF);
printf("WARNING: APM powerdown failed!\n");
/*
- * RB_POWERDOWN implies RB_HALT... fall into it...
+ * RB_POWERDOWN includes RB_HALT... fall into it...
*/
#endif
}
=20
if (howto & RB_HALT) {
- printf("\n");
- printf("The operating system has halted.\n");
- printf("Please press any key to reboot.\n\n");
+ printf("\nThe operating system has halted.\n"
+ "Please press any key to reboot.\n\n");
=20
-#ifdef BEEP_ONHALT
+#ifdef BEEP_ONHALT /* XXX could be: defined(BEEP_ONHALT_COUNT) && (BEEP_O=
NHALT_COUNT > 0) */
{
int c;
for (c =3D BEEP_ONHALT_COUNT; c > 0; c--) {
@@ -944,21 +969,61 @@
}
#endif
=20
- cnpollc(1); /* for proper keyboard command handling */
- if (cngetc() =3D=3D 0) {
- /* no console attached, so just hlt */
- for(;;) {
- __asm volatile("hlt");
+ cnpollc(1); /* for proper keyboard command handling without
+ * interrupts */
+ /*
+ * ACK!!! The line discipline does _NOT_ get used from within
+ * the kernel for console I/O (though it probably should be).
+ *
+ * If any output above went out too fast for the device
+ * connected to a serial console then we'll read a <CTRL-S>
+ * here, and/or perhaps a <CTRL-Q>, and we'll just have to
+ * ignore them.
+ */
+#define ASCII_XON 0x11
+#define ASCII_XOFF 0x13
+ do {
+ if ((keyval =3D cngetc()) =3D=3D 0) {
+ /*
+ * no console attached, or perhaps a BREAK
+ * condition caused a read error, so just
+ * invoke the HLT instruction and wait for the
+ * operator to push the reset (or power)
+ * button.
+ */
+ printf("\nCannot read from the console, calling
the HLT instruction.\n=
\n");
+ printf("RESET or power cycle the system to
reboot.\n\n");
+
+ goto cpu_halt;
}
- }
+#ifdef DEBUG
+ else if (keyval =3D=3D ASCII_XOFF || keyval =3D=3D
ASCII_XON) {
+ printf("(ignoring flow control char (0x%x)\n",
keyval);
+ /* XXX even this could trigger another XOFF,
sigh... */
+ }
+#endif
+ } while (keyval =3D=3D ASCII_XOFF || keyval =3D=3D ASCII_XON);
+
cnpollc(0);
}
=20
+#ifdef DEBUG /* XXX if booted with '-v' perhaps? */
+ if (keyval)
+ printf("(read key value 0x%x)\n\n", keyval);
+#endif
printf("rebooting...\n");
if (cpureset_delay > 0)
delay(cpureset_delay * 1000);
cpu_reset();
- for(;;) ;
+ printf("cpu_reset() returned, waiting for hardware to reset or be
reset..=
.\n\n");
+
+ cpu_halt:
+ /*
+ * XXX to halt or not to halt -- is one halt good enough?
+ */
+ for (;;) {
+ __asm volatile("hlt");
+ }
/*NOTREACHED*/
}
=20
@@ -2191,10 +2256,48 @@
#include <dev/ic/mc146818reg.h> /* for NVRAM POST */
#include <i386/isa/nvram.h> /* for NVRAM POST */
=20
+/* XXX some copied from sys/arch/x86/pci/pci_machdep.c, should be in <x86/=
include/pci_machdep.h> */
+/* XXX they're also used in sys/arch/i386/stand/lib/test/pci_user.c */
+#define PCI_MODE1_ENABLE 0x80000000UL
+#define PCI_MODE1_ADDRESS_REG 0x0cf8
+
+#define PCI_MODE1_RESET_CTL_REG 0x0cf9
+#define PCI_MODE1_DATA_REG 0x0cfc
+
+/*
+ * From Radisys 82600 High Integration Dual PCI System Controller Data Boo=
k:
+ *=20
+ * Bits 1 and 2 in this register are used by the 82600 to generate a hard =
reset
+ * or a soft reset. During a hard reset, the 82600 asserts CPURST# and LP=
RST#
+ * and resets its own core logic. BPRST# is also asserted if the 82600 is
+ * configured as the BPCI Central Resource. During a soft reset, the 82600
+ * only asserts INIT#.
+ *
+ * Bit Description
+ *
+ * 7:3 Reserved.
+ *
+ * 2 Reset CPU (RCPU) =81=AD R/W. A transition of this bit from a 0 to a 1
+ * initiates a reset. The type of reset is determined by bit 1. This bit
+ * cannot be read as a 1.
+ *
+ * 1 System Reset (SRST) =81=AD R/W. This bit is used to select the type =
of
+ * reset generated when bit 2 in this register transitions to a 1. A
+ * value of 1 selects a hard reset and 0 selects a soft reset
+ *
+ * 0 Reserved.
+ */
+#define PCI_RESET_RCPU (1 << 2)
+#define PCI_RESET_SRST (1 << 1)
+
+#define PCAT_SYS_CTL_A 0x92 /* AT System Control Port A */
+#define PCAT_SYS_CTL_A_FRST 0x01 /* Fast Reset, aka Fast Init */
+
void
cpu_reset()
{
struct region_descriptor region;
+ u_int8_t reg8;
=20
disable_intr();
=20
@@ -2220,20 +2323,58 @@
* See AMD Geode SC1100 Processor Data Book, Revision 2.0,
* sections 6.3.1, 6.3.2, and 6.4.1.
*/
- if (cpu_info_primary.ci_signature =3D=3D 0x540) {
- outl(0xcf8, 0x80009044ul);
- outl(0xcfc, 0xf);
+ /* XXX OpenBSD puts this in
sys/arch/i386/pci/geodesc.c:sc1100_sysreset()=
*/
+ if (cpu_info_primary.ci_signature =3D=3D 0x540) { /* CPU_GEODE1100??? */
+ outl(PCI_MODE1_ADDRESS_REG, PCI_MODE1_ENABLE | 0x9044);
+ outl(PCI_MODE1_DATA_REG, 0xf);
+ }
+
+ /* XXX OpenBSD has ACPI reset stuff in sys/dev/acpi/acpi.c:acpi_reset()
*/
+
+ /*
+ * Try the PCI system & cpu reset _first_ (from FreeBSD and GNU/Linux)
+ *
+ * Write 0x6 to PCI Reset Control Register (0xcf9) to reset the CPU,
+ * the PCI controller itself, and to trigger a system-wide reset.
+ *
+ * This is the best method for all recent and modern systems that
+ * include any form of PCI controller.
+ */
+ reg8 =3D inb(PCI_MODE1_RESET_CTL_REG);
+ reg8 |=3D PCI_RESET_RCPU | PCI_RESET_SRST;
+ outb(PCI_MODE1_RESET_CTL_REG, reg8);
+ delay(500000); /* wait 0.5 sec to see if that did it */
+
+ /*
+ * Try reset by setting the 0x01 bit of the System Control Port A
+ * (0x92) (also from FreeBSD)
+ *
+ * This is the second-best way to reset any i386 system, and should
+ * work on everything back to the PC/AT.
+ *
+ * Note this doesn't work (or didn't) in VMware.
+ */
+ reg8 =3D inb(PCAT_SYS_CTL_A);
+ /* Check the the hardware actually has the port in question */
+ if (reg8 !=3D 0xff) {
+ /* FAST_INIT must be zero before a one can be written */
+ if ((reg8 & PCAT_SYS_CTL_A_FRST) !=3D 0)
+ outb(PCAT_SYS_CTL_A, reg8 & ~PCAT_SYS_CTL_A_FRST);
+ outb(PCAT_SYS_CTL_A, reg8 | PCAT_SYS_CTL_A_FRST);
+ delay(500000); /* wait 0.5 sec to see if that did it */
}
=20
/*
- * The keyboard controller has 4 random output pins, one of which is
- * connected to the RESET pin on the CPU in many PCs. We tell the
- * keyboard controller to pulse this line a couple of times.
+ * The keyboard controller has 4 output pins, one of which is connected
+ * to the CPU RESET line in many PCs. We tell the keyboard controller
+ * to pulse this line a couple of times.
+ *
+ * XXX FreeBSD only does it once, then waits for 0.5 sec
*/
outb(IO_KBD + KBCMDP, KBC_PULSE0);
delay(100000);
outb(IO_KBD + KBCMDP, KBC_PULSE0);
- delay(100000);
+ delay(500000);
=20
/*
* Try to cause a triple fault and watchdog reset by making the IDT
@@ -2244,7 +2385,8 @@
lidt(®ion);
__asm volatile("divl %0,%1" : : "q" (0), "a" (0));
=20
-#if 0
+#if 0 /* XXX FreeBSD and OpenBSD actually do resort to this as a last go */
+ /* XXX unfortunately PTD is no longer defined in NetBSD's
sys/arch/i386/i=
nclude/pmap.h.... */
/*
* Try to cause a triple fault and watchdog reset by unmapping the
* entire address space and doing a TLB flush.
@@ -2252,8 +2394,6 @@
memset((caddr_t)PTD, 0, PAGE_SIZE);
tlbflush();
#endif
-
- for (;;);
}
=20
void
--=20
Greg A. Woods
Planix, Inc.
<woods%planix.com@localhost> +1 416 489-5852 x122
http://www.planix.com/
--pgp-sign-Multipart_Mon_Jan_26_19:09:13_2009-1
Content-Type: application/pgp-signature
Content-Transfer-Encoding: 7bit
-----BEGIN PGP SIGNATURE-----
Version: PGPfreeware 5.0i for non-commercial use
MessageID: 1s7QRM50oH1Lz4lqelV5OjySez4cy+1K
iQA/AwUBSX5QqmZ9cbd4v/R/EQIyzwCgkElB92ReJAMKQASL/vACc4Oz3moAoN1o
iKFZ5JdwgQzglRMgMLrEePT4
=Wq+m
-----END PGP SIGNATURE-----
--pgp-sign-Multipart_Mon_Jan_26_19:09:13_2009-1--
Home |
Main Index |
Thread Index |
Old Index