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(&region);
        __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