1 2 #include "kernel/kernel.h" 3 4 #include <ctype.h> 5 #include <string.h> 6 #include <machine/cmos.h> 7 #include <machine/bios.h> 8 #include <machine/cpu.h> 9 #include <minix/portio.h> 10 #include <minix/cpufeature.h> 11 #include <sys/reboot.h> 12 #include <assert.h> 13 #include <signal.h> 14 #include <machine/vm.h> 15 16 #include <minix/u64.h> 17 18 #include "archconst.h" 19 #include "arch_proto.h" 20 #include "serial.h" 21 #include "oxpcie.h" 22 #include "direct_utils.h" 23 #include <machine/multiboot.h> 24 25 #ifdef USE_ACPI 26 #include "acpi.h" 27 #endif 28 29 #define KBCMDP 4 /* kbd controller port (O) */ 30 #define KBC_PULSE0 0xfe /* pulse output bit 0 */ 31 #define IO_KBD 0x060 /* 8042 Keyboard */ 32 33 int cpu_has_tsc; 34 35 void 36 reset(void) 37 { 38 uint8_t b; 39 /* 40 * The keyboard controller has 4 random output pins, one of which is 41 * connected to the RESET pin on the CPU in many PCs. We tell the 42 * keyboard controller to pulse this line a couple of times. 43 */ 44 outb(IO_KBD + KBCMDP, KBC_PULSE0); 45 busy_delay_ms(100); 46 outb(IO_KBD + KBCMDP, KBC_PULSE0); 47 busy_delay_ms(100); 48 49 /* 50 * Attempt to force a reset via the Reset Control register at 51 * I/O port 0xcf9. Bit 2 forces a system reset when it 52 * transitions from 0 to 1. Bit 1 selects the type of reset 53 * to attempt: 0 selects a "soft" reset, and 1 selects a 54 * "hard" reset. We try a "hard" reset. The first write sets 55 * bit 1 to select a "hard" reset and clears bit 2. The 56 * second write forces a 0 -> 1 transition in bit 2 to trigger 57 * a reset. 58 */ 59 outb(0xcf9, 0x2); 60 outb(0xcf9, 0x6); 61 busy_delay_ms(500); /* wait 0.5 sec to see if that did it */ 62 63 /* 64 * Attempt to force a reset via the Fast A20 and Init register 65 * at I/O port 0x92. Bit 1 serves as an alternate A20 gate. 66 * Bit 0 asserts INIT# when set to 1. We are careful to only 67 * preserve bit 1 while setting bit 0. We also must clear bit 68 * 0 before setting it if it isn't already clear. 69 */ 70 b = inb(0x92); 71 if (b != 0xff) { 72 if ((b & 0x1) != 0) 73 outb(0x92, b & 0xfe); 74 outb(0x92, b | 0x1); 75 busy_delay_ms(500); /* wait 0.5 sec to see if that did it */ 76 } 77 78 /* Triple fault */ 79 x86_triplefault(); 80 81 /* Give up on resetting */ 82 while(1) { 83 ; 84 } 85 } 86 87 static __dead void 88 halt(void) 89 { 90 for ( ; ; ) 91 halt_cpu(); 92 } 93 94 static __dead void 95 poweroff(void) 96 { 97 const char *shutdown_str; 98 99 #ifdef USE_ACPI 100 acpi_poweroff(); 101 #endif 102 /* Bochs/QEMU poweroff */ 103 shutdown_str = "Shutdown"; 104 while (*shutdown_str) outb(0x8900, *(shutdown_str++)); 105 106 /* VMware magic power off; likely to halt CPU */ 107 poweroff_vmware_clihlt(); 108 109 /* fallback option: hang */ 110 halt(); 111 } 112 113 __dead void arch_shutdown(int how) 114 { 115 unsigned char unused_ch; 116 /* Mask all interrupts, including the clock. */ 117 outb( INT_CTLMASK, ~0); 118 119 /* Empty buffer */ 120 while(direct_read_char(&unused_ch)) 121 ; 122 123 if(kinfo.minix_panicing) { 124 /* Printing is done synchronously over serial. */ 125 if (kinfo.do_serial_debug) 126 reset(); 127 128 /* Print accumulated diagnostics buffer and reset. */ 129 direct_cls(); 130 direct_print("Minix panic. System diagnostics buffer:\n\n"); 131 direct_print(kmess.kmess_buf); 132 direct_print("\nSystem has panicked, press any key to reboot"); 133 while (!direct_read_char(&unused_ch)) 134 ; 135 reset(); 136 } 137 138 if((how & RB_POWERDOWN) == RB_POWERDOWN) { 139 /* Power off if possible, hang otherwise */ 140 poweroff(); 141 NOT_REACHABLE; 142 } 143 144 if(how & RB_HALT) { 145 /* Hang */ 146 for (; ; ) halt_cpu(); 147 NOT_REACHABLE; 148 } 149 150 /* Reset the system by forcing a processor shutdown. 151 * First stop the BIOS memory test by setting a soft 152 * reset flag. 153 */ 154 reset(); 155 NOT_REACHABLE; 156 } 157 158 #ifdef DEBUG_SERIAL 159 void ser_putc(char c) 160 { 161 int i; 162 int lsr, thr; 163 164 #if CONFIG_OXPCIE 165 oxpcie_putc(c); 166 #else 167 lsr= COM1_LSR; 168 thr= COM1_THR; 169 for (i= 0; i<100000; i++) 170 { 171 if (inb( lsr) & LSR_THRE) 172 break; 173 } 174 outb( thr, c); 175 #endif 176 } 177 178 #endif 179