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