20 #include "Ps2Controller.h" 21 #include "pedigree/kernel/Log.h" 22 #include "pedigree/kernel/machine/Controller.h" 23 #include "pedigree/kernel/machine/Device.h" 24 #include "pedigree/kernel/machine/IrqManager.h" 25 #include "pedigree/kernel/machine/Machine.h" 26 #include "pedigree/kernel/machine/Trace.h" 27 #include "pedigree/kernel/processor/IoBase.h" 28 #include "pedigree/kernel/utilities/Vector.h" 29 #include "pedigree/kernel/utilities/assert.h" 32 :
Controller(pDev), m_pBase(0), m_bHasSecondPort(false),
33 m_FirstPortBuffer(16384), m_SecondPortBuffer(16384),
34 m_bFirstIrqEnabled(false), m_bSecondIrqEnabled(false), m_ConfigByte(0),
35 m_bDebugStateFirstIrqEnabled(false), m_bDebugStateSecondIrqEnabled(false)
39 Ps2Controller::Ps2Controller()
40 : m_FirstPortBuffer(16384), m_SecondPortBuffer(16384)
44 void Ps2Controller::initialise()
46 TRACE(
"PS2 Controller startup");
47 m_pBase = addresses()[0]->m_Io;
50 TRACE(
"PS2: disabling devices");
55 TRACE(
"PS2: disabling IRQs");
56 m_ConfigByte = sendCommandWithResponse(0x20);
57 m_ConfigByte = (m_ConfigByte & ~0x3) |
59 sendCommand(0x60, m_ConfigByte);
61 m_bHasSecondPort = (m_ConfigByte & (1 << 5)) != 0;
63 TRACE(
"PS2: performing self-test");
64 uint8_t selfTestResponse = sendCommandWithResponse(0xAA);
65 NOTICE(
"PS/2: self-test response: " <<
Hex << selfTestResponse);
68 TRACE(
"PS2: enabling ports");
73 TRACE(
"PS2: resetting first device");
77 readFirstPort(status);
78 NOTICE(
"PS/2: first port reset result: " <<
Hex << ack <<
", " << status);
80 TRACE(
"PS2: resetting second device");
81 writeSecondPort(0xFF);
84 readSecondPort(status);
85 readSecondPort(extra);
87 "PS/2: second port reset result: " <<
Hex << ack <<
", " << status
90 IrqManager &irqManager = *Machine::instance().getIrqManager();
92 if (m_FirstIrqId == 0)
94 ERROR(
"PS/2: failed to register first IRQ handler!");
98 if (m_SecondIrqId == 0)
100 ERROR(
"PS/2: failed to register second IRQ handler!");
103 irqManager.
control(1, IrqManager::MitigationThreshold, 100);
104 irqManager.
control(12, IrqManager::MitigationThreshold, 100);
106 TRACE(
"PS2: startup complete");
112 m_pBase->write8(command, 4);
117 sendCommand(command);
120 m_pBase->write8(data, 0);
125 sendCommand(command);
129 return m_pBase->read8(0);
134 sendCommand(command, data);
138 return m_pBase->read8(0);
144 m_pBase->write8(byte, 0);
149 sendCommand(0xD4, byte);
154 return m_bHasSecondPort;
159 IrqManager &irqManager = *Machine::instance().getIrqManager();
162 m_bFirstIrqEnabled =
false;
163 m_bSecondIrqEnabled =
false;
164 irqManager.enable(1,
false);
165 irqManager.enable(12,
false);
168 uint8_t flagAdd = 0x40, flagRemove = ~0;
186 m_ConfigByte = sendCommandWithResponse(0x20);
187 NOTICE(
"Old config byte: " <<
Hex << m_ConfigByte);
188 m_ConfigByte |= flagAdd;
189 m_ConfigByte &= flagRemove;
190 NOTICE(
"New config byte: " <<
Hex << m_ConfigByte);
191 sendCommand(0x60, m_ConfigByte);
195 m_bFirstIrqEnabled = firstEnabled;
196 irqManager.enable(1, firstEnabled);
197 m_bSecondIrqEnabled = secondEnabled;
198 irqManager.enable(12, secondEnabled);
204 return m_pBase->read8();
207 uint8_t Ps2Controller::readByteNonBlock()
209 if ((m_pBase->read8(4) & 1) == 0)
213 return m_pBase->read8();
218 if (!m_bFirstIrqEnabled)
225 size_t numRead = m_FirstPortBuffer.read(&byte, 1, block);
231 if (!m_bSecondIrqEnabled)
238 size_t numRead = m_SecondPortBuffer.read(&byte, 1, block);
244 m_bDebugState = debugState;
247 IrqManager &irqManager = *Machine::instance().getIrqManager();
250 irqManager.enable(1,
false);
251 irqManager.enable(12,
false);
253 m_bDebugStateFirstIrqEnabled = m_bFirstIrqEnabled;
254 m_bDebugStateSecondIrqEnabled = m_bSecondIrqEnabled;
257 m_bFirstIrqEnabled =
false;
258 m_bSecondIrqEnabled =
false;
260 setIrqEnable(
false,
false);
263 if (m_bDebugStateSecondIrqEnabled)
266 writeSecondPort(0xF5);
273 m_bDebugStateFirstIrqEnabled, m_bDebugStateSecondIrqEnabled);
276 if (m_bDebugStateSecondIrqEnabled)
279 writeSecondPort(0xF4);
292 if ((m_pBase->read8(4) & 1) == 0)
294 ERROR(
"PS/2: IRQ #" << number <<
" with no pending data");
298 uint8_t received = readByte();
300 size_t numWritten = 0;
303 if (m_bFirstIrqEnabled)
305 m_FirstPortBuffer.write(&received, 1,
false);
311 if (m_bSecondIrqEnabled)
313 m_SecondPortBuffer.write(&received, 1,
false);
320 ERROR(
"PS/2: unexpected IRQ #" << number);
323 #ifdef VERBOSE_KERNEL 324 if (ok && !numWritten)
327 "PS/2: dropping byte " <<
Hex << received
328 <<
" from device, not enough buffer space");
335 void Ps2Controller::waitForReading()
338 while ((m_pBase->read8(4) & 1) == 0)
342 void Ps2Controller::waitForWriting()
345 while (m_pBase->read8(4) & 2)
virtual bool irq(irq_id_t number, InterruptState &state)
bool hasSecondPort() const
Reports whether this PS/2 controller has two ports.
uint8_t readByte()
Reads a single byte from the PS/2 controller by polling.
uint8_t sendCommandWithResponse(uint8_t command)
Send a command to the PS/2 controller and report its response.
void writeFirstPort(uint8_t byte)
Send a byte to the first port of the PS/2 controller.
EXPORTED_PUBLIC void setIrqEnable(bool firstEnabled, bool secondEnabled)
Enables/disables IRQs for the first or second ports.
void setDebugState(bool debugState)
Sets the debug state (blocks IRQs to allow polling).
EXPORTED_PUBLIC bool readSecondPort(uint8_t &byte, bool block=true)
Reads a single byte from the second port.
bool readFirstPort(uint8_t &byte, bool block=true)
Reads a single byte from the first port.
EXPORTED_PUBLIC void writeSecondPort(uint8_t byte)
Send a byte to the second port of the PS/2 controller.
virtual irq_id_t registerIsaIrqHandler(uint8_t irq, IrqHandler *handler, bool bEdge=false)=0
virtual bool control(uint8_t irq, ControlCode code, size_t argument)
void sendCommand(uint8_t command)
Send a command to the PS/2 controller that has no response or data.