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

📄 smbmisc.c

📁 winddk src目录下的WDM源码压缩!
💻 C
📖 第 1 页 / 共 3 页
字号:
    IN UCHAR            SmbCmd,
    OUT PULONG          Result
    )
// function to read-word from the SMB device (charger or selector)
// N.B. word is returned as a ULONG
{
    SMB_REQUEST     SmbReq;

    PAGED_CODE();

    SmbReq.Protocol = SMB_READ_WORD;
    SmbReq.Address  = Address;
    SmbReq.Command  = SmbCmd;
    SmbBattGenericRequest (SmbHcFdo, &SmbReq);

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


UCHAR
SmbBattGenericWW(
    IN PDEVICE_OBJECT   SmbHcFdo,
    IN UCHAR            Address,
    IN UCHAR            SmbCmd,
    IN ULONG            Data
    )
// function to write-word to SMB device (charger or selector)
{
    SMB_REQUEST     SmbReq;

    PAGED_CODE();

    SmbReq.Protocol = SMB_WRITE_WORD;
    SmbReq.Address  = 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, ("SmbBattGenericWW: Address: %02x:%02x = %04x\n", Address, SmbCmd, Data));
    SmbBattGenericRequest (SmbHcFdo, &SmbReq);
    return SmbReq.Status;

}



VOID
SmbBattGenericRequest (
    IN PDEVICE_OBJECT   SmbHcFdo,
    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 (!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, ("SmbBattGenericRequest: SmbHc hasn't been opened yet \n"));
        SmbReq->Status = SMB_UNKNOWN_FAILURE;
        return ;
    }


    Irp = IoAllocateIrp (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 acquire and not release etc.
    //
    if (useLock) {
        if (!NT_SUCCESS (SmbBattAcquireGlobalLock (SmbHcFdo, &globalLock))) {
            useLock = FALSE;
        }
    }

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

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

    //
    // Check result code
    //

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



NTSTATUS
SmbBattSetSelectorComm (
    IN  PSMB_BATT   SmbBatt,
    OUT PULONG      OldSelectorState
    )
/*++

Routine Description:

    This routine sets the communication path through the selector to the calling
    battery.  It returns the original selector state in the variable provided.

    NOTE:   It is assumed that the caller already has acquired the device lock on the
            selector before calling us.

    NOTE:   This function should always be called in a pair with SmbBattResetSelectorComm

Arguments:

    SmbBatt             - Nonpaged extension for current battery

    OldSelectorState    - Original selector state at start of this function

Return Value:

    NTSTATUS

--*/
{
    PBATTERY_SELECTOR       selector;
    UCHAR                   smbStatus;
    ULONG                   requestData;

    PAGED_CODE();

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

    //
    // We only need to do this if there is a selector in the system.
    //

    if (SmbBatt->SelectorPresent) {

        selector            = SmbBatt->Selector;
        *OldSelectorState   = selector->SelectorState;

        //
        // If the battery isn't present, fail the request.
        //
        if (!(selector->SelectorState & SmbBatt->SelectorBitPosition)) {
            return STATUS_NO_SUCH_DEVICE;
        }

        //
        // See if we are already set up to talk with the requesting battery.
        // We will check against the cached information in the selector struct.
        //

        if (selector->SelectorState & (SmbBatt->SelectorBitPosition << SELECTOR_SHIFT_COM)) {
            return STATUS_SUCCESS;
        }

        //
        // Build the data word to change the selector communications.  This will
        // look like the following:
        //
        // PRESENT field        0xf     we don't want to change anything here
        // CHARGE field         0xf     we don't want to change anything here
        // POWER BY field       0xf     we don't want to change anything here
        // SMB field            0x_     the bit set according to the battery number
        //

        requestData = (SmbBatt->SelectorBitPosition << SELECTOR_SHIFT_COM) | SELECTOR_SET_COM_MASK;

        smbStatus = SmbBattGenericWW (
                        SmbBatt->SmbHcFdo,
                        selector->SelectorAddress,
                        selector->SelectorStateCommand,
                        requestData
                    );

        if (smbStatus != SMB_STATUS_OK) {
            BattPrint (BAT_ERROR, ("SmbBattSetSelectorComm:  couldn't write selector state - %x\n", smbStatus));
            return STATUS_UNSUCCESSFUL;
        } else {
            selector->SelectorState |= SELECTOR_STATE_SMB_MASK;
            selector->SelectorState &= requestData;

            BattPrint (BAT_IO, ("SmbBattSetSelectorComm: state after write -  %x\n", selector->SelectorState));
        }

    }   // if (subsystemExt->SelectorPresent)

    BattPrint(BAT_TRACE, ("SmbBattSetSelectorComm: EXITING\n"));
    return STATUS_SUCCESS;
}



NTSTATUS
SmbBattResetSelectorComm (
    IN PSMB_BATT    SmbBatt,
    IN ULONG        OldSelectorState
    )
/*++

Routine Description:

    This routine resets the communication path through the selector to the its
    original state.  It returns the original selector state in the variable provided.

    NOTE:   It is assumed that the caller already has acquired the device lock on the
            selector before calling us.

    NOTE:   This function should always be called in a pair with SmbBattSetSelectorComm

Arguments:

    SmbBatt             - Nonpaged extension for current battery

    OldSelectorState    - Original selector state to be restored

Return Value:

    NTSTATUS

--*/
{
    PBATTERY_SELECTOR       selector;
    UCHAR                   smbStatus;
    ULONG                   tmpState;

    NTSTATUS                status      = STATUS_SUCCESS;

    PAGED_CODE();

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

    //
    // We only need to do this if there is a selector in the system.
    //

    if (SmbBatt->SelectorPresent) {

        selector = SmbBatt->Selector;

        //
        // See if we were already set up to talk with the requesting battery.
        // We will check against the cached information in the selector struct.
        //

        if ((OldSelectorState & selector->SelectorState) & SELECTOR_STATE_SMB_MASK) {
            return STATUS_SUCCESS;
        }

        //
        // Change the selector communications back.  The SMB field is the only
        // that we will write.
        //

        tmpState  = SELECTOR_SET_COM_MASK;
        tmpState |= OldSelectorState & SELECTOR_STATE_SMB_MASK;

        smbStatus = SmbBattGenericWW (
                        SmbBatt->SmbHcFdo,
                        selector->SelectorAddress,
                        selector->SelectorStateCommand,
                        tmpState
                    );

        if (smbStatus != SMB_STATUS_OK) {
            BattPrint (
                BAT_ERROR,
                ("SmbBattResetSelectorComm: couldn't write selector state - %x\n",
                smbStatus)
            );
            status = STATUS_UNSUCCESSFUL;
        } else {
            selector->SelectorState |= SELECTOR_STATE_SMB_MASK;
            selector->SelectorState &= tmpState;
            BattPrint (
                BAT_IO,
                ("SmbBattResetSelectorComm: state after write -  %x\n",
                selector->SelectorState)
            );
        }

    }   // if (subsystemExt->SelectorPresent)

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



#if DEBUG
NTSTATUS
SmbBattDirectDataAccess (
    IN PSMB_NP_BATT         DeviceExtension,
    IN PSMBBATT_DATA_STRUCT IoBuffer,
    IN ULONG                InputLen,
    IN ULONG                OutputLen
    )
/*++

Routine Description:

    This routine is used to handle IOCTLs acessing the SMBBatt commands directly.

Arguments:

    DeviceExtension         - Device extension for the smart battery subsystem

    IoBuffer                - Buffer that contains the input structure and will
                              contain the results of the read.

Return Value:

    NTSTATUS
--*/
{
    PSMB_BATT_SUBSYSTEM     SubsystemExt;
    PSMB_BATT               SmbBatt;

    UCHAR                   address;
    UCHAR                   command;
    UCHAR                   smbStatus;
    ULONG                   oldSelectorState;
    ULONG                   ReturnBufferLength;
    UCHAR               strLength;
    UCHAR               strBuffer[SMB_MAX_DATA_SIZE+1]; // +1 extra char to hold NULL
    UCHAR               strBuffer2[SMB_MAX_DATA_SIZE+1];
    UNICODE_STRING      unicodeString;
    ANSI_STRING         ansiString;
    UCHAR               tempFlags;

    NTSTATUS                status = STATUS_SUCCESS;

    PAGED_CODE();

    if (InputLen < sizeof(SMBBATT_DATA_STRUCT)) {
        return STATUS_INVALID_BUFFER_SIZE;
    }

    if ((DeviceExtension->SmbBattFdoType == SmbTypeBattery)
            && (IoBuffer->Address == SMB_BATTERY_ADDRESS)) {
        // This is a battery data request
        SmbBatt = DeviceExtension->Batt;
        SmbBattLockSelector (SmbBatt->Selector);
        SmbBattLockDevice (SmbBatt);
        status = SmbBattSetSelectorComm (SmbBatt, &oldSelectorState);
        if (NT_SUCCESS (status)) {
            if ((InputLen >= sizeof(SMBBATT_DATA_STRUCT)) && (OutputLen == 0)) {
                // This is a write command
                status = STATUS_NOT_IMPLEMENTED;
            } else if ((InputLen == sizeof(SMBBATT_DATA_STRUCT)) && (OutputLen > 0)){
                // This is a Read command

                if ((IoBuffer->Command >= BAT_REMAINING_CAPACITY_ALARM) &&
                    (IoBuffer->Command <= BAT_SERIAL_NUMBER)) {

                    // ReadWord Commands
                    if (OutputLen == sizeof(SMBBATT_DATA_STRUCT)) {
                        tempFlags = SmbBatt->Info.Valid;
                        SmbBatt->Info.Valid |= VALID_TAG_DATA;
                        SmbBattRW(SmbBatt, IoBuffer->Command, &IoBuffer->Data.Ulong);
                        if (SmbBatt->Info.Valid & VALID_TAG_DATA) {
                            ReturnBufferLength = sizeof(ULONG);
                        } else {
                            status = STATUS_DATA_ERROR;
                        }
                        SmbBatt->Info.Valid = tempFlags;
                    } else {
                        status = STATUS_INVALID_BUFFER_SIZE;
                    }

                } else if ((IoBuffer->Command >= BAT_MANUFACTURER_NAME) &&
                    (IoBuffer->Command <= BAT_MANUFACTURER_DATA)) {

                    // ReadBlock Commands
                    if (OutputLen == (SMBBATT_DATA_STRUCT_SIZE)+(SMB_MAX_DATA_SIZE*2)) {
                        memset (&IoBuffer->Data.Block[0], 0, (SMB_MAX_DATA_SIZE*2));
                        unicodeString.Buffer        = &IoBuffer->Data.Block[0];
                        unicodeString.MaximumLength = SMB_MAX_DATA_SIZE*2;
                        unicodeString.Length        = 0;

                        memset (strBuffer, 0, sizeof(strBuffer));
                        memset (strBuffer2, 0, sizeof(strBuffer2));
                        do {
                            SmbBattRB (
                                SmbBatt,

⌨️ 快捷键说明

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