⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smbbatt.c

📁 winddk src目录下的WDM源码压缩!
💻 C
📖 第 1 页 / 共 5 页
字号:
                // Check the status that was read versus what we wrote
                // to see if the operation was successful
                //

                // To support simultaneous charging of more than one battery,
                // we can't check the charge nibble to see if it is equal to
                // what we wrote, but we can check to see if the battery
                // we specified to charge is now set to charge.

                tmp = (selectorState & SELECTOR_STATE_CHARGE_MASK) >> SELECTOR_SHIFT_CHARGE;
                if (SmbBattReverseLogic(SmbBatt->Selector, tmp)) {
                    tmp ^= SELECTOR_STATE_PRESENT_MASK;
                }

                if (tmp & SmbBatt->SelectorBitPosition) {

                    BattPrint(BAT_IRPS, ("SmbBattSetInformation: successfully set charging battery\n"));

                    //
                    // Success!  Save the new selector state in the cache
                    //

                    SmbBatt->Selector->SelectorState = selectorState;
                    status = STATUS_SUCCESS;

                } else {
                    BattPrint(BAT_ERROR, ("SmbBattSetInformation:  couldn't set charging battery\n"));
                    status = STATUS_UNSUCCESSFUL;
                }
                break;

            case BatteryDischarge:

                BattPrint(BAT_IRPS, ("SmbBattSetInformation: Got SetInformation for BatteryDischarge\n"));

                //
                // Set the appropriate bit in the selector state power by nibble
                //

                newSelectorState = SELECTOR_SET_POWER_BY_MASK;
                newSelectorState |= (SmbBatt->SelectorBitPosition << SELECTOR_SHIFT_POWER);

                //
                // Write the new selector state, then read it back.  The system
                // may or may not let us do this.
                //

                smbStatus = SmbBattGenericWW (
                                SmbBatt->SmbHcFdo,
                                SmbBatt->Selector->SelectorAddress,
                                SmbBatt->Selector->SelectorStateCommand,
                                newSelectorState
                            );

                if (smbStatus != SMB_STATUS_OK) {
                    BattPrint(BAT_ERROR,
                             ("SmbBattSetInformation:  couldn't write selector state - %x\n",
                             smbStatus)
                    );

                    status = STATUS_UNSUCCESSFUL;
                    break;
                }

                smbStatus = SmbBattGenericRW (
                                SmbBatt->SmbHcFdo,
                                SmbBatt->Selector->SelectorAddress,
                                SmbBatt->Selector->SelectorStateCommand,
                                &selectorState
                            );

                if ((smbStatus != SMB_STATUS_OK)) {
                    BattPrint(BAT_ERROR,
                             ("SmbBattSetInformation:  couldn't read selector state - %x\n",
                             smbStatus)
                    );

                    status = STATUS_UNSUCCESSFUL;
                    break;
                }


                //
                // Check the status that was read versus what we wrote
                // to see if the operation was successful
                //

                // To support simultaneous powering of more than one battery,
                // we can't check the power nibble to see if it is equal to
                // what we wrote, but we can check to see if the battery
                // we specified to power by is now set to power the system.

                tmp = (selectorState & SELECTOR_STATE_POWER_BY_MASK) >> SELECTOR_SHIFT_POWER;
                if (SmbBattReverseLogic(SmbBatt->Selector, tmp)) {
                    tmp ^= SELECTOR_STATE_PRESENT_MASK;
                }

                if (tmp & SmbBatt->SelectorBitPosition) {

                    BattPrint(BAT_IRPS, ("SmbBattSetInformation: successfully set powering battery\n"));

                    //
                    // Success!  Save the new selector state in the cache
                    //

                    SmbBatt->Selector->SelectorState = selectorState;
                    status = STATUS_SUCCESS;

                } else {
                    BattPrint(BAT_ERROR, ("SmbBattSetInformation:  couldn't set powering battery\n"));
                    status = STATUS_UNSUCCESSFUL;
                }
                break;

        }   // switch (Level)

        //
        // Release the lock on the selector
        //

        SmbBattUnlockSelector (SmbBatt->Selector);

    }   // if (SmbBatt->Selector->SelectorPresent)

    BattPrint(BAT_TRACE, ("SmbBattSetInformation: EXITING\n"));
    return status;
}



NTSTATUS
SmbBattGetPowerState (
    IN PSMB_BATT        SmbBatt,
    OUT PULONG          PowerState,
    OUT PLONG           Current
    )
/*++

Routine Description:

    Returns the current state of AC power.  There are several cases which
    make this far more complex than it really ought to be.

    NOTE: the selector must be locked before entering this routine.

Arguments:

    SmbBatt         - Miniport context value for battery

    AcConnected     - Pointer to a boolean where the AC status is returned

Return Value:

    NTSTATUS

--*/
{
    ULONG               tmp;
    ULONG               chargeBattery;
    ULONG               powerBattery;
    NTSTATUS            status;
    UCHAR               smbStatus;

    PAGED_CODE();

    status = STATUS_SUCCESS;
    *PowerState = 0;

    //
    // Is there a selector in the system?  if not, go read directly from the charger
    //

    if ((SmbBatt->SelectorPresent) && (SmbBatt->Selector)) {

        //
        // There is a selector, we will examine the CHARGE nibble of the state register
        //

        SmbBattGenericRW(
                SmbBatt->SmbHcFdo,
                SMB_SELECTOR_ADDRESS,
                SELECTOR_SELECTOR_STATE,
                &SmbBatt->Selector->SelectorState);

        chargeBattery  = (SmbBatt->Selector->SelectorState & SELECTOR_STATE_CHARGE_MASK) >> SELECTOR_SHIFT_CHARGE;
        powerBattery  = (SmbBatt->Selector->SelectorState & SELECTOR_STATE_POWER_BY_MASK) >> SELECTOR_SHIFT_POWER;


        //
        // If the bits in the CHARGE_X nibble of the selector state register are in the
        // reverse logic state, then AC is connected, otherwise AC is not connected.
        //
        // NOTE: This code depends on every selector implementing this.  If it turns out
        // that this is optional, we can no longer depend on this, and must enable the
        // code below it.
        //

        if (SmbBattReverseLogic(SmbBatt->Selector, chargeBattery)) {
            *PowerState |= BATTERY_POWER_ON_LINE;
        }

        //
        // Look at Charge Indicator if it is supported
        //

        if (*PowerState & BATTERY_POWER_ON_LINE) {

            if (SmbBatt->Selector->SelectorInfo & SELECTOR_INFO_CHARGING_INDICATOR_BIT) {
                if (SmbBattReverseLogic(SmbBatt->Selector, powerBattery)) {
                    *PowerState |= BATTERY_CHARGING;
                }
            }

            if (*Current > 0) {
                *PowerState |= BATTERY_CHARGING;

            }

        } else {

            if (*Current <= 0) {

                //
                // There is some small leakage on some systems, even when AC
                // is present.  So, if AC is present, and the draw
                // is below this "noise" level we will not report as discharging
                // and zero this out.
                //

                if (*Current < -25) {
                    *PowerState |= BATTERY_DISCHARGING;

                } else {
                    *Current = 0;

                }
            }

            //else {
            //    *PowerState |= BATTERY_CHARGING;
            //
            //}

            // If we don't report as discharging, then the AC adapter removal
            // might cause a PowerState of 0 to return, which PowerMeter assumes
            // means, don't change anything

            *PowerState |= BATTERY_DISCHARGING;

        }

    } else {

        //
        // There is no selector, so we'll try to read from the charger.
        //

        smbStatus = SmbBattGenericRW (
                        SmbBatt->SmbHcFdo,
                        SMB_CHARGER_ADDRESS,
                        CHARGER_STATUS,
                        &tmp
                    );

        if (smbStatus != SMB_STATUS_OK) {
            BattPrint (
                BAT_ERROR,
                ("SmbBattGetPowerState: Trying to get charging info, couldn't read from charger at %x, status %x\n",
                SMB_CHARGER_ADDRESS,
                smbStatus)
            );

            *PowerState = 0;

            status = STATUS_UNSUCCESSFUL;
        }

        // Read Charger Successful

        else {

            if (tmp & CHARGER_STATUS_AC_PRESENT_BIT) {
                *PowerState = BATTERY_POWER_ON_LINE;

                if (*Current > 0) {
                    *PowerState |= BATTERY_CHARGING;
                }


            } else {

                if (*Current <= 0) {

                    //
                    // There is some small leakage on some systems, even when AC
                    // is present.  So, if AC is present, and the draw
                    // is below this "noise" level we will not report as discharging
                    // and zero this out.
                    //

                    if (*Current < -25) {
                        *PowerState |= BATTERY_DISCHARGING;
                    } else {
                        *Current = 0;
                    }
                }

                // If we don't report as discharging, then the AC adapter removal
                // might cause a PowerState of 0 to return, which PowerMeter assumes
                // means, don't change anything
                *PowerState |= BATTERY_DISCHARGING;

            }
        }
    }

    return status;
}



NTSTATUS
SmbBattQueryStatus (
    IN PVOID Context,
    IN ULONG BatteryTag,
    OUT PBATTERY_STATUS BatteryStatus
    )
/*++

Routine Description:

    Called by the class driver to retrieve the batteries current status

    N.B. the battery class driver will serialize all requests it issues to
    the miniport for a given battery.  However, this miniport implements
    a lock on the battery device as it needs to serialize to the smb
    battery selector device as well.

Arguments:

    Context         - Miniport context value for battery

    BatteryTag      - Tag of current battery

    BatteryStatus   - Pointer to structure to return the current battery status

Return Value:

    Success if there is a battery currently installed, else no such device.

--*/
{
    PSMB_BATT           SmbBatt;
    NTSTATUS            status;
    BOOLEAN             IoCheck;
    LONG                Current;
    ULONG               oldSelectorState = 0;

    PAGED_CODE();

    BattPrint(BAT_TRACE, ("SmbBattQueryStatus: ENTERING\n"));


    if (BatteryTag == BATTERY_TAG_INVALID) {
        return STATUS_NO_SUCH_DEVICE;
    }

    status = STATUS_SUCCESS;

    //
    // Get device lock and make sure the selector is set up to talk to us.
    // Since multiple people may be doing this, always lock the selector
    // first followed by the battery.
    //

    SmbBatt = (PSMB_BATT) Context;
    SmbBattLockSelector (SmbBatt->Selector);
    SmbBattLockDevice (SmbBatt);

    status = SmbBattSetSelectorComm (SmbBatt, &oldSelectorState);
    if (!NT_SUCCESS (status)) {
        BattPrint(BAT_ERROR, ("SmbBattQueryStatus: can't set selector communications path\n"));
    } else {

        do {
            if (BatteryTag != SmbBatt->Info.Tag) {
                status = STATUS_NO_SUCH_DEVICE;
                break;
            }

            SmbBattRW(SmbBatt, BAT_VOLTAGE, &BatteryStatus->Voltage);
            BatteryStatus->Voltage *= SmbBatt->Info.VoltageScale;

            SmbBattRW(SmbBatt, BAT_REMAINING_CAPACITY, &BatteryStatus->Capacity);
            BatteryStatus->Capacity *= SmbBatt->Info.PowerScale;

            SmbBattRSW(SmbBatt, BAT_CURRENT, &Current);
            Current *= SmbBatt->Info.CurrentScale;

            BattPrint(BAT_DATA,
                ("SmbBattQueryStatus: (%01x)\n"
                "-------  Remaining Capacity - %x\n"
                "-------  Voltage            - %x\n"
                "-------  Current            - %x\n",
                SmbBatt->SelectorBitPosition,
                BatteryStatus->Capacity,
                BatteryStatus->Voltage,
                Current)
            );

            BatteryStatus->Rate = (Current * ((LONG)BatteryStatus->Voltage))/1000;

            //
            // Check to see if we are currently connected to AC.
            //

            status = SmbBattGetPowerState (SmbBatt, &BatteryStatus->PowerState, &Current);
            if (!NT_SUCCESS (status)) {

                BatteryStatus->PowerState = 0;
            }

            //
            // Re-verify static info in case there's been an IO error
            //

            IoCheck = SmbBattVerifyStaticInfo (SmbBatt, BatteryTag);

        } while (IoCheck);

    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -