void ApplePS2Mouse::stop(IOService * provider)
{
  //
  // The driver has been instructed to stop.  Note that we must break all
  // connections to other service objects now (ie. no registered actions,
  // no pointers and retains to objects, etc), if any.
  //

  assert(_device == provider);

  //
  // Disable the mouse itself, so that it may stop reporting mouse events.
  //

  setMouseEnable(false);

  //
  // Disable the mouse clock and the mouse IRQ line.
  //

  setCommandByte(kCB_DisableMouseClock, kCB_EnableMouseIRQ);

  //
  // Uninstall the interrupt handler.
  //

  if ( _interruptHandlerInstalled )  _device->uninstallInterruptAction();
  _interruptHandlerInstalled = false;

  //
  // Uninstall the power control handler.
  //

  if ( _powerControlHandlerInstalled ) _device->uninstallPowerControlAction();
  _powerControlHandlerInstalled = false;

  //
  // Uinstall message handler.
  //
  if (_messageHandlerInstalled)
  {
    _device->uninstallMessageAction();
    _messageHandlerInstalled = false;
  }
    
  //
  // Release the pointer to the provider object.
  //

  _device->release();
  _device = 0;

  super::stop(provider);
}
void ApplePS2Mouse::scheduleMouseReset()
{
  //
  // Request the mouse to stop. A 0xF5 command is issued.
  //

  setMouseEnable(false);

  //
  // Reset the mouse (synchronous).
  //

  resetMouse();
}
void ApplePS2Mouse::stop(IOService * provider)
{
  //
  // The driver has been instructed to stop.  Note that we must break all
  // connections to other service objects now (ie. no registered actions,
  // no pointers and retains to objects, etc), if any.
  //

  assert(_device == provider);

  //
  // Disable the mouse itself, so that it may stop reporting mouse events.
  //

  setMouseEnable(false);

  // free up the command gate
  IOWorkLoop* pWorkLoop = getWorkLoop();
  if (pWorkLoop)
  {
    if (_cmdGate)
    {
      pWorkLoop->removeEventSource(_cmdGate);
      _cmdGate->release();
      _cmdGate = 0;
    }
    if (_buttonTimer)
    {
      pWorkLoop->removeEventSource(_buttonTimer);
      _buttonTimer->release();
      _buttonTimer = 0;
    }
  }
    
  //
  // Uninstall the interrupt handler.
  //

  if ( _interruptHandlerInstalled )  _device->uninstallInterruptAction();
  _interruptHandlerInstalled = false;

  //
  // Uninstall the power control handler.
  //

  if ( _powerControlHandlerInstalled ) _device->uninstallPowerControlAction();
  _powerControlHandlerInstalled = false;

  //
  // Uinstall message handler.
  //
  if (_messageHandlerInstalled)
  {
    _device->uninstallMessageAction();
    _messageHandlerInstalled = false;
  }
    
  //
  // Release the pointer to the provider object.
  //

  OSSafeReleaseNULL(_device);;

  super::stop(provider);
}
void ApplePS2Mouse::resetMouse()
{
  PS2MouseId type;

  //
  // Reset the mouse to its default state.
  //

  PS2Request * request = _device->allocateRequest();
  if (request)
  {
    request->commands[0].command = kPS2C_SendMouseCommandAndCompareAck;
    request->commands[0].inOrOut = kDP_SetDefaults;
    request->commandsCount = 1;
    _device->submitRequestAndBlock(request);
    _device->freeRequest(request);
  }

  //
  // Obtain our mouse's resolution and sampling rate.
  //

  if (_mouseInfoBytes == (UInt32)-1)
  {
    _mouseInfoBytes = getMouseInformation();
    switch (_mouseInfoBytes & 0x00FF00)
    {
        case 0x0000: _resolution = (25)  << 16; break; //  25 dpi
        case 0x0100: _resolution = (50)  << 16; break; //  50 dpi
        case 0x0200: _resolution = (100) << 16; break; // 100 dpi
        case 0x0300: _resolution = (200) << 16; break; // 200 dpi
        default:     _resolution = (150) << 16; break; // 150 dpi
    }
  }
  else
  {
    setMouseResolution(_mouseInfoBytes >> 8);
  }

  //
  // Enable the Intellimouse mode, should this be an Intellimouse.
  //

  if ( (type = setIntellimouseMode()) != kMouseTypeStandard )
  {
    _packetLength = kPacketLengthIntellimouse;
    _type         = type;

    if (_type == kMouseTypeIntellimouseExplorer)
      _buttonCount = 5;
    else
      _buttonCount = 3;

    //
    // Report the resolution of the scroll wheel. This property must
    // be present to enable acceleration for Z-axis movement.
    //
    setProperty(kIOHIDScrollResolutionKey, (10 << 16), 32);
  }
  else
  {
    _packetLength = kPacketLengthStandard;
    _type         = kMouseTypeStandard;
    _buttonCount  = 3;

    removeProperty(kIOHIDScrollResolutionKey);
  }

  _packetByteCount = 0;

  //
  // Enable the mouse clock (should already be so) and the mouse IRQ line.
  //

  setCommandByte(kCB_EnableMouseIRQ, kCB_DisableMouseClock);

  //
  // Finally, we enable the mouse itself, so that it may start reporting
  // mouse events.
  //

  setMouseEnable(true);
}