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

📄 smbmisc.c

📁 winddk src目录下的WDM源码压缩!
💻 C
📖 第 1 页 / 共 3 页
字号:
/*++

Copyright (c) 1990  Microsoft Corporation

Module Name:

    smbmisc.c

Abstract:

    SMBus handler functions

Author:

    Ken Reneris

Environment:

Notes:


Revision History:

    Chris Windle    1/27/98     Bug Fixes

--*/

#include "smbbattp.h"


//
// Make the SelectorBit table pageable
//

//#ifdef ALLOC_DATA_PRAGMA
//#pragma data_seg("PAGE")
//#endif

//
// Lookup table for the battery that corresponds to bit positions and
// whether or not reverse logic is being used (to indicate charging or
// discharging).
//
// NOTE: To support Simultaneous Charging and Powering, this table
// has been modified to account for multiple bits.  Also, it can't be
// used for battery index lookup since it assumes one bit set maximum.
// Instead, use special indexes for multiple batteries as follows:
//
// 1st Battery = Index & 0x03
// 2nd Battery = (Index >> 2) & 0x03 (Battery A not allowed)
// 3rd Battery = (Index >> 4) & 0x03 (Battery A not allowed)
//
// In < 4 battery systems the Battery D bit can be used to determine
// the nibbles that are inverted, and it allows the following combinations:
//
//          Battery A & B
//          Battery A & C
//          Battery B & C
//          Battery A, B, & C
//

const SELECTOR_STATE_LOOKUP SelectorBits [16] = {
    {BATTERY_NONE,  FALSE},         // Bit Pattern: 0000
    {BATTERY_A,     FALSE},         //              0001
    {BATTERY_B,     FALSE},         //              0010
    {MULTIBATT_AB,  FALSE},         //              0011
    {BATTERY_C,     FALSE},         //              0100
    {MULTIBATT_AC,  FALSE},         //              0101
    {MULTIBATT_BC,  FALSE},         //              0110
    {MULTIBATT_ABC, FALSE},         //              0111
    {MULTIBATT_ABC, TRUE},          //              1000
    {MULTIBATT_BC,  TRUE},          //              1001
    {MULTIBATT_AC,  TRUE},          //              1010
    {BATTERY_C,     TRUE},          //              1011
    {MULTIBATT_AB,  TRUE},          //              1100
    {BATTERY_B,     TRUE},          //              1101
    {BATTERY_A,     TRUE},          //              1110
    {BATTERY_NONE,  TRUE}           //              1111
};

//
// Note: For 4-Battery Systems to support Simultaneous Capability
// properly, the following two assumptions must be made:
//      - Battery D can never be used simultaneously.
//      - Three batteries can not be used simultaneously.
//
// This allows for only the following possible battery combinations:
//
//          Battery A & B
//          Battery A & C
//          Battery B & C
//
// The following table is used for 4-battery lookup
//

const SELECTOR_STATE_LOOKUP SelectorBits4 [16] = {
    {BATTERY_NONE,  FALSE},         // Bit Pattern: 0000
    {BATTERY_A,     FALSE},         //              0001
    {BATTERY_B,     FALSE},         //              0010
    {MULTIBATT_AB,  FALSE},         //              0011
    {BATTERY_C,     FALSE},         //              0100
    {MULTIBATT_AC,  FALSE},         //              0101
    {MULTIBATT_BC,  FALSE},         //              0110
    {BATTERY_D,     TRUE},          //              0111
    {BATTERY_D,     FALSE},         //              1000
    {MULTIBATT_BC,  TRUE},          //              1001
    {MULTIBATT_AC,  TRUE},          //              1010
    {BATTERY_C,     TRUE},          //              1011
    {MULTIBATT_AB,  TRUE},          //              1100
    {BATTERY_B,     TRUE},          //              1101
    {BATTERY_A,     TRUE},          //              1110
    {BATTERY_NONE,  TRUE}           //              1111
};


#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE,SmbBattLockDevice)
#pragma alloc_text(PAGE,SmbBattUnlockDevice)
#pragma alloc_text(PAGE,SmbBattLockSelector)
#pragma alloc_text(PAGE,SmbBattUnlockSelector)
#pragma alloc_text(PAGE,SmbBattRequest)
#pragma alloc_text(PAGE,SmbBattRB)
#pragma alloc_text(PAGE,SmbBattRW)
#pragma alloc_text(PAGE,SmbBattRSW)
#pragma alloc_text(PAGE,SmbBattWW)
#pragma alloc_text(PAGE,SmbBattGenericRW)
#pragma alloc_text(PAGE,SmbBattGenericWW)
#pragma alloc_text(PAGE,SmbBattGenericRequest)
#pragma alloc_text(PAGE,SmbBattSetSelectorComm)
#pragma alloc_text(PAGE,SmbBattResetSelectorComm)
#if DEBUG
#pragma alloc_text(PAGE,SmbBattDirectDataAccess)
#endif
#pragma alloc_text(PAGE,SmbBattIndex)
#pragma alloc_text(PAGE,SmbBattReverseLogic)
#pragma alloc_text(PAGE,SmbBattAcquireGlobalLock)
#pragma alloc_text(PAGE,SmbBattReleaseGlobalLock)
#endif



VOID
SmbBattLockDevice (
    IN PSMB_BATT    SmbBatt
    )
{
    PAGED_CODE();

    //
    // Get device lock on the battery
    //

    ExAcquireFastMutex (&SmbBatt->NP->Mutex);
}



VOID
SmbBattUnlockDevice (
    IN PSMB_BATT    SmbBatt
    )
{
    PAGED_CODE();

    //
    // Release device lock on the battery
    //

    ExReleaseFastMutex (&SmbBatt->NP->Mutex);
}



VOID
SmbBattLockSelector (
    IN PBATTERY_SELECTOR    Selector
    )
{
    PAGED_CODE();

    //
    // Get device lock on the selector
    //

    if (Selector) {
        ExAcquireFastMutex (&Selector->Mutex);
    }
}



VOID
SmbBattUnlockSelector (
    IN PBATTERY_SELECTOR    Selector
    )
{
    PAGED_CODE();

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

    if (Selector) {
        ExReleaseFastMutex (&Selector->Mutex);
    }
}



NTSTATUS
SmbBattSynchronousRequest (
    IN PDEVICE_OBJECT       DeviceObject,
    IN PIRP                 Irp,
    IN PVOID                Context
    )
/*++

Routine Description:

    Completion function for synchronous IRPs sent to this driver.
    Context is the event to set

--*/
{
    PKEVENT         Event;

    Event = (PKEVENT) Context;
    KeSetEvent (Event, IO_NO_INCREMENT, FALSE);
    return STATUS_MORE_PROCESSING_REQUIRED;
}



VOID
SmbBattRequest (
    IN PSMB_BATT    SmbBatt,
    IN PSMB_REQUEST SmbReq
    )
// function to issue SMBus request
{
    KEVENT              Event;
    PIRP                Irp;
    PIO_STACK_LOCATION  IrpSp;
    NTSTATUS            Status;
    BOOLEAN             useLock = SmbBattUseGlobalLock;
    ACPI_MANIPULATE_GLOBAL_LOCK_BUFFER globalLock;

    PAGED_CODE();

    //
    // Build Io Control for SMB bus driver for this request
    //

    KeInitializeEvent (&Event, NotificationEvent, FALSE);

    if (!SmbBatt->SmbHcFdo) {
        //
        // The SMB host controller either hasn't been opened yet (in start device) or
        // there was an error opening it and we did not get deleted somehow.
        //

        BattPrint(BAT_ERROR, ("SmbBattRequest: SmbHc hasn't been opened yet \n"));
        SmbReq->Status = SMB_UNKNOWN_FAILURE;
        return ;
    }

    Irp = IoAllocateIrp (SmbBatt->SmbHcFdo->StackSize, FALSE);
    if (!Irp) {
        SmbReq->Status = SMB_UNKNOWN_FAILURE;
        return ;
    }

    IrpSp = IoGetNextIrpStackLocation(Irp);
    IrpSp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
    IrpSp->Parameters.DeviceIoControl.IoControlCode = SMB_BUS_REQUEST;
    IrpSp->Parameters.DeviceIoControl.InputBufferLength = sizeof(SMB_REQUEST);
    IrpSp->Parameters.DeviceIoControl.Type3InputBuffer = SmbReq;
    IoSetCompletionRoutine (Irp, SmbBattSynchronousRequest, &Event, TRUE, TRUE, TRUE);

    //
    // Issue it
    //

    //
    // Note: uselock is a cached value of the global variable, so in case the
    // value changes, we won't aquire and not release etc.
    //
    if (useLock) {
        if (!NT_SUCCESS (SmbBattAcquireGlobalLock (SmbBatt->SmbHcFdo, &globalLock))) {
            useLock = FALSE;
        }
    }

    IoCallDriver (SmbBatt->SmbHcFdo, Irp);
    KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
    Status = Irp->IoStatus.Status;
    IoFreeIrp (Irp);

    if (useLock) {
        SmbBattReleaseGlobalLock (SmbBatt->SmbHcFdo, &globalLock);
    }

    //
    // Check result code
    //

    if (!NT_SUCCESS(Status)) {
        BattPrint(BAT_ERROR, ("SmbBattRequest: error in SmbHc request - %x\n", Status));
        SmbReq->Status = SMB_UNKNOWN_FAILURE;
    }
}



VOID
SmbBattRB(
    IN PSMB_BATT    SmbBatt,
    IN UCHAR        SmbCmd,
    OUT PUCHAR      Buffer,
    OUT PUCHAR      BufferLength
    )
// function to read-block from the battery
{
    SMB_REQUEST     SmbReq;

    PAGED_CODE();

    SmbReq.Protocol = SMB_READ_BLOCK;
    SmbReq.Address  = SMB_BATTERY_ADDRESS;
    SmbReq.Command  = SmbCmd;
    SmbBattRequest (SmbBatt, &SmbReq);

    if (SmbReq.Status == SMB_STATUS_OK) {
        ASSERT (SmbReq.BlockLength < SMB_MAX_DATA_SIZE);
        memcpy (Buffer, SmbReq.Data, SmbReq.BlockLength);
        *BufferLength = SmbReq.BlockLength;
    } else {
        // some sort of failure, check tag data for cache validity
        SmbBatt->Info.Valid &= ~VALID_TAG_DATA;
    }
}



VOID
SmbBattRW(
    IN PSMB_BATT    SmbBatt,
    IN UCHAR        SmbCmd,
    OUT PULONG      Result
    )
// function to read-word from the battery
// N.B. word is returned as a ULONG
{
    SMB_REQUEST     SmbReq;

    PAGED_CODE();

    SmbReq.Protocol = SMB_READ_WORD;
    SmbReq.Address  = SMB_BATTERY_ADDRESS;
    SmbReq.Command  = SmbCmd;
    SmbBattRequest (SmbBatt, &SmbReq);

    if (SmbReq.Status != SMB_STATUS_OK) {
        // some sort of failure, check tag data for cache validity
        SmbBatt->Info.Valid &= ~VALID_TAG_DATA;
    }

    *Result = SmbReq.Data[0] | SmbReq.Data[1] << WORD_MSB_SHIFT;
    BattPrint(BAT_IO, ("SmbBattRW: Command: %02x == %04x\n", SmbCmd, *Result));
}


VOID
SmbBattRSW(
    IN PSMB_BATT    SmbBatt,
    IN UCHAR        SmbCmd,
    OUT PLONG       Result
    )
// function to read-signed-word from the battery
// N.B. word is returned as a LONG
{
    ULONG           i;

    PAGED_CODE();

    SmbBattRW(SmbBatt, SmbCmd, &i);
    *Result = ((SHORT) i);
}


VOID
SmbBattWW(
    IN PSMB_BATT    SmbBatt,
    IN UCHAR        SmbCmd,
    IN ULONG        Data
    )
// function to write-word to the battery
{
    SMB_REQUEST     SmbReq;

    PAGED_CODE();

    SmbReq.Protocol = SMB_WRITE_WORD;
    SmbReq.Address  = SMB_BATTERY_ADDRESS;
    SmbReq.Command  = SmbCmd;
    SmbReq.Data[0]  = (UCHAR) (Data & WORD_LSB_MASK);
    SmbReq.Data[1]  = (UCHAR) (Data >> WORD_MSB_SHIFT) & WORD_LSB_MASK;
    BattPrint(BAT_IO, ("SmbBattWW: Command: %02x = %04x\n", SmbCmd, Data));
    SmbBattRequest (SmbBatt, &SmbReq);

    if (SmbReq.Status != SMB_STATUS_OK) {
        // some sort of failure, check tag data for cache validity
        SmbBatt->Info.Valid &= ~VALID_TAG_DATA;
    }
}



UCHAR
SmbBattGenericRW(
    IN PDEVICE_OBJECT   SmbHcFdo,
    IN UCHAR            Address,

⌨️ 快捷键说明

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