]> 4ch.mooo.com Git - 16.git/blob - src/lib/doslib/hw/cpu/apiclib.c
added a bunch of things~ and midi stuff~
[16.git] / src / lib / doslib / hw / cpu / apiclib.c
1
2 #include <stdio.h>
3 #include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */
4 #include <stdlib.h>
5 #include <unistd.h>
6 #include <assert.h>
7 #include <string.h>
8 #include <setjmp.h>
9 #include <fcntl.h>
10 #include <dos.h>
11
12 #include <hw/cpu/cpu.h>
13 #include <hw/dos/dos.h>
14 #include <hw/dos/doswin.h>
15 #include <hw/flatreal/flatreal.h>
16
17 #include <hw/cpu/apiclib.h>
18
19 unsigned char                   apic_flags = 0;
20 uint32_t                        apic_base = 0;
21 const char*                     apic_error_str = NULL;
22
23 void forget_apic() {
24         apic_flags = 0; /* to permit re-probing */
25 }
26
27 int probe_apic() {
28         if (apic_flags == 0) {
29                 uint32_t reg;
30
31                 /* FIXME: Some say the APIC-like interface appeared in the late 486 era, though as a separate chip,
32                  *        unlike the Pentium and later that put the APIC on-chip. How do we detect those? */
33                 apic_flags = APIC_FLAG_PROBED;
34
35                 cpu_probe();
36                 if (cpu_basic_level < CPU_586) {
37                         apic_error_str = "APIC support requires at least a 586/Pentium class system";
38                         return 0;
39                 }
40                 detect_windows();
41                 if (windows_mode >= WINDOWS_STANDARD) {
42                         apic_error_str = "I will not attempt to play with the APIC from within Windows";
43                         apic_flags |= APIC_FLAG_CANT_DETECT;
44                         return 0;
45                 }
46                 if (cpu_v86_active) {
47                         apic_error_str = "I will not attempt to play with the APIC from virtual 8086 mode";
48                         apic_flags |= APIC_FLAG_CANT_DETECT;
49                         return 0;
50                 }
51                 if (!(cpu_flags & CPU_FLAG_CPUID)) {
52                         apic_error_str = "APIC detection requires CPUID";
53                         return 0;
54                 }
55                 if (!(cpu_cpuid_features.a.raw[2/*EDX*/] & (1UL << 9UL))) {
56                         apic_error_str = "CPU does not have on-chip APIC";
57                         return 0;
58                 }
59                 if (!(cpu_cpuid_features.a.raw[2/*EDX*/] & (1UL << 5UL))) {
60                         apic_error_str = "CPU does have on-chip APIC but no support for RDMSR/WRMSR";
61                         return 0;
62                 }
63
64                 reg = cpu_rdmsr(0x0000001B); /* hopefully, we do not crash */
65                 apic_base = (unsigned long)(reg & 0xFFFFF000UL);
66                 apic_flags |= APIC_FLAG_PRESENT;
67                 apic_flags |= (reg & (1UL << 11UL)) ? APIC_FLAG_GLOBAL_ENABLE : 0;
68                 apic_flags |= (reg & (1UL << 8UL)) ? APIC_FLAG_PROBE_ON_BOOT_CPU : 0;
69         }
70
71         return (apic_flags & APIC_FLAG_PRESENT)?1:0;
72 }
73