The Pedigree Project  0.1
Pc.cc
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "Pc.h"
21 #if defined(ACPI)
22 #include "Acpi.h"
23 #endif
24 #if defined(SMP)
25 #include "Smp.h"
26 #endif
27 #if defined(APIC)
28 #include "Apic.h"
29 #endif
30 #include "Pic.h"
31 #include "Pit.h"
32 #include "Rtc.h"
33 #include "pedigree/kernel/Log.h"
34 #include "pedigree/kernel/machine/Bus.h"
35 #include "pedigree/kernel/machine/Controller.h"
36 #include "pedigree/kernel/machine/Device.h"
37 #include "pedigree/kernel/machine/Pci.h"
38 #include "pedigree/kernel/panic.h"
39 #include "pedigree/kernel/utilities/String.h"
40 #include "pedigree/kernel/utilities/Vector.h"
41 #include "pedigree/kernel/utilities/new"
42 
43 class IrqManager;
44 class Keyboard;
45 class SchedulerTimer;
46 class Serial;
47 class Timer;
48 class Vga;
49 
50 Pc Pc::m_Instance;
51 
53 {
54  // Initialise Vga
55  if (m_Vga.initialise() == false)
56  panic("Pc: Vga initialisation failed");
57 
58  // Initialise the Real-time Clock / CMOS (without IRQs).
59  Rtc &rtc = Rtc::instance();
60  if (rtc.initialise1() == false)
61  panic("Pc: Rtc initialisation phase 1 failed");
62 
63 // Initialise ACPI
64 #if defined(ACPI)
65  Acpi &acpi = Acpi::instance();
66  acpi.initialise();
67 #endif
68 
69 // Initialise SMP
70 #if defined(SMP)
71  Smp &smp = Smp::instance();
72  smp.initialise();
73 #endif
74 
75 // Check for a local APIC
76 #if defined(APIC)
77 
78  // Physical address of the local APIC
79  uint64_t localApicAddress = 0;
80 
81  // Get the Local APIC address & I/O APIC list from either the ACPI or the
82  // SMP tables
83  bool bLocalApicValid = false;
84 #if defined(ACPI)
85  if ((bLocalApicValid = acpi.validApicInfo()) == true)
86  localApicAddress = acpi.getLocalApicAddress();
87 #endif
88 #if defined(SMP)
89  if (bLocalApicValid == false && (bLocalApicValid = smp.valid()) == true)
90  localApicAddress = smp.getLocalApicAddress();
91 #endif
92 
93  // Initialise the local APIC, if we have gotten valid data from
94  // the ACPI/SMP structures
95  if (bLocalApicValid == true && localApicAddress &&
96  m_LocalApic.initialise(localApicAddress))
97  {
98  NOTICE("Local APIC initialised");
99  }
100 
101 #endif
102 
103 // Check for an I/O APIC
104 #if defined(APIC)
105 
106  // TODO: Check for I/O Apic
107  // TODO: Initialise the I/O Apic
108  // TODO: IMCR?
109  // TODO: Mask the PICs?
110  if (false)
111  {
112  }
113 
114  // Fall back to dual 8259 PICs
115  else
116  {
117 #endif
118 
119  NOTICE("Falling back to dual 8259 PIC Mode");
120 
121  // Initialise PIC
122  Pic &pic = Pic::instance();
123  if (pic.initialise() == false)
124  panic("Pc: Pic initialisation failed");
125 
126 #if defined(APIC)
127  }
128 #endif
129 
130  // Initialise serial ports.
131  m_pSerial[0].setBase(0x3F8);
132  m_pSerial[1].setBase(0x2F8);
133  m_pSerial[2].setBase(0x3E8);
134  m_pSerial[3].setBase(0x2E8);
135 
136  // Initialse the Real-time Clock / CMOS IRQs.
137  if (rtc.initialise2() == false)
138  panic("Pc: Rtc initialisation phase 2 failed");
139 
140  // Initialise the PIT
141  Pit &pit = Pit::instance();
142  if (pit.initialise() == false)
143  panic("Pc: Pit initialisation failed");
144 
145  // Set up PS/2
146  m_Ps2Controller.initialise();
147  m_Keyboard.initialise();
148 
149 // Find and parse the SMBIOS tables
150 #if defined(SMBIOS)
151  m_SMBios.initialise();
152 #endif
153 
154  m_bInitialised = true;
155 }
156 
157 void Pc::deinitialise()
158 {
159  m_bInitialised = false;
160 }
161 
162 #if defined(MULTIPROCESSOR)
163 void Pc::initialiseProcessor()
164 {
165  // TODO: we might need to initialise per-processor ACPI shit, no idea atm
166 
167  // Initialise the local APIC
168  if (m_LocalApic.initialiseProcessor() == false)
169  panic("Pc::initialiseProcessor(): Failed to initialise the local APIC");
170 }
171 #endif
172 
174 {
175  m_Keyboard.startReaderThread();
176 }
177 
179 {
180  // Firstly add the ISA bus.
181  m_IsaBus.setSpecificType(String("isa"));
182 
183  // ATA controllers.
184  m_AtaMaster.setSpecificType(String("ata"));
185  m_AtaMaster.addresses().pushBack(
186  new Device::Address(String("command"), 0x1F0, 8, true));
187  m_AtaMaster.addresses().pushBack(
188  new Device::Address(String("control"), 0x3F0, 8, true));
189  m_AtaMaster.setInterruptNumber(14);
190  m_IsaBus.addChild(&m_AtaMaster);
191  m_AtaMaster.setParent(&m_IsaBus);
192 
193  m_AtaSlave.setSpecificType(String("ata"));
194  m_AtaSlave.addresses().pushBack(
195  new Device::Address(String("command"), 0x170, 8, true));
196  m_AtaSlave.addresses().pushBack(
197  new Device::Address(String("control"), 0x370, 8, true));
198  m_AtaSlave.setInterruptNumber(15);
199  m_IsaBus.addChild(&m_AtaSlave);
200  m_AtaSlave.setParent(&m_IsaBus);
201 
202  // PS/2
203  m_Ps2Controller.setSpecificType(String("ps2"));
204  m_Ps2Controller.addresses().pushBack(
205  new Device::Address(String("ps2-base"), 0x60, 5, true));
206  m_Ps2Controller.setInterruptNumber(
207  1); // 12 for mouse, handled by the driver
208  m_IsaBus.addChild(&m_Ps2Controller);
209  m_Ps2Controller.setParent(&m_IsaBus);
210 
211  // IB700 Watchdog Timer
212  m_Watchdog.addresses().pushBack(
213  new Device::Address(String("ib700-base"), 0x441, 4, true));
214  m_IsaBus.addChild(&m_Watchdog);
215  m_Watchdog.setParent(&m_IsaBus);
216 
217  Device::addToRoot(&m_IsaBus);
218 
219  // Initialise the PCI interface
220  PciBus::instance().initialise();
221 }
222 
224 {
225  return &m_pSerial[n];
226 }
227 
229 {
230  return 4;
231 }
232 
233 Vga *Pc::getVga(size_t n)
234 {
235  return &m_Vga;
236 }
237 
239 {
240  return 1;
241 }
242 
243 IrqManager *Pc::getIrqManager()
244 {
245  return &Pic::instance();
246 }
247 
249 {
250 #ifdef MULTIPROCESSOR
251  return &m_LocalApic;
252 #else
253  return &Pit::instance();
254 #endif
255 }
256 
258 {
259  return &Rtc::instance();
260 }
261 
263 {
264  return m_pKeyboard;
265 }
266 
268 {
269  m_pKeyboard = kb;
270 }
271 
272 #ifdef MULTIPROCESSOR
273 void Pc::stopAllOtherProcessors()
274 {
275  m_LocalApic.interProcessorInterruptAllExcludingThis(
276  IPI_HALT_VECTOR, 0 /* Fixed delivery mode */);
277 }
278 #endif
279 
281  : m_Vga(0x3C0, 0xB8000), m_pKeyboard(0)
282 #if defined(SMBIOS)
283  ,
284  m_SMBios()
285 #endif
286 #if defined(APIC)
287  ,
288  m_LocalApic()
289 #endif
290  ,
291  m_Keyboard(&m_Ps2Controller), m_IsaBus("ISA"), m_Ps2Controller()
292 {
293  m_pKeyboard = &m_Keyboard;
294 }
296 {
297 }
virtual ~Pc()
Definition: Pc.cc:295
virtual void initialise3()
Called after processor startup - for thread creation etc.
Definition: Pc.cc:173
Definition: Pc.h:49
virtual void setKeyboard(Keyboard *kb)
Definition: Pc.cc:267
static Pic & instance()
Definition: mach_pc/Pic.h:46
Definition: Pit.h:36
virtual Timer * getTimer()
Definition: Pc.cc:257
virtual void setInterruptNumber(uintptr_t n)
Definition: Device.h:268
virtual Vector< Address * > & addresses()
Definition: Device.h:256
static void addToRoot(Device *device)
Definition: Device.cc:102
Definition: String.h:49
void initialise()
Definition: Pci.cc:59
virtual Serial * getSerial(size_t n)
Definition: Pc.cc:223
bool initialise1() INITIALISATION_ONLY
Definition: Rtc.cc:234
virtual Keyboard * getKeyboard()
Definition: Pc.cc:262
virtual void setBase(uintptr_t nBaseAddr)
virtual SchedulerTimer * getSchedulerTimer()
Definition: Pc.cc:248
virtual void setSpecificType(String str)
Definition: Device.h:174
#define NOTICE(text)
Definition: Log.h:74
void addChild(Device *pDevice)
Definition: Device.cc:127
static Pit & instance()
Definition: Pit.h:40
void setParent(Device *p)
Definition: Device.h:154
virtual size_t getNumVga()
Definition: Pc.cc:238
Pc() INITIALISATION_ONLY
Definition: Pc.cc:280
virtual size_t getNumSerial()
Definition: Pc.cc:228
bool initialise() INITIALISATION_ONLY
Definition: Pit.cc:45
void EXPORTED_PUBLIC panic(const char *msg) NORETURN
Definition: panic.cc:121
bool initialise2() INITIALISATION_ONLY
Definition: Rtc.cc:288
virtual void initialiseDeviceTree()
Definition: Pc.cc:178
virtual Vga * getVga(size_t n)
Definition: Pc.cc:233
virtual void initialise()
Initialises the device.
Definition: Rtc.h:42
bool initialise() INITIALISATION_ONLY
Definition: mach_pc/Pic.cc:131
virtual void initialise() INITIALISATION_ONLY
Definition: Pc.cc:52