Skip to content

Commit

Permalink
Simplify mux logic (#42)
Browse files Browse the repository at this point in the history
  • Loading branch information
1Revenger1 authored Oct 17, 2021
1 parent 25335ff commit 6f9a2b1
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 72 deletions.
105 changes: 39 additions & 66 deletions VoodooPS2Controller/VoodooPS2Controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ void ApplePS2Controller::onWatchdogTimer()
void ApplePS2Controller::handleInterrupt(bool watchdog)
{
// Loop only while there is data currently on the input stream.
bool wakePort[kPS2MaxIdx] {};
bool wakePort[kPS2MuxMaxIdx] {};

while (1)
{
Expand Down Expand Up @@ -202,21 +202,15 @@ void ApplePS2Controller::handleInterrupt(bool watchdog)
#endif

port = getPortFromStatus(status);
if (port >= kPS2MaxIdx || _devices[port] == nullptr)
{
continue;
}

if (kPS2IR_packetReady == _dispatchDriverInterrupt(port, data))
{
wakePort[port] = true;
}
} // while (forever)

// wake up workloop based mouse interrupt source if needed
size_t max_idx = _muxPresent ? kPS2MaxIdx : kPS2MuxIdx;
for (size_t i = kPS2KbdIdx; i < max_idx; i++) {
if (wakePort[i] && _devices[i] != nullptr)
for (size_t i = kPS2KbdIdx; i < _nubsCount; i++) {
if (wakePort[i])
{
_devices[i]->packetActionInterrupt();
}
Expand Down Expand Up @@ -422,6 +416,7 @@ void ApplePS2Controller::resetController(bool wakeup)
else if (!wakeup)
{
_muxPresent = setMuxMode(true);
_nubsCount = _muxPresent ? kPS2MuxMaxIdx : kPS2AuxMaxIdx;
}

resetDevices();
Expand Down Expand Up @@ -456,7 +451,7 @@ void ApplePS2Controller::resetDevices()
{
writeCommandPort(kCP_TransmitToMuxedMouse + i);
writeDataPort(kDP_SetDefaultsAndDisable);
readDataPort(kPS2MuxIdx + i); // (discard acknowledge; success irrelevant)
readDataPort(kPS2AuxIdx + i); // (discard acknowledge; success irrelevant)
}
}

Expand All @@ -477,24 +472,22 @@ void ApplePS2Controller::flushDataPort()
bool ApplePS2Controller::setMuxMode(bool enable)
{
UInt8 param = kDP_MuxCmd;
// getPortFromStatus will return kPS2MuxIdx when _muxPresent is true
size_t readPort = _muxPresent ? kPS2MuxIdx : kPS2AuxIdx;

writeCommandPort(kCP_WriteMouseOutputBuffer);
writeDataPort(param);
if (readDataPort(readPort) != param)
if (readDataPort(kPS2AuxIdx) != param)
return false;

param = enable ? kDP_EnableMuxCmd1 : kDP_DisableMuxCmd1;
writeCommandPort(kCP_WriteMouseOutputBuffer);
writeDataPort(param);
if (readDataPort(readPort) != param)
if (readDataPort(kPS2AuxIdx) != param)
return false;

param = enable ? kDP_GetMuxVersion : kDP_DisableMuxCmd2;
writeCommandPort(kCP_WriteMouseOutputBuffer);
writeDataPort(param);
UInt8 ver = readDataPort(readPort);
UInt8 ver = readDataPort(kPS2AuxIdx);

// We want the version on enable, and original command on disable
if ((enable && ver == param) ||
Expand Down Expand Up @@ -640,39 +633,21 @@ bool ApplePS2Controller::start(IOService * provider)
goto fail;
}


if (_muxPresent)
{
for (size_t i = kPS2MuxIdx; i < kPS2MaxIdx; i++)
{
_devices[i] = OSTypeAlloc(ApplePS2MouseDevice);
if ( !_devices[i] ||
!_devices[i]->init(i) ||
!_devices[i]->attach(this) )
{
OSSafeReleaseNULL(_devices[i]);
goto fail;
}
}
}
else
for (size_t i = kPS2AuxIdx; i < _nubsCount; i++)
{
_devices[kPS2AuxIdx] = OSTypeAlloc(ApplePS2MouseDevice);
if ( !_devices[kPS2AuxIdx] ||
!_devices[kPS2AuxIdx]->init(kPS2AuxIdx) ||
!_devices[kPS2AuxIdx]->attach(this) )
_devices[i] = OSTypeAlloc(ApplePS2MouseDevice);
if ( !_devices[i] ||
!_devices[i]->init(i) ||
!_devices[i]->attach(this) )
{
OSSafeReleaseNULL(_devices[kPS2AuxIdx]);
OSSafeReleaseNULL(_devices[i]);
goto fail;
}
}

for (size_t i = kPS2KbdIdx; i < kPS2MaxIdx; i++)
for (size_t i = kPS2KbdIdx; i < _nubsCount; i++)
{
if (_devices[i])
{
_devices[i]->registerService();
}
_devices[i]->registerService();
}

registerService();
Expand Down Expand Up @@ -734,7 +709,7 @@ void ApplePS2Controller::stop(IOService * provider)
OSSafeReleaseNULL(_notificationServices);

// Free the nubs we created.
for (size_t i = 0; i < kPS2MaxIdx; i++) {
for (size_t i = 0; i < kPS2MuxMaxIdx; i++) {
OSSafeReleaseNULL(_devices[i]);
}

Expand Down Expand Up @@ -969,7 +944,7 @@ void ApplePS2Controller::setCommandByteGated(PS2Request* request)

bool ApplePS2Controller::submitRequest(PS2Request * request)
{
assert(request->port < kPS2MaxIdx);
assert(request->port < kPS2MuxMaxIdx);

//
// Submit the request to the controller for processing, asynchronously.
Expand All @@ -987,7 +962,7 @@ bool ApplePS2Controller::submitRequest(PS2Request * request)

void ApplePS2Controller::submitRequestAndBlock(PS2Request * request)
{
assert(request->port < kPS2MaxIdx);
assert(request->port < kPS2MuxMaxIdx);

_cmdGate->runAction(OSMemberFunctionCast(IOCommandGate::Action, this, &ApplePS2Controller::submitRequestAndBlockGated), request);
}
Expand Down Expand Up @@ -1142,10 +1117,12 @@ void ApplePS2Controller::processRequest(PS2Request * request)
break;

case kPS2C_WriteDataPort:
if (devicePort == kPS2AuxIdx) {
writeCommandPort(kCP_TransmitToMouse);
} else if (devicePort > kPS2AuxIdx) {
writeCommandPort(kCP_TransmitToMuxedMouse + (devicePort - kPS2MuxIdx));
if (devicePort >= kPS2AuxIdx) {
if (_muxPresent) {
writeCommandPort(kCP_TransmitToMuxedMouse + (devicePort - kPS2AuxIdx));
} else {
writeCommandPort(kCP_TransmitToMouse);
}
}

writeDataPort(request->commands[index].inOrOut);
Expand All @@ -1160,10 +1137,12 @@ void ApplePS2Controller::processRequest(PS2Request * request)
//

case kPS2C_SendCommandAndCompareAck:
if (devicePort == kPS2AuxIdx) {
writeCommandPort(kCP_TransmitToMouse);
} else if (devicePort > kPS2AuxIdx) {
writeCommandPort(kCP_TransmitToMuxedMouse + (devicePort - kPS2MuxIdx));
if (devicePort >= kPS2AuxIdx) {
if (_muxPresent) {
writeCommandPort(kCP_TransmitToMuxedMouse + (devicePort - kPS2AuxIdx));
} else {
writeCommandPort(kCP_TransmitToMouse);
}
}

writeDataPort(request->commands[index].inOrOut);
Expand Down Expand Up @@ -1261,14 +1240,13 @@ void ApplePS2Controller::processRequestQueue(IOInterruptEventSource *, int)
size_t ApplePS2Controller::getPortFromStatus(UInt8 status)
{
bool auxPort = status & kMouseData;
if (_muxPresent && auxPort)
{
return kPS2MuxIdx + ((status >> 6) & 3);
}
else
{
return auxPort ? kPS2AuxIdx : kPS2KbdIdx;
size_t port = auxPort ? kPS2AuxIdx : kPS2KbdIdx;

if (_muxPresent && auxPort) {
port += (status >> PS2_STA_MUX_SHIFT) & PS2_STA_MUX_MASK;
}

return port;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Expand Down Expand Up @@ -1949,20 +1927,15 @@ void ApplePS2Controller::dispatchDriverPowerControl( UInt32 whatToDo, size_t por
{
// Should be called with kPS2Aux or kPS2Kbd.
// "port" set to kPS2Aux will run the power action for all mux ports
assert (port < kPS2MuxIdx);
assert (port < kPS2AuxMaxIdx);

if (port == kPS2KbdIdx)
{
_devices[kPS2KbdIdx]->powerAction(whatToDo);
return;
}

if (!_muxPresent) {
_devices[kPS2AuxIdx]->powerAction(whatToDo);
return;
}

for (size_t i = kPS2MuxIdx; i < kPS2MaxIdx; i++) {
for (size_t i = kPS2AuxIdx; i < _nubsCount; i++) {
_devices[i]->powerAction(whatToDo);
}
}
Expand Down
15 changes: 9 additions & 6 deletions VoodooPS2Controller/VoodooPS2Controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,19 +193,21 @@ enum {
};

// i8042 Mux indexes
#define PS2_MUX_IDX 2
#define PS2_MUX_PORTS 4

#define PS2_STA_MUX_MASK 0x03
#define PS2_STA_MUX_SHIFT 0x06

// Normally, the i8042 controller has 2 ports. With the mux active,
// there are 5 ports. 1 Keyboard port and 4 mux ports. All the muxed ports
// share the same IRQ. When the controller is in the multiplexer mode, the
// index for the aux port is skipped.
// share the same IRQ. When the controller is in a multiplexed mode, 3
// additional ports are added.

enum {
kPS2KbdIdx = 0,
kPS2AuxIdx = 1,
kPS2MuxIdx = PS2_MUX_IDX,
kPS2MaxIdx = PS2_MUX_IDX + PS2_MUX_PORTS
kPS2AuxMaxIdx = 2,
kPS2MuxMaxIdx = PS2_MUX_PORTS + 1
};

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Expand Down Expand Up @@ -248,7 +250,7 @@ class EXPORT ApplePS2Controller : public IOService
int _ignoreInterrupts {0};
int _ignoreOutOfOrder {0};

ApplePS2Device * _devices [kPS2MaxIdx] {nullptr};
ApplePS2Device * _devices [kPS2MuxMaxIdx] {nullptr};

IONotifier* _publishNotify {nullptr};
IONotifier* _terminateNotify {nullptr};
Expand All @@ -273,6 +275,7 @@ class EXPORT ApplePS2Controller : public IOService
int _wakedelay {10};
bool _mouseWakeFirst {false};
bool _muxPresent {false};
size_t _nubsCount {0};
IOCommandGate* _cmdGate {nullptr};
#if WATCHDOG_TIMER
IOTimerEventSource* _watchdogTimer {nullptr};
Expand Down

0 comments on commit 6f9a2b1

Please sign in to comment.