Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Home NTDEV

Before Posting...

Please check out the Community Guidelines in the Announcements and Administration Category.

More Info on Driver Writing and Debugging


The free OSR Learning Library has more than 50 articles on a wide variety of topics about writing and debugging device drivers and Minifilters. From introductory level to advanced. All the articles have been recently reviewed and updated, and are written using the clear and definitive style you've come to expect from OSR over the years.


Check out The OSR Learning Library at: https://www.osr.com/osr-learning-library/


SMBus Intel Apollo Lake Driver Information

bkriegerbkrieger Member Posts: 8

Hello all,

Anyone have any information on the driver provided by Intel for the Apollo Lake SMBus? It comes with the chipset install, but I am unable to find any documentation or a .h for usage anywhere. I have reached out to them with no luck so far. A board I am working with has a PWM located on the SMBus that I need to access from Windows.

New to the forum, so if this is the wrong place for an inquiry like this please just let me know.

Thanks!
Brendan

Comments

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 14,563

    It's possible someone here knows, but Intel has their own set of forums: https://community.intel.com/

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 9,077

    It's the right place to ask the question, but I'll be surprised if anybody here can give you then answer.

    Does it really have a driver installed? Because that's pretty rare. In my experience, the SMBus is used for boot-time stuff (like configuring the DDR) and after that, isn't accessed. The INF typically indicates the infamous "NO_DRV" as the driver.

    PEter

    Peter Viscarola
    OSR
    @OSRDrivers

  • bkriegerbkrieger Member Posts: 8

    Thanks for the link Tim.

    Upon closer inspection I think you are correct Peter. Thanks for the information.

  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 9,077

    An SMBus controller driver is reasonably simple to write. The problem is that you don't really know what's happening with that control from the BIOS side of the world. The BIOS typically assumes that "nothing else" is using the controller (because there's NO_DRV loaded). So it may use the SMBus controller without respecting the interlocks that are typically available for this purpose.

    So, it's sort of a problem. In general, it is not a solvable problem, and not "safe" to write your own SMBus driver if you're targeting general purpose systems. You're better off connecting your device someplace else. OTOH, if you're dealing with a closed system of which you have 100% control... that's a different issue.

    Peter

    Peter Viscarola
    OSR
    @OSRDrivers

  • bkriegerbkrieger Member Posts: 8

    Can't spin the board and move the device to another interface at the moment. I have access to the BIOS on this device. On the fence as far as whether to flesh out the ACPI a little more for the device and create a driver for the ACPI device, or just make sure the BIOS isn't using the SMBus for anything else and write a Windows SMBus driver.

    Brendan

  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 9,077
    edited December 2021

    Everything I write from now on will assume you're using a system in a "closed" environment -- That is, you're not creating a general-purpose solution.

    Your question caused me to look back at some ancient code I wrote 10+ years ago. At that time, I did an R&D project involving a proprietary device on the SMBus, on a closed system. For the project (using a standard white-box machine), the BIOS provided SMBus-specific ACPI methods that allowed me to read/write registers on attached peripheral devices (_SBR and _SBW) -- This was all documented in something called the SMBus Control Method Interface (CMI) spec, which is "standardized" and public.

    This avoided my having to write a host-side controller driver and gave me the HOPE that the ACPI-side of the world did all the right synchronization.

    I wrote a (reasonably simple) driver that exported IOCTLs to user-mode and serviced those IOCTLs by evaluating ACPI methods.

    I have no idea if the ACPI BIOS in more modern Windows systems still includes these methods... but I wouldn't be surprised to discover that it did. You know, once standardized, and somebody's using it somewhere... it can never disappear ;-)

    I hope that helps,

    Peter

    ETA: Comments about modern Windows systems having these same methods in the BIOS.

    Peter Viscarola
    OSR
    @OSRDrivers

  • bkriegerbkrieger Member Posts: 8

    I will go down the route of exposing ACPI methods via a driver for now. Sounds a bit safer and easier, and there do appear to be methods for the bus already. Thanks for the help Peter!

  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 9,077

    there do appear to be methods for the bus already

    You realize that you probably don't need to do anything to expose these, right? You can just call them using IOCTL_ACPI_EVAL_METHOD and friends? Just instantiate a driver in the SMBus controller stack.

    I just didn't want to leave that unstated, in case it's something you missed.

    Peter

    Peter Viscarola
    OSR
    @OSRDrivers

  • bkriegerbkrieger Member Posts: 8
    edited December 2021

    Makes sense. I will utilize those in the driver. Do you know what the difference/s between the regular, v1, and v2 IOCTLS is/are?

  • bkriegerbkrieger Member Posts: 8

    Anyone have any thoughts on why IOCTL_ACPI_EVAL_METHOD would return STATUS_NOT_IMPLEMENTED?

    NTSTATUS                                                     status = STATUS_SUCCESS;
    
    WDFDEVICE                                                            pDevice = WdfIoQueueGetDevice(Queue);
    UCHAR                                                                    brightnessVal = 0;
    ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER  inputBuf;
    ACPI_EVAL_OUTPUT_BUFFER                              outputBuf;
    WDF_MEMORY_DESCRIPTOR                              inputDesc;
    WDF_MEMORY_DESCRIPTOR                              outputDesc;
    ULONG_PTR                                                           bytesReturned;
    
    
            RtlZeroMemory(&inputBuf, sizeof(inputBuf));
    
            inputBuf.Signature = ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER_SIGNATURE;
            inputBuf.MethodNameAsUlong = (ULONG)('MLCB'); // BCLM expressed little-endian
            inputBuf.IntegerArgument = (ULONG)brightnessVal;
    
            WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&inputDesc, &inputBuf, sizeof(inputBuf));
    
            RtlZeroMemory(&outputBuf, sizeof(outputBuf));
            WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&outputDesc, &outputBuf, sizeof(outputBuf));
    
            if (WdfDeviceGetIoTarget(pDevice) == NULL)
            {
                KdPrint((DRIVERNAME " +Get PDO target failed\n"));
                WdfRequestComplete(Request, status);
    
            }
    
            status = WdfIoTargetSendInternalIoctlSynchronously(WdfDeviceGetIoTarget(pDevice), NULL, 
                IOCTL_ACPI_EVAL_METHOD,
                &inputDesc,
                &outputDesc,
                NULL,
                NULL);
    
            if (status)
                KdPrint((DRIVERNAME " +Send Ioctl Failed %x\n", status));
    

    Here is the ACPI code:

    Device(BKPW) {
    NAME(_HID, "ACPI0004")
    Method (BCLM, 0x1)
    {
    _SB.PCI0.SBUS.SWRW(0xC0,0x90,Arg0*40)
    Return()
    }

    }

    The driver is attaching to ACPI0004 without issue. Just not sure why the IOCTL is failing.

    Thanks!
    Brendan

  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 9,077

    Hmmm… while I’m not in a position to compare your code to code that’s “known good” at the moment, my experience has been that these calls “just work”…. I do remember that formatting the input and output buffers was a PITA, though. Don’t know if that applies here. Sorry, I know that’s not optimally helpful (it’s a holiday week).

    The only thing I can suggest offhand is to set a breakpoint in the AML and see what’s up. I’ve done this… it can be tedious, but it can also be useful.

    Peter

    Peter Viscarola
    OSR
    @OSRDrivers

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 14,563
    edited December 2021

    Ah, you've made an error that is very easy to make. IOCTL_ACPI_EVAL_METHOD needs to be sent as a normal ioctl (IRP_MJ_DEVICE_CONTROL), not as an internal ioctl (IRP_MJ_INTERNAL_DEVICE_CONTROL). You need WdfIoTargetSendIoctlSynchronously not WdfIoTargetSendInternalIoctlSynchronously.

    I know that because I've done the same thing.

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 9,077

    LOL… excellent pickup, Mr. Roberts. Bravo on your sharp reading.

    Peter

    Peter Viscarola
    OSR
    @OSRDrivers

  • bkriegerbkrieger Member Posts: 8

    Thanks Tim! Sadly still getting the STATUS_NOT_IMPLEMENTED error after using WdfIoTargetSendIoctlSynchronously instead, but I'm sure that was going to cause other problems for me down the line.

  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 9,077

    Perhaps try one of the V1 or V2 sync or a sync variants?

    Peter

    Peter Viscarola
    OSR
    @OSRDrivers

  • bkriegerbkrieger Member Posts: 8

    Thanks Peter and Tim for the help! Turned out the STATUS_NOT_IMPLEMENTED issue boiled down to the HID I had chosen for the ACPI device. Changed it in the BIOS and updated my INF, and the IOCTL is working now.

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. Sign in or register to get started.

Upcoming OSR Seminars
OSR has suspended in-person seminars due to the Covid-19 outbreak. But, don't miss your training! Attend via the internet instead!
Internals & Software Drivers 19-23 June 2023 Live, Online
Writing WDF Drivers 10-14 July 2023 Live, Online
Kernel Debugging 16-20 October 2023 Live, Online
Developing Minifilters 13-17 November 2023 Live, Online