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